The image keyword in GitLab CI/CD specifies the Docker image that the GitLab Runner should use to run a job. This Docker image contains the operating system, libraries, and tools needed to execute the commands in your job’s script section.
You can define an image at two main levels:
- Globally (as a default): Using the
default:image:keyword. This image will be used for all jobs unless a job specifies its own image. - Job-level: Defined within a specific job. This overrides any global default image for that particular job.
Example .gitlab-ci.yml with image:
YAML
# .gitlab-ci.yml
# 1. Default Image: Applied to all jobs unless overridden
default:
image: alpine:latest # A lightweight Linux distribution
stages:
- setup
- build
- test
# Job 1: Uses the default image (alpine:latest)
check_environment:
stage: setup
script:
- echo "--- Checking Environment (using default image: alpine) ---"
- uname -a # Shows kernel information (from alpine)
- cat /etc/os-release # Shows OS information (from alpine)
- echo "No specific tools needed here, alpine is fine."
# Job 2: Specifies its own image (node) for Node.js tasks
build_javascript_app:
stage: build
image: node:18-alpine # Specifies a Node.js image (alpine variant for smaller size)
script:
- echo "--- Building JavaScript App (using image: node:18-alpine) ---"
- node -v # Checks Node.js version
- npm -v # Checks npm version
- echo "Attempting to create a dummy package.json and install a package"
- echo '{ "name": "my-app", "version": "1.0.0" }' > package.json
- npm install lodash # Example npm command, requires Node.js environment
- echo "Node.js specific build commands would go here."
# Job 3: Specifies another image (python) for Python tasks
run_python_script:
stage: test
image: python:3.9-slim # Specifies a slim Python image
script:
- echo "--- Running Python Script (using image: python:3.9-slim) ---"
- python --version # Checks Python version
- pip --version # Checks pip version
- echo "Creating a dummy Python script..."
- echo "print('Hello from Python in GitLab CI!')" > hello.py
- python hello.py # Executes the Python script
- echo "Python specific test commands would go here."
# Job 4: Back to using the default image
another_generic_task:
stage: test
script:
- echo "--- Another Generic Task (using default image: alpine) ---"
- echo "This job uses the default 'alpine:latest' image again."
- ls -la
Code language: PHP (php)
Explanation:
default:image: alpine:latest- The
default:block allows you to set default configurations for all jobs. image: alpine:latestwithindefault:specifies thatalpine:latest(a minimal Docker image based on Alpine Linux) will be the default execution environment for all jobs in this pipeline.- This is useful if many of your jobs can run with a basic set of tools or if you want a consistent lightweight base.
- The
check_environmentJob:- This job does not have its own
imagekeyword. - Therefore, it inherits the image
alpine:latestfrom thedefault:section. - The
scriptcommands (uname -a,cat /etc/os-release) are executed within an Alpine Linux environment.
- This job does not have its own
build_javascript_appJob:image: node:18-alpine: This job overrides the default image.- It specifies that this particular job must run using the
node:18-alpineDocker image. This image comes with Node.js (version 18) and npm pre-installed. - The
scriptcommands (node -v,npm -v,npm install lodash) rely on the Node.js environment provided by this image. These commands would likely fail or not be available in the defaultalpine:latestimage.
run_python_scriptJob:image: python:3.9-slim: This job also overrides the default image.- It specifies the
python:3.9-slimimage, which provides a Python 3.9 environment. - The
scriptcommands (python --version,pip --version,python hello.py) require Python to be installed, which this image provides.
another_generic_taskJob:- Similar to
check_environment, this job does not define its ownimage. - It will fall back to using the default
alpine:latestimage.
- Similar to
How it Works and Key Concepts:
- GitLab Runner and Docker Executor:
- The
imagekeyword is primarily used by GitLab Runners configured with the Docker executor (or other container-based executors like Kubernetes). - When a job with an
imagedefined starts, the Docker executor on the runner pulls the specified Docker image (if not already cached) from a Docker registry. - It then starts a container from that image and runs the job’s
scriptcommands inside this container.
- The
- Environment Isolation:
- Each job runs in a fresh, isolated container based on its specified image. This ensures that jobs do not interfere with each other and that the environment is consistent every time the job runs.
- Image Sources:
- By default, GitLab Runners pull images from Docker Hub (e.g.,
alpine:latest,node:18-alpine,python:3.9-slimare all standard images on Docker Hub). - You can also configure your GitLab Runner or specify in the
imagekeyword to use images from private Docker registries or the GitLab Container Registry associated with your project or group.- Example for GitLab Container Registry:
image: $CI_REGISTRY_IMAGE/my-custom-image:tag - Example for a private registry:
image: my.private.registry.com/namespace/image:tag
- Example for GitLab Container Registry:
- By default, GitLab Runners pull images from Docker Hub (e.g.,
- Choosing the Right Image:
- Select images that contain the necessary tools, languages, and libraries for your job.
- Prefer official images when possible.
- Consider using slim or alpine variants of images (e.g.,
node:18-alpine,python:3.9-slim) as they are smaller and can lead to faster job startup times due to quicker image downloads.
- No Image Defined:
- If no
imageis specified (neither globally indefault:nor at the job level), the job will run in the environment of the GitLab Runner itself. This is less common for Docker-based runners, as the main advantage is the containerized environment. If the runner is ashellexecutor, it runs directly on the host machine.
- If no
Using the image keyword effectively allows you to create tailored, consistent, and isolated environments for each step in your CI/CD pipeline, ensuring your jobs have the exact dependencies they need to succeed.