Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Cloud / Hosting 05.07.2026 · 10 min Lesezeit

GitLab CE mit Docker installieren: Vollständige DevOps-Plattform mit Git, CI/CD und Container-Registry

GitLab CE mit Docker Compose selbst hosten: Git-Hosting, CI/CD mit GitLab Runner und Container-Registry einrichten, Runner mit Authentifizierungstoken registrieren, Backups und Updates planen.

Geprüft am 30.09.2026 · für gitlab-ce 19.4.1-ce.0

WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Symbolbild zur Anleitung: GitLab CE mit Docker installieren

GitLab Community Edition (CE) bündelt Git-Hosting, Merge Requests, CI/CD-Pipelines, Container-Registry und Package-Registry in einer selbst gehosteten Instanz. Die MIT-lizenzierte Plattform läuft als ein Docker-Container auf Ihrem Linux-Server. Diese Anleitung führt von der leeren VM bis zur laufenden Instanz mit registriertem GitLab Runner für CI/CD-Pipelines.

Voraussetzungen

  1. Linux-Host oder VM – z. B. Ubuntu 24.04, Debian 12/13 oder Rocky Linux 9. Docker Desktop für Windows unterstützt GitLab nicht.
  2. Docker Engine ≥ 20.10.10 und Docker Compose Plugin v2 (docker compose ohne Bindestrich) installiert. Falls noch nicht vorhanden: Docker und Docker Compose auf Linux installieren (Ubuntu/Debian).
  3. RAM: mindestens 8 GB (Untergrenze laut GitLab für speicherarme Umgebungen), 16 GB als Richtwert für eine Einzelinstanz. PostgreSQL, Redis, Sidekiq und Puma laufen alle im selben Container.
  4. CPU: 8 vCPU sind der GitLab-Richtwert für eine Einzelinstanz, x86_64 oder ARM64.
  5. Speicher: mindestens 40 GB auf SSD plus Platz für Repositories und CI/CD-Artefakte.
  6. Statischer Hostname oder FQDN für den Wert external_url; ohne feste Adresse entstehen fehlerhafte Clone-URLs.
  7. Optional: Reverse Proxy (z. B. Caddy oder Nginx) für HTTPS-Terminierung; SMTP-Relay für E-Mail-Benachrichtigungen (GitLab hat keinen eingebauten Mailserver).

Schritt 1: Projektordner und Verzeichnisstruktur anlegen

Konfiguration, Logs und Repositories liegen unter dem Basispfad GITLAB_HOME. GitLab empfiehlt /srv/gitlab.

sudo mkdir -p /srv/gitlab
sudo mkdir -p /opt/gitlab-compose
cd /opt/gitlab-compose

/opt/gitlab-compose nimmt compose.yaml und .env auf.

Verifizieren:

ls -la /srv/gitlab /opt/gitlab-compose

Erwartetes Ergebnis: beide Verzeichnisse existieren, Eigentümer root. Die Unterordner config, logs und data legt Docker beim ersten Start an.

Schritt 2: .env-Datei mit Zugangsdaten anlegen

Die .env enthält die variablen Werte und gehört nicht in ein Git-Repository. Erstellen Sie die Datei unter /opt/gitlab-compose/.env und passen Sie die drei Pflichtfelder an:

# /opt/gitlab-compose/.env
# Basispfad fuer alle Volume-Mounts auf dem Host
GITLAB_HOME=/srv/gitlab

# Hostname oder IP-Adresse der GitLab-Instanz
# Muss mit dem Port in GITLAB_OMNIBUS_CONFIG uebereinstimmen
GITLAB_HOSTNAME=gitlab.example.com

# Initiales Root-Passwort (mind. 12 Zeichen, Sonderzeichen erlaubt)
# Wird bei erstem Start gesetzt; Datei /etc/gitlab/initial_root_password
# wird nach 24 h automatisch geloescht!
GITLAB_ROOT_PASSWORD=ChangeMe_MinLength12!

Schützen Sie die Datei vor unbefugtem Zugriff:

chmod 600 /opt/gitlab-compose/.env

Verifizieren:

ls -la /opt/gitlab-compose/.env

