Zum Hauptinhalt springen

Build

Der Docker Build erstellt ein Docker Image anhand eines Dockerfile. Das Image ist die Vorlage, aus der später Container gestartet werden.


1. Dockerfile erstellen

Ein Dockerfile definiert Schritt für Schritt, wie dein Image gebaut wird.

Zusätzlich solltest du immer eine .dockerignore anlegen, damit unnötige Dateien (z. B. .env, node_modules) nicht ins Image gelangen.

Beispiel Dockerfiel (Node App)

# 🔸 Build-Argument vor dem FROM: Basis-Image konfigurierbar
ARG NODE_VERSION=20
FROM node:${NODE_VERSION}

# 🔸 Argument auch nach FROM nochmal definieren, falls später genutzt wird
ARG APP_ENV=production
ARG APP_DIR=/createdFolder
ARG APP_PORT=3000

# 🔸 Umgebungsvariable zur Laufzeit verfügbar machen
ENV NODE_VERSION=${NODE_VERSION}
ENV NODE_ENV=${APP_ENV}
ENV PORT=${APP_PORT}
ENV WORKDIR=${APP_DIR}

# 🔸 Arbeitsverzeichnis im Container
WORKDIR ${WORKDIR}

# 🔸 Abhängigkeiten zuerst kopieren (für Build-Caching)
COPY package*.json ./
RUN npm install

# 🔸 Restliche Dateien kopieren in WORKDIR
COPY . .

# 🔸 Port dokumentieren (optional, für Info-Zwecke)
EXPOSE ${PORT}

# 🔸 Port dokumentieren (optional, für Info-Zwecke)
RUN echo "Ausgabe: NODE_VERSION=$NODE_VERSION, NODE_ENV=$NODE_ENV, PORT=$PORT, WORKDIR=${WORKDIR}"

# 🔸 Startkommando
CMD ["node", "start"]

::: 💡 Vorteil dieser Reihenfolge: Layer-Caching → npm install wird nur neu gebaut, wenn sich package.json ändert. :::


2. Image bauen (Standard)

Image mit Default-Werten erstellen:

docker build -t myapp .
 PS C:\DEVELOPMENT\Dockertest> docker build -t myapp .
[+] Building 4.4s (11/11) FINISHED docker:desktop-linux
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 965B 0.0s
=> [internal] load metadata for docker.io/library/node:20 0.5s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/6] FROM docker.io/library/node:20@sha256:2c071012e93673d595e1399564c4a48a70a5c0a0acd7db8211d5e6f6316b431a 0.0s
=> => resolve docker.io/library/node:20@sha256:2c071012e93673d595e1399564c4a48a70a5c0a0acd7db8211d5e6f6316b431a 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 997B 0.0s
=> CACHED [2/6] WORKDIR /createdFolder 0.0s
=> CACHED [3/6] COPY package*.json ./ 0.0s
=> [4/6] RUN npm install 2.3s
=> [5/6] COPY . . 0.1s
----------------------------------------------------------------------------------------------------------------------
=> [6/6] RUN echo "Ausgabe: NODE_VERSION=20.19.4, NODE_ENV=production, PORT=3000, WORKDIR=/createdFolder" 0.4s
----------------------------------------------------------------------------------------------------------------------
=> exporting to image 0.8s
=> => exporting layers 0.5s
=> => exporting manifest sha256:f4b74052d1f4fc92f59d10519e9db2beb1296c3f511c7f1c464d1a1d37b636dd 0.0s
=> => exporting config sha256:02419a4e53365db3344390b2963c8b4b9c856e6ee40cf0af5483fda14142dc08 0.0s
=> => exporting attestation manifest sha256:dbba38c0807f802a5eda6581106a0bc7f4bd6e652d9cb5aae93f4757bda9ff68 0.0s
=> => exporting manifest list sha256:6f7441fa3e624fded91a24d50de2ea344a1e4434439e3d1511241d8837a2cc8e 0.0s
=> => naming to docker.io/library/myapp:latest 0.0s
=> => unpacking to docker.io/library/myapp:latest

Ergebnis:

  • Docker liest das Dockerfile
  • erstellt Layer
  • speichert ein Image lokal

Danach Container starten:

docker run -p 3000:3000 myapp

3. Build Arguments (Custom Build)

Du kannst dein Image konfigurierbar machen über --build-arg.

Beispiel:

docker build `
--build-arg NODE_VERSION=18 `
--build-arg APP_ENV=development `
--build-arg APP_PORT=4000 `
--build-arg APP_DIR=/app `
-t myapp-custom .
PS C:\DEVELOPMENT\Dockertest> docker build `
>> --build-arg NODE_VERSION=18 `
>> --build-arg APP_ENV=development `
>> --build-arg APP_PORT=4000 `
>> --build-arg APP_DIR=/app `
>> -t myapp-dev .
[+] Building 5.0s (12/12) FINISHED docker:desktop-linux
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 965B 0.0s
=> [internal] load metadata for docker.io/library/node:18 0.9s
=> [auth] library/node:pull token for registry-1.docker.io 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> CACHED [1/6] FROM docker.io/library/node:18@sha256:c6ae79e38498325db67193d391e6ec1d224d96c693a8a4d94349855671 0.0s
=> => resolve docker.io/library/node:18@sha256:c6ae79e38498325db67193d391e6ec1d224d96c693a8a4d943498556716d3783 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 64B 0.0s
=> [2/6] WORKDIR /app 0.1s
=> [3/6] COPY package*.json ./ 0.1s
=> [4/6] RUN npm install 2.3s
=> [5/6] COPY . . 0.1s
----------------------------------------------------------------------------------------------------------------------
=> [6/6] RUN echo "Ausgabe: NODE_VERSION=18.20.8, NODE_ENV=development, PORT=4000, WORKDIR=/app" 0.5s
----------------------------------------------------------------------------------------------------------------------
=> exporting to image 0.9s
=> => exporting layers 0.6s
=> => exporting manifest sha256:6a84492c4052afb02a2e22d44361ec50498e9463c86925c2a6b7925ef36b322a 0.0s
=> => exporting config sha256:927df1229e3c0f024e866c1d93eabbb3ec20036dc571bb1722f3984c7476cb11 0.0s
=> => exporting attestation manifest sha256:6df6d3f18603e93b190f6f59daf4ababd28eb0ca09cb1be0250ee286dab81cb9 0.0s
=> => exporting manifest list sha256:2dd3e4c53f4a954e582d372eb6eeee42f567faac02e0a62b9778bfd73fb1b19f 0.0s
=> => naming to docker.io/library/myapp-custom:latest 0.0s
=> => unpacking to docker.io/library/myapp-custom:latest 0.2s

Dann Container starten:

docker run -p 3000:4000 myapp-custom

4. .dockerignore

In der .dockerignore alle Datein auflisten die später beim build des images nicht mit kopiert werden sollen. (Gleiches prinzip wie bei einer .gitignore)

Beispiel:

node_modules
.env
.git
dist
Dockerfile
docker-compose.yml