In this article
JavaScript-MCP-Server mit Docker paketieren
MCP-Server lassen sich problemlos als Erweiterungen in LLMs einbinden. Ihre Einrichtung kann jedoch mühsam sein, da dafür eine Entwicklungsumgebung erforderlich ist. Abhilfe schafft ein Docker-Image für unsere MCP-Server.
In einem früheren Beitrag habe ich erklärt, wie Sie MCP-Server mit Docker ausführen, sodass Sie als Nutzer, der MCP-Server verbinden möchte, sich nicht mit der Installation der richtigen Python-Version oder der Einrichtung von npm oder npx für JavaScript-basierte MCP-Server herumschlagen müssen.
In diesem Beitrag konzentrieren wir uns auf Sie als Entwickler von MCP-Servern und zeigen, wie einfach es ist, Nutzern von MCP ein Docker-Image bereitzustellen. Dafür richten wir die MCP-Entwicklungsumgebung wie folgt ein:
Eine
Dockerfilefür Ihren MCP-Server einrichtenEinen GitHub-Actions-Workflow erstellen, der das Docker-Image erstellt
Einen GitHub-Actions-Workflow erstellen, der das Docker-Image in GitHub Packages veröffentlicht
Wir gehen davon aus, dass das MCP-Server-Projekt mit JavaScript (oder TypeScript) erstellt wurde und auf einer Node.js-Entwicklungsumgebung basiert.
Als Voraussetzung benötigen Sie eine Node.js-Entwicklungsumgebung, das MCP-Projekt, das Sie mit Docker paketieren möchten, und die lokal verfügbare Anwendung Docker Desktop.
Eine Dockerfile für Ihren MCP-Server einrichten
Ein Dockerfile ist der Baustein für Docker-Images. Es legt fest, wie ein Image erstellt wird und wie es ausgeführt wird, wenn ein Container erstellt wird.
Erstellen Sie die folgende Dockerfile:
FROM node:22-slim AS builder
WORKDIR /app
COPY . /app
RUN --mount=type=cache,target=/root/.npm npm install
RUN --mount=type=cache,target=/root/.npm npm run build
RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --omit-dev
FROM node:22-slim AS release
WORKDIR /app
COPY --from=builder /app/dist /app/dist
COPY --from=builder /app/package.json /app/package.json
COPY --from=builder /app/package-lock.json /app/package-lock.json
ENV NODE_ENV=production
RUN npm ci --ignore-scripts --omit-dev
ENTRYPOINT ["node", "/app/dist/bin/cli.cjs"]Was passiert in dieser Dockerfile?
Dieser Docker-Image-Build-Workflow besteht aus mehreren Schritten und folgt der Best Practice, das Image zum Erstellen des Projekts von dem Image zu trennen, das zum Starten eines Docker-Containers verwendet wird. Er folgt den 10 Best Practices für Node.js, um Node.js-Anwendungen mit Docker zu containerisieren.
Es wird ein Verzeichnis
/appdefiniert, in dem sich die Dateien des MCP-Server-Projekts im Container befindenBeim Ausführen des Docker-Containers wird die Datei
/app/dist/bin/cli.cjsals Argument an dienode-Laufzeitumgebung übergeben. Wahrscheinlich möchten Sie diesen Eintrag an den Einstiegspunkt Ihres MCP-Servers anpassen, zum Beispielindex.jsoderserver.js.
Wie geht es weiter? Nachdem wir nun eine Dockerfile haben, können wir das Image lokal erstellen und ausführen, um sicherzustellen, dass es funktioniert. So erstellen Sie dieses Docker-Image (Sie können my-mcp-server durch den Namen ersetzen, mit dem Sie das Docker-Image taggen möchten):
docker build -t my-mcp-server .Führen Sie den obigen Befehl im Stammverzeichnis des Projekts aus. Dort sollte sich auch Ihre Dockerfile befinden. Anschließend wird ein neues Docker-Image erstellt.
Wie wird der MCP-Server aus einem Docker-Image ausgeführt? Verwenden Sie diesen Befehl:
docker run -i --rm --init -e DOCKER_CONTAINER=true my-mcp-serverWir starten einen neuen Container aus dem zuvor erstellten Docker-Image my-mcp-server. Mit den Argumenten -i und --rm teilen wir Docker mit, dass es sich um einen interaktiven Prozess handelt, der eine Verbindung zu STDIO herstellt. Sobald der Container beendet wird, wird er in einem sauberen Aufräumschritt auch entfernt.
Wie nutzen Anwender einen MCP-Server über Docker?
Da wir nun einen MCP-Server haben: Wie können MCP-Clients und Host-Anwendungen ihn nutzen? Wie konfigurieren sie den auszuführenden Befehl, wenn es sich nicht um Pythons ux, pip oder Node.js’ npx handelt?
Docker muss verfügbar sein, und viele Entwickler werden wahrscheinlich Docker oder eine Docker-kompatible Alternative wie Podman installiert haben. Sobald Docker verfügbar ist, können sie den MCP-Server wie folgt konfigurieren:
{
"mcpServers": {
"my-mcp-server": {
"command": "docker",
"env": {},
"args": [
"run",
"-i",
"--rm",
"my-mcp-server"
]
}
}Fast! Das ist kein vollständiges Beispiel und funktioniert für MCP-Nutzer nicht. Vielleicht ist Ihnen aufgefallen, dass wir im Docker-Befehl auf my-mcp-server verweisen. Aber woher weiß Docker, wo es dieses Image abrufen soll, und haben wir es dort überhaupt veröffentlicht?
Genau, dieser Teil fehlt noch. Wir haben eine Dockerfile erstellt und lokal ein Docker-Image erstellt, es aber nirgendwo veröffentlicht. Um es Softwareentwicklern, die auf GitHub entwickeln, leicht zu machen, veröffentlichen wir das Image in der GitHub-Packages-Registry, die Docker-Images hosten kann. Genau das macht auch der offizielle GitHub MCP Server.
Einen GitHub-Actions-Workflow erstellen, der das Docker-Image erstellt und in GitHub Packages veröffentlicht
Zunächst erstellen wir einen GitHub-Actions-Workflow, der ein Docker-Image erstellt. Der CI-Workflow umfasst die folgenden Schritte:
Das Docker-Image erstellen
Das Docker-Image in GitHub Packages veröffentlichen
Das Docker-Image signieren
Die vollständige Workflow-Datei, die Sie im folgenden Verzeichnis im Stammverzeichnis Ihres Projekts erstellen sollten: .github/workflows/docker-publish-to-github.yml.
Bevor Sie diese Datei ausführen und speichern, sollten Sie die Umgebungsvariable IMAGE_NAME so ändern, dass sie statt des Beispielnamens my-mcp-server den Namen Ihres eigenen Docker-Images verwendet:
name: "Docker: GitHub Packages"
on:
push:
branches:
- main
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/my-mcp-server
jobs:
build_and_publish:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
id-token: write
attestations: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
type=ref,event=pr
flavor: |
prefix=
suffix=
- name: Build and push Docker image
id: push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: trueAußerdem werden Sie feststellen, dass die obige GitHub-Actions-Workflow-Datei zum Erstellen des Docker-Images davon ausgeht, dass der Name des Trunk-Branches main lautet.
Als Nächstes müssen Sie den GitHub-Actions-Runnern Schreibberechtigungen erteilen. Gehen Sie dazu im Repository zu Settings -> Actions -> General und aktivieren Sie die Lese- und Schreibberechtigungen wie folgt:

Sie möchten mit MCPs noch mehr erreichen?
Sie fragen sich, wie es von hier aus weitergeht? Ich habe einige hilfreiche Ressourcen zusammengestellt, die Ihnen dabei helfen, MCP-Server besser zu verstehen und abzusichern:
Ein Leitfaden für Einsteiger zum visuellen Verständnis der MCP-Architektur
Von Prompt-Injection bis zu anderen Sicherheitslücken: MCP-Sicherheit – Das Alte ist wieder neu
22. Oktober 2025
DevSecCon2025 – The AI Security Summit
Sichern Sie sich Ihren Platz und gestalten Sie den Wandel hin zu KI-nativer Entwicklung sicher.