Erwartetes Ergebnis: Berechtigungen -rw-------, Eigentümer root.

Schritt 3: compose.yaml erstellen

Die compose.yaml definiert den GitLab-Container und einen GitLab Runner für CI/CD-Pipelines.

# /opt/gitlab-compose/compose.yaml
services:
  gitlab:
    image: gitlab/gitlab-ce:19.4.1-ce.0
    container_name: gitlab
    restart: always
    hostname: ${GITLAB_HOSTNAME}
    # shm_size PFLICHT: ohne diese Zeile schreibt Prometheus in einen
    # zu kleinen /dev/shm-Bereich und erzeugt "unmapped file"-Fehler
    shm_size: '256m'
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'http://${GITLAB_HOSTNAME}:8929'
        # SSH-Port: muss mit dem Host-seitigen Port-Mapping uebereinstimmen
        gitlab_rails['gitlab_shell_ssh_port'] = 2424
        # Root-Passwort aus .env setzen (Alternative: nach Start manuell auslesen)
        gitlab_rails['initial_root_password'] = '${GITLAB_ROOT_PASSWORD}'
        # Optional: Container-Registry aktivieren
        # registry_external_url 'http://${GITLAB_HOSTNAME}:5050'
        # Optional: SMTP (kein Mailserver eingebaut)
        # gitlab_rails['smtp_enable'] = true
        # gitlab_rails['smtp_address'] = "smtp.example.com"
        # gitlab_rails['smtp_port'] = 587
    ports:
      - '8929:8929'
      - '2424:22'
    volumes:
      - '${GITLAB_HOME}/config:/etc/gitlab'
      - '${GITLAB_HOME}/logs:/var/log/gitlab'
      - '${GITLAB_HOME}/data:/var/opt/gitlab'
    logging:
      driver: 'json-file'
      options:
        max-size: '50m'
        max-file: '5'

  gitlab-runner:
    image: gitlab/gitlab-runner:v19.4.1
    container_name: gitlab-runner
    restart: always
    depends_on:
      - gitlab
    volumes:
      - '${GITLAB_HOME}/runner/config:/etc/gitlab-runner'
      - '/var/run/docker.sock:/var/run/docker.sock'
    logging:
      driver: 'json-file'
      options:
        max-size: '20m'
        max-file: '3'

Port in external_url (:8929) und Port-Mapping (8929:8929) müssen übereinstimmen, sonst zeigt GitLab falsche Clone-URLs. Werte aus GITLAB_OMNIBUS_CONFIG landen nicht in /etc/gitlab/gitlab.rb, sondern werden bei jedem Container-Start neu ausgewertet.

Port 8929 überträgt unverschlüsselt HTTP und ist auf allen Schnittstellen erreichbar. Geben Sie ihn per Firewall nur im internen Netz frei; für Zugriff aus dem Internet gehört ein Reverse Proxy mit HTTPS davor. Der Runner erhält über /var/run/docker.sock Vollzugriff auf Docker und damit faktisch Root-Rechte auf dem Host. Lassen Sie deshalb nur vertrauenswürdige Projekte Jobs auf diesem Runner ausführen.

Verifizieren:

docker compose -f /opt/gitlab-compose/compose.yaml config

Erwartetes Ergebnis: Docker Compose gibt die vollständig interpolierte Konfiguration ohne Fehler aus; alle ${...}-Variablen sind durch Werte aus der .env ersetzt.

Schritt 4: GitLab starten und Initialisierung abwarten

Starten Sie den Stack aus dem Compose-Verzeichnis heraus:

cd /opt/gitlab-compose
docker compose up -d

Docker lädt das Image (ca. 1,2 GB komprimiert) und startet den Container. Die erste Initialisierung dauert 3 bis 5 Minuten, auf langsamerer Hardware bis zu 10 Minuten. In dieser Zeit zeigt der Browser „502 Whoops, GitLab is taking too much time to respond“. Das ist der normale Initialisierungsablauf.

# Logs live verfolgen (mit Ctrl+C abbrechen)
docker compose logs -f gitlab

# Auf das Signal warten, dass GitLab bereit ist:
docker compose logs -f gitlab | grep -i 'server booted'

