Premessa

Questo tutorial mira a guidare uno sviluppatore principiante nella configurazione di un ambiente di sviluppo Django containerizzato, partendo dall'installazione iniziale fino alla configurazione completa.

Prerequisiti di Sistema

1. Installazioni Preliminari

Prima di iniziare, assicurati di aver installato i seguenti strumenti:

Per Ubuntu/Debian:

# Aggiornamenti di sistema
sudo apt update && sudo apt upgrade -y

# Installazioni essenziali
sudo apt install -y \
    git \
    curl \
    wget \
    software-properties-common \
    apt-transport-https \
    ca-certificates \
    gnupg \
    lsb-release \
    postgresql-client \
    python3-pip \
    python3-venv \
    build-essential \
    libpq-dev

Per altre distribuzioni Linux, adatta i comandi:

  • Fedora/CentOS: dnf o yum
  • Arch Linux: pacman

2. Installazione di Docker

# Installazione di Docker
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker compose-plugin

# Aggiungi il tuo utente al gruppo docker
sudo usermod -aG docker $USER

# Riavvia per applicare le modifiche
sudo systemctl restart docker

3. Verifiche

# Verifica delle installazioni
docker --version
docker compose --version
python3 --version
psql --version

Struttura del Progetto Django Dockerizzato

Creazione della Struttura del Progetto

# Creare la directory del progetto
mkdir progetto_django_docker
cd progetto_django_docker

# Struttura delle directory
mkdir -p app/mio_progetto
touch app/Dockerfile
touch app/requirements.txt
touch app/entrypoint.sh
touch docker compose.yml
touch .env

1. File requirements.txt

# app/requirements.txt
Django==4.2.7
psycopg2-binary==2.9.9
gunicorn==21.2.0
python-dotenv==1.0.0

2. Dockerfile

# app/Dockerfile
FROM python:3.11-slim

# Metadati
LABEL maintainer="Tuo Nome <tua.email@esempio.com>"

# Variabili d'ambiente
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV PYTHONPATH=/app

# Directory di lavoro
WORKDIR /app

