Używasz Dockera w homelabie? — 4 błędy, które popełnia prawie każdy (i jak je naprawić)

Spis treści

  1. Dlaczego zarządzanie Dockerem w homelabie bywa chaotyczne
  2. Błąd #1 — Używasz docker run zamiast Docker Compose
  3. Błąd #2 — Używasz Docker Volumes tam, gdzie wystarczą bind mounty
  4. Błąd #3 — Wklejasz sekrety bezpośrednio do pliku Compose
  5. Błąd #4 — Każdy serwis ma osobny plik Compose
  6. Bonus: Portainer — GUI, które zmienia wszystko
  7. Kompletny przykład stosu: WordPress + MariaDB + Nginx
  8. Dobre praktyki Docker w homelabie — podsumowanie
  9. FAQ — najczęściej zadawane pytania

Dlaczego zarządzanie Dockerem w homelabie bywa chaotyczne

Docker to jedno z najpotężniejszych narzędzi dostępnych dla homelaberów, selfhosterów i entuzjastów technologii. Pozwala uruchomić dziesiątki usług — od Plex Media Servera, przez Nextcloud, aż po własny serwer VPN — na jednej, niedrogiej maszynie, bez zaśmiecania systemu zależnościami.

Ale jest haczyk: Docker jest łatwy do uruchomienia i trudny do utrzymania. Większość ludzi poznaje go przez szybkie tutoriale oparte na komendzie docker run, nie zastanawiając się, co będzie za rok, gdy będą chcieli coś zmienić, zaktualizować lub przywrócić z backupu.

Wynik? Systemy pełne kontenerów zarządzanych niespójnie. Klucze API widoczne w plain texcie. Pliki konfiguracyjne porozrzucane po całym dysku. I całe godziny stracone na odtwarzanie komend, których się nie zanotowało.

Ten artykuł opisuje cztery konkretne błędy, które popełnia większość użytkowników Dockera w środowiskach domowych, oraz dokładnie tłumaczy, jak je wyeliminować. Jeśli stosujesz chociaż jeden z tych błędnych wzorców — ten przewodnik jest dla Ciebie.

Bezpłatne warsztaty: 16 Rzeczy, które musisz znać w Proxmoxie

Dowiedz się, jak zbudować nowoczesny klaster HA z Ceph, zabezpieczać dane za pomocą Proxmox Backup Server oraz automatyzować wdrożenia dzięki Proxmox Helper Scripts.

Środa, 27 maja o 16:00

Sprawdź szczegóły: https://asdevops.pl/warsztaty/

 

 


Błąd #1 — Używasz docker run zamiast Docker Compose

Na czym polega problem?

Polecenie docker run jest świetne do szybkich testów. Uruchamiasz kontener, sprawdzasz, czy działa, i… zostawiasz go. Problem pojawia się, gdy miesiąc później musisz zmienić port, dodać zmienną środowiskową albo zaktualizować obraz. Musisz wtedy:

  • Pamiętać (lub odtwarzać) oryginalną komendę
  • Zatrzymać kontener
  • Usunąć go
  • Uruchomić z nową komendą

Przy 20 kontenerach w homelabie to recepta na chaos.

Dlaczego Docker Compose jest lepszy?

Docker Compose to narzędzie, które pozwala opisać konfigurację kontenera (lub całego stosu usług) w pliku YAML. Zmiana ustawień sprowadza się do edycji pliku i jednej komendy:

docker compose up -d

Compose automatycznie wykrywa, co się zmieniło, i przebudowuje tylko to, co konieczne.

Jak wygląda plik Docker Compose?

Oto przykład prostego pliku docker-compose.yml dla Audiobookshelf (popularny serwer audiobooków):

services:
  audiobookshelf:
    image: ghcr.io/advplyr/audiobookshelf:latest
    container_name: audiobookshelf
    ports:
      - "13378:80"
    volumes:
      - /portainer/audiobookshelf/audiobooks:/audiobooks
      - /portainer/audiobookshelf/podcasts:/podcasts
      - /portainer/audiobookshelf/config:/config
      - /portainer/audiobookshelf/metadata:/metadata
    restart: unless-stopped

