Dlaczego Docker?
Docker pozwala uruchamiać aplikacje w lekkich, odizolowanych kontenerach. Dzięki temu masz identyczne środowisko w fazie developmentu, testów i produkcji.
Bez Dockera
Problemy, z którymi spotykasz się bez Dockera:
- różne wersje bibliotek i Pythona między developerami,
- błędy „u mnie działa",
- problemy z zależnościami i konfiguracją systemu.
Z Dockerem
Korzyści z używania Dockera:
- powtarzalne środowisko,
- prosty deployment,
- łatwe skalowanie i integracja z CI/CD.
Docker rozwiązuje problem „u mnie działa" poprzez enkapsulację całego środowiska aplikacji w kontenerze, który działa identycznie na każdym komputerze.
Konfiguracja Docker dla Django
Zacznij od stworzenia pliku Dockerfile w katalogu projektu:
Dockerfile1 2 3 4 5 6 7 8 9 10 11 12# Dockerfile FROM python:3.12-slim ENV PYTHONUNBUFFERED=1 WORKDIR /app COPY requirements.txt /app/ RUN pip install --no-cache-dir -r requirements.txt COPY . /app/ CMD ["gunicorn", "app.wsgi:application", "--bind", "0.0.0.0:8000"]
Ten obraz:
- bazuje na oficjalnym Pythonie (obraz
python:3.12-slimjest lekki i bezpieczny), - instaluje zależności z
requirements.txt, - uruchamia aplikację przez Gunicorn — produkcyjny serwer WSGI (zamiast wbudowanego serwera deweloperskiego Django).
Flaga --no-cache-dir zmniejsza rozmiar obrazu, a PYTHONUNBUFFERED=1 zapewnia, że logi są wyświetlane w czasie rzeczywistym.
docker-compose – cały ekosystem
Większość projektów Django wymaga nie tylko aplikacji, ale też bazy danych, cache'a i serwera statycznych plików. docker-compose.yml pozwala uruchomić wszystkie te usługi jednym poleceniem:
YAML1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31version: '3.9' services: web: build: . command: gunicorn app.wsgi:application --bind 0.0.0.0:8000 volumes: - .:/app ports: - "8000:8000" depends_on: - db - redis environment: - DEBUG=False - DATABASE_URL=postgres://django:secret@db:5432/django_db db: image: postgres:15 environment: POSTGRES_USER: django POSTGRES_PASSWORD: secret POSTGRES_DB: django_db volumes: - postgres_data:/var/lib/postgresql/data redis: image: redis:7 volumes: postgres_data:
Uruchom wszystko komendą:
Bash1docker-compose up --build
I gotowe — masz lokalne środowisko z PostgreSQL, Redisem i Django. Flag --build wymusza przebudowę obrazów, co jest przydatne po zmianach w Dockerfile.
Zmienna konfiguracja (dotenv i secrets)
Nie trzymaj haseł w kodzie. Zamiast tego używaj pliku .env:
INI1 2 3 4DEBUG=False SECRET_KEY=your-secret-key-here DATABASE_URL=postgres://django:secret@db:5432/django_db REDIS_URL=redis://redis:6379/0
I załaduj je w settings.py np. przez bibliotekę python-decouple:
Bash1pip install python-decouple
W settings.py:
Python1 2 3 4 5 6 7 8 9 10 11from decouple import config SECRET_KEY = config('SECRET_KEY') DEBUG = config('DEBUG', cast=bool, default=False) DATABASE_URL = config('DATABASE_URL') # Parsowanie DATABASE_URL dla Django import dj_database_url DATABASES = { 'default': dj_database_url.config(default=DATABASE_URL) }
Pamiętaj, aby dodać .env do .gitignore, aby nie commitować wrażliwych danych do repozytorium. W środowisku produkcyjnym używaj zmiennych środowiskowych serwera lub zarządzanych sekretów (np. AWS Secrets Manager, HashiCorp Vault).
Wdrożenie produkcyjne (Gunicorn + Nginx)
W środowisku produkcyjnym Django powinno być uruchamiane za pomocą Gunicorn (aplikacja) i Nginx (reverse proxy). Gunicorn obsługuje wiele workerów równolegle, co zapewnia lepszą wydajność niż serwer deweloperski Django.
Konfiguracja Nginx
Przykładowa konfiguracja Nginx (nginx.conf):
NGINX1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20server { listen 80; server_name example.com; location /static/ { alias /app/static/; } location /media/ { alias /app/media/; } location / { proxy_pass http://web:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
Docker Compose z Nginx
Dodaj nowy serwis do docker-compose.yml:
YAML1 2 3 4 5 6 7 8 9 10 11nginx: image: nginx:latest ports: - "80:80" - "443:443" volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf - ./static:/app/static - ./media:/app/media depends_on: - web
W produkcji użyj HTTPS — skonfiguruj certyfikaty SSL (np. przez Let's Encrypt i Certbot). Nginx obsługuje również kompresję, cache'owanie i ochronę przed podstawowymi atakami.
CI/CD – automatyzacja wdrażania
Ręczne wdrażanie to przeszłość. Z pomocą GitHub Actions, GitLab CI lub Jenkins możesz w pełni zautomatyzować proces wdrożeniowy. CI/CD pipeline automatycznie uruchamia testy, sprawdza jakość kodu i wdraża aplikację po każdym pushu do repozytorium.
Przykład GitHub Actions
Przykład .github/workflows/deploy.yml:
YAML1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46name: Django CI/CD on: push: branches: [ main ] jobs: test: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: 3.12 - name: Install dependencies run: | pip install -r requirements.txt - name: Run tests run: | python manage.py test - name: Run linting run: | pip install flake8 black flake8 . black --check . deploy: needs: test runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - name: Checkout uses: actions/checkout@v4 - name: Deploy with Docker run: | docker-compose -f docker-compose.prod.yml build docker-compose -f docker-compose.prod.yml up -d
Ten pipeline:
- pobiera kod z repozytorium,
- instaluje zależności,
- uruchamia testy jednostkowe,
- sprawdza jakość kodu (linting),
- automatycznie wdraża aplikację (tylko jeśli testy przeszły).
W prawdziwym projekcie dodaj też etapy dla staging environment, rollback w przypadku błędów oraz powiadomienia o statusie wdrożenia.
Dobre praktyki przy wdrażaniu Django
Przy wdrażaniu aplikacji Django warto pamiętać o kilku kluczowych zasadach:
-
Oddziel środowiska — osobne konfiguracje dla dev, staging, prod. Używaj osobnych plików
.envidocker-composedla każdego środowiska. -
Używaj
.env— nigdy nie trzymaj haseł, kluczy API i tokenów w repozytorium. Wszystkie wrażliwe dane powinny być w zmiennych środowiskowych. -
Kompresuj i serwuj statyczne pliki przez CDN — użyj
collectstatici skonfiguruj CDN (CloudFront, Cloudflare) dla lepszej wydajności. Django oferujeWhiteNoisejako prostszą alternatywę. -
Monitoruj błędy — np. przez Sentry, który automatycznie zbiera i raportuje błędy z aplikacji. To pozwala szybko reagować na problemy w produkcji.
-
Automatyzuj testy i linting przed każdym merge'em — blokuj merge, jeśli testy nie przechodzą lub kod nie spełnia standardów jakości.
-
Twórz backupy bazy danych automatycznie — użyj cron +
pg_dump(dla PostgreSQL) lub narzędzi cloud (AWS RDS automatyczne backupy). Testuj również proces przywracania z backupu. -
Używaj migracji bazodanowych — zawsze stosuj migracje w procesie wdrożenia (
python manage.py migrate). Rozważ rollback plan na wypadek problemów.
Skalowanie i dalsza automatyzacja
Kiedy aplikacja rośnie, potrzebujesz bardziej zaawansowanych narzędzi:
-
Docker Swarm lub Kubernetes — do zarządzania kontenerami w klastrze. Umożliwiają automatyczne skalowanie, load balancing i wysoką dostępność.
-
GitOps — np. ArgoCD do zarządzania infrastrukturą jako kod. Zmiany w repozytorium automatycznie synchronizują się z środowiskiem produkcyjnym.
-
Monitoring i alerty — Prometheus + Grafana do monitorowania metryk aplikacji i infrastruktury. Ustaw alerty dla krytycznych metryk (CPU, pamięć, błędy).
-
Load balancer — NGINX lub Traefik jako load balancer przed wieloma instancjami aplikacji. Zapewnia równomierne obciążenie i odporność na awarie.
-
Auto-scaling — automatyczne dodawanie nowych instancji aplikacji w zależności od obciążenia (np. Kubernetes HPA lub AWS Auto Scaling).
Podsumowanie
Docker i CI/CD to standard w nowoczesnym wdrażaniu aplikacji Django. Pozwalają zachować spójność środowisk, automatyzować testy i deployment, minimalizować błędy oraz wdrażać nowe wersje aplikacji szybciej i bezpieczniej. Zacznij od prostego Dockerfile i pipeline'u CI, a z czasem rozbuduj go o staging, testy integracyjne i automatyczne release'y. Pamiętaj, że wdrożenie to proces iteracyjny — zaczynaj od prostych rozwiązań i ulepszaj je w miarę rozwoju projektu.