# Installare le dipendenze di sistema
RUN apt-get update && apt-get install -y \
    postgresql-client \
    build-essential \
    libpq-dev \
    && rm -rf /var/lib/apt/lists/*

# Copiare e installare i requirements
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copiare il resto del progetto
COPY . .

# Dare i permessi allo script di entrypoint
RUN chmod +x /app/entrypoint.sh

# Punto di ingresso
ENTRYPOINT ["/app/entrypoint.sh"]

Script entrypoint.sh: Comprendere l'Attesa del Database

Perché Attendere il Database?

#!/bin/bash
# Attesa della disponibilità del database
echo "In attesa del database..."
while ! nc -z db 5432; do
  sleep 1
done
echo "Database pronto!"

Contesto Tecnico

All'avvio di un'applicazione containerizzata, non tutti i servizi partono istantaneamente. Il database PostgreSQL può richiedere alcuni secondi per essere completamente operativo.

Problematica Concreta

Se la tua applicazione Django tenta di connettersi al database prima che sia pronto, incontrerai un errore di connessione. Questo potrebbe bloccare l'avvio completo della tua applicazione.

Come Funziona?

  • nc -z db 5432: Verifica se la porta 5432 (porta PostgreSQL) è accessibile
  • while: Ciclo fino a quando la connessione è possibile
  • sleep 1: Pausa di un secondo tra ogni tentativo

Codice Completo con Migrazioni

#!/bin/bash
# Attesa del database
echo "In attesa del database..."
while ! nc -z db 5432; do
  sleep 1
done
echo "Database pronto!"

# Applicare le migrazioni Django
python manage.py migrate

# Avviare il server web
exec gunicorn --bind 0.0.0.0:8000 mio_progetto.wsgi:application

Docker Compose: Comprendere la Configurazione

Struttura del File docker compose.yml

version: '3.8'  # Versione della sintassi Docker Compose

services:
  # Servizio Web (Applicazione Django)
  web:
    build: 
      context: ./app
      dockerfile: Dockerfile
    volumes:
      - ./app:/app  # Sincronizzazione del codice sorgente
    ports:
      - "8000:8000"  # Mappatura delle porte
    env_file:
      - .env  # File di ambiente
    depends_on:
      - db  # Dipendenza dal servizio database
    networks:
      - dev_network  # Rete personalizzata

  # Servizio Database
  db:
    image: postgres:15-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data  # Persistenza dei dati
    environment:
      - POSTGRES_DB=progetto_db
      - POSTGRES_USER=progetto_user
      - POSTGRES_PASSWORD=password_segreta
    ports:
      - "5432:5432"  # Esposizione della porta PostgreSQL
    networks:
      - dev_network

# Volumi e Reti
volumes:
  postgres_data:  # Volume per i dati PostgreSQL

networks:
  dev_network:
    driver: bridge  # Tipo di rete

Spiegazioni Dettagliate

1. Reti (Networks)

  • dev_network: Una rete personalizzata che permette la comunicazione tra container
  • driver: bridge: Crea una rete isolata sull'host

2. Porte: Interna vs Esterna

  • Formato: "8000:8000"
  • Prima porta: Porta esterna (accessibile dall'host)
  • Seconda porta: Porta interna del container

3. Dipendenze tra Servizi

  • depends_on: - db significa che il servizio web si avvierà dopo il servizio database
  • Garantisce un ordine di avvio, non una garanzia di "pronto all'uso"

Accesso al Terminale dei Container

# Accedere al terminale di un servizio specifico
docker compose exec web bash
docker compose exec db bash

Punti Importanti

  • Funziona SOLO quando i container sono in esecuzione
  • Permette di effettuare azioni direttamente nel container
  • Equivalente a un accesso SSH per i container

Consigli Aggiuntivi

  • Le versioni recenti di Docker rilevano automaticamente la versione di Compose
  • Specificare sempre un contesto e un Dockerfile per maggiore chiarezza
  • Utilizzare variabili d'ambiente per configurazioni sensibili

Comandi Utili

# Avviare i servizi
docker compose up

# Avviare in modalità distaccata
docker compose up -d

# Fermare i servizi
docker compose down

# Vedere i log
docker compose logs

# Eseguire un comando in un servizio
docker compose run web python manage.py createsuperuser

Perché Questi Dettagli Sono Importanti?

  • Comprensione approfondita dei meccanismi
  • Debug più efficiente
  • Configurazione più flessibile
  • Migliore padronanza dell'ambiente di sviluppo

File .env

# Configurazione Django
DEBUG=1
SECRET_KEY=la_tua_chiave_segreta_ultra_sicura
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1

# Configurazione Database
DB_NAME=progetto_db
DB_USER=progetto_user
DB_PASSWORD=password_segreta
DB_HOST=db
DB_PORT=5432

Creazione del Progetto Django

Inizializzazione del Progetto

# Creare e inizializzare il progetto Django
docker compose run --rm web django-admin startproject mio_progetto .

# Configurare settings.py per il database
# Modificare la sezione DATABASES:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.getenv('DB_NAME', 'progetto_db'),
        'USER': os.getenv('DB_USER', 'progetto_user'),
        'PASSWORD': os.getenv('DB_PASSWORD', 'password_segreta'),
        'HOST': os.getenv('DB_HOST', 'db'),
        'PORT': os.getenv('DB_PORT', '5432'),
    }
}

Avvio e Utilizzo

Comandi Essenziali

# Costruire e avviare i container
docker compose up --build

# Fermare i container
docker compose down

# Creare una nuova applicazione
docker compose run --rm web python manage.py startapp mia_nuova_app

# Creare migrazioni
docker compose run --rm web python manage.py makemigrations

# Applicare le migrazioni
docker compose run --rm web python manage.py migrate

Consigli e Buone Pratiche

  1. Sicurezza:
    • Non committare mai il file .env
    • Utilizzare un .env.example con valori fittizi
    • Generare chiavi segrete robuste
  2. Prestazioni:
    • Utilizzare volumi per lo sviluppo
    • Ottimizzare le immagini Docker
    • Gestire le dipendenze con cautela
  3. Sviluppo:
    • Utilizzare docker compose.override.yml per configurazioni specifiche
    • Impostare un workflow git adatto

Risoluzione dei Problemi

  • Verificare i log: docker compose logs
  • Verificare lo stato dei container: docker compose ps
  • Connessione a un container: docker compose exec web bash

Evoluzioni Possibili

  • Aggiungere un container per Redis/Celery
  • Configurare un proxy Nginx
  • Configurare un volume per i file statici