
Eigene Docker-Images für GitLab CI: Node.js Build-Container und lokale Registry
In diesem Beitrag geht es darum, wie man ein eigenes Docker-Image auf Debian-Basis erstellt, das Node.js enthält und sich ideal für den Einsatz in GitLab CI/CD-Pipelines eignet. Das Ziel: eine statische Website mit Astro bauen und automatisch auf einen Webserver deployen – ganz ohne externe Abhängigkeiten wie Docker Hub.
Ich nutze dafür eine eigene Docker-Registry, die lokal oder direkt auf meinem GitLab-Server läuft.
Ziel des Setups
- 🧱 Ein reproduzierbarer CI-Container, der nur das enthält, was wirklich gebraucht wird
- 🚀 Kein Abhängigkeits- oder Pull-Limit vom Docker Hub
- 🔐 Deployment via SCP direkt auf den Zielserver
- 🔁 Wiederverwendbar für andere Node.js-Projekte
Dockerfile: Node.js auf Debian 12
FROM debian:12
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg \
openssh-client \
lsb-release \
&& rm -rf /var/lib/apt/lists/*
ENV NODE_MAJOR=18
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash - && \
apt-get install -y nodejs
Dieses Image ist bewusst schlank gehalten:
- Debian 12 als stabile Basis
- Node.js 18 aus den offiziellen Nodesource-Repos
- SSH-Tools für das spätere Deployment via
scp
Image bauen und lokal taggen
docker build -t nodebuilder:latest -f nodebuilder.docker .
docker tag nodebuilder:latest localhost:5000/nodebuilder:latest
Lokale Docker-Registry starten
Falls du noch keine lokale Registry betreibst, kannst du sie so starten:
docker run -d -p 5000:5000 --restart=always --name registry registry:2
Die Registry lauscht dann unter http://localhost:5000
.
Wenn du GitLab verwendest, kannst du auch die integrierte Container Registry nutzen (z. B. gitlab.dunzweiler.me:5050
), sofern deine Runner Zugriff darauf haben.
Image in Registry pushen
docker push localhost:5000/nodebuilder:latest
Oder bei GitLab Registry:
docker tag nodebuilder:latest gitlab.dunzweiler.me:5050/dunzweiler_public/nodebuilder_docker/nodebuilder
docker push gitlab.dunzweiler.me:5050/dunzweiler_public/nodebuilder_docker/nodebuilder
GitLab CI/CD: Build und Deployment
Das ist meine gitlab-ci.yml
, wie ich sie für meine Astro-basierte Blogseite einsetze:
image: gitlab.dunzweiler.me:5050/dunzweiler_public/nodebuilder_docker/nodebuilder
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
pages:
script:
- npm install
- npm run build
- mkdir ~/.ssh/
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh-keyscan -H $SCP_HOST >> ~/.ssh/known_hosts
- scp -r -i ~/.ssh/id_rsa dist/* $SCP_USER@$SCP_HOST:/var/www/blog/
only:
- master
Erklärung:
image
: Das eigene, vorher gepushte Docker-Imagecache
: Spart Zeit bei wiederholten Builds (z. B.node_modules
)script
:- Build-Prozess mit
npm
- Einrichtung des SSH-Zugriffs
- Deployment via
scp
- Build-Prozess mit
- Die SSH-Variablen
SSH_PRIVATE_KEY
,SCP_USER
undSCP_HOST
sind in GitLab als geschützte Variablen (protected variables) hinterlegt
Typische Fehlerquellen
- ❗ Image nicht gepusht: Das CI-Joblog sagt „Image not found“ → Push in Registry vergessen?
- ❗ SSH-Fehler: Schlüssel nicht gesetzt oder falsche Berechtigungen (
chmod 600
) - ❗ Deployment schlägt fehl: Hostname falsch, Pfad nicht vorhanden oder SSH-Host unbekannt →
ssh-keyscan
hilft
Vorteile des eigenen CI-Images
Vorteil | Beschreibung |
---|---|
Keine Drittanbieter-Abhängigkeit | Kein Docker Hub notwendig |
Kontrolle über Umgebung | Reproduzierbares Build-Verhalten |
Schnellere Builds | Kein externer Pull, Caching lokal oder via GitLab möglich |
Sicherheit | Deployment mit SSH-Schlüssel, keine Passwörter im Klartext |
Erweiterbar | Tools wie rsync , imagemagick , etc. können bei Bedarf ergänzt werden |
Fazit
Wer mit GitLab arbeitet und regelmäßig Builds ausführt, sollte über eigene CI-Images nachdenken. Besonders bei statischen Seiten wie Astro oder Next.js macht ein aufgeräumtes Node.js-Image Sinn – und spart auf Dauer Nerven, Zeit und externen Traffic.
Ob lokal oder per GitLab Registry – so ein Image ist schnell gebaut und bringt viel Kontrolle zurück ins eigene Setup.