Skip to main content

Building Docker Images in Pipelines

1. Building Images with Docker Build

Property Description Example
docker build Command to build a Docker image from a Dockerfile docker build -t my-image .
-t Tag the image with a name docker build -t my-app:latest .
-f Specify the Dockerfile path docker build -f ./Dockerfile.prod -t prod-image .
--build-arg Pass build-time variables to the Dockerfile docker build --build-arg NODE_VERSION=18 -t my-app .

Example: Building a Docker Image in GitLab CI

build_image:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t my-app:latest .
    - docker push my-app:latest
Note: The docker:dind service is required to run Docker inside a Docker container.

2. Using Docker-in-Docker

Option Values Notes
services dind Use the Docker-in-Docker service to run Docker commands inside a job
image docker:20.10.16-dind Base image with Docker-in-Docker support (requires Docker 20.10+)
variables DOCKER_HOST: tcp://docker:2375 Set DOCKER_HOST to connect to the Docker daemon inside the service

Example: Building and pushing a Docker image using DnD

build_docker:
  image: docker:20.10.16-dind
  services:
    - docker:20.10.16-dind
  variables:
    DOCKER_HOST: tcp://docker:2375
  script:
    - docker build -t my-app .
    - docker tag my-app $CI_REGISTRY_IMAGE:latest
    - docker push $CI_REGISTRY_IMAGE:latest
Note: DnD requires Docker 20.10 or newer and uses a separate container to run the Docker daemon.

3. Using Kaniko for Builds

Example: Basic Kaniko Job Configuration

build-with-kaniko:
  image: gcr.io/kaniko-project/executor:v1.20.0
  stage: build
  script:
    - mkdir -p /kaniko/.docker
    - echo "{\"auths\":{\"gcr.io\":{\"auth\":\"$(echo -n "${GCP_SERVICE_ACCOUNT}" | base64 -w0)"}}}" > /kaniko/.docker/config.json
    - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination gcr.io/my-project/my-app:latest
Option Description Notes
--context Path to the build context directory Required. Usually set to $CI_PROJECT_DIR
--dockerfile Path to the Dockerfile Optional, defaults to Dockerfile
--destination Registry and image name to push to Required. Format: <registry>/<image>:<tag>
--cache Enable caching for faster builds Optional. Set to true to enable caching
--cache-ttl Time to live for cached layers (in hours) Optional. Default is 12 hours
Note: Kaniko runs entirely in the container and does not require Docker daemon, making it ideal for CI/CD environments.
Warning: Ensure that the service account used has appropriate permissions to push images to the target registry.

Key Features of Kaniko

  • Runs without Docker daemon
  • Supports multi-stage builds
  • Can use build arguments and secrets
  • Works in containerized environments like GitLab CI

4. Using Buildah for Builds

Property Description Example
image Docker image to use for the job quay.io/buildah/stable:latest
before_script Commands to run before build process buildah bud -t myapp .
script Buildah commands to execute buildah bud -t myapp .

Example: Buildah Docker Image

buildah bud -t myapp .
Note: Buildah is a tool for building OCI-compliant container images without requiring a Docker daemon.
Warning: Ensure the Buildah image has necessary permissions to access Docker registry if pushing images.

Key Features of Buildah

  • No Docker daemon required
  • OCI image format support
  • Can build from Dockerfiles or directly from commands
  • Supports multi-platform builds

5. Using Multi-Stage Docker Builds

Stage Description Use Case Example
FROM alpine:latest Base image for building Minimal build environment
FROM alpine:latest AS builder
RUN apk add --no-cache gcc g++ make
FROM node:18-alpine Runtime image for final container Production deployment
FROM node:18-alpine AS runtime
WORKDIR /app
COPY --from=builder /app/dist ./dist

Example: Multi-stage build in GitLab CI

build:
  stage: build
  image: docker:20.10.16
  services:
    - docker:dind
  script:
    - docker build --target builder -t my-app:builder .
    - docker build --target runtime -t my-app:runtime .
  artifacts:
    paths:
      - my-app:runtime
Note: Multi-stage builds reduce final image size and improve security by separating build-time dependencies from runtime.

6. Optimizing Build Cache (--cache-from)

Option Values Description
--cache-from type=registry,ref=<image-name> Specifies the image to use for build cache
--cache-from type=local,src=<path> Specifies a local cache directory

Example: Using --cache-from with Docker Build

docker build --cache-from type=registry,ref=registry.gitlab.com/group/project:latest -t registry.gitlab.com/group/project:build .
Note: The --cache-from option helps speed up builds by reusing layers from previous builds.

7. Building Multi-Architecture Images

Option Values Description
platform linux/amd64, linux/arm64 Target architecture for the image build
buildx true Enables Docker Buildx for multi-architecture support

Example: Building for AMD64 and ARM64

build-multi-arch:
  stage: build
  image: docker:20.10.16
  services:
    - docker:dind
  script:
    - docker buildx create --name mybuilder --use
    - docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest .
Note: Requires Docker Buildx and QEMU emulation for ARM support.
Warning: Ensure that base images are compatible with target platforms.

8. Using Build Arguments (--build-arg)

Argument Description Example
--build-arg Passes build-time variables to the Docker image build process --build-arg NODE_VERSION=18

Example: Setting Build Arguments in GitLab CI

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build --build-arg NODE_VERSION=18 -t my-app .
Note: Build arguments are only available during the build process and are not persisted in the final image.

9. Setting Build Context

Property Description Default Notes
build_context Path to the build context directory . Used by Docker to determine the root directory for the build
dockerfile Path to the Dockerfile Dockerfile Can be relative to build context or absolute path

Example: Setting build context in a GitLab CI job

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t my-app -f ./build/Dockerfile .
Note: The build_context is the directory from which Docker reads files during the build process. It's important to set this correctly to ensure all necessary files are included in the image.

10. Tagging Images

Tag Type Description Example Notes
tag Static tag for the image latest Default if no tag specified
tag Git branch name main Useful for tracking development
tag Git commit short SHA abc1234 Ensures reproducibility
tag Git tag (annotated) v1.0.0 Used for releases
tag Timestamp 20250405.123456 Useful for CI builds

Example: Using Git Tags for Image Tagging

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG

Example: Tagging with Branch and Commit SHA

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t $CI_REGISTRY_IMAGE:${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHORT_SHA} .
    - docker push $CI_REGISTRY_IMAGE:${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHORT_SHA}
Note: The $CI_REGISTRY_IMAGE variable is automatically set by GitLab CI/CD when using the built-in container registry.

Was this article helpful?