Search code examples
dockergradlegitlab-cijava-14docker-in-docker

Gitlab's CI docker in docker login and test containers


I have a project that needs a TestContainers running to execute end2end tests. The Containers 's image is another project which docker image is pushed to GitLab's Container Registry. This means that, whenever I want to do docker pull of this image, I need to do a docker login first.

Locally it works fine, I just do a login, run my tests and everything's ok.. on the pipeline is another story.

In GitLab's documentation, on the pipeline's configuration file .gitlab-ci.yml, they use image: docker:19.03.12. The problem with that is that I need to run ./gradlew, and said image doesn't have java for it to run. Otherwise, if I set the image to image: gradle:jdk14, even if I setup DockerInDocker, when I run docker login, it says docker is not recognized as a command.

I tried creating a custom image with Docker and Java14, but still get the following error:

com.github.dockerjava.api.exception.NotFoundException: {"message":"pull access denied for registry.gitlab.com/projects/projecta, repository does not exist or may require 'docker login': denied: requested access to the resource is denied"}

As you can see in the gitlab-ci file, it's running docker login before executing the tests, and according to the pipeline's output is successful

.gitlab-ci.yml

image: gradle:jdk14

variables:
  GRADLE_OPTS: "-Dorg.gradle.daemon=false"

stages:
  - build
  - test

before_script:
  - export GRADLE_USER_HOME=`pwd`/.gradle

assemble:
  stage: build
  script:
    - ./gradlew assemble
  only:
    changes:
      - "**/*.gradle.kts"
      - gradle.properties
  cache:
    key: $CI_PROJECT_NAME
    paths:
      - .gradle/wrapper
      - .gradle/caches
    policy: push

cache:
  key: $CI_PROJECT_NAME
  paths:
    - .gradle/wrapper
    - .gradle/caches
  policy: pull

test:
  stage: test
  image: registry.gitlab.com/project/docker-jdk14:latest #<-- my custom image
  dependencies:
    - checkstyle
  services:
    - docker:dind
  variables:
    DOCKER_HOST: "tcp://docker:2375"
    DOCKER_DRIVER: overlay2
    DOCKER_TLS_CERTDIR: ""
  script:
    - docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
    - ./gradlew test

I have the feeling that I'm missing something but so far the only explanation I can come up with is that the docker login the pipeline is executing doesn't set the credentials to the inner docker instance.

Is there anyway to call the login in the inner instance instead of the outer one?

I thought about doing the login call inside the test.. but that would be my last option.


Solution

  • If I'm reading your question correctly you're trying to run CI for project gitlab.com/projects/projectb, which uses image built in project gitlab.com/projects/projecta during tests.

    You're attempting to pull image registry.gitlab.com/projects/projecta using username and password from predefined variables $CI_DEPLOY_USER and $CI_DEPLOY_PASSWORD.

    It doesn't work, because that user has only permissions to access gitlab.com/projects/projectb. What you need to do is to create deploy token for project gitlab.com/projects/projecta with permissions to access the registry, supply it to your CI in gitlab.com/projects/projectb via custom variables and use those to login to $CI_REGISTRY.