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. |
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
| 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.
Warning: Avoid using
latest tag in production; pin to specific image digests for reproducibility.