Teraz zamiast pamiętać długą komendę docker run z dziesiątkami flag, edytujesz czytelny plik i restartujesz stos. Chcesz zmienić port? Edytujesz 13378:80. Chcesz dodać zmienną? Dopisujesz linijkę.

Jak przejść z docker run na Compose?

  1. Zatrzymaj istniejący kontener: docker stop <nazwa>
  2. Utwórz plik docker-compose.yml w dedykowanym katalogu, np. /portainer/audiobookshelf/
  3. Przepisz parametry z komendy docker run na format YAML (narzędzia takie jak composerize.com robią to automatycznie)
  4. Uruchom stos: docker compose up -d

Pro tip: Przechowuj wszystkie pliki Compose w jednym miejscu, np. /opt/stacks/ lub /portainer/. Dzięki temu backup konfiguracji to kopia jednego katalogu.


Błąd #2 — Używasz Docker Volumes tam, gdzie wystarczą bind mounty

Docker Volumes vs. bind mounty — jaka jest różnica?

Docker Volumes to mechanizm, w którym Docker sam zarządza miejscem przechowywania danych. Tworzy specjalny folder (domyślnie w /var/lib/docker/volumes/) z własnymi uprawnieniami. To rozwiązanie jest świetne do baz danych w środowiskach produkcyjnych, ale w homelabie ma istotną wadę: nie wiesz od razu, gdzie są Twoje dane.

Bind mounty to po prostu mapowanie konkretnego katalogu na Twoim hoście do kontenera. Ty decydujesz, gdzie dane lądują.

Dlaczego bind mounty są lepsze w homelabie?

W środowisku domowym priorytetem jest kontrola i łatwość zarządzania. Bind mounty dają Ci:

  • Pełną wiedzę o lokalizacji danych — wiesz dokładnie, gdzie szukać pliku konfiguracyjnego
  • Łatwy backup — skopiuj jeden katalog i masz wszystko
  • Prostą edycję — możesz edytować plik konfiguracyjny bezpośrednio z hosta, bez wchodzenia do kontenera
  • Kontrolę uprawnień — Ty decydujesz, kto ma dostęp do folderu

Jak stosować bind mounty w praktyce?

Zalecana strategia: utwórz jeden nadrzędny katalog dla wszystkich danych Dockera, np. /portainer/, i w nim katalog dla każdego kontenera:

/portainer/
├── audiobookshelf/
│   ├── config/
│   └── metadata/
├── nextcloud/
│   ├── config/
│   └── data/
├── nginx-proxy-manager/
│   ├── data/
│   └── letsencrypt/
└── mariadb/
    └── data/

W pliku Compose bind mounty wyglądają tak:

volumes:
  - /portainer/nextcloud/config:/config
  - /portainer/nextcloud/data:/data

Lewy element ścieżki to katalog na hoście, prawy to ścieżka wewnątrz kontenera.

Przykład:

Kiedy Docker Volumes mają sens?

Volumes nadal mają swoje zastosowania:

  • Bazy danych z dużym ruchem (np. PostgreSQL w środowisku produkcyjnym), gdzie wydajność I/O jest krytyczna
  • Dane, które nie muszą być bezpośrednio edytowalne przez użytkownika
  • Środowiska wielokontenerowe z zaawansowanymi wymaganiami dotyczącymi uprawnień

W typowym homelabie — z kilkudziesięcioma kontenerami, selfhostowanymi aplikacjami i regularnymi backupami — bind mounty są prawie zawsze lepszym wyborem.


Błąd #3 — Wklejasz sekrety bezpośrednio do pliku Compose

Dlaczego to jest problem?

Wyobraź sobie taki fragment pliku docker-compose.yml:

environment:
  - OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxxxxxx
  - DB_PASSWORD=MojeSuperTajneHaslo123
  - SMTP_PASSWORD=haslo_do_maila

Ten plik prawdopodobnie trafi do repozytorium Git. Albo będzie leżał na dysku dostępnym przez Samba. Albo przez przypadek pokażesz go na screenshocie podczas szukania pomocy na Reddicie.

Wyciek kluczy API może kosztować Cię setki dolarów (np. za zużycie OpenAI). Wyciek hasła do bazy danych może skompromitować całą infrastrukturę.

Rozwiązanie: plik .env

