Gitlab CI: pull Docker images from Private Nexus

  docker, gitlab, gitlab-ci, nexus

I’m having some issues settings up Gitlab CI on my local network using cached docker images.

Setup:

  • GitLab running on my server
  • Nexus running on a NAS
  • GitLab-CI runner on my laptop
  • All on a local network

Nexus is configured to cache docker images from DockerHub and store them locally. This works fine for docker on the bare machines. However, when the CI runner tries to pull a docker image, it gets blocked with the message below.

Using Docker executor with image synology:9042/library/gradle:alpine ...
Pulling docker image synology:9042/library/gradle:alpine ...
WARNING: Failed to pull image with policy "always": Error response from daemon: Head http://synology:9042/v2/library/gradle/manifests/alpine: no basic auth credentials (manager.go:205:0s)
ERROR: Preparation failed: failed to pull image "synology:9042/library/gradle:alpine" with specified policies [always]: Error response from daemon: Head http://synology:9042/v2/library/gradle/manifests/alpine: no basic auth credentials (manager.go:205:0s)

From my understanding, docker is being used from the install on my laptop (MacOs) and the sock is being mounted in a docker container (config below). This docker instance is logged into the nexus server and can pull images fine. The auths config is included in the config.json for this docker install.

version: '2.3'

services:
    GitlabRunner:
        image: gitlab/gitlab-runner:alpine-v13.9.0-rc1
        volumes:
         - /Users/<snip>/gitlab-runner/config:/etc/gitlab-runner
         - /var/run/docker.sock:/var/run/docker.sock
        restart: always
        networks:
          - 'default'

networks:
  default:
    driver: 'bridge'

Following information here and here I setup a variable in the GitLab Runner called DOCKER_AUTH_CONFIG with the contents of

"auths": {
    "synology:9042": {
      "auth": "Z3JhZGxlOmdyYWRsZQ=="
    }
}

where the auth is the base64 encode of the username and password (gradle for both). I have also tried allowing anonymous access on nexus, but that failed too. The CI job works fine if I point it at docker hub but removing the ‘synology:9042/’ from the image name.

image: synology:9042/library/gradle:alpine

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

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

build:
  stage: build
  script: gradle --build-cache assemble
  cache:
    key: "$CI_COMMIT_REF_NAME"
    policy: push
    paths:
      - build
      - .gradle
  tags:
    - test

Other things I’ve tried:

  • stopping using osx keychain for credentials
  • running it on the same machine as gitlab install
  • ensuring every docker instance is logged into nexus
  • explicitly logging in from the CI script

For completion, here is the TOML config for the runner

concurrent = 4
check_interval = 10
log_level = "info"

[session_server]
  session_timeout = 1800

[[runners]]
  name = "test"
  url = "http://my.gitlab.server:port/"
  token = "tYsvSq7jSwvNYyMhj7fU"
  executor = "docker"
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
    [runners.cache.azure]
  [runners.docker]
    tls_verify = false
    image = "synology:9042/library/gradle:alpine"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    shm_size = 0

Any pointers would be greatly appreciated.

Source: Docker Questions

LEAVE A COMMENT