Hoppa till innehållet

Cookieinställningar

Välj vilka typer av cookies du tillåter. Du kan alltid ändra ditt val via Cookieinställningar längst ned på varje sida. Integritetspolicy

Nödvändiga

Alltid på

Behövs för att logga in, spara din varukorg och komma ihåg dina val. De är alltid på.

Vilka cookies?
  • weboke_sessie, weboke_klant, weboke_remember: din session och att du förblir inloggad
  • weboke_basket: din varukorg
  • wkBtwIncl: visa priser med eller utan moms
  • wok_cookies: ditt cookieval, 12 månader

Mäter vilken annons som leder till ett besök eller en beställning, så att vi inte betalar för annonser som inte ger något.

Vilka cookies?
  • Google Ads via Google Tag Manager (_gcl_au, _gcl_aw), upp till 90 dagar
  • OpenAI Ads, annonser i ChatGPT
  • wok_aff: via vilken partner du kom till oss (affiliateprogram), 60 dagar

4,6

Land och språk

Varje land har en egen webbplats med landets priser och moms.

Visa

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å app ansluter 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-stopped startar 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 med ports: - "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-data behå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-wachtwoord
anna@web1:/srv/notities$ sudo chmod 600 .env

Då 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 containrar

down 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:

  1. 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.
  2. 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.
  3. Regler i kedjan DOCKER-USER. Docker skapar en tom kedja DOCKER-USER som 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.sock i 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: true eller network_mode: host bara 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 .env med rättigheterna 600.
  • docker compose config, up -d, ps, logs, pull, down; down -v tar ä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.1 med en omvänd proxy framför.
  • Ingen docker.sock, privileged eller network_mode: host utan goda skäl.

Quiz

1. ufw är inställt på "neka allt utom 22, 80 och 443". Din compose-fil har ports: - "5432:5432" vid databasen. Kan databasen nås från internet?



2. Hur når containern app databasen i samma compose-tillämpning, om databasen inte publicerar någon port?



3. Efter en omstart av servern körs dina containrar inte längre. Vad saknas troligen i compose-filen?



4. Vad är skillnaden mellan docker compose down och docker compose down -v?



5. Ett dashboardprogram ber i sin guide om - /var/run/docker.sock:/var/run/docker.sock. Vad betyder det för säkerheten?



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.

Uppgift Z9.3: Granska en compose-fil

Fil till den här uppgiften: compose-nakijken.txt





















Det du fyller i och det vi hittar sparar vi inte. Din webbläsare kommer ihåg dina svar och om du klarade uppgiften. Är du inloggad sparar vi bara att du klarade uppgiften (nästan) i Mina kurser; där kan du också ta bort det.

Läs mer

Ett ögonblick…

Ställ in dina domäner

Ställ in namnservrar, koppling till ditt webbhotell och vem som blir innehavare för varje domän.

Hämtar dina domäner…