Using a private Docker Image from Gitlab Registry as the base image for CI
Asked Answered
A

6

24

How should I authenticate if I want to use an image from the Gitlab Registry as a base image of another CI build?

According to https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/configuration/advanced-configuration.md#using-a-private-docker-registry I first have to manually login on the runner machine. Somehow it feels strange to login with an existing Gitlab user.

Is there a way to use the CI variable "CI_BUILD_TOKEN" (which is described as "Token used for authenticating with the GitLab Container Registry") for authentication to pull the base image from Gitlab Registry?

EDIT: I found out that I can use images from public projects. But I don't really want to make my docker projects public.

UPDATE: Starting with Gitlab 8.14 you can just use the docker images from the build in docker registry. See https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/configuration/advanced-configuration.md#support-for-gitlab-integrated-registry

Acatalectic answered 8/7, 2016 at 14:55 Comment(1)
The last link gives me not found error!Supraliminal
C
8

Edit 2024: this answer is now eight years old, look at the other answers.


No, this is currently not possible in any elegant way. GitLab should implement explicit credentials for the base images, it will be the most straight-forward and correct solution.

You need to docker login on the GitLab Runner machine. You can't use the gitlab-ci-token since they expire and also project-dependant, so you can't actually use one token for every project. Using your own login is pretty much the only solution available right now (happy to get corrected on this one).

Chromoprotein answered 8/7, 2016 at 15:7 Comment(4)
Thanks. You're right. It's not possible right now. Pointers I found: gitlab.com/gitlab-org/gitlab-ce/issues/19219 and gitlab.com/gitlab-org/gitlab-ce/issues/19275Acatalectic
To follow up on this, there are a couple gitlab tickets related to exposing this functionality in a more elegant way (gitlab.com/gitlab-org/gitlab-ce/issues/19275). However, this appears to sit in backlog right now. Hopefully, with more support, this capability will be something that the team identifies to be as important as the user community seems to.Berbera
It seems like in 2024 there is a way to login. Would you mind to update the answer?Conversazione
@AlexeySh. I don't think I need to, the better voted for and more recent answer is at the top. The OP might re-accept it and then it's done.Chromoprotein
P
25

All of the above answers including the acepted one are deprecated, This is possible in 2021:

https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#access-an-image-from-a-private-container-registry


TL;DR

Set the CI/CD variable DOCKER_AUTH_CONFIG value with appropriate authentication information in following format:

Step 1:

# The use of "-n" - prevents encoding a newline in the password.
echo -n "my_username:my_password" | base64

# Example output to copy
bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=

Step 2 (This JSON is the value to be set for DOCKER_AUTH_CONFIG variable):

{
    "auths": {
        "registry.example.com:5000": {
            "auth": "(Base64 content from above)"
        }
    }
}
Pindus answered 9/12, 2021 at 16:8 Comment(0)
G
9

Now it's possible, they have included that option months ago.

Use gitlab-ci-tokenas user and the variable $CI_BUILD_TOKEN as password.

This example works on GitLab 8.13.6. It builds the test image if needed, and in the next stage uses it to perform syntax checks:

build_test:
  stage: build_test_image
  script:
    - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
    - docker build -t $CI_REGISTRY_IMAGE:test -f dockerfiles/test/Dockerfile .
    - docker push $CI_REGISTRY_IMAGE:test
  tags:
    - docker_build
  environment: test

test_syntax:
  image: $CI_REGISTRY_IMAGE:test
  stage: test
  script:
    - flake8 --ignore=E501,E265,E402 .

UPDATE: Re-reading the question, the accepted answer is correct. In my example, the job test_syntax will fail to authenticate to the registry, unless the user logins manually from the runner machine. Although, it can work if the 2 runners are on the same host, but it's not the best solution anyway.

In gitlab-ci-multi-runner 1.8 there's an option to add the Registry credentials as a variable, so you only need to login once to get the encoded credentials. See documentation.

Grevera answered 14/12, 2016 at 15:45 Comment(2)
What type of runner are you using to do this? If you're using a shell runner then GitLab CI isn't pulling the image from the registry but is instead using the image you just built on the host in the previous stage.Hodge
Actually I'm using 2 runners. One with shell executor, another with docker executor. The intended usage of the shell executor is only to build Docker images, that's why I'm using the tag docker_build. Note also the image directive inside the job test_syntax and the lack of it on build_test.Grevera
C
8

Edit 2024: this answer is now eight years old, look at the other answers.