Eckdaten im Überblick:

ParameterWert
Imagegitlab/gitlab-ce:19.4.1-ce.0
Web-UI (HTTP)Port 8929 → http://HOSTNAME:8929
HTTPSüber Reverse Proxy (siehe Häufige Fragen)
Git SSHHost-Port 2424 → Container-Port 22
Config-Volume${GITLAB_HOME}/config:/etc/gitlab
Logs-Volume${GITLAB_HOME}/logs:/var/log/gitlab
Daten-Volume${GITLAB_HOME}/data:/var/opt/gitlab
shm_size256m (Pflicht)
Min. RAM8 GB (Richtwert 16 GB)
CPU8 vCPU (Richtwert)
ARM64ab v18.1/v18.2 offiziell multi-arch

Verifizieren:

docker compose ps
NAME            IMAGE                           STATUS          PORTS
gitlab          gitlab/gitlab-ce:19.4.1-ce.0    Up 5 minutes (healthy)   0.0.0.0:2424->22/tcp, 0.0.0.0:8929->8929/tcp
gitlab-runner   gitlab/gitlab-runner:v19.4.1    Up 5 minutes

Sobald GitLab vollständig gestartet ist:

curl -I http://localhost:8929

Erwartetes Ergebnis: HTTP/1.1 302 Found mit Location: http://HOSTNAME:8929/users/sign_in.

Schritt 5: Erst-Einrichtung im Browser und Root-Passwort sichern

Rufen Sie http://HOSTNAME:8929 im Browser auf. GitLab leitet auf die Login-Seite weiter. Melden Sie sich mit dem Benutzernamen root und dem in der .env gesetzten Passwort an.

Haben Sie das Root-Passwort nicht über GITLAB_OMNIBUS_CONFIG gesetzt, lesen Sie das generierte Passwort aus:

docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_password

Wichtig: GitLab löscht diese Datei nach 24 Stunden automatisch. Sichern Sie das Passwort sofort. Nehmen Sie nach dem ersten Login diese Grundkonfiguration im Bereich Admin vor:

  1. Sign-up deaktivieren (Admin → Settings → General → Sign-up restrictions, Häkchen bei Sign-up enabled entfernen).
  2. E-Mail-Benachrichtigungen: SMTP-Einstellungen in GITLAB_OMNIBUS_CONFIG ergänzen.
  3. Root-Passwort ändern: Avatar oben → Edit profile → Password.

Verifizieren: Login mit root funktioniert, Dashboard lädt ohne Fehler, der Admin-Bereich ist erreichbar unter http://HOSTNAME:8929/admin.

Schritt 6: GitLab Runner registrieren für CI/CD-Pipelines

Der GitLab-Runner-Container läuft seit Schritt 4, ist aber noch nicht mit der GitLab-Instanz verbunden. CI/CD-Jobs bleiben in der Warteschlange, bis ein Runner registriert ist. Seit GitLab 16 erzeugen Sie den Runner zuerst in der Oberfläche und erhalten ein Runner-Authentifizierungstoken; das frühere Registrierungstoken („Register an instance runner“) gilt als veraltet:

  1. Admin → CI/CD → Runners → Create instance runner, Betriebssystem Linux wählen, Tags setzen oder Run untagged aktivieren, Create runner.
  2. Das angezeigte Token mit Präfix glrt- kopieren. GitLab zeigt es nur während der Registrierung an.

Registrieren Sie den Runner dann im Container:

docker exec -it gitlab-runner gitlab-runner register

Die interaktiven Abfragen:

Enter the GitLab instance URL:
# Eingabe: http://gitlab.example.com:8929

Enter the registration token:
# Eingabe: glrt-... (Token aus der Oberfläche)

Enter a name for the runner:
# Eingabe: docker-runner

Enter an executor:
# Eingabe: docker

Enter the default Docker image:
# Eingabe: alpine:3.22

Der Runner speichert seine Konfiguration unter ${GITLAB_HOME}/runner/config/config.toml.

Verifizieren:

docker compose logs gitlab-runner | tail -20

