Vai al contenuto

Impostazioni cookie

Scelga per ogni tipo quali cookie consente. Può modificare la sua scelta in qualsiasi momento tramite Impostazioni cookie in fondo a ogni pagina. Informativa sulla privacy

Necessari

Sempre attivi

Servono per accedere, conservare il carrello e ricordare le sue scelte. Sono sempre attivi.

Quali cookie?
  • weboke_sessie, weboke_klant, weboke_remember: la sua sessione e la permanenza dell'accesso
  • weboke_basket: il suo carrello
  • wkBtwIncl: visualizzazione dei prezzi con o senza IVA
  • wok_cookies: la sua scelta sui cookie, 12 mesi

Misurano quale annuncio porta a una visita o a un ordine, così non paghiamo annunci che non funzionano.

Quali cookie?
  • Google Ads tramite Google Tag Manager (_gcl_au, _gcl_aw), fino a 90 giorni
  • OpenAI Ads, annunci in ChatGPT
  • wok_aff: tramite quale partner è arrivato da noi (programma di affiliazione), 60 giorni

4,6

Paese e lingua

Ogni paese ha il suo sito, con i prezzi e l'IVA di quel paese.

Vedi

Docker compose e il firewall

Modulo 9: Docker e docker compose · Tempo di lettura: 12 minuti

Obiettivo della lezione: Dopo questa lezione Lei sarà in grado di descrivere servizi in un file compose, di avviarli, aggiornarli e fermarli, e saprà spiegare perché le porte pubblicate da Docker aggirano ufw e come evitarlo.

Concetti chiave: compose.yaml, services, image, ports, volumes, environment, .env, restart, networks, depends_on, healthcheck, docker compose up -d, pull, logs, down, version: obsoleto, Docker e ufw, DOCKER-USER, pubblicazione su 127.0.0.1, segreti, docker.sock

Perché compose?

Con docker run (lezione 9.2) Lei avvia un solo container con una lunga riga di opzioni. Un'applicazione reale è spesso composta da più container: un programma, un database, un reverse proxy. Ricordare quelle righe e digitarle di nuovo dopo un riavvio o un aggiornamento prima o poi porta a un errore.

Docker Compose descrive tutti i container di un'applicazione in un unico file: compose.yaml. Lei mette quel file in una cartella dedicata, per esempio /srv/status/compose.yaml, e gestisce tutto con docker compose. Il file è al tempo stesso la Sua documentazione: che cosa è in esecuzione, quale image, quali porte, dove si trovano i dati. Inserisca quella cartella nel Suo backup (lezione 8.1) e potrà ripristinare l'applicazione su un nuovo server in pochi minuti.

Il plug-in si chiama docker compose (con uno spazio, versione 2). Il vecchio programma separato docker-compose (con il trattino) è stato sostituito; lo si trova ancora nelle vecchie guide. Anche il campo version: "3.8" in cima ai file più vecchi è obsoleto: Compose usa sempre lo schema più recente e con version: mostra soltanto un avviso.

Leggere un file compose

Un esempio con un programma e un database PostgreSQL:

# /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:

Passo per passo:

  • services: ogni servizio diventa un container. Il nome (app, db) è anche il nome host con cui i container si trovano a vicenda. Compose crea una rete propria per l'applicazione, quindi app si collega al database su db:5432.
  • image: sempre con un tag di versione (lezione 9.1).
  • restart: che cosa fa Docker quando il container si ferma o il server si riavvia. unless-stopped lo riavvia, a meno che Lei non lo abbia fermato di proposito. Senza una policy di restart la Sua applicazione non torna attiva dopo un riavvio (lezione 4.2).
  • ports: solo l'app pubblica una porta, e soltanto su 127.0.0.1. Il database non pubblica nulla: l'app lo raggiunge tramite la rete interna. Un database con ports: - "5432:5432" è uno degli errori più frequenti (vedere più avanti).
  • environment: impostazioni per il programma. La password non è scritta in chiaro, ma come ${DB_PASSWORD}.
  • volumes: il volume con nome db-data conserva il database quando il container viene sostituito.
  • depends_on con healthcheck: l'app parte solo quando il database è davvero pronto, non semplicemente avviato.

Segreti in un file .env

Compose legge variabili come ${DB_PASSWORD} da un file .env nella stessa cartella:

# /srv/notities/.env
DB_PASSWORD=Kies-hier-een-lang-willekeurig-wachtwoord
anna@web1:/srv/notities$ sudo chmod 600 .env

In questo modo la password non compare nel file compose che magari conserva in Git o incolla in un forum per chiedere aiuto. Aggiunga .env a .gitignore. Generi la password con un gestore di password oppure con openssl rand -base64 24.

Uso quotidiano

Tutti i comandi vanno eseguiti nella cartella che contiene il file compose:

anna@web1:/srv/notities$ sudo docker compose config     # verificare il file, variabili compilate
anna@web1:/srv/notities$ sudo docker compose up -d      # avviare tutto (o aggiornare in base al file)
anna@web1:/srv/notities$ sudo docker compose ps         # stato per servizio
anna@web1:/srv/notities$ sudo docker compose logs -f app
anna@web1:/srv/notities$ sudo docker compose pull       # scaricare le nuove immagini
anna@web1:/srv/notities$ sudo docker compose up -d      # sostituire i container con le nuove immagini
anna@web1:/srv/notities$ sudo docker compose down       # arrestare e rimuovere i container

down lascia intatti i volumi. down -v rimuove anche i volumi dell'applicazione, e con essi il Suo database. Lo digiti solo se vuole davvero ricominciare da zero.