Plik .env to standardowy sposób przechowywania zmiennych środowiskowych poza główną konfiguracją. Docker Compose automatycznie go wczytuje, jeśli znajdzie się w tym samym katalogu co docker-compose.yml.

Krok 1: Utwórz plik .env w katalogu ze stosem:

# /portainer/moj-stos/.env
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxxxxxx
DB_PASSWORD=MojeSuperTajneHaslo123
DB_ROOT_PASSWORD=InneHasloRoot
SMTP_PASSWORD=haslo_do_maila

Krok 2: W pliku docker-compose.yml odwołaj się do zmiennych:

services:
  moja-aplikacja:
    image: moja-aplikacja:latest
    environment:
      - OPENAI_API_KEY=${OPENAI_API_KEY}
      - DB_PASSWORD=${DB_PASSWORD}

Krok 3: Dodaj .env do .gitignore, jeśli używasz Gita:

.env
*.env

Dodatkowe zabezpieczenia

  • Ogranicz uprawnienia do pliku: chmod 600 .env
  • Używaj menedżera sekretów dla krytycznej infrastruktury (np. HashiCorp Vault, Docker Secrets)
  • Regularnie rotuj klucze API i hasła
  • Nie commituj pliku .env do publicznych repozytoriów — nawet „na chwilę”

Uwaga dla użytkowników Portainera: Portainer ma wbudowaną obsługę zmiennych środowiskowych i sekretów bezpośrednio w interfejsie. Możesz definiować zmienne w sekcji „Environment” podczas tworzenia stosu, zamiast polegać na plikach .env na dysku.


Błąd #4 — Każdy serwis ma osobny plik Compose

Problem z „jeden kontener = jeden plik”

Jeśli uruchamiasz WordPress, musisz mieć:

  • Kontener WordPress
  • Kontener MariaDB (baza danych)
  • Opcjonalnie: Nginx Proxy Manager (reverse proxy)

Jeśli każdy z nich ma własny plik Compose, napotykasz trzy problemy:

  1. Brak wspólnej sieci — kontenery nie widzą się nawzajem bezpośrednio, musisz konfigurować zewnętrzne sieci
  2. Zarządzanie w trzech miejscach — zmiana czegoś w stosie wymaga edycji wielu plików
  3. Niezgodność wersji — możesz przypadkowo zaktualizować MariaDB bez aktualizacji WordPressa

Rozwiązanie: powiązane serwisy w jednym pliku Compose

Docker Compose pozwala definiować wiele serwisów w jednym pliku. Kontenery w tym samym pliku automatycznie tworzą wspólną sieć wewnętrzną i mogą się do siebie odwoływać przez nazwy serwisów.

Przykład — WordPress + MariaDB w jednym pliku:

services:
  wordpress:
    image: wordpress:latest
    container_name: wordpress
    ports:
      - "8080:80"
    environment:
      - WORDPRESS_DB_HOST=mariadb          # nazwa serwisu, nie IP!
      - WORDPRESS_DB_NAME=${DB_NAME}
      - WORDPRESS_DB_USER=${DB_USER}
      - WORDPRESS_DB_PASSWORD=${DB_PASSWORD}
    volumes:
      - /portainer/wordpress/html:/var/www/html
    depends_on:
      - mariadb
    restart: unless-stopped

  mariadb:
    image: mariadb:latest
    container_name: mariadb
    environment:
      - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
      - MYSQL_DATABASE=${DB_NAME}
      - MYSQL_USER=${DB_USER}
      - MYSQL_PASSWORD=${DB_PASSWORD}
    volumes:
      - /portainer/wordpress/db:/var/lib/mysql
    restart: unless-stopped

Zwróć uwagę na WORDPRESS_DB_HOST=mariadb — WordPress łączy się z bazą danych przez nazwę serwisu, nie przez adres IP. Docker automatycznie to rozwiązuje wewnątrz wspólnej sieci.

Kiedy rozdzielić serwisy?

Nie wszystkie usługi powinny być w jednym pliku. Rozdziel serwisy, gdy:

  • Serwisy są niezależne i nie muszą się ze sobą komunikować
  • Chcesz skalować lub aktualizować je niezależnie
  • Masz dedykowany reverse proxy (np. Nginx Proxy Manager, Traefik) — ten często działa jako osobny stos

