In diesem Beitrag erkläre ich die Installation und den Betrieb eines eigenen GitLab mit verbundener Registry, alles hinter der Reverse Proxy Treafik.

Voraussetzung

Für diesen Guide gehe ich davon aus, dass Docker und Traefik bereits installiert ist. Alle notwendigen Schritte hierzu haben ich in diesem Beitrag bereits erklärt.

Das Setup

Ordnerstruktur

mkdir -p /opt/containers/gitlab/{data,registry}
mkdir -p /opt/containers/gitlab/data/{config,logs,data,database}
mkdir -p /opt/containers/gitlab/registry/{data,certs}

Zu Beginn erstelle ich die Ordner für alle Daten von Container die ich später deployen werden.
Für diesen Zweck hat sich in der Vergangenheit der Ordner /opt immer sehr bewährt.

GitLab Dockerfile

nano /opt/containers/gitlab/docker-compose.yml

version: '3'

services:
  gitlab:
    image: 'gitlab/gitlab-ce:latest'
    container_name: gitlab
    restart: unless-stopped
    hostname: 'git.example.com'
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'https://git.example.com'
        nginx['listen_port'] = 80
        nginx['listen_https'] = false
        nginx['proxy_set_headers'] = {
          "X-Forwarded-Proto" => "https",
          "X-Forwarded-Ssl" => "on"
        }
      
        gitlab_rails['db_adapter'] = "postgresql"
        gitlab_rails['db_database'] = "gitlab"
        gitlab_rails['db_username'] = "postgres"
        gitlab_rails['db_password'] = "<DATABASE_PASSWORD>"
        gitlab_rails['db_host'] = "gitlab_database"

        
        registry['enable'] = false 
        gitlab_rails['registry_enabled'] = true
        gitlab_rails['registry_host'] = "registry.git.example.com"
        gitlab_rails['registry_api_url'] = "https://registry.git.example.com"
        gitlab_rails['registry_issuer'] = "gitlab-issuer"

        gitlab_rails['smtp_enable'] = true
        gitlab_rails['smtp_address'] = "mail.example.com"
        gitlab_rails['smtp_port'] = 465
        gitlab_rails['smtp_user_name'] = "[email protected]"
        gitlab_rails['smtp_password'] = "<SMTP_PASSWORD>"
        gitlab_rails['smtp_domain'] = "mail.example.com"
        gitlab_rails['smtp_authentication'] = "login"
        gitlab_rails['smtp_enable_starttls_auto'] = true
        gitlab_rails['smtp_tls'] = false
        gitlab_rails['smtp_ssl'] = true
        gitlab_rails['smtp_force_ssl'] = true
        gitlab_rails['gitlab_email_from'] = '[email protected]'
    ports:
      - "2222:22"
    networks:
      - proxy
    volumes:
      - /opt/containers/gitlab/data/config:/etc/gitlab
      - /opt/containers/gitlab/data/logs:/var/log/gitlab
      - /opt/containers/gitlab/data/data:/var/opt/gitlab
      - /opt/containers/gitlab/registry/certs:/certs
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.gitlab.entrypoints=http"
      - "traefik.http.routers.gitlab.rule=Host(`git.example.com`)"
      - "traefik.http.middlewares.gitlab-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.routers.gitlab.middlewares=gitlab-https-redirect"
      - "traefik.http.routers.gitlab-secure.entrypoints=https"
      - "traefik.http.routers.gitlab-secure.rule=Host(`git.example.com`)"
      - "traefik.http.routers.gitlab-secure.tls=true"
      - "traefik.http.routers.gitlab-secure.tls.certresolver=http"
      - "traefik.http.routers.gitlab-secure.service=gitlab"
      - "traefik.http.services.gitlab.loadbalancer.server.port=80"
      - "traefik.docker.network=proxy"

  registry:
    restart: unless-stopped
    image: registry:2.7
    container_name: gitlab_registry
    volumes:
      - /opt/containers/gitlab/registry/data:/registry
      - /opt/containers/gitlab/registry/certs:/certs
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.registry.entrypoints=http"
      - "traefik.http.routers.registry.rule=Host(`registry.git.example.com`)"
      - "traefik.http.middlewares.registry-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.routers.registry.middlewares=registry-https-redirect"
      - "traefik.http.routers.registry-secure.entrypoints=https"
      - "traefik.http.routers.registry-secure.rule=Host(`registry.git.example.com`)"
      - "traefik.http.routers.registry-secure.tls=true"
      - "traefik.http.routers.registry-secure.tls.certresolver=http"
      - "traefik.http.routers.registry-secure.service=registry"
      - "traefik.http.services.registry.loadbalancer.server.port=5000"
      - "traefik.docker.network=proxy"
    networks:
        - proxy
    environment:
          REGISTRY_LOG_LEVEL: debug
          REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /registry
          REGISTRY_AUTH_TOKEN_REALM: https://git.example.com/jwt/auth
          REGISTRY_AUTH_TOKEN_SERVICE: container_registry
          REGISTRY_AUTH_TOKEN_ISSUER: gitlab-issuer
          REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE: /certs/gitlab-registry.crt
          REGISTRY_STORAGE_DELETE_ENABLED: 'true'

  database:
    image: postgres:11-alpine
    container_name: gitlab_database
    restart: unless-stopped
    networks:
      - proxy
    environment:
      POSTGRES_PASSWORD: "<DATABASE_PASSWORD>"
      POSTGRES_DB: gitlab
    volumes:
        - /opt/containers/gitlab/data/database:/var/lib/postgresql/data

