Building Docker Images on CircleCI 2.0
To help users build, run, and publish new images, we’ve introduced a special feature which creates a separate environment for each build. This environment is remote, fully-isolated and has been configured to execute Docker commands.
If your build requires
docker-compose commands, you’ll need to add a special step into your
jobs: build: steps: # ... steps for building/testing app ... - setup_remote_docker
setup_remote_docker executes, a remote environment will be created, and your current primary container will be configured to use it. Then, any docker-related commands you use will be safely executed in this new environment.
Here’s an example where we build and push a Docker image for our demo docker project:
version: 2 jobs: build: docker: - image: golang:1.6.4 # (1) working_directory: /go/src/github.com/circleci/cci-demo-docker steps: - checkout # ... steps for building/testing app ... - setup_remote_docker # (2) # use a primary image that already has Docker (recommended) # or install it during a build like we do here - run: name: Install Docker client command: | set -x VER="17.03.0-ce" curl -L -o /tmp/docker-$VER.tgz https://get.docker.com/builds/Linux/x86_64/docker-$VER.tgz tar -xz -C /tmp -f /tmp/docker-$VER.tgz mv /tmp/docker/* /usr/bin # build and push Docker image - run: | TAG=0.1.$CIRCLE_BUILD_NUM docker build -t circleci/cci-demo-docker:$TAG . # (3) docker login -u $DOCKER_USER -p $DOCKER_PASS # (4) docker push circleci/cci-demo-docker:$TAG
Let’s break down what’s happening during this build’s execution:
- All commands are executed in the primary container.
setup_remote_dockeris called, a new remote environment is created, and your primary container is configured to use it.
- All docker-related commands are also executed in your primary container, but building/pushing images and running containers happens in the remote Docker Engine.
- We use project environment variables to store credentials for Docker Hub.
Separation of Environments
It’s impossible to start a service in remote docker and ping it directly from a primary container (and vice versa). To solve that, you’ll need to interact with a service from remote docker, as well as through the same container:
# start service and check that it’s running - run: | docker run -d --name my-app my-app docker exec my-app curl --retry 10 --retry-connrefused http://localhost:8080
A different way to do this is to use another container running in the same network as the target container:
- run: | docker run -d --name my-app my-app docker run --network container:my-app appropriate/curl --retry 10 --retry-connrefused http://localhost:8080
It’s not possible to mount a folder from the build container into an isolated Docker container (and vice versa).
If you have any questions, head over to our community forum for support from us and other users.