A Buildkite plugin that lets you build, run and push build steps using Docker Compose.
- Containers are built, run and linked on demand using Docker Compose
- Containers are namespaced to each build job, and cleaned up after use
- Supports pre-building of images, allowing for fast parallel builds across distributed agents
- Supports pushing tagged images to a repository
The following pipeline will run test.sh
inside a app
service container using Docker Compose, the equivalent to running docker-compose run app test.sh
:
steps:
- command: test.sh
plugins:
- docker-compose#v3.5.0:
run: app
You can also specify a custom Docker Compose config file and what environment to pass through if you need:
steps:
- command: test.sh
plugins:
- docker-compose#v3.5.0:
run: app
config: docker-compose.tests.yml
env:
- BUILDKITE_BUILD_NUMBER
or multiple config files:
steps:
- command: test.sh
plugins:
- docker-compose#v3.5.0:
run: app
config:
- docker-compose.yml
- docker-compose.test.yml
You can leverage the docker-login plugin in tandem for authenticating with a registry. For example, the following will build and push an image to a private repo, and pull from that private repo in subsequent run commands:
steps:
- plugins:
- docker-login#v2.0.1:
username: xyz
- docker-compose#v3.5.0:
build: app
image-repository: index.docker.io/myorg/myrepo
- wait
- command: test.sh
plugins:
- docker-login#v2.0.1:
username: xyz
- docker-compose#v3.5.0:
run: app
If you want to control how your command is passed to docker-compose, you can use the command parameter on the plugin directly:
steps:
- plugins:
- docker-compose#v3.5.0:
run: app
command: ["custom", "command", "values"]
If you’re generating artifacts in the build step, you’ll need to ensure your Docker Compose configuration volume mounts the host machine directory into the container where those artifacts are created.
For example, if you had the following step:
steps:
- command: generate-dist.sh
artifact_paths: "dist/*"
plugins:
- docker-compose#v3.5.0:
run: app
Assuming your application’s directory inside the container was /app
, you would need to ensure your app
service in your Docker Compose config has the following host volume mount:
volumes:
- "./dist:/app/dist"
You can also use the volumes
plugin option to add or override a volume, for example:
steps:
- command: generate-dist.sh
artifact_paths: "dist/*"
plugins:
- docker-compose#v3.5.0:
run: app
volumes:
- "./dist:/app/dist"
By default, docker-compose makes whatever environment variables it gets available for interpolation of docker-compose.yml, but it doesn't pass them in to your containers.
You can use the environment key in docker-compose.yml to either set specific environment vars or "pass through" environment variables from outside docker-compose.
If you want to add extra environment above what is declared in your docker-compose.yml
,
this plugin offers a environment
block of it's own:
steps:
- command: generate-dist.sh
plugins:
- docker-compose#v3.5.0:
run: app
env:
- BUILDKITE_BUILD_NUMBER
- BUILDKITE_PULL_REQUEST
- MY_CUSTOM_ENV=llamas
Note how the values in the list can either be just a key (so the value is sourced from the environment) or a KEY=VALUE pair.
You can use the build args key in docker-compose.yml to set specific build arguments when building an image.
Alternatively, if you want to set build arguments when pre-building an image, this plugin offers an args
block of it's own:
steps:
- command: generate-dist.sh
plugins:
- docker-compose#v3.5.0:
build: app
image-repository: index.docker.io/myorg/myrepo
args:
- MY_CUSTOM_ARG=panda
Note that the values in the list must be a KEY=VALUE pair.
To speed up run steps that use the same service/image (such as steps that run in parallel), you can add a pre-build step to your pipeline:
steps:
- label: ":docker: Build"
plugins:
- docker-compose#v3.5.0:
build: app
image-repository: index.docker.io/myorg/myrepo
- wait
- label: ":docker: Test %n"
command: test.sh
parallelism: 25
plugins:
- docker-compose#v3.5.0:
run: app
All run
steps for the service app
will automatically pull and use the pre-built image.
Sometimes your compose file has multiple services that need building. The example below will build images for the app
and tests
service and then the run step will pull them down and use them for the run as needed.
steps:
- label: ":docker: Build"
agents:
queue: docker-builder
plugins:
- docker-compose#v3.5.0:
build:
- app
- tests
image-repository: index.docker.io/myorg/myrepo
- wait
- label: ":docker: Test %n"
command: test.sh
parallelism: 25
plugins:
- docker-compose#v3.5.0:
run: tests
If you want to push your Docker images ready for deployment, you can use the push
configuration (which operates similar to docker-compose push:
steps:
- label: ":docker: Push"
plugins:
- docker-compose#v3.5.0:
push: app
If you need to authenticate to the repository to push (e.g. when pushing to Docker Hub), use the Docker Login plugin:
steps:
- label: ":docker: Push"
plugins:
- docker-login#v2.0.1:
username: xyz
- docker-compose#v3.5.0:
push: app
To push multiple images, you can use a list:
steps:
- label: ":docker: Push"
plugins:
- docker-login#v2.0.1:
username: xyz
- docker-compose#v3.5.0:
push:
- first-service
- second-service
If you want to push to a specific location (that's not defined as the image
in your docker-compose.yml), you can use the {service}:{repo}:{tag}
format, for example:
steps:
- label: ":docker: Push"
plugins:
- docker-login#v2.0.1:
username: xyz
- docker-compose#v3.5.0:
push:
- app:index.docker.io/myorg/myrepo/myapp
- app:index.docker.io/myorg/myrepo/myapp:latest
A newly spawned agent won't contain any of the docker caches for the first run which will result in a long build step. To mitigate this you can reuse caches from a previously built image (if it was pushed from a previous build):
steps:
- label: ":docker Build an image"
plugins:
- docker-compose#v3.5.0:
build: app
image-repository: index.docker.io/myorg/myrepo
cache-from: app:index.docker.io/myorg/myrepo/myapp:latest
- wait
- label: ":docker: Push to final repository"
plugins:
- docker-compose#v3.5.0:
push:
- app:index.docker.io/myorg/myrepo/myapp
- app:index.docker.io/myorg/myrepo/myapp:latest
The name of a service to build and store, allowing following pipeline steps to run faster as they won't need to build the image. The step’s command
will be ignored and does not need to be specified.
Either a single service or multiple services can be provided as an array.
The name of the service the command should be run within. If the docker-compose command would usually be docker-compose run app test.sh
then the value would be app
.
A list of services to push in the format service:image:tag
. If an image has been pre-built with the build step, that image will be re-tagged, otherwise docker-compose's built in push operation will be used.
Pull down multiple pre-built images. By default only the service that is being run will be pulled down, but this allows multiple images to be specified to handle prebuilt dependent images.
The file name of the Docker Compose configuration file to use. Can also be a list of filenames.
Default: docker-compose.yml
The repository for pushing and pulling pre-built images, same as the repository location you would use for a docker push
, for example "index.docker.io/myorg/myrepo"
. Each image is tagged to the specific build so you can safely share the same image repository for any number of projects and builds.
The default is ""
which only builds images on the local Docker host doing the build.
This option can also be configured on the agent machine using the environment variable BUILDKITE_PLUGIN_DOCKER_COMPOSE_IMAGE_REPOSITORY
.
The name to use when tagging pre-built images. If multiple images are built in the build phase, you must provide an array of image names.
Other docker-compose services that should be aliased to the main service that was built. This is for when different docker-compose services share the same prebuilt image.
A list of KEY=VALUE that are passed through as build arguments when image is being built.
A list of either KEY or KEY=VALUE that are passed through as environment variables to the container.
Sets the command for the Docker image, and defaults the shell
option to false
. Useful if the Docker image has an entrypoint, or doesn't contain a shell.
This option can't be used if your step already has a top-level, non-plugin command
option present.
Examples: [ "/bin/mycommand", "-c", "test" ]
, ["arg1", "arg2"]
Set the shell to use for the command. Set it to false
to pass the command directly to the docker-compose run
command. The default is ["/bin/sh", "-e", "-c"]
unless you have provided a command
.
Example: [ "powershell", "-Command" ]
Whether to skip the repository checkout phase. This is useful for steps that use a pre-built image. This will fail if there is no pre-built image.
Specify the container working directory via docker-compose run --workdir
.
Run as specified username or uid via docker-compose run --user
.
Whether to match the user ID and group ID for the container user to the user ID and group ID for the host user. It is similar to specifying user: 1000:1000, except it avoids hardcoding a particular user/group ID.
Using this option ensures that any files created on shared mounts from within the container will be accessible to the host user. It is otherwise common to accidentally create root-owned files that Buildkite will be unable to remove, since containers by default run as the root user.
A number of times to retry failed docker pull. Defaults to 0.
This option can also be configured on the agent machine using the environment variable BUILDKITE_PLUGIN_DOCKER_COMPOSE_PULL_RETRIES
.
A number of times to retry failed docker push. Defaults to 0.
This option can also be configured on the agent machine using the environment variable BUILDKITE_PLUGIN_DOCKER_COMPOSE_PUSH_RETRIES
.
A list of images to pull caches from in the format service:index.docker.io/myorg/myrepo/myapp:tag
before building, ignoring any failures. If multiple images are listed for a service, the first one to successfully pull will be used. Requires docker-compose file version 3.2+
.
A list of volumes to mount into the container. If a matching volume exists in the Docker Compose config file, this option will override that definition.
Additionally, volumes may be specified via the agent environment variable BUILDKITE_DOCKER_DEFAULT_VOLUMES
, a ;
(semicolon) delimited list of mounts in the -v
syntax. (Ex. buildkite:/buildkite;./app:/app
).
Gracefully shuts down all containers via 'docker-compose stop`.
The default is false
.
Prevent the removal of volumes after the command has been run.
The default is false
.
Build with --no-cache
, causing Docker Compose to not use any caches when building the image.
The default is false
.
Build with --parallel
, causing Docker Compose to run builds in parallel. Requires docker-compose 1.23+
.
The default is false
.
If set to false, doesn't allocate a TTY. This is useful in some situations where TTY's aren't supported, for instance windows.
The default is true
on unix, false
on windows
If set to false, doesn't start linked services.
The default is true
.
If set to false, disables the ansi output from containers.
The default is true
.
If set to true, docker compose will use the service's network aliases in the network(s) the container connects to.
The default is false
.
Sets docker-compose
to run with --verbose
The default is false
.
If set to true, docker compose will remove the primary container after run. Equivalent to --rm
in docker-compose.
The default is true
.
Sets the --entrypoint
argument when running docker-compose
.
Select when to upload container logs.
on-error
Upload logs for all containers when an error occursalways
Always upload logs for all containernever
Never upload logs for all container
The default is on-error
.
To run the tests:
docker-compose run --rm tests
MIT (see LICENSE)