Dobra zasada: jeśli serwisy logicznie należą do jednej aplikacji lub regularnie aktualizujesz je razem, trzymaj je w jednym pliku.


Bonus: Portainer — GUI, które zmienia zarządzanie Dockerem

Wszystkie opisane wyżej praktyki można wdrożyć przez CLI. Ale jeśli zarządzasz kilkudziesięcioma kontenerami, graficzny interfejs użytkownika dramatycznie upraszcza pracę.

Portainer to open-source’owa platforma do zarządzania kontenerami z interfejsem webowym. Pozwala:

  • Tworzyć i edytować stosy Compose bezpośrednio w przeglądarce
  • Przeglądać logi kontenerów w czasie rzeczywistym
  • Zarządzać wolumenami, sieciami i obrazami
  • Monitorować zużycie zasobów
  • Zarządzać wieloma hostami Docker (i nawet klastrami Kubernetes)

Uruchomienie Portainera:

services:
  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    ports:
      - "9443:9443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /portainer/portainer/data:/data
    restart: unless-stopped

Po uruchomieniu wejdź na https://twój-serwer:9443 i skonfiguruj konto administratora.

Uwaga bezpieczeństwa: Portainer ma dostęp do socketu Dockera, co daje mu pełną kontrolę nad systemem. Nie wystawiaj go publicznie bez silnego uwierzytelnienia (2FA, VPN lub co najmniej silne hasło + HTTPS).


Kompletny przykład stosu: WordPress + MariaDB + Nginx Proxy Manager

Poniżej kompletny, gotowy do użycia przykład trzech powiązanych serwisów w jednym pliku Compose, z użyciem pliku .env i bind mountów.

Plik .env:

# Baza danych
DB_ROOT_PASSWORD=zmien_to_na_silne_haslo
DB_NAME=wordpress_db
DB_USER=wp_user
DB_PASSWORD=zmien_to_na_inne_silne_haslo

# Nginx Proxy Manager
NPM_DB_PASSWORD=jeszcze_inne_haslo

Plik docker-compose.yml:

services:

  # ----- WordPress -----
  wordpress:
    image: wordpress:latest
    container_name: wordpress
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: mariadb
      WORDPRESS_DB_NAME: ${DB_NAME}
      WORDPRESS_DB_USER: ${DB_USER}
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
    volumes:
      - /portainer/wordpress/html:/var/www/html
    depends_on:
      - mariadb
    restart: unless-stopped

  # ----- MariaDB -----
  mariadb:
    image: mariadb:lts
    container_name: mariadb
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASSWORD}
    volumes:
      - /portainer/wordpress/db:/var/lib/mysql
    restart: unless-stopped

  # ----- Nginx Proxy Manager -----
  nginx-proxy-manager:
    image: jc21/nginx-proxy-manager:latest
    container_name: nginx-proxy-manager
    ports:
      - "80:80"
      - "443:443"
      - "81:81"   # panel administracyjny
    volumes:
      - /portainer/npm/data:/data
      - /portainer/npm/letsencrypt:/etc/letsencrypt
    restart: unless-stopped

Uruchom całość jedną komendą:

docker compose up -d

Dobre praktyki Docker w homelabie — podsumowanie

PraktykaZamiastUżywaj
Definiowanie kontenerówdocker run z długimi flagamiDocker Compose (pliki YAML)
Przechowywanie danychDocker VolumesBind mounty do katalogu /portainer/
Zmienne i sekretyPlain text w pliku ComposePlik .env z odwołaniami ${ZMIENNA}
Powiązane serwisyOsobne pliki ComposeJeden plik Compose dla całego stosu
Zarządzanie konteneramiCzysto CLIPortainer (GUI) + CLI dla automatyzacji

Checklist dla nowych stosów

Zanim uruchomisz nowy kontener w homelabie, sprawdź:

  • Czy mam plik docker-compose.yml zamiast komendy docker run?
  • Czy używam bind mountów z jasno zdefiniowanymi ścieżkami?
  • Czy klucze API i hasła są w pliku .env, a nie w pliku Compose?
  • Czy powiązane serwisy są w jednym pliku Compose?
  • Czy plik .env ma ograniczone uprawnienia (chmod 600)?
  • Czy mam plan backupu dla katalogów z danymi?

