Skip to main content

Working with Docker Images

1. Using Docker Images

Property Description Example
image Docker image to use for the job node:18-alpine
services Additional services to run with the job postgres:13
variables Environment variables to pass to the container DB_HOST=postgres

Example: Using a Docker image in a job

job_name:
  image: node:18-alpine
  script:
    - npm install
    - npm test

Example: Using a service with Docker image

job_name:
  image: node:18-alpine
  services:
    - postgres:13
  script:
    - npm install
    - npm test
Note: The image keyword defines the Docker image to use for a job. It can be a custom image or a public image from Docker Hub.

2. Specifying Image Tags

Tag Type Format Description Example
Image Tag latest Default tag if none specified docker:latest
Image Tag v1.0 Versioned tag for stable releases myapp:v1.0
Image Tag sha256:hash Immutable tag based on content digest myapp@sha256:abc123...
Image Tag branch-name Tag based on Git branch name myapp:feature-branch
Image Tag short-sha Short Git commit hash myapp:abc1234

Example: Using Tag in GitLab CI

build_job:
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t myapp:$CI_COMMIT_SHORT_SHA .
    - docker push myapp:$CI_COMMIT_SHORT_SHA

3. Setting Image Entrypoint

Property Description Default Notes
entrypoint Override the default entrypoint of the image ["/bin/sh", "-c"] Can be a string or array of strings

Example: Setting entrypoint in a job

job_name:
  image: alpine:latest
  entrypoint: ["/bin/sh", "-c"]
  script:
    - echo "Hello from custom entrypoint"
Note: The entrypoint is set at runtime and overrides the image's default entrypoint.

4. Pulling Images from Private Registries

Registry Type Authentication Method Configuration Example Notes
GitLab Container Registry CI_REGISTRY_USER and CI_REGISTRY_PASSWORD docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY Automatically available in GitLab CI/CD pipelines
Amazon ECR Using AWS credentials via aws ecr get-login-password docker login -u AWS -p $(aws ecr get-login-password --region us-east-1) https://123456789012.dkr.ecr.us-east-1.amazonaws.com Requires aws-cli installed in the runner
Docker Hub Using DOCKERHUB_USERNAME and DOCKERHUB_TOKEN docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_TOKEN Token can be generated from Docker Hub account settings
Azure Container Registry Using Azure CLI with service principal az acr login --name myregistry Requires Azure CLI and appropriate permissions set up

Example: Using GitLab Container Registry

image: docker:latest

services:
  - docker:dind

before_script:
  - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY

script:
  - docker pull $CI_REGISTRY_IMAGE:latest
Note: Ensure that the GitLab project has the necessary permissions to access the private registry.
Warning: Avoid hardcoding credentials in scripts. Use GitLab CI/CD variables for sensitive information.

5. Using CI_REGISTRY Variables

Variable Description Usage
CI_REGISTRY Registry URL for the project's container registry docker build -t $CI_REGISTRY/image-name .
CI_REGISTRY_USER Username for pushing to the registry docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
CI_REGISTRY_PASSWORD Password for pushing to the registry docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
CI_REGISTRY_IMAGE Full image name including registry URL and project path docker push $CI_REGISTRY_IMAGE

Example: Pushing an image to the registry

docker build -t $CI_REGISTRY_IMAGE .
docker push $CI_REGISTRY_IMAGE
Note: These variables are automatically set for each job in GitLab CI/CD and are only available when using the docker executor or when Docker is installed in the job environment.

6. Configuring Pull Policy

Policy Description Default Behavior Notes
always Always pull the image from the registry before running the job. Never Ensures latest image is used, but increases job time.
never Never pull the image; use only locally available images. Never Useful in offline environments or when image is pre-loaded.
if-not-present Pull the image only if it's not already present locally. Yes Default policy in most GitLab CI runners.

Example: Setting Pull Policy in .gitlab-ci.yml

job_name:
  image: my-image:latest
  pull_policy: always
Note: The pull_policy setting is supported in GitLab Runner v14.0 and later.

7. Using Image Aliases

Alias Image Reference Description
latest my-app:latest Points to the most recently built image
stable my-app:stable Represents a stable, production-ready version
v1.2.0 my-app:v1.2.0 Specific version tag for reproducible builds

Example: Defining Image Aliases in .gitlab-ci.yml

image:
  name: my-app:latest
  entrypoint: ["/bin/sh"]

services:
  - name: my-app:stable
    alias: database
Note: Image aliases are useful for referencing images with different tags or versions within the same pipeline.

8. Caching Docker Images

Option Values Notes
cache.key docker Cache key to use for Docker layer caching
cache.paths ['/root/.docker'] Paths to cache Docker images and layers
cache.uncompressed true Whether to use uncompressed cache (default: false)

Example: Caching Docker Images in GitLab CI

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  cache:
    key: "docker"
    paths:
      - /root/.docker
  script:
    - docker build -t my-image .
    - docker save my-image > image.tar

9. Using Minimal Base Images

Base Image Description Size (MB) Use Case
alpine:latest Small, security-focused Linux distribution based on BusyBox 5.5 Lightweight containers with minimal dependencies
debian:slim Debian with minimal packages and no recommended dependencies 120 Stable environments with full package support
ubuntu:slim Ubuntu with minimal packages and no recommended dependencies 125 Compatibility with Ubuntu-based tools and libraries
gcr.io/distroless/base Google Distroless image with minimal OS and runtime 15 Highly secure, minimal runtime for production services

Example: Using Alpine as Base Image in GitLab CI

build_job:
  image: alpine:latest
  script:
    - apk add --no-cache nodejs npm
    - npm install
    - npm run build
Note: Alpine uses musl libc instead of glibc, which may cause compatibility issues with some Node.js modules compiled against glibc.

10. Debugging Image Issues

Example: Inspect Docker Image Layers

docker inspect --format="{{.RootFS.Layers}}" <image-id>
Issue Description Solution
Missing Dependencies Image lacks required packages or libraries Use docker run -it <image> /bin/bash to enter container and verify packages
Permission Denied Container fails to execute commands due to permissions Add RUN chmod +x /path/to/script in Dockerfile
Layer Caching Issues Changes in Dockerfile don't reflect in image Use --no-cache flag during build: docker build --no-cache -t <tag>
Note: Use docker history <image-id> to inspect image layer changes.

Example: Check Image Size

docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
Warning: Avoid using latest tag in production; pin to specific image digests for reproducibility.

Was this article helpful?