← From Zero to Deployed Alle LektionenAll lessons Setup ModelleModels

Phase 1 · Grundlagen

06 · Container und Docker

Du kannst erklären, was ein Container ist und warum „läuft nur bei mir“ damit aufhört.

Phase 1 · Foundations

06 · Containers and Docker

You can explain what a container is and why "only runs on my machine" stops with it.

„Bei mir läuft's“ ist der Klassiker unter den Ausreden. Container packen deine App so ein, dass sie überall gleich läuft — auf deinem Laptop und in der Cloud. Das macht das Deployen dramatisch einfacher.

Die Idee

Ein Container ist eine Lunchbox für deine App. Darin liegt nicht nur die App, sondern alles, was sie zum Laufen braucht: die richtige Version von Node, alle Bibliotheken, die Einstellungen. Dieselbe Box öffnet sich überall gleich — kein „dir fehlt noch dies und das“.

Stell dir vor, das Instagram-Backend läuft auf tausend Servern. Ohne Container müsste jeder Server exakt gleich eingerichtet sein — ein Albtraum. Mit Container schickt man überall dieselbe Lunchbox, und überall läuft dasselbe.

So funktioniert es

Ein vollständiges Dockerfile für das Instagram-Backend, Zeile für Zeile erklärt:

# Basis: schlankes Linux mit vorinstalliertem Node 20
FROM node:20-slim

# Arbeitsverzeichnis innerhalb der Box
WORKDIR /app

# zuerst nur die Abhängigkeitsliste kopieren (nutzt den Build-Cache)
COPY package*.json ./

# Abhängigkeiten installieren (ohne Dev-Werkzeuge, kleiner)
RUN npm ci --omit=dev

# dann den restlichen Code hineinlegen
COPY . .

# Cloud Run gibt den Port über die Variable PORT vor
ENV PORT=8080
EXPOSE 8080

# womit die App startet
CMD ["node", "server.js"]
flowchart LR
    D[Dockerfile
Rezept] --> I[Image
gepackte Vorlage] I --> C1[Container 1] I --> C2[Container 2] I --> C3[Container 3]

Aus einem Image startest du beliebig viele identische Container — genau das braucht Instagram, um bei viel Andrang zu skalieren.

So steuerst du es

Gute Praxis: kleine Basis-Images (-slim), Abhängigkeiten getrennt vom Code kopieren (damit der Cache greift), und keine Geheimnisse ins Image backen — sie stecken sonst dauerhaft in jeder Kopie.

Der wichtigste Stolperstein: Die App muss auf dem Port aus der Umgebungsvariable PORT lauschen. Sonst startet sie lokal, aber die Cloud erreicht sie nicht.

So sagst du es dem Agenten:

„Schreibe ein Dockerfile für dieses Node-Backend, das auf process.env.PORT lauscht (Fallback 8080).“

„Kopiere package*.json vor dem restlichen Code, damit der Docker-Cache greift.“

„Backe keine Geheimnisse ins Image; das DB-Passwort kommt später als Umgebungsvariable.“

Typische Fehler: App lauscht auf festem Port statt PORT; Geheimnisse ins Image kopiert; riesige Images, weil node_modules oder .git mit hineinkopiert wurden (dagegen hilft eine .dockerignore).

Kurz-Check

  1. Was steckt in einem Container zusätzlich zur App?
  2. Was ist der Unterschied zwischen Image und Container?
  3. Warum ist die PORT-Umgebungsvariable wichtig für die Cloud?
Antworten anzeigen
  1. Alles zum Laufen: die richtige Laufzeit, Bibliotheken und Einstellungen.
  2. Image = eingefrorene Vorlage; Container = laufende Kopie davon (du kannst viele aus einem Image starten).
  3. Die Cloud gibt den Port vor; lauscht die App auf einem anderen, ist sie nicht erreichbar.

"It runs on my machine" is the classic excuse. Containers pack your app so it runs the same everywhere — on your laptop and in the cloud. That makes deploying dramatically simpler.

The idea

A container is a lunchbox for your app. Inside is not just the app, but everything it needs to run: the right version of Node, all libraries, the settings. The same box opens the same everywhere — no "you're still missing this and that".

Imagine the Instagram backend runs on a thousand servers. Without containers, every server would have to be set up identically — a nightmare. With containers you ship the same lunchbox everywhere, and everywhere the same thing runs.

How it works

A complete Dockerfile for the Instagram backend, explained line by line:

# Base: slim Linux with Node 20 preinstalled
FROM node:20-slim

# Working directory inside the box
WORKDIR /app

# copy only the dependency list first (uses the build cache)
COPY package*.json ./

# install dependencies (without dev tools, smaller)
RUN npm ci --omit=dev

# then copy the rest of the code
COPY . .

# Cloud Run provides the port via the PORT variable
ENV PORT=8080
EXPOSE 8080

# how the app starts
CMD ["node", "server.js"]
flowchart LR
    D[Dockerfile
recipe] --> I[Image
packed template] I --> C1[Container 1] I --> C2[Container 2] I --> C3[Container 3]

From one image you start any number of identical containers — exactly what Instagram needs to scale under load.

How you steer it

Good practice: small base images (-slim), copy dependencies separately from the code (so the cache works), and never bake secrets into the image — they would live permanently in every copy.

The biggest pitfall: the app must listen on the port from the PORT environment variable. Otherwise it starts locally but the cloud cannot reach it.

How to tell the agent:

"Write a Dockerfile for this Node backend that listens on process.env.PORT (fallback 8080)."

"Copy package*.json before the rest of the code so the Docker cache works."

"Do not bake secrets into the image; the DB password comes later as an environment variable."

Common mistakes: app listens on a fixed port instead of PORT; secrets copied into the image; huge images because node_modules or .git were copied in (a .dockerignore fixes that).

Quick check

  1. What is inside a container beyond the app?
  2. What is the difference between image and container?
  3. Why is the PORT environment variable important for the cloud?
Show answers
  1. Everything needed to run: the right runtime, libraries, and settings.
  2. Image = frozen template; container = running copy of it (you can start many from one image).
  3. The cloud sets the port; if the app listens on a different one, it is unreachable.