Skip to main content

Configuring Docker Operations

1. Setting Up Remote Docker

Property Value Description
docker remote Specifies that CircleCI should use remote Docker execution environment
image circleci/node:18 Docker image to run the job in
working_directory /home/circleci/project Working directory inside the container

Example: Basic Remote Docker Configuration

version: 2.1
jobs:
  build:
    docker:
      - image: circleci/node:18
        environment:
          NODE_ENV: test
    working_directory: /home/circleci/project
    steps:
      - checkout
      - run: npm install
Note: Remote Docker is the default execution environment in CircleCI 2.1 and later.
Warning: Ensure that your Docker image includes all necessary dependencies for your build process.

2. Enabling Docker Layer Caching

Note: Docker layer caching in CircleCI significantly reduces build times by reusing previously downloaded or built layers.
Configuration Key Description Values Notes
docker Enables Docker support in the job true Required to enable Docker layer caching
cache-from Specifies Docker images to use for layer caching circleci/<image-name>:<tag> Can be a list of images

Example: Using cache-from in a CircleCI config

version: 2.1
jobs:
  build:
    docker:
      - image: circleci/<span class="highlight">node</span>:18
        environment:
          <span class="highlight">DOCKER_BUILDKIT</span>: 1
      - image: circleci/<span class="highlight">postgres</span>:13
    steps:
      - checkout
      - run: |
          docker build --cache-from circleci/<span class="highlight">node</span>:18 -t my-app .
      - save_cache:
          key: v1-dependencies-{{ checksum <span class="highlight">"package-lock.json"</span> }}
          paths:
            - <span class="highlight">node_modules</span>

Example: Using cache-from with multiple images

version: 2.1
jobs:
  build:
    docker:
      - image: circleci/<span class="highlight">node</span>:18
        environment:
          <span class="highlight">DOCKER_BUILDKIT</span>: 1
      - image: circleci/<span class="highlight">postgres</span>:13
    steps:
      - checkout
      - run: |
          docker build --cache-from circleci/<span class="highlight">node</span>:18 --cache-from circleci/<span class="highlight">postgres</span>:13 -t my-app .
      - save_cache:
          key: v1-dependencies-{{ checksum <span class="highlight">"package-lock.json"</span> }}
          paths:
            - <span class="highlight">node_modules</span>

Key Benefits of Docker Layer Caching

  • Reduces build times by reusing layers from previous builds
  • Improves CI/CD pipeline efficiency
  • Works best with DOCKER_BUILDKIT=1
Warning: Ensure that the cache keys are stable and consistent to avoid cache misses.

3. Building Docker Images

Property Description Example
build Defines the Docker image build configuration build: .
context Specifies the build context directory context: ./app
dockerfile Path to the Dockerfile dockerfile: ./Dockerfile.prod
tags Tags to apply to the built image tags: [latest, v1.0]

Example: Building a Docker Image

build:
  context: .
  dockerfile: ./Dockerfile
  tags:
    - latest
    - "v1.0"
Note: The context is the directory from which Docker reads files to build the image.
Warning: Ensure Dockerfile is in the correct path and context is set properly to avoid build errors.

4. Tagging Docker Images

Tag Type Description Example Notes
circleci/docker-tag Standard Docker image tag format circleci/docker-tag:latest Used for versioning Docker images in CircleCI
circleci/docker-tag:branch Tag based on Git branch name circleci/docker-tag:feature-branch Helps identify images built from specific branches
circleci/docker-tag:commit Tag based on Git commit SHA circleci/docker-tag:abc12345 Ensures uniqueness for each build

Example: Using CircleCI's built-in Docker tagging

version: 2.1
jobs:
  build:
    docker:
      - image: circleci/python:3.9
    steps:
      - checkout
      - setup_remote_docker
      - run:
          name: Build Docker image with tag
          command: |
            docker build -t circleci/python:3.9-${CIRCLE_SHA1} .
