Setup GitLab Container Registry — GitLab Managed

Lal Zada
6 min readSep 23, 2024

--

Source: https://unsplash.com/@chuttersnap

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:

  1. 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:

--

--

Lal Zada

Tech article every week - A software engineer over a decade experience in building apps, infrastructure and CI/CDs