Docker pakker din app + alt den skal bruge (biblioteker, runtime) i en container, der kører ens på enhver maskine. Kræver Docker Desktop installeret. Hvert eksempel står alene.
Et image er en opskrift (som en klasse). En container er en kørende kopi (som et objekt). Du bygger ét image og kan starte mange containere ud fra det.
# Tjek at Docker virker
docker --version
docker run hello-world
# Hent nginx-webserver fra Docker Hub
docker pull nginx
# Start den: -p port-mapping, -d baggrund
docker run -d -p 8080:80 --name web nginx
# Åbn http://localhost:8080 i browseren
# Se hvad der kører
docker ps
# Stop og fjern
docker stop web
docker rm web
-p 8080:80 betyder: "min maskines port 8080 → containerens port 80". -d = kør i baggrunden. --name giver containeren et navn, så du ikke skal huske det tilfældige id.
docker ps # kørende containere
docker ps -a # også stoppede
docker images # hentede images
docker stop navn # stop container
docker start navn # start igen
docker rm navn # slet container
docker rmi nginx # slet image
# Ryd ALT ubrugt op (pas på!)
docker system prune
docker system prune sletter alle stoppede containere og ubrugte images – god til at frigøre diskplads.# Dockerfile (ingen filendelse)
FROM node:20-alpine # basis-image
WORKDIR /app # arbejdsmappe i containeren
COPY package*.json ./ # kopier pakkefiler
RUN npm install # installer afhængigheder
COPY . . # kopier resten af koden
EXPOSE 3000 # dokumenter port
CMD ["node", "app.js"] # start-kommando
# Byg image ud fra Dockerfile
docker build -t min-app .
# Kør dit eget image
docker run -d -p 3000:3000 min-app
FROM vælger fundamentet (fx node, python, mcr.microsoft.com/dotnet). COPY flytter filer ind. RUN kører kommandoer ved byg. CMD er hvad der startes. Rækkefølgen udnytter cache: pakkefiler først, kode til sidst.
# .dockerignore (samme idé som .gitignore)
node_modules
bin
obj
.git
*.log
.env
Uden .dockerignore kopierer COPY . . alt – også build-output og hemmeligheder – ind i imaget. Det gør det stort og usikkert.
# Se hvad containeren skriver
docker logs web
docker logs -f web # følg live (Ctrl+C stop)
# Åbn en terminal INDE i containeren
docker exec -it web bash
# (eller "sh" hvis bash ikke findes)
# Kopier filer ind/ud
docker cp web:/app/fil.txt ./
docker cp fil.txt web:/app/
# Container-data forsvinder ved sletning!
# Volume = mappe der overlever:
docker run -d -p 5432:5432 \\
-v min-data:/var/lib/postgresql/data \\
-e POSTGRES_PASSWORD=hemmelig \\
postgres:16
# Se og slet volumes
docker volume ls
docker volume rm min-data
-v monterer en volume (eller en lokal mappe) ind i containeren. Databaser skal altid have en volume, ellers er data væk når containeren slettes. -e sætter miljøvariable.
# compose.yaml
services:
web:
build: .
ports:
- "3000:3000"
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: hemmelig
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:
docker compose up -d # start alt
docker compose down # stop og fjern alt
docker compose logs -f # følg logs for alle
Compose starter hele stakken (app + database) med én kommando. Containerne kan hinanden ved navn: appen forbinder til databasen som db:5432.
docker run -d -p 8080:80 imgstart container i baggrunden
docker ps / ps -akørende / alle containere
docker stop / start / rmstyr container
docker build -t navn .byg image fra Dockerfile
docker logs -f navnfølg container-logs live
docker exec -it navn shterminal inde i container
docker system pruneryd op (frigør plads)
docker compose up -dstart hele stakken
docker pull navnhent image fra Docker Hub
docker run uden -p → porten er ikke tilgængelig fra din maskine..dockerignore → node_modules kopieres med, og build bliver enormt langsomt.-p 8081:80.docker-kommandoer virker. Tjek hval-ikonet i systembakken.docker logs navn viser næsten altid hvorfor en container stoppede.