docker compose config è l'equivalente di nginx -t e sshd -t: mostra come Compose interpreta il Suo file, con tutte le variabili sostituite, prima che Lei avvii qualcosa. Faccia attenzione a non incollare l'output da nessuna parte, perché contiene le password.

Docker aggira ufw

Arriviamo al punto di sicurezza più importante di questo modulo. Nella lezione 5.2 Lei ha impostato ufw su "rifiuta tutto, tranne SSH, 80 e 443". Ci si aspetterebbe che un container con ports: - "5432:5432" non sia quindi raggiungibile. Non è così.

La documentazione di Docker lo dice esplicitamente: Docker e ufw usano le regole del firewall in modi tra loro incompatibili. Quando Lei pubblica una porta, Docker inserisce direttamente delle regole nel firewall del kernel. Queste regole inoltrano il traffico al container (traduzione degli indirizzi, DNAT) prima che vengano applicate le regole di ufw. Il pacchetto quindi aggira ufw. ufw status non mostra nulla di particolare, mentre la porta è raggiungibile da tutto internet. Lo stesso vale per firewalld.

Inoltre, senza un indirizzo, Docker pubblica su 0.0.0.0 e [::], quindi sia su IPv4 sia su IPv6 (lezione 9.1).

Tre modi per farlo correttamente, dal più semplice al più complesso:

  1. Non pubblicare nulla che non debba essere pubblico. Database, cache e servizi interni non ricevono ports:. I container della stessa applicazione compose si raggiungono tramite la rete interna.
  2. Pubblicare su loopback. "127.0.0.1:8081:8080". Così solo il server stesso può accedervi, e Lei mette davanti un reverse proxy (nginx o Caddy, modulo 7) in ascolto sulla 443. Docker può anche avere questo comportamento come predefinito: un'impostazione del daemon fa sì che tutte le porte pubblicate senza indirizzo finiscano su 127.0.0.1.
  3. Regole nella catena DOCKER-USER. Docker crea una catena vuota DOCKER-USER che viene attraversata prima delle sue regole. Lì Lei può inserire regole proprie, per esempio "solo questo indirizzo IP può accedere alle porte pubblicate". È un lavoro avanzato con iptables o nftables, e facile da sbagliare. Per la maggior parte dei piccoli server bastano i punti 1 e 2.

Verifichi sempre dall'esterno, come nella lezione 5.1: nc -vz -w 3 <ip> 5432 dal Suo portatile, oppure con il controllo del corso degli esercizi Z5.1 e Z10.4.

Altre due cose da non fare

  • Non montare /var/run/docker.sock in un container, a meno che non sappia esattamente perché. Un container con accesso al socket di Docker può avviare a sua volta dei container, anche uno con l'intero disco dell'host (lezione 9.2). Alcuni strumenti (dashboard, aggiornatori automatici) lo richiedono; in pratica significa dare a quel programma i privilegi di root.
  • Non usare privileged: true o network_mode: host solo perché lo dice una guida. Entrambi eliminano in gran parte l'isolamento del container. Li usi solo se lo sviluppatore spiega perché sono necessari.

Riepilogo

  • Un file compose (compose.yaml) descrive tutti i container di un'applicazione; è al tempo stesso documentazione e va incluso nel Suo backup.
  • Usi tag di versione, una policy di restart, volumi con nome, un healthcheck dove possibile, e i segreti in un .env con permessi 600.
  • docker compose config, up -d, ps, logs, pull, down; down -v rimuove anche i volumi.
  • Le porte pubblicate aggirano ufw e firewalld. Pubblichi solo ciò che deve essere pubblico, altrimenti su 127.0.0.1 con un reverse proxy davanti.
  • Niente docker.sock, privileged o network_mode: host senza un buon motivo.

Quiz

1. ufw è impostato su "rifiuta tutto tranne 22, 80 e 443". Il Suo file compose ha ports: - "5432:5432" nel database. Il database è raggiungibile da internet?



2. Come raggiunge il container app il database nella stessa applicazione compose, se il database non pubblica alcuna porta?



3. Dopo un riavvio del server i Suoi container non sono più in esecuzione. Che cosa manca probabilmente nel file compose?



4. Qual è la differenza tra docker compose down e docker compose down -v?



5. Un programma di dashboard richiede nella sua guida - /var/run/docker.sock:/var/run/docker.sock. Che cosa significa per la sicurezza?



Esercizio

Esercizio Z9.3: Verificare un file compose. Nel file di esempio compose-nakijken.txt si trova (come file di testo) il file compose di un piccolo negozio online con un'app, un database, una cache e uno strumento di amministrazione. Contiene sei errori trattati in questa lezione o nelle lezioni 9.1 e 9.2. Indichi per ogni blocco di righe numerato se è corretto o sbagliato, e per ogni errore scelga la correzione giusta. Il programma confronta le risposte con la chiave fissa. Se ha un Suo file compose, lo controlli poi secondo gli stessi punti.

Esercizio Z9.3: Verificare un file compose

File relativo a questo esercizio: compose-nakijken.txt





















Quello che inserisce e quello che rileviamo non vengono salvati. Il Suo browser ricorda le Sue risposte e se ha superato l'esercizio. Se ha effettuato l'accesso, conserviamo in I miei corsi solo il fatto che l'esercizio era (quasi) corretto; anche lì può eliminarlo.

Per approfondire

Un momento…

Configuri i suoi domini

Per ogni dominio imposti i nameserver, il collegamento al suo hosting e chi ne diventa l'intestatario.

Caricamento dei suoi domini…