Rolling From v1 Docker Registry to v2 with Jenkins

Steps for rolling to new registry with dependencies
August 29, 2016
gitlab docker registry jenkins

So I’ve been lax about updating our private Docker Registry from v1 to v2. It comes from also staying a safe few versions behind on the Docker core software itself.

This past weekend I updated from the old lxc-docker to the new docker-engine package, bringing me up to 1.12.1 on all of our systems. This came about as a side effect of deploying the new Container Registry within Gitlab, which is incompatible with the docker login from 1.9.x. Talk about shaving yaks.

Order Of Operations

Details

One of my big complaints about the v1 registry was the lack of support for SNI that necessitated running it on its own port. Call me a snob, but I like registry.domain.com/group/project a lot better than registry.domain.com:5000/group/project, particularly in the output of docker ps.

The new container registry allows me to leverage SNI support to run the registry over HTTPS and have Gitlab’s nginx process route the traffic correctly. Since I’m also running Gitlab in a container behind haproxy (with SSL offloading) on my host, it looks something like:

docker -> haproxy (443) -> gitlab (80) -> registry (5000)

That’s just awesome.

Here’s the redacted components from my config:

###############################
# Container registry settings #
###############################

registry_external_url 'https://registry.example.com'

# Settings used by GitLab application
gitlab_rails['registry_enabled'] = true
gitlab_rails['registry_host'] = "registry.example.com"
gitlab_rails['registry_api_url'] = "http://localhost:5000"
gitlab_rails['registry_key_path'] = "/var/opt/gitlab/gitlab-rails/certificate.key"
gitlab_rails['registry_path'] = "/var/opt/gitlab/gitlab-rails/shared/registry"
gitlab_rails['registry_issuer'] = "omnibus-gitlab-issuer"

# Settings used by Registry application
registry['enable'] = true
container_registry.html#container-registry-storage-driver
registry['token_realm'] = "https://git.example.com"
registry['storage'] = {
  's3' => {
    'accesskey' => 'access-key',
    'secretkey' => 'secret-key',
    'bucket' => 'docker-registry',
    'region' => 'us-east-1'
  }
}

##################
# Registry NGINX #
##################

registry_nginx['ssl_certificate'] = "/etc/gitlab/ssl/certificate.pem"
registry_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/certificate.key"
registry_nginx['listen_port'] = 80 # override only if you use a reverse proxy: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/nginx.md#setting-the-nginx-listen-port
registry_nginx['listen_https'] = false # override only if your reverse proxy internally communicates over HTTP: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/nginx.md#supporting-proxied-ssl
registry_nginx['proxy_set_headers'] = {
  "Host" => "$http_host",
  "X-Real-IP" => "$remote_addr",
  "X-Forwarded-For" => "$proxy_add_x_forwarded_for",
  "X-Forwarded-Proto" => "https",
  "X-Forwarded-Ssl" => "on"
}

We have a wildcard certificate for our domain that I put into the ssl folder in /etc/gitlab (mounted persistently from the Docker host).

After that I created the Jenkins user inside of Gitlab and gave him a password. Within Jenkins I configured credentials with username/passsword for this pair and assigned that to the Docker Build and Publish plugin in my jobs. Jenkins now builds the containers, logs into the registry, and pushes them up.

Hotness.