Modul 9 · 9.3
Docker compose och brandväggen
Modul 9: Docker och docker compose · Lästid: 12 minuter
Lärandemål: Efter den här lektionen kan du beskriva tjänster i en compose-fil, starta, uppdatera och stoppa dem, och du kan förklara varför Dockers publicerade portar går förbi ufw och hur du förhindrar det.
Nyckelbegrepp: compose.yaml, services, image, ports, volumes, environment, .env, restart, networks, depends_on, healthcheck, docker compose up -d, pull, logs, down, utfasad version:, Docker och ufw, DOCKER-USER, publicera på 127.0.0.1, hemligheter, docker.sock
Varför compose?
Med docker run (lektion 9.2) startar du en container med en lång rad alternativ. En riktig tillämpning består ofta av flera containrar: ett program, en databas, en omvänd proxy. Att komma ihåg de raderna och skriva in dem igen efter en omstart eller uppdatering går fel förr eller senare.
Docker Compose beskriver alla containrar i en tillämpning i en enda fil: compose.yaml. Du lägger filen i en egen mapp, till exempel /srv/status/compose.yaml, och sköter allt med docker compose. Filen är samtidigt din dokumentation: vad som körs, vilken image, vilka portar och var datan finns. Ta med mappen i din säkerhetskopia (lektion 8.1), så kan du återställa tillämpningen på en ny server på några minuter.
Insticksprogrammet heter docker compose (med mellanslag, version 2). Det gamla fristående programmet docker-compose (med bindestreck) har ersatts; du ser det fortfarande i gamla guider. Även fältet version: "3.8" överst i gamla filer är utfasat: Compose använder alltid det senaste schemat och ger bara en varning vid version:.
Läsa en compose-fil
Ett exempel med ett program och en PostgreSQL-databas:
# /srv/notities/compose.yaml
services:
app:
image: ghcr.io/example/notities:1.4
restart: unless-stopped
ports:
- "127.0.0.1:8081:8080"
environment:
DB_HOST: db
DB_USER: notities
DB_PASSWORD: ${DB_PASSWORD}
depends_on:
db:
condition: service_healthy
db:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_USER: notities
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U notities"]
interval: 10s
retries: 5
volumes:
db-data:Steg för steg:
- services: varje tjänst blir en container. Namnet (
app,db) är också det värdnamn som containrarna använder för att hitta varandra. Compose skapar ett eget nätverk för tillämpningen, såappansluter till databasen pådb:5432. - image: alltid med en versionstagg (lektion 9.1).
- restart: vad Docker gör när containern stannar eller servern startas om.
unless-stoppedstartar den igen, utom när du själv medvetet stoppade den. Utan en restart-policy kommer din tillämpning inte tillbaka efter en omstart (lektion 4.2). - ports: bara appen publicerar en port, och bara på
127.0.0.1. Databasen publicerar ingenting: appen når den via det interna nätverket. En databas medports: - "5432:5432"är ett av de vanligaste misstagen (se nedan). - environment: inställningar för programmet. Lösenordet står inte där i klartext, utan som
${DB_PASSWORD}. - volumes: den namngivna volymen
db-databehåller databasen när containern byts ut. - depends_on med healthcheck: appen startar först när databasen verkligen är redo, inte bara startad.
Hemligheter i en .env-fil
Compose läser variabler som ${DB_PASSWORD} från en fil .env i samma mapp:
# /srv/notities/.env
DB_PASSWORD=Kies-hier-een-lang-willekeurig-wachtwoordanna@web1:/srv/notities$ sudo chmod 600 .envDå står lösenordet inte i compose-filen, som du kanske sparar i Git eller klistrar in på ett forum när du ber om hjälp. Lägg .env i .gitignore. Skapa lösenordet med en lösenordshanterare eller med openssl rand -base64 24.
Daglig användning
Alla kommandon kör du i mappen med compose-filen:
anna@web1:/srv/notities$ sudo docker compose config # kontrollera filen, variabler ifyllda
anna@web1:/srv/notities$ sudo docker compose up -d # starta allt (eller uppdatera enligt filen)
anna@web1:/srv/notities$ sudo docker compose ps # status per tjänst
anna@web1:/srv/notities$ sudo docker compose logs -f app
anna@web1:/srv/notities$ sudo docker compose pull # hämta nya images
anna@web1:/srv/notities$ sudo docker compose up -d # ersätt containrarna med de nya images
anna@web1:/srv/notities$ sudo docker compose down # stoppa och ta bort containrardown låter dina volymer vara kvar. down -v tar även bort tillämpningens volymer, och därmed din databas. Skriv det bara om du verkligen vill börja om från början.
docker compose config motsvarar nginx -t och sshd -t: det visar hur Compose tolkar din fil, med alla variabler ifyllda, innan du startar något. Klistra inte in utdata någonstans, eftersom lösenorden står i den.
Docker går förbi ufw
Nu kommer den viktigaste säkerhetspunkten i den här modulen. I lektion 5.2 ställde du in ufw på "neka allt utom SSH, 80 och 443". Du skulle då förvänta dig att en container med ports: - "5432:5432" inte går att nå. Så är det inte.
Docker-dokumentationen säger det rakt ut: Docker och ufw använder brandväggsregler på sätt som inte går ihop. När du publicerar en port lägger Docker själv in regler i kärnans brandvägg. De reglerna skickar trafiken vidare till containern (adressöversättning, DNAT) innan ufw:s regler tillämpas. Paketet går alltså runt ufw. ufw status visar inget särskilt, samtidigt som porten kan nås från hela internet. Samma sak gäller för firewalld.
Dessutom publicerar Docker utan adress på 0.0.0.0 och [::], alltså på både IPv4 och IPv6 (lektion 9.1).
Tre sätt att göra rätt, från enkelt till avancerat:
- Publicera inget som inte behöver vara publikt. Databaser, cacheminnen och interna tjänster får ingen
ports:. Containrar i samma compose-tillämpning når varandra via det interna nätverket. - Publicera på loopback.
"127.0.0.1:8081:8080". Då kommer bara servern själv åt porten, och du sätter en omvänd proxy (nginx eller Caddy, modul 7) framför som lyssnar på 443. Docker kan också få detta som standard: en daemon-inställning gör att alla publicerade portar utan adress hamnar på127.0.0.1. - Regler i kedjan DOCKER-USER. Docker skapar en tom kedja
DOCKER-USERsom gås igenom före dess egna regler. Där kan du lägga egna regler, till exempel "bara den här IP-adressen får nå de publicerade portarna". Det är avancerat arbete med iptables eller nftables och lätt att göra fel. För de flesta små servrar räcker 1 och 2.
Kontrollera alltid utifrån, som i lektion 5.1: nc -vz -w 3 <ip> 5432 från din laptop, eller kurskontrollen i uppgift Z5.1 och Z10.4.
Två saker till som du inte gör
- Montera inte
/var/run/docker.socki en container, om du inte vet exakt varför. En container med åtkomst till Docker-socketen kan själv starta containrar, även en med hela värdens disk (lektion 9.2). Vissa hjälpprogram (dashboards, automatiska uppdaterare) ber om det; i praktiken ger du då programmet root. - Ingen
privileged: trueellernetwork_mode: hostbara för att en guide säger det. Båda tar till stor del bort containerns isolering. Använd dem bara när skaparen förklarar varför det behövs.
Sammanfattning
- En compose-fil (
compose.yaml) beskriver alla containrar i en tillämpning; den är samtidigt dokumentation och hör hemma i din säkerhetskopia. - Använd versionstaggar, en restart-policy, namngivna volymer, en healthcheck där det går och hemligheter i en
.envmed rättigheterna 600. docker compose config,up -d,ps,logs,pull,down;down -vtar även bort volymerna.- Publicerade portar går förbi ufw och firewalld. Publicera bara det som måste vara publikt, och annars på
127.0.0.1med en omvänd proxy framför. - Ingen docker.sock,
privilegedellernetwork_mode: hostutan goda skäl.
Quiz
Uppgift
Uppgift Z9.3: Granska en compose-fil. I exempelfilen compose-nakijken.txt finns (som textfil) compose-filen för en liten webbutik med en app, en databas, en cache och ett administrationsverktyg. Den innehåller sex fel som har gåtts igenom i den här lektionen eller i lektion 9.1 och 9.2. Ange för varje numrerat radblock om det är rätt eller fel, och välj rätt rättelse för varje fel. Programmet jämför med den fasta facit. Har du en egen compose-fil, gå sedan igenom den med samma punkter.
Läs mer
- Docker-dokumentationen, How Compose works (compose.yaml): https://docs.docker.com/compose/intro/compose-application-model/
- Docker-dokumentationen, Version and name top-level elements: https://docs.docker.com/reference/compose-file/version-and-name/
- Docker-dokumentationen, Packet filtering and firewalls (Docker and ufw): https://docs.docker.com/engine/network/packet-filtering-firewalls/
- Docker-dokumentationen, Port publishing and mapping: https://docs.docker.com/engine/network/port-publishing/
- Docker-dokumentationen, Interpolation (variabler och .env): https://docs.docker.com/reference/compose-file/interpolation/
- VPS: från första inloggningen till en säker server 6.2: Din arbetsmapp med compose.yaml, .env och Caddy
- VPS: från första inloggningen till en säker server 6.3: Docker och brandväggen: publicera portar säkert