Erwartetes Ergebnis: keine ERROR-Zeilen; unter Admin → CI/CD → Runners erscheint der Runner als online. Legen Sie eine einfache .gitlab-ci.yml ins Repository, um einen Test-Job auszulösen:

test-job:
  script:
    - echo "Pipeline funktioniert!"

Schritt 7: Container-Registry aktivieren (optional)

Die Container-Registry ist standardmäßig deaktiviert. Ergänzen Sie registry_external_url und ein Port-Mapping:

    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'http://${GITLAB_HOSTNAME}:8929'
        gitlab_rails['gitlab_shell_ssh_port'] = 2424
        gitlab_rails['initial_root_password'] = '${GITLAB_ROOT_PASSWORD}'
        registry_external_url 'http://${GITLAB_HOSTNAME}:5050'
    ports:
      - '8929:8929'
      - '2424:22'
      - '5050:5050'

Anschließend den Stack neu starten:

cd /opt/gitlab-compose
docker compose up -d

Verifizieren:

curl -I http://localhost:5050/v2/

Erwartetes Ergebnis: HTTP/1.1 401 Unauthorized. Das zeigt, dass die Registry läuft und eine Authentifizierung erwartet. Anmeldung mit docker login HOSTNAME:5050 und GitLab-Zugangsdaten. Docker akzeptiert eine Registry ohne HTTPS nur, wenn sie auf dem Client als insecure-registries eingetragen ist; für den Produktivbetrieb gehört HTTPS davor.

Schritt 8: Updates und Backups

Updates durchführen

GitLab erlaubt keine Sprünge über Major-Versionen (z. B. nicht 17.x direkt auf 19.x). Prüfen Sie den Upgrade-Pfad unter docs.gitlab.com/update/upgrade_paths/. Minor-Updates (z. B. 19.3.x auf 19.4.x) laufen so:

# 1. Backup erstellen (siehe unten)
# 2. Image-Tag in compose.yaml auf neue Version aendern, dann:
cd /opt/gitlab-compose
docker compose pull
docker compose up -d

Datenbankmigrationen laufen beim Start automatisch, GitLab ist dabei einige Minuten nicht erreichbar.

Backups erstellen

Ein vollständiges Backup besteht aus zwei Teilen:

# Teil 1: Repositories, Issues, CI/CD-Konfigurationen
docker exec -t gitlab gitlab-backup create

# Teil 2: Secrets-Datei (wird von gitlab-backup create NICHT gesichert!)
# Ohne diese Datei sind alle CI/CD-Variablen und 2FA-Secrets verloren
cp /srv/gitlab/config/gitlab-secrets.json /pfad/zum/backup-ziel/gitlab-secrets.json

Die Backup-Datei liegt unter /srv/gitlab/data/backups/. Eine Backup-Strategie mit Kopie außer Haus zeigt die Anleitung 3-2-1-Backup-Strategie umsetzen: Restic, USB-Disk und S3-Cloud.

Verifizieren:

ls -lh /srv/gitlab/data/backups/

Erwartetes Ergebnis: Datei mit Namensschema TIMESTAMP_gitlab_backup.tar vorhanden.

Troubleshooting / Typische Fehler

  1. „writing value to /dev/shm/gitlab/sidekiq/gauge... failed with unmapped file“ – shm_size: '256m' fehlt. Ergänzen und docker compose up -d ausführen.
  2. Falsche Clone-URLs – Port in external_url passt nicht zum Port-Mapping (siehe Schritt 3).
  3. „502 Whoops“ nach dem ersten Start – GitLab initialisiert sich noch. 3 bis 5 Minuten warten und Logs beobachten: docker compose logs -f gitlab | grep -i booted.
  4. Root-Passwort verloren – Reset über die Rails-Konsole: docker exec -it gitlab gitlab-rails console → user = User.find_by(username: 'root'); user.password = 'NeuesPasswort12!'; user.save!
  5. CI/CD-Jobs warten endlos – Runner nicht registriert, falsche URL oder Job-Tags passen nicht zum Runner. Schritt 6 wiederholen, docker compose logs gitlab-runner prüfen.
  6. Container startet nicht, „ThreadError: Operation not permitted“ – Docker älter als 20.10.10. Docker aktualisieren: apt-get upgrade docker-ce docker-ce-cli containerd.io.
  7. OOM-Killer beendet Prozesse – Zu wenig RAM (mindestens 8 GB). Mit docker stats gitlab prüfen.
  8. Host-Festplatte läuft voll – Log-Rotation fehlt. Die logging-Sektion der obigen compose.yaml übernehmen.
  9. Upgrade schlägt fehl – Pflicht-Zwischenversion übersprungen. Backup einspielen und Upgrade-Pfad unter docs.gitlab.com/update/upgrade_paths/ einhalten.

