GitLab (Archived) offers a fairly complete experience with the ability to run Continuous Integration jobs and the ability to store produced artifacts. In this small note I will show how to use the CI to build a docker (Archived) image stored in our repository.

For explanation purposes I will use the following extremely simple Dockerfile and save it in a newly created repository.

# Dockerfile
FROM fedora:34
RUN dnf install -y git
CMD git --version

We proceed then by creating the .gitlab-ci.yml file to configure the CI jobs:

# .gitlab-ci.yml
build_docker:
  stage: build
  image: docker:23-git
  services:
  - docker:23-dind
  variables:
    DOCKER_DRIVER: overlay
  script:
  - docker login -u gitlab-ci-token -p "$CI_JOB_TOKEN" "$CI_REGISTRY"
  - docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" .
  - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
  only:
  - branches
  - tags

Notice that we ask for docker:dind (docker-in-docker) since our CI job will run in a Docker container and we need to be able to build dockers inside of a docker container. This also motivates the introduction of DOCKER_DRIVER: overlay.

As you can see the script is fairly simple, we just make extensive usage of GitLab CI Predefined Variables (Archived) to make sure the script is adapted to each repository we deploy it to, and will automatically tag each newly built image depending on the tags and branch names.

You can then see the pushed images in your repository side menu under Packages & Registries > Container Registry and you will be able to clone those containers from an URL like registry.gitlab.com/${USER}/${PROJECT}:${COMMIT_REF}.

Update 2023-05-28: Two days ago the 24 series of docker-in-docker were pushed, and the above solution no longer works. That's why I put a 23 in the docker images; I'm waiting to see if I manage to understand what needs to be changed to make the above snippets work again with the new docker version.