Note: CircleCI automatically sets CIRCLE_SHA1 to the short Git commit hash, which is useful for uniquely tagging Docker images.
Warning: Avoid using latest as a tag in production environments, as it can lead to unpredictable behavior when images are updated.

5. Pushing to Registries

Registry Push Command Notes
Docker Hub docker push <username>/<image> Requires Docker Hub account and image repository
Amazon ECR docker push <aws-account-id>.dkr.ecr.<region>.amazonaws.com/<repository> Needs AWS CLI configured with appropriate permissions
Google Container Registry (GCR) docker push gcr.io/<project-id>/<image> Requires gcloud CLI and project setup
Azure Container Registry (ACR) docker push <registry-name>.azurecr.io/<image> Authentication via Azure CLI or service principal

Example: Pushing to Docker Hub

docker build -t myapp .
docker tag myapp <username>/myapp:latest
docker push <username>/myapp:latest

Example: Pushing to Amazon ECR

aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <aws-account-id>.dkr.ecr.<region>.amazonaws.com
docker build -t <aws-account-id>.dkr.ecr.<region>.amazonaws.com/<repository> .
docker push <aws-account-id>.dkr.ecr.<region>.amazonaws.com/<repository>
Note: Ensure that your CircleCI environment has the necessary credentials and permissions to push to the target registry.

6. Authenticating with Docker Hub

Option Values Notes
docker.login true Enables automatic login to Docker Hub
docker.username process.env.DOCKER_USERNAME Environment variable for Docker Hub username
docker.password process.env.DOCKER_PASSWORD Environment variable for Docker Hub password

Example: Configuring Docker Login in CircleCI

version: 2.1
jobs:
  build:
    docker:
      - image: circleci/node:16
    steps:
      - checkout
      - run:
          name: Login to Docker Hub
          command: |
            echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin
      - run:
          name: Build and Push Image
          command: |
            docker build -t my-app .
            docker push my-app
Note: Store Docker credentials as CircleCI environment variables to avoid exposing them in config files.
Warning: Using docker login with a password is less secure than using a personal access token (PAT). Consider using PATs for better security.

7. Using Private Registries

Registry Type Authentication Method Configuration Example Notes
Docker Hub docker login docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD Requires Docker Hub credentials stored as CircleCI environment variables
Amazon ECR AWS credentials via aws configure eval $(aws ecr get-login --region us-east-1 --no-include-email) Uses AWS CLI to fetch temporary login credentials
Google Container Registry (GCR) Service account key JSON gcloud auth activate-service-account --key-file=service-account.json Requires GCP project and service account setup
Azure Container Registry (ACR) Azure CLI login az acr login --name myregistry Uses Azure CLI to authenticate with ACR

Example: Using a Private Docker Image from ECR

version: 2.1
jobs:
  build:
    docker:
      - image: 123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp:latest
    steps:
      - checkout
      - run:
          name: Run application
          command: |
            echo "Running application from private ECR image"
Note: Ensure that the CircleCI project has appropriate AWS IAM permissions to access ECR repositories.
Warning: Never hardcode credentials in CircleCI configuration files. Always use environment variables or CircleCI context secrets.

8. Using Docker Compose

Property Description Example
docker-compose.yml File defining services, networks, and volumes for Docker Compose version: '3.8'
services Defines the containers to run in the CircleCI job app:
image Specifies the Docker image to use for a service image: node:18
ports Maps container ports to host ports ports: ["3000:3000"]
volumes Mounts directories or files into the container volumes: ['./:/app']
environment Sets environment variables in the container environment: NODE_ENV: production

Example: Running a Node.js App with Docker Compose

version: '3.8'
services:
  app:
    image: node:18
    working_dir: /app
    command: npm run start
    ports:
      - "3000:3000"
    volumes:
      - .:/app
    environment:
      NODE_ENV: production