Häufige Fragen

Wie lange dauert der erste Start von GitLab CE?

3 bis 5 Minuten, auf langsamer Hardware bis zu 10 Minuten (Details in Schritt 4).

Wie unterscheidet sich GitLab CE von GitLab EE?

Die Community Edition (CE) ist MIT-lizenziert und enthält Git-Hosting, Merge Requests, CI/CD, SAST, Container-Registry, Issue-Tracking, Wiki und Package-Registry. Der Enterprise Edition vorbehalten sind unter anderem DAST, das Security-Dashboard, GitLab Geo und erweiterte Compliance-Funktionen. Für die meisten KMU-Teams reicht CE.

Funktioniert GitLab CE auf ARM64-Servern?

Ja. Seit GitLab 18 gibt es offizielle Multi-Arch-Images (amd64 und arm64) unter gitlab/gitlab-ce, Docker wählt die passende Architektur automatisch. Die RAM-Anforderung von mindestens 8 GB gilt auch hier.

Wie richte ich HTTPS ein?

Entweder über Let's Encrypt im Container (in GITLAB_OMNIBUS_CONFIG: external_url 'https://…' und letsencrypt['enable'] = true, erfordert öffentlich erreichbare Ports 80 und 443 mit entsprechendem Port-Mapping) oder über einen Reverse Proxy wie Caddy oder Nginx, der Anfragen an den internen Port 8929 weiterleitet. Bei mehreren Diensten auf einem Server ist der Reverse Proxy die bessere Wahl.

Wie führe ich ein Backup durch?

Mit docker exec -t gitlab gitlab-backup create plus einer Kopie von ${GITLAB_HOME}/config/gitlab-secrets.json, die das Backup nicht enthält (siehe Schritt 8).

Wie aktualisiere ich GitLab auf eine neue Version?

Backup erstellen, Image-Tag in compose.yaml auf die Zielversion setzen, docker compose pull && docker compose up -d ausführen (siehe Schritt 8). Prüfen Sie vorher den offiziellen Upgrade-Pfad unter docs.gitlab.com/update/upgrade_paths/ prüfen.

Warum braucht GitLab keinen separaten Datenbank-Container?

Das Omnibus-Paket bündelt PostgreSQL, Redis, Sidekiq, Puma, Nginx und Prometheus in einem Container. Das vereinfacht den Betrieb und erklärt den hohen RAM-Bedarf.

Fazit

GitLab CE vereint Git-Hosting, CI/CD-Pipelines und Container-Registry in einem Docker-Container und ersetzt damit mehrere separate Dienste. Dafür brauchen Sie mindestens 8 GB RAM, Upgrades entlang des offiziellen Upgrade-Pfads und eine Sicherung von gitlab-secrets.json vor jedem Upgrade.

Als schlankere Alternative ohne eingebaute CI/CD eignet sich Gitea mit Docker: eigener Git-Server als GitHub-Alternative.

Weiterführende Anleitungen und Quellen

  1. Docker und Docker Compose auf Linux installieren – die Self-Hosting-Grundlage
  2. Caddy als Reverse Proxy einrichten: Anfänger-Anleitung mit automatischem HTTPS
  3. Gitea mit Docker: eigener Git-Server als GitHub-Alternative
  4. 3-2-1-Backup-Strategie umsetzen: Restic, USB-Disk und S3-Cloud
  5. Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only

Offizielle Quellen: GitLab Docs: Install GitLab in a Docker container · GitLab Docs: Configure GitLab running in a Docker container · Docker Hub: gitlab/gitlab-ce