No, this is currently not possible in any elegant way. GitLab should implement explicit credentials for the base images, it will be the most straight-forward and correct solution.

You need to docker login on the GitLab Runner machine. You can't use the gitlab-ci-token since they expire and also project-dependant, so you can't actually use one token for every project. Using your own login is pretty much the only solution available right now (happy to get corrected on this one).

Chromoprotein answered 8/7, 2016 at 15:7 Comment(4)
Thanks. You're right. It's not possible right now. Pointers I found: gitlab.com/gitlab-org/gitlab-ce/issues/19219 and gitlab.com/gitlab-org/gitlab-ce/issues/19275Acatalectic
To follow up on this, there are a couple gitlab tickets related to exposing this functionality in a more elegant way (gitlab.com/gitlab-org/gitlab-ce/issues/19275). However, this appears to sit in backlog right now. Hopefully, with more support, this capability will be something that the team identifies to be as important as the user community seems to.Berbera
It seems like in 2024 there is a way to login. Would you mind to update the answer?Conversazione
@AlexeySh. I don't think I need to, the better voted for and more recent answer is at the top. The OP might re-accept it and then it's done.Chromoprotein
T
4

This is absolutely possible as of September 2018. I'll post my naive implementation here.

Context:

  • You'll need to leverage the docker:dind service, which lets you run the docker command inside of a docker container.
  • This will require you to use a valid docker login, which you can do using GitLab's builtin variables (gitlab-ci-token, $CI-JOB-TOKEN).
  • You should then be able to authenticate to your repo's registry (example $REGISTRY value: registry.gitlab.com/$USER/$REPO:$TAG), which will allow you to push or pull docker containers from inside the CI/CD context, as well as from any authenticated docker server.

Implementation:

Create this block at top level to ensure it runs before the following jobs:

before_script: 
        - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $REGISTRY

Job to build and save images to your registry:

build_container:
    image: docker:latest
    stage: build
    services:
        - docker:dind
    script:
        - docker build -t $REGISTRY .
        - docker push $REGISTRY

Job that uses the custom image:

build_app:
    image: $REGISTRY
    stage: deploy
    script:
        - npm run build

Regarding Cross-Repo Jobs:

I accomplish this by creating a "bot" GitLab user and assigning them access to repos/groups as appropriate. Then it's just a matter of replacing gitlab-ci-token and $CI_JOB_TOKEN with appropriate environment variables. This is only necessary if the base image is private.

Telescopic answered 4/9, 2018 at 16:24 Comment(2)
before_script doesn't run "before" the job. It is simply concatenated with the script element, and run in the context of the image specified in the job. Given that, this doesn't look like it will work?Cockshy
I'm usually using the before_script within an extended job so that it can be shared with multiple other docker jobs (one each for push to gitlab/dockerhub/etc., depending on tag/branch). It's intended to be run within the context of the image and leveraging the dind service, as the image needs to have access to docker commands for any of login, build, push to work. As long as the login comes first, this all works as intended. I use this strategy for multiple production applications; if you're having a specific problem I can try to help you out.Telescopic
D
1

Its possible you first have to login to gitlab container registry of the image you want to use, kindly see below example. Notice the before_script: which basically auths you before using the image.

image: docker:latest
services:
  - docker:dind

stages:
  - build

variables:
  CONTAINER_RELEASE_IMAGE: registry.gitlab.com/obonyojimmy/node-mono-clr:latest

before_script:
  - docker login -u $CI_REGISTRY_USER -p $CI_BUILD_TOKEN registry.gitlab.com

build-app:
  stage: build
  image: $CONTAINER_RELEASE_IMAGE
  script:
    - npm run build
Derosier answered 21/12, 2016 at 14:10 Comment(1)
docker will throw an error unless you add "$": $CONTAINER_RELEASE_IMAGEMorelli
F
1

I had a similar situation. My Java application uses Testcontainers lib in tests and this lib runs Docker container from private registry. I spent a lot of time trying to figure this out and I managed to handle this by creating a ~/.docker/config.json file in before_script section. I hope it'll help somebody:

image: openjdk:11-jdk-slim

stages:
  - build

before_script:
  - mkdir ~/".docker"
  - echo "{\"auths\":{\"$REGISTRY_HOST\":{\"auth\":\"$(printf "$REGISTRY_USER:$REGISTRY_PASSWORD" | openssl base64 -A)\"}}}" > ~/".docker/config.json"

build:
  stage: build
  services:
    - docker:dind
  script:
    - ./gradlew build

Feldstein answered 4/1, 2023 at 14:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.