In the series of Dockerized GitLab, we already have seen how to setup GitLab runner using Shell, Docker, Docker-in-Docker and Kaniko executors.
Since we know how to build our dockerized projects using GitLab CI and docker executors. Now is a good time to look into the process of how and where we can push our project’s docker images/builds so later in the deployment stage (CD), we can deploy it to our target servers after we have built it in our GitLab CI.
With the GitLab container registry, every project can have its own space to store Docker images.
Enable Container Registry
As we already have our docker-compose.yml
file ready for managing GitLab server and Runner containers, we just need to add a couple of additional lines for enabling our GitLab container registry.
docker-compose.yml
can be found in this post
version: '3.8'
services:
gitlab-server:
image: 'gitlab/gitlab-ce:latest'
container_name: gitlab-server
environment:
GITLAB_ROOT_EMAIL: "admin@buildwithlal.com"
GITLAB_ROOT_PASSWORD: "Abcd@0123456789"
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://localhost:8000'
nginx['listen_port'] = 8000
# new changes for enabling container registry
gitlab_rails['registry_enabled'] = true
# docker CLI from inside the pipeline's job will use this URL to push docker images
registry_external_url 'http://localhost:5001'
ports:
- '8000:8000'
# expose new port for registry hosting
- '5001:5001'
volumes:
- ./gitlab/config:/etc/gitlab
- ./gitlab/data:/var/opt/gitlab
gitlab-runner:
image: gitlab/gitlab-runner:alpine
container_name: gitlab-runner
network_mode: 'host'
volumes:
- /var/run/docker.sock:/var/run/docker.sock
Here you can notice that we have just added these 2 new lines and YEAH!, our container registry is ready.
gitlab_rails['registry_enabled'] = true
registry_external_url 'http://localhost:5001'
registry_enabled
is self explanatory which enables the registry inside GitLab.
registry_external_url
will make the registry accessible outside GitLab server so we can use docker CLI to login to this registry, push and pull docker images.
If your containers are already running using docker compose, hit CTRL+C
to stop running containers and then run this docker compose command to start containers back with new changes applied.
docker compose up --build --force-recreate
You can check containers health and exposed ports using
docker ps
Now you can visit your GitLab dashboard at http://localhost:8000
Setup a new Repository
Once you are logged in with your defined user
and password
from the docker-compose.yml
file, Go ahead and create a new repository/project
After the repository is created, you should be redirected to the newly created repository and you can see that the Container Registry option is now available.
For now, we have not pushed any docker images yet so it is empty.
If you install GitLab by using the Linux package, the container registry may or may not be available by default. So using this way you can enable the container registry. You can also check those helpful docker CLI commands for, how to use the container registry for this project to login and push docker images.
Test Container Registry
Now to test this registry, we’ll quickly add a Dockerfile to our project root directory.
Dockerfile
FROM python:3.10-alpine
RUN python --version
Before we setup our project pipeline, make sure that you have already registered a GitLab runner as a docker executor. IF NOT, please check here
Once you commit your Dockerfile
and you have your Runner ready, lets configure our project pipeline by going to
Repository → Build → Pipeline Editor → Configure Pipeline
Add this snippet to your pipeline i.e gitlab-ci.yml
file
build:
stage: build
image: docker:latest
tags:
- docker
script:
- echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
- docker build -t "$CI_REGISTRY_IMAGE:${CI_COMMIT_SHA:0:8}" .
- docker push "$CI_REGISTRY_IMAGE:${CI_COMMIT_SHA:0:8}"
All of these environment variables are predefined variables provided by GitLab. See more details on GitLab CI/CD predefined variables here.
The CI_REGISTRY_USER
holds a per-job user with read-write access to the container registry. Its password is also automatically created and available in CI_REGISTRY_PASSWORD
.
$CI_REGISTRY
is our container registry host URL which is localhost:5001
.
$CI_REGISTRY_IMAGE
is the container registry URL for our repository which is localhost:5001/root/build-with-lal
$CI_REGISTRY_IMAGE:${CI_COMMIT_SHA:0:8}
will become localhost:5001/root/build-with-lal:97892e33
which is the full registry image URL for this specific commit.
0:8
will slice the git commit into first 8 chars only to avoid having long image tags.
So we are building docker image from our Dockerfile
, then we tag that built image which will look like this localhost:5001/root/build-with-lal:97892e33
And then lastly we push this tagged image to our container registry.
Once you commit the pipeline changes, the pipeline will run immediately and it should look like this
Now if you go back to your project’s container registry, you should see an image is pushed there
Clicking on this repository image i.e build-with-lal
will go to the list of all tags you have pushed for this repository
Lets copy the image pull URL by clicking on Copy Image Path
and then run that copied docker pull command on our local terminal
docker pull localhost:5001/root/build-with-lal:96e63838
You can see that it won’t allow you to pull the docker image from the registry as by default the container registry is private and need authentication.
Now lets try to login to our container registry using docker login
docker login --username admin@buildwithlal.com --password Abcd@0123456789 localhost:5001
It should download that specific tagged image to your local machine.
So we have enabled container registry, then we tested it by pushing tagged docker images and then we downloaded that image from the container registry into our local maching using docker login and docker pull.
Container Registry Storage Backends
You can configure the container registry to use various storage backends by configuring a storage driver. By default the GitLab container registry is configured to use the file system driver configuration.
The different supported drivers are:
Filesystem — Path on the local file system which is the default storage
Azure — Microsoft Azure Blob Storage
GCS — Google Cloud Storage
S3 — Amazon Simple Storage Service
Use file system
If you want to store your images on the file system, you can change the storage path for the container registry, follow the steps below.
The default location where images are stored in Linux package installations is /var/opt/gitlab/gitlab-rails/shared/registry
.
To change it:
- Edit
/etc/gitlab/gitlab.rb
:
gitlab_rails['registry_path'] = "/path/to/registry/storage"
You can add this to docker-compose.yml
, the way we’ve added other configurations.
More details on storage backend can be found here on GitLab
Using 3rd Party Container Registry
Using third-party container registries in GitLab was deprecated in GitLab 15.8
and support ended in GitLab 16.0
.
Registry Authentication
Registry doesn’t have a way to authenticate users internally so it relies on GitLab to validate credentials. The connection between Registry and GitLab is TLS encrypted. The key is used by GitLab to sign the tokens while the certificate is used by Registry to validate the signature
Source Code
Thank you for making it till the end 🎉
If this article helped you, make sure to: