GitLab CI/CD: Architecting, Deploying, and Optimizing Pipelines
Continuous Integration with GitLab
Publish Image to Gitlab Container Registry
In this guide, you’ll learn how to authenticate with GitLab’s integrated Container Registry and publish your Docker images—both manually and via GitLab CI/CD pipelines. The Container Registry is available for every GitLab project, offering a secure, private registry alongside your code.
Authentication Methods
GitLab supports several registry authentication methods:
- Personal Access Tokens
- Deploy Tokens
- Project Access Tokens
- Group Access Tokens
Refer to the official GitLab Container Registry guide for details on creating and managing tokens.
Logging in with a Token
Locally, you can log in using any valid token:
TOKEN=<your_token>
docker login registry.example.com -u <username> --password-stdin <<< "$TOKEN"
Within a GitLab CI/CD job, leverage predefined variables for seamless authentication:
docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin <<< "$CI_REGISTRY_PASSWORD"
docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin <<< "$CI_JOB_TOKEN"
docker login $CI_REGISTRY -u $CI_DEPLOY_USER --password-stdin <<< "$CI_DEPLOY_PASSWORD"
Note
Always keep your tokens secure. GitLab’s predefined variables (e.g., CI_JOB_TOKEN
) expire automatically, reducing exposure risk.
Building and Pushing Images Manually
If you prefer to build and push outside of CI/CD, follow these steps:
docker build -t registry.gitlab.com/<group>/<project>/<image-name> .
docker push registry.gitlab.com/<group>/<project>/<image-name>
Replace <group>
, <project>
, and <image-name>
with your specific values.
GitLab CI/CD Job: publish_gitlab_container_registry
Below is an example publish_gitlab_container_registry
job that:
- Loads a prebuilt image archive
- Authenticates to the registry
- Tags the image
- Pushes it upstream
publish_gitlab_container_registry:
stage: containerization
needs:
- docker_build
- docker_test
image: docker:24.0.5
services:
- docker:24.0.5-dind
script:
- docker load -i image/solar-system-image-$CI_PIPELINE_ID.tar
- echo "Registry: $CI_REGISTRY | User: $CI_REGISTRY_USER | Repo: $CI_REGISTRY_IMAGE"
- docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"
- docker tag $DOCKER_USERNAME/solar-system:$IMAGE_VERSION $CI_REGISTRY_IMAGE/ss-image:$IMAGE_VERSION
- docker images
- docker push $CI_REGISTRY_IMAGE/ss-image:$IMAGE_VERSION
Predefined CI/CD Variables
Variable | Description | Example |
---|---|---|
CI_REGISTRY | Hostname of the container registry | registry.gitlab.com |
CI_REGISTRY_USER | Username for Docker login (typically a CI job token) | $CI_REGISTRY_USER |
CI_REGISTRY_PASSWORD | Password or token for authentication | $CI_REGISTRY_PASSWORD |
CI_REGISTRY_IMAGE | Full path to the project’s image repo | registry.gitlab.com/group/project |
Viewing the Registry Before and After Push
Before any push, the Container Registry is empty:
After committing your .gitlab-ci.yml
and running the pipeline, the publish_gitlab_container_registry
job executes in parallel with other containerization steps:
Troubleshooting Login Errors
If you encounter a syntax error using --password-stdin
, switch to the -p
flag:
-script:
- - docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" --password-stdin <<< "$CI_REGISTRY_PASSWORD"
+script:
+ - docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"
Warning
Passing passwords directly via -p
can be insecure. Use --password-stdin
where possible, and ensure your CI logs are protected.
Verifying a Successful Push
Once the job completes, your logs should look like this:
$ docker load -i image/solar-system-image-$CI_PIPELINE_ID.tar
$ echo "Registry: $CI_REGISTRY = $CI_REGISTRY_USER = $CI_REGISTRY_IMAGE"
$ docker login $CI_REGISTRY --username="$CI_REGISTRY_USER" --password="$CI_REGISTRY_PASSWORD"
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
$ docker tag $DOCKER_USERNAME/solar-system:$IMAGE_VERSION $CI_REGISTRY_IMAGE/ss-image:$IMAGE_VERSION
$ docker images
$ docker push $CI_REGISTRY_IMAGE/ss-image:$IMAGE_VERSION
Returning to the Container Registry now reveals the newly published image:
Here you can inspect tags, image sizes, and manifest digests. You’ve successfully published your Docker image to GitLab’s Container Registry!
Watch Video
Watch video content