Docker Security Best Practices – jak zabezpieczyć kontenery produkcyjne
Kontenery zmieniły sposób budowania i wdrażania aplikacji. Dzięki Dockerowi programista może uruchomić identyczne środowisko lokalnie, na serwerze testowym i w chmurze.
Jednak często pojawia się błędne przekonanie:
„Kontener to osobna maszyna wirtualna, więc aplikacja jest całkowicie odizolowana.”
W rzeczywistości kontener współdzieli kernel Linux z hostem.
Oznacza to, że bezpieczeństwo kontenera zależy nie tylko od samej aplikacji, ale również od:
- konfiguracji Dockera,
- kernela,
- uprawnień,
- obrazów,
- sieci,
- mechanizmów izolacji.
Profesjonalne środowisko Docker powinno traktować kontenery jako procesy z dodatkowymi warstwami izolacji, a nie jako pełne maszyny.
Architektura bezpieczeństwa Dockera
Bezpieczny Docker wykorzystuje wiele mechanizmów jednocześnie:
Container
↓
Application Security
↓
Docker Configuration
↓
Namespace Isolation
↓
cgroups v2
↓
Seccomp Profiles
↓
AppArmor / SELinux
↓
Linux Kernel
↓
Hardware
Żaden pojedynczy mechanizm nie zapewnia pełnej ochrony.
1. Nie uruchamiaj kontenerów jako root
To jeden z najczęstszych błędów.
Domyślnie:
docker run nginx
uruchamia proces jako root wewnątrz kontenera.
Przykład:
Container
root UID 0
↓
proces nginx
Nie zawsze oznacza to root na hoście, ale zwiększa skutki potencjalnego przejęcia aplikacji.
Lepsze rozwiązanie
Tworzenie użytkownika aplikacji:
FROM nginx
RUN useradd -r appuser
USER appuser
Teraz:
Container
appuser
↓
nginx
2. Używaj minimalnych obrazów
Duży obraz = większa powierzchnia ataku.
Przykład:
Pełny Ubuntu:
Pakiety: 1000+
Minimalny obraz:
Pakiety: kilkadziesiąt
Mniej komponentów oznacza:
- mniej podatności,
- mniej narzędzi dla atakującego,
- łatwiejszy audyt.
Popularne podejścia:
- Alpine Linux,
- Debian slim,
- distroless images.
3. Nie instaluj niepotrzebnych narzędzi
Częsty błąd:
RUN apt install \
vim \
curl \
wget \
ssh
W kontenerze produkcyjnym często nie są potrzebne.
Dlaczego?
Jeżeli atakujący przejmie kontener:
Shell
↓
curl
↓
pobranie malware
Każde dodatkowe narzędzie zwiększa możliwości atakującego.
4. Regularnie aktualizuj obrazy
Obraz Dockera nie jest jednorazowym plikiem.
Z czasem pojawiają się:
- CVE kernela,
- podatności bibliotek,
- błędy aplikacji.
Przykład:
Stary obraz:
nginx
openssl
glibc
może zawierać znane podatności.
Sprawdzanie:
docker scout cves image_name
lub narzędzia:
- Trivy,
- Grype,
- Clair.
5. Nie używaj tagu latest
Zły przykład:
docker pull nginx:latest
Problem:
jutro może oznaczać inną wersję.
Lepsze:
docker pull nginx:1.27.0
Daje:
- powtarzalność,
- kontrolę zmian,
- łatwiejszy rollback.
6. Skanuj obrazy pod kątem podatności
Proces powinien wyglądać:
Developer
↓
Build image
↓
Security scan
↓
Registry
↓
Production
Przykład:
trivy image myapp:v1
Wynik:
CRITICAL: 2
HIGH: 5
MEDIUM: 12
7. Chroń Docker Socket
Najbardziej niebezpieczny plik:
/var/run/docker.sock
Przykład:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
To daje kontenerowi możliwość zarządzania Dockerem.
Praktycznie:
Container
↓
Docker API
↓
root privileges
Unikaj:
docker.sock
↓
container
jeżeli nie jest absolutnie wymagane.
8. Używaj Rootless Docker
Rootless Docker zmienia model:
Klasycznie:
docker daemon
↓
root
Rootless:
docker daemon
↓
normal user
Korzyści:
- mniejsze uprawnienia,
- ograniczenie skutków przejęcia,
- lepsza separacja.
9. Ogranicz capabilities Linux
Linux capabilities dzielą uprawnienia root na mniejsze części.
Przykład:
Domyślnie kontener otrzymuje zestaw capabilities.
Sprawdzenie:
capsh --print
Najlepsza praktyka:
Usuń wszystko:
docker run \
--cap-drop ALL \
myapp
Dodaj tylko wymagane:
--cap-add NET_BIND_SERVICE
10. Nie używaj privileged containers
Najbardziej niebezpieczna opcja:
docker run --privileged
Efekt:
Kontener otrzymuje bardzo szeroki dostęp do hosta.
Schemat:
Container
↓
Kernel
↓
Urządzenia hosta
W produkcji:
unikać.
11. Włącz Seccomp
Seccomp ogranicza dostęp kontenera do syscalli kernela.
Bez ograniczeń:
Container
↓
setuid()
mount()
ptrace()
Z Seccomp:
Container
↓
dozwolone syscall
↓
Kernel
Docker posiada domyślny profil Seccomp.
Nie wyłączaj go bez powodu.

12. Używaj AppArmor lub SELinux
Kontenery potrzebują dodatkowej kontroli dostępu.
Przykład:
SELinux:
Container process
↓
SELinux policy
↓
Allowed resources
AppArmor:
Application
↓
Profile
↓
Allowed actions
13. Ogranicz zasoby kontenerów
Kontener bez limitów może zużyć cały host.
Przykład:
docker run nginx
Brak limitów.
Lepsze:
docker run \
--memory=512m \
--cpus=1 \
nginx
Chroni przed:
- fork bomb,
- wyczerpaniem RAM,
- przeciążeniem CPU.
14. Zabezpiecz sieć Docker
Domyślna sieć Docker:
container ↔ container
Nie zawsze jest potrzebna.
Twórz własne sieci:
docker network create backend
Izolacja:
Frontend
X
Database
15. Nie przechowuj sekretów w obrazie
Błąd:
ENV PASSWORD=123456
Po zbudowaniu:
hasło zostaje w historii obrazu.
Lepsze:
- Docker Secrets,
- Vault,
- Kubernetes Secrets,
- zmienne runtime.
16. Podstawowa ochrona Dockerfile
Przykład bezpieczniejszego Dockerfile:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
USER nobody
CMD ["python","app.py"]
Cechy:
✅ mały obraz
✅ brak cache
✅ użytkownik non-root
✅ przewidywalne środowisko
17. Podpisuj obrazy
Problem:
Skąd wiadomo, że obraz pochodzi od właściwego autora?
Rozwiązania:
- Docker Content Trust,
- Cosign,
- Sigstore.
Schemat:
Build
↓
Sign
↓
Registry
↓
Verify
↓
Deploy
18. Monitoruj kontenery
Bez monitoringu nie ma bezpieczeństwa.
Sprawdzaj:
- logi,
- anomalie,
- procesy,
- sieć.
Narzędzia:
- journald,
- Prometheus,
- Grafana,
- Falco,
- SIEM.
19. Audytuj działania administratorów
Warto wiedzieć:
- kto uruchomił kontener,
- kto zmienił konfigurację,
- kto pobrał obraz.
Integracja:
Docker
↓
auditd
↓
SIEM
20. Regularnie aktualizuj hosta
Najważniejszy element:
Kontenery nie mają własnego kernela.
Schemat:
Container
↓
Kernel hosta
Podatność kernela może wpłynąć na wszystkie kontenery.
Docker Security Checklist
Obrazy
✅ skanuj CVE
✅ używaj małych obrazów
✅ unikaj latest
✅ podpisuj obrazy
Kontenery
✅ non-root user
✅ brak privileged
✅ ograniczone capabilities
✅ limity CPU/RAM
Host
✅ aktualny kernel
✅ SELinux/AppArmor
✅ nftables
✅ auditd
✅ monitoring
Secrets
✅ brak haseł w Dockerfile
✅ używaj secret management
✅ rotuj klucze
Docker Security w praktycznej architekturze
Profesjonalny serwer:
Internet
↓
nftables firewall
↓
Reverse Proxy
↓
Docker Network
↓
Containers
↓
┌────────────┬────────────┐
Seccomp AppArmor SELinux
↓
Linux Kernel
↓
auditd + journald
Podsumowanie
Bezpieczny Docker nie polega na jednym ustawieniu.
To połączenie wielu warstw:
- minimalne obrazy,
- użytkownicy non-root,
- Rootless Docker,
- ograniczone capabilities,
- Seccomp,
- AppArmor/SELinux,
- kontrola sieci,
- monitoring,
- audyt.
Największy błąd administratorów polega na traktowaniu kontenera jak małej maszyny wirtualnej.
Kontener to nadal proces działający na Linuxie.
Dlatego bezpieczeństwo Dockera zaczyna się od zrozumienia samego systemu Linux: kernela, namespaces, cgroups, uprawnień i mechanizmów kontroli dostępu.