networks:
  proxy:
    external: true

Dieses Dockerfile erstellt drei Container auf dem Docker-Host.
1. GitLab CE
2. Registry für Container
3. Postgres Datenbank für GitLab

Konfiguration des Dockerfiles

In dem Dockerfile sind einige Stellen gekennzeichnet, die mit eigenen Daten befüllt werden müssen.

Zeile 8, 11, 56, 60, 92 – Subdomain für GitLab – git.example.com muss durch eine eigene Domain / Subdomain ersetzt werden, die auf den Docker-Host zeigt.

Zeile 22, 105 – Datenbankpasswort – <DATABASE_PASSWORD> muss durch ein Passwort für die Datenbank ersetzt werden.
In der aktuellen Konfiguration ist die Datenbank nur im Netzwerk proxy und somit von außen nicht erreichbar. Trotzdem empfehle ich immer ein sicheres, generiertes Passwort zu verwenden, bspw. durch LastPass.

Zeile 28, 29, 77, 81 – Subdomain für Registry – registry.git.example.com muss durch eine eigene Domain / Subdomain ersetzt werden, die auf den Docker-Host zeigt.

Zeile 33 bis 43 – SMTP Mail Zugangsdaten – Damit GitLab E-Mails versenden kann muss ein SMTP Server und Postfach angegeben werden. Hier kann neben einem eigenen Mail-Server auf Gmail oder ein anderer Anbieter verwendet werden.

Container starten

Wichtig! Bevor die Container nun gestartet werden, müssen die Subdomains/Domains per A / AAAA Records auf die IP-Adresse des Docker-Host zeigen!

cd /opt/containers/gitlab

docker-compose up -d

GitLab ist ein sehr komplexer Service, daher ist es auch nicht verwunderlich, dass der Start schon mal einige Minuten in Anspruch nehmen kann.

Abschlussarbeiten

Damit GitLab und die Registry miteinander kommunizieren können, muss zuletzt noch ein Zertifikat ausgetauscht werden.

cd /opt/containers/gitlab/registry/certs/
docker cp gitlab:/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key .
openssl req  -key gitlab-registry.key -new -subj "/CN=gitlab-issuer" -x509 -days 365 -out gitlab-registry.crt

Das war es schon!
Nun haben wir unser eigenes GitLab mit Registry für Container und alles schön hinter einer Reverse Proxy mit automatischen SSL Zertifikaten.

Alle Dateien zu diesem Beitrag inkl. docker-compose.yml findest du hier.