FAQ — najczęściej zadawane pytania

Czy muszę używać Portainera, żeby stosować te praktyki?

Nie. Wszystkie opisane techniki działają z czystym CLI Dockera. Portainer to narzędzie ułatwiające zarządzanie, ale nie jest wymagany. Możesz zarządzać stosami Compose bezpośrednio przez terminal.

Czym różni się Docker Compose v1 od v2?

Docker Compose v1 to oddzielne narzędzie instalowane jako docker-compose (z myślnikiem). Docker Compose v2 jest wbudowany w Docker CLI jako docker compose (ze spacją). Aktualnie zalecana jest wersja v2, która jest aktywnie rozwijana. Jeśli używasz nowoczesnej wersji Dockera, prawdopodobnie masz już v2.

Czy mogę używać bind mountów z wolumeny Docker jednocześnie?

Tak. W jednym pliku Compose możesz mieszać bind mounty i Docker Volumes dla różnych serwisów lub nawet różnych ścieżek w tym samym serwisie. Na przykład dane aplikacyjne możesz trzymać w bind mountach, a dane bazy danych w Docker Volume — jeśli masz ku temu powód.

Jak bezpiecznie przechowywać pliki .env przy użyciu Gita?

Najlepsze podejście: trzymaj w repozytorium plik .env.example z przykładowymi (pustymi lub fikcyjnymi) wartościami, a prawdziwy .env dodaj do .gitignore. Dzięki temu inni wiedzą, jakich zmiennych potrzebuje projekt, ale sekrety nie trafią do repozytorium.

Ile kontenerów można uruchomić na jednej maszynie?

To zależy od sprzętu i rodzaju aplikacji. Na mini PC z 16 GB RAM (np. ACEMAGIC M5, KAMRUI Hyper H1) bez problemu można uruchomić 30–50 lekkich kontenerów. Aplikacje takie jak Plex z transkodowaniem lub modele AI będą wymagały znacznie więcej zasobów.

Czy Docker Compose nadaje się do środowisk produkcyjnych?

Docker Compose świetnie sprawdza się w środowiskach jednowęzłowych (single-node), czyli dokładnie w homelabie. Dla środowisk produkcyjnych z wieloma serwerami i wymaganiami dotyczącymi wysokiej dostępności lepszym wyborem jest Kubernetes lub Docker Swarm.

Co to jest Docker Stack i czym różni się od Compose?

Docker Stack to polecenie (docker stack deploy) do wdrażania plików Compose w klastrze Docker Swarm. Składnia pliku jest bardzo podobna do zwykłego Compose, ale obsługuje dodatkowe opcje jak repliki i ograniczenia rozmieszczenia. W pojedynczym homelabie bez Swarma wystarczy standardowy docker compose.


Wnioski końcowe

Docker jest narzędziem, które bardzo łatwo zacząć używać źle. Komenda docker run daje natychmiastową satysfakcję, ale prowadzi do niereprodukowanej, trudnej w utrzymaniu infrastruktury. Sekrety w plikach konfiguracyjnych to bomba z opóźnionym zapłonem. Docker Volumes bez przemyślanej strategii to chaos przy backupach.

Cztery zmiany opisane w tym artykule — Docker Compose, bind mounty, pliki .env i wspólne stosy dla powiązanych serwisów — to nie są zaawansowane koncepty. To standardy branżowe, które po prostu sprawiają, że Twój homelab jest łatwiejszy do zarządzania, bezpieczniejszy i łatwiejszy do odtworzenia po awarii.

Wdroż je. Nie pożałujesz.

Bezpłatne warsztaty: 16 Rzeczy, które musisz znać w Proxmoxie

Dowiedz się, jak zbudować nowoczesny klaster HA z Ceph, zabezpieczać dane za pomocą Proxmox Backup Server oraz automatyzować wdrożenia dzięki Proxmox Helper Scripts.

Środa, 27 maja o 16:00

Sprawdź szczegóły: https://asdevops.pl/warsztaty/

 

 

 

 

Bezpłatne warsztaty: 16 Rzeczy, które musisz znać w Proxmoxie

X