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 . |
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 node:18-alpine | Runtime image for final container | Production deployment | |
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.