Bereitstellung von NestJS-Containern
Node.js/Nest.js-Bereitstellungen vereinfachen: Schritt-für-Schritt-Anleitung mit Docker und Google Cloud
Ein korrigierter Leitfaden zu mehrstufigen Node.js- und NestJS-Containern, unveränderlichen Artefakten und der Wahl zwischen Docker Hub und Cloud Build für die Bereitstellung in Cloud Run.
8 Min. LesezeitVon Abdullah Raheel
Einen Node.js- oder NestJS-Dienst bereitstellen
Dies ist der Bereitstellungsweg, den ich 2023 für einen NestJS-Microservice genutzt habe: ein Docker-Image bauen, es mit GitHub Actions veröffentlichen und in Cloud Run bereitstellen. Die Teile des ursprünglichen Leitfadens, die ich heute nicht mehr ausliefern würde, habe ich korrigiert.
Docker bündelt Laufzeit, Abhängigkeiten und Anwendung in einem Image. Dadurch verringern sich die Unterschiede zwischen lokalen, CI- und Cloud Run-Umgebungen; Konfiguration und Infrastruktur können sich dennoch unterscheiden.
Diese Anleitung umfasst drei Phasen: das Image bauen und prüfen, es mit GitHub Actions und Docker Hub veröffentlichen und es mit manuellen Revisionen oder kontinuierlicher Bereitstellung in Google Cloud bereitstellen.
Voraussetzungen
- Installieren Sie Docker, bevor Sie mit dem Build beginnen.
- Installieren Sie unter Windows WSL (Windows Subsystem for Linux), damit Docker die erforderliche Linux-Umgebung nutzen kann.
- Falls die WSL-Installation mit dem Fehler 0x80370114 scheitert, aktivieren Sie die erforderlichen Virtualisierungsfunktionen, bevor Sie fortfahren.
Phase 1: Docker-Image erstellen
Der ursprüngliche Leitfaden von 2023 nutzte eine einzelne Node 18 Alpine-Phase, installierte Produktionsabhängigkeiten und führte anschließend den Nest-Build im selben Image aus. Diese Reihenfolge ist kein verlässlicher NestJS-Build: TypeScript und andere Buildwerkzeuge liegen häufig in devDependencies. Das korrigierte Image trennt die Kompilierung von der Laufzeit, sodass der Build über die vollständige Werkzeugkette verfügt, ohne sie in den Produktivbetrieb auszuliefern.
FROM node:18-alpine AS build
WORKDIR /usr/src/app
# Copy manifests first so dependency layers can be reused.
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:18-alpine AS runtime
ENV NODE_ENV=production
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force
COPY --from=build /usr/src/app/dist ./dist
EXPOSE 8080
USER node
CMD ["node", "dist/main.js"]Die Buildphase nutzt npm ci, wofür eine eingecheckte Lockdatei erforderlich ist, und kompiliert mit den im Projekt festgelegten Nest- und TypeScript-Versionen. Die Laufzeitphase erhält Produktionsabhängigkeiten und die kompilierte Ausgabe und gibt Root-Rechte anschließend über den Benutzer node des Images ab.
Dockerfile
.dockerignore
node_modules
npm-debug.log
distDie ignorierten Dateien halten den Docker-Buildkontext klein und verhindern, dass Hostabhängigkeiten oder ein vorhandenes dist-Verzeichnis in das Image kopiert werden.
Container lokal ausführen und prüfen
Bauen Sie das Image, und bestätigen Sie, dass Docker es erstellt hat.
docker build --tag nest-microservice .
docker imagesStarten Sie einen Container im Hintergrund, und ordnen Sie seinen internen Port 8080 dem lokalen Port 5000 zu. Prüfen Sie docker ps, rufen Sie den HTTP-Zustandsendpunkt auf, und untersuchen Sie docker logs, bevor Sie das Image veröffentlichen.
docker run -d --publish 5000:8080 --name nest-container nest-microservice
docker ps
docker ps --all
docker stop nest-containerNachdem das lokale Image und der Container funktionieren, übertragen Sie Dockerfile und .dockerignore in das GitHub-Repository.
Phase 2: Image mit GitHub Actions veröffentlichen
Für kontinuierliche Integration benötigen Sie ein GitHub-Repository mit dem Node.js- oder NestJS-Quellcode und ein Docker Hub-Konto. Erstellen Sie ein persönliches Zugriffstoken für Docker Hub, und speichern Sie Kontonamen und Token als Repository-Geheimnisse mit den Namen DOCKERHUB_USERNAME und DOCKERHUB_TOKEN.
Der nachfolgende Arbeitsablauf von 2023 lief bei jedem Push auf main, checkte den Quellcode aus, meldete sich bei Docker Hub an, aktivierte Buildx, baute das Dockerfile im Stammverzeichnis und übertrug abdullahraheel/nest-microservice:latest. Er bleibt als ursprüngliche Implementierung einschließlich seiner historischen Action-Versionen erhalten.
name: ci
on:
push:
branches:
- "main"
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/nest-microservice:latest- Speichern und committen Sie den Arbeitsablauf.
- Pushen Sie die Änderung auf main, damit der Arbeitsablauf startet.
- Prüfen Sie den Actions-Lauf, und diagnostizieren Sie bei einem fehlgeschlagenen Auftrag genau den betroffenen Schritt.
- Prüfen Sie, ob das veröffentlichte Repository und der Tag in Docker Hub erscheinen.
Phase 3: Image in Google Cloud Run bereitstellen
Erstellen Sie ein Google Cloud-Projekt, öffnen Sie Cloud Run, und erstellen Sie einen Dienst. Geben Sie für eine manuelle Bereitstellung das Docker Hub-Image im Format username/repository:tag an, wählen Sie Region und Diensteinstellungen, und erstellen Sie die Revision. Das Beispiel-Image lautet abdullahraheel/nest-microservice:latest; verwenden Sie das genaue Repository und den Tag aus Ihrem eigenen Arbeitsablauf.
Cloud Build für kontinuierliche Bereitstellung verbinden
- Wählen Sie Create Service und anschließend die Option zur Einrichtung einer kontinuierlichen Bereitstellung mit Cloud Build.
- Wählen Sie Repositoryanbieter und Repository aus.
- Wählen Sie den Bereitstellungsbranch; in diesem Beispiel ist es main.
- Wählen Sie Dockerfile als Buildtyp aus, und geben Sie den Pfad an.
- Speichern Sie die Konfiguration, und erstellen Sie den Dienst.
Sobald die Verbindung aktiv ist, veranlassen in main zusammengeführte Änderungen, dass Cloud Build das Repository baut und den Dienst automatisch erneut bereitstellt. Das ist eine Alternative zur Bereitstellung des in Phase 2 erzeugten Docker Hub-Images, kein weiterer Abnehmer desselben Artefakts.
Zusammenfassung und Verweise
- Bauen Sie das NestJS- oder Node.js-Projekt als Docker-Image, und prüfen Sie seinen Container lokal.
- Wählen Sie einen Bereitstellungsweg: Veröffentlichen Sie ein versioniertes Image mit GitHub Actions, oder lassen Sie Cloud Build das verbundene Repository bauen.
- Stellen Sie eine genaue Image-Revision manuell bereit, oder nutzen Sie den verbundenen Cloud Build-Weg für automatische Dienstrevisionen.
- Verwenden Sie einen externen Scheduler oder eine Singleton-Steuerung für zeitgesteuerte Aufgaben; eine Cloud Run-Webinstanz ist nicht von sich aus ein einzelner dauerhafter Cron-Worker.