Note: CircleCI supports Docker Compose v2 and v3 formats. Ensure your docker-compose.yml is compatible with the version used by CircleCI.
Warning: Avoid using docker-compose up in CircleCI workflows. Use the circleci/cli or setup_remote_docker steps instead.

Key Points

  • Docker Compose files define multi-container applications.
  • CircleCI supports docker-compose.yml for defining services and dependencies.
  • Use setup_remote_docker to enable Docker Compose in CircleCI.
  • Environment variables and volumes can be configured in the docker-compose.yml.

9. Running Multi-Container Tests

Option Values Notes
docker docker Use Docker for multi-container testing
service service Define services to run in containers
test test Run tests in the container environment

Example: Running Multi-Container Tests

version: 2.1
jobs:
  test:
    docker:
      - image: circleci/node:16
        environment:
          NODE_ENV: test
      - image: circleci/mongo:4.0
        environment:
          MONGO_INITDB_ROOT_USERNAME: testuser
          MONGO_INITDB_ROOT_PASSWORD: testpass
    steps:
      - checkout
      - run:
          name: Run Tests
          command: npm test
Note: Ensure that your test containers are properly configured to communicate with each other using service names as hostnames.

10. Optimizing Docker Builds

Optimization Description Implementation
Multi-stage builds Build artifacts in one stage, copy only necessary files to final image
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
Layer caching Re-use layers by ordering instructions to minimize rebuilds
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
Use .dockerignore Exclude unnecessary files to reduce build context size
.git
.gitignore
README.md
node_modules
npm-debug.log
.DS_Store

Example: Caching Dependencies

FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Cache dependencies in a separate layer
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
Note: Multi-stage builds reduce image size and improve security by excluding development dependencies.
Warning: Avoid copying entire directories without .dockerignore, as it increases build context and time.

11. Using BuildKit Features

Feature Description Usage Notes
buildkit.enabled Enables BuildKit for Docker builds buildkit.enabled: true Required for BuildKit features
buildkit.cache-from Specifies cache sources for BuildKit buildkit.cache-from: [\"type=registry,ref=myapp:latest\"] Improves build performance
buildkit.cache-to Specifies cache destinations for BuildKit buildkit.cache-to: {\"type\": \"registry\", \"ref\": \"myapp:cache\"} Enables caching between builds

Example: Enabling BuildKit in CircleCI

version: 2.1
jobs:
  build:
    docker:
      - image: circleci/node:16
    steps:
      - checkout
      - run:
          name: Enable BuildKit
          command: |
            echo 'export DOCKER_BUILDKIT=1' >> $BASH_ENV
      - run:
          name: Build with Cache
          command: |
            docker build --cache-from myapp:latest -t myapp .
Note: BuildKit requires Docker 18.09 or higher.

12. Debugging Docker Issues

Example: Debugging a failing Docker build

version: 2.1
jobs:
  build:
    docker:
      - image: circleci/node:16
    steps:
      - checkout
      - run:
          name: Debug build environment
          command: |
            echo "Node version:"
            node --version
            echo "NPM version:"
            npm --version
            echo "Working directory contents:"
            ls -la
Issue Symptoms Resolution Steps
Image not found Error: pull access denied for circleci/node, repository does not exist or may require 'docker login' Ensure image name is correct. Use official CircleCI images or login to private registries.
Build timeout Timeout exceeded: job exceeded maximum runtime of 5 minutes Add working_directory to reduce path traversal. Optimize Docker image size.
Permission denied Permission denied when trying to access file or directory Use user: root in job config or ensure proper file permissions in image.

Debugging Steps

  1. Check logs for error messages and stack traces
  2. Verify Docker image name and tag
  3. Run circleci local execute locally to test configuration
  4. Use circleci config validate to check syntax
  5. Review CircleCI documentation for image-specific quirks
Note: Use circleci local execute to simulate job execution locally for faster debugging.
Warning: Avoid including sensitive credentials in logs or configuration files.

Was this article helpful?