Optymalizacja i bezpieczeństwo w Dockerze


1. Wprowadzenie

Docker jest niezwykle wydajnym narzędziem do tworzenia, uruchamiania i skalowania aplikacji, ale bez odpowiedniej optymalizacji i zabezpieczenia może prowadzić do:

  • dużych, powolnych obrazów kontenerów,
  • podatności bezpieczeństwa,
  • nadmiernego zużycia zasobów,
  • ryzyka wycieku danych lub dostępu do hosta.

W tej lekcji omówimy kluczowe zasady optymalizacji obrazów Dockera oraz praktyki bezpieczeństwa, które pozwolą tworzyć lekkie, szybkie i bezpieczne kontenery gotowe do pracy w środowisku produkcyjnym.


2. Minimalizacja rozmiaru obrazu (Multi-stage Build)

2.1 Dlaczego rozmiar obrazu ma znaczenie

Każdy obraz Dockera składa się z warstw (layers). Im więcej warstw i większe pliki w środku, tym:

  • dłuższy czas budowania i pobierania obrazu,
  • większe obciążenie sieci,
  • wolniejsze wdrożenia,
  • większe ryzyko ujawnienia niepotrzebnych plików (np. kluczy, zależności dev).

Dlatego minimalizacja rozmiaru obrazu to podstawowy krok w optymalizacji środowiska Dockerowego.


2.2 Wybór lekkiej bazy obrazu

Zawsze zaczynaj od najmniejszego możliwego obrazu bazowego. Przykłady:

Język / środowisko Standardowy obraz Lekka alternatywa
Python python:3.10 python:3.10-slim lub python:3.10-alpine
Node.js node:20 node:20-alpine
Java openjdk:17 eclipse-temurin:17-jre-alpine

Obrazy z przyrostkiem „-slim” lub „-alpine” zawierają tylko minimalny zestaw bibliotek.


2.3 Multi-stage Build – budowanie wieloetapowe

Multi-stage build pozwala rozdzielić proces budowania aplikacji (kompilację, instalację zależności) od jej końcowego uruchomienia. Dzięki temu końcowy obraz zawiera tylko to, co niezbędne do działania aplikacji.


Przykład: aplikacja Node.js

Co zyskaliśmy:

  • końcowy obraz jest znacznie mniejszy (tylko kod + zależności produkcyjne),
  • nie zawiera narzędzi do budowania, testów, czy npm cache,
  • mniejsza powierzchnia ataku i szybsze wdrożenie.

Przykład: aplikacja Python (Flask)

Zalety:

  • końcowy obraz jest bardzo lekki (ok. 100–150 MB zamiast 500 MB),
  • brak tymczasowych plików builda,
  • łatwiejsza dystrybucja i utrzymanie.

2.4 Usuwanie niepotrzebnych plików

Po instalacji zależności warto usuwać cache i pliki tymczasowe:


3. Ustawianie uprawnień i użytkowników w kontenerze

3.1 Problem: kontener jako root

Domyślnie większość obrazów Dockera uruchamia procesy jako root (administrator). To niebezpieczne, bo jeśli ktoś przejmie kontrolę nad kontenerem, może uzyskać dostęp do systemu hosta.


3.2 Rozwiązanie: użytkownicy nieuprzywilejowani

Twórz dedykowanego użytkownika w kontenerze:

Od tego momentu wszystkie polecenia w kontenerze będą wykonywane przez appuser, a nie root.


3.3 Ustawianie właściciela plików

Przed przełączeniem na użytkownika należy nadać mu prawa do katalogu aplikacji:

To zapobiega błędom typu Permission denied przy uruchamianiu aplikacji.


3.4 Dodatkowe zabezpieczenia

  • Ogranicz dostęp do sieci i portów, których aplikacja nie potrzebuje.
  • Używaj read-only filesystem, jeśli aplikacja nie zapisuje danych:
  • Ustaw ograniczenia zasobów (CPU, pamięć) w docker-compose.yml:

4. Narzędzia do skanowania bezpieczeństwa

Kontenery często zawierają zależności i biblioteki z zewnętrznych źródeł, co zwiększa ryzyko podatności. Dlatego warto regularnie skanować obrazy i zależności pod kątem znanych błędów bezpieczeństwa (CVEs).


4.1 Trivy (Aqua Security)

Trivy to popularne narzędzie open-source do skanowania obrazów Dockerowych, plików konfiguracyjnych i kodu źródłowego.


Instalacja:

lub na macOS:

Skanowanie obrazu:

Wynik zawiera listę podatnych pakietów i ich poziom ryzyka:

Skanowanie katalogu projektu:

Wykrywa błędy w plikach requirements.txt, package.json, a także w Dockerfile.


4.2 Snyk

Snyk to komercyjne (z darmową wersją) narzędzie do skanowania kodu, kontenerów i zależności.


Instalacja:
Skanowanie obrazu Dockerowego:
Integracje:
  • działa z GitHub Actions, GitLab CI, Jenkins,
  • umożliwia automatyczne naprawianie podatnych wersji zależności,
  • wykrywa błędy konfiguracyjne w docker-compose.yml i Dockerfile.

4.3 Inne narzędzia warte uwagi

Narzędzie Opis
Grype Skaner open-source od Anchore; szybki, łatwy w CI/CD.
Clair Zaawansowany skaner API; integruje się z rejestrami obrazów.
Dockle Analizuje najlepsze praktyki bezpieczeństwa w Dockerfile.

5. Dobre praktyki bezpieczeństwa w Dockerze

  1. Zawsze aktualizuj obrazy bazowe – używaj konkretnych wersji (node:20.10.1 zamiast latest).
  2. Używaj nieuprzywilejowanych użytkowników (USER appuser).
  3. Minimalizuj zawartość obrazu – usuń narzędzia developerskie, cache i testy.
  4. Skanuj obrazy regularnie (Trivy, Snyk).
  5. Ustal polityki bezpieczeństwa w CI/CD – blokuj build przy krytycznych CVE.
  6. Używaj .env do przechowywania sekretów – nigdy nie umieszczaj haseł w Dockerfile.
  7. Korzystaj z signed images (Docker Content Trust).
  8. Ogranicz dostęp sieciowy – nie otwieraj niepotrzebnych portów.
  9. Używaj wolumenów tylko tam, gdzie to konieczne.
  10. Regularnie czyszcz środowisko Dockera:

6. Podsumowanie

Optymalizacja i bezpieczeństwo są kluczowymi aspektami pracy z Dockerem — zwłaszcza w środowiskach produkcyjnych. Dzięki zastosowaniu opisanych technik:

  • Obrazy będą mniejsze i szybsze w uruchamianiu,
  • Kontenery będą bezpieczniejsze i trudniejsze do przejęcia,
  • Proces CI/CD będzie bardziej niezawodny i przewidywalny.

Najważniejsze punkty do zapamiętania:

  • Używaj multi-stage build, aby tworzyć lekkie obrazy.
  • Uruchamiaj kontenery jako nie-root.
  • Regularnie skanuj obrazy narzędziami takimi jak Trivy i Snyk.
  • Aktualizuj swoje obrazy bazowe i zależności.
  • Przechowuj konfigurację i sekrety poza kodem źródłowym.