Blog JSystems - uwalniamy wiedzę!

Szukaj

„Uczyć się Dockera czy Kubernetesa?" - to jedno z najczęstszych pytań osób wchodzących w świat konteneryzacji. Tkwi w nim ukryte założenie, że to wybór typu albo-albo, jak Windows kontra Linux. Otóż nie. Docker i Kubernetes to nie rywale o ten sam tron - to dwa narzędzia robiące zupełnie różne rzeczy, które najczęściej działają razem. Docker pakuje pojedynczą aplikację w kontener. Kubernetes zarządza setkami takich kontenerów rozsianych po wielu serwerach. W tym artykule pokażemy konkretnym kodem, co każde z nich robi, gdzie kończy się Docker, a zaczyna Kubernetes - i uczciwie odpowiemy na najtrudniejsze pytanie: czy Twój projekt w ogóle potrzebuje Kubernetesa.

Z tego artykułu wyniesiesz:
  • Dlaczego Docker i Kubernetes to nie konkurenci, tylko warstwy tego samego stosu
  • Co Docker robi sam na jednym hoście - z prawdziwym Dockerfile i plikiem docker compose
  • Co dokłada Kubernetes na wielu maszynach - z manifestem Deployment i Service oraz komendami kubectl
  • Tabelę porównawczą i diagram pokazujący różnicę skali
  • Uczciwą odpowiedź, kiedy wystarczy sam Docker, a kiedy Kubernetes naprawdę się opłaca - oraz lżejsze alternatywy

Najczęstsze nieporozumienie: to nie są konkurenci

Wyobraź sobie firmę kurierską. Najpierw ktoś musi zapakować przesyłkę: włożyć produkt do pudełka, zabezpieczyć, nakleić etykietę. To jest Docker - bierze Twoją aplikację razem ze wszystkim, czego potrzebuje do działania (środowiskiem uruchomieniowym, bibliotekami, konfiguracją), i zamyka w jednym, przenośnym pudełku zwanym kontenerem (container). Takie pudełko działa identycznie na laptopie programisty, na serwerze testowym i na produkcji.

Ale jedna firma kurierska to nie jedno pudełko. To tysiące paczek, dziesiątki samochodów, magazyny, trasy, zastępstwa, gdy auto się zepsuje. Ktoś musi tym wszystkim dyrygować - i to jest właśnie Kubernetes. On nie pakuje przesyłek. On zarządza całą flotą spakowanych już kontenerów: decyduje, na którym serwerze co uruchomić, pilnuje, żeby zawsze działała zaplanowana liczba kopii, i przekierowuje ruch, gdy któraś maszyna padnie.

Docker pakuje aplikację. Kubernetes zarządza setkami spakowanych aplikacji działających na dziesiątkach serwerów. Jedno bez drugiego ma sens - ale razem tworzą fundament nowoczesnej infrastruktury.

Dlatego pytanie „Docker czy Kubernetes" jest jak pytanie „pudełko czy firma logistyczna". W praktyce: najpierw uczysz się pakować (Docker), a dopiero potem - jeśli rosną Ci skala i wymagania - dyrygować flotą (Kubernetes). Docker jest też warunkiem wstępnym: Kubernetes orkiestruje właśnie kontenery, więc bez ich zrozumienia nie ma się czym dyrygować.

Co Docker robi sam - jeden host, jedno pudełko

Sercem Dockera jest obraz (image) - przepis na kontener - i sam kontener, czyli uruchomiona instancja tego przepisu. Obraz budujesz na podstawie pliku Dockerfile, który opisuje krok po kroku, jak złożyć środowisko aplikacji. Oto realistyczny przykład dla prostej usługi w Pythonie:

# Bazujemy na lekkim obrazie z Pythonem
FROM python:3.12-slim

# Katalog roboczy wewnątrz kontenera
WORKDIR /app

# Najpierw zależności - ta warstwa cache'uje się, dopóki nie zmienisz requirements
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Potem kod aplikacji
COPY . .

# Port, na którym nasłuchuje aplikacja
EXPOSE 8000

# Polecenie startowe kontenera
CMD ["gunicorn", "-b", "0.0.0.0:8000", "app:app"]

Mając taki plik, budujesz obraz i uruchamiasz kontener dwoma poleceniami. To wszystko dzieje się na jednej maszynie - Twoim laptopie albo pojedynczym serwerze:

# Zbuduj obraz i nadaj mu nazwę
user@host:~$ docker build -t sklep-api:1.0 .
[+] Building 12.3s (10/10) FINISHED
 => => naming to docker.io/library/sklep-api:1.0

# Uruchom kontener w tle, mapując port 8000 hosta na port kontenera
user@host:~$ docker run -d -p 8000:8000 --name sklep sklep-api:1.0
a3f9c1d4e8b2...

# Sprawdź, że działa
user@host:~$ docker ps
CONTAINER ID   IMAGE          STATUS         PORTS                    NAMES
a3f9c1d4e8b2   sklep-api:1.0  Up 8 seconds   0.0.0.0:8000->8000/tcp   sklep

Większość aplikacji nie jest jednak samotną wyspą - potrzebuje bazy danych, czasem cache'u czy kolejki. Tu wkracza docker compose: opisujesz wszystkie usługi w jednym pliku compose.yaml i podnosisz je razem jedną komendą. To wciąż jeden host, ale już kilka współpracujących kontenerów:

services:
  api:
    build: .                    # buduj z lokalnego Dockerfile
    ports:
      - "8000:8000"
    environment:
      DATABASE_URL: "postgresql://app:secret@db:5432/sklep"
    depends_on:
      - db

  db:
    image: postgres:16
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: sklep
    volumes:
      - dbdata:/var/lib/postgresql/data    # dane przeżywają restart

volumes:
  dbdata:

Komenda docker compose up -d uruchamia obie usługi, tworzy między nimi prywatną sieć (dzięki czemu api łączy się z bazą po nazwie db) i pilnuje wolumenu z danymi. Dla ogromnej liczby projektów to wystarcza w zupełności. Masz konteneryzację, powtarzalne środowisko i wdrożenie jedną komendą. Pytanie brzmi: czego tu jeszcze brakuje?

Gdzie kończy się Docker

Cała ta układanka żyje na jednym hoście. A teraz wyobraź sobie typowe wymagania produkcyjne, których sam Docker nie spełni:

  • Serwer pada o trzeciej w nocy. Twoja aplikacja znika razem z nim. Nikt jej automatycznie nie przeniesie na inną maszynę.
  • Ruch rośnie pięciokrotnie podczas promocji. Jeden kontener nie wyrobi, a Docker sam nie dorzuci kolejnych ani nie rozłoży między nie ruchu.
  • Wdrażasz nową wersję. docker compose up ubije stary kontener i postawi nowy - przez chwilę usługa jest niedostępna.
  • Aplikacja przestaje odpowiadać, choć kontener „działa". Docker nie wie, że proces w środku się zawiesił, więc go nie zrestartuje.

To nie wady Dockera - to po prostu nie jego zadanie. Dokładnie te problemy rozwiązuje warstwa orkiestracji (orchestration), a jej najpopularniejszym przedstawicielem jest Kubernetes.

Co dokłada Kubernetes - klaster, deklaracje, samonaprawa

Kubernetes (w skrócie K8s) to system orkiestracji kontenerów działający na klastrze wielu maszyn. Maszyny te dzielą się na węzły robocze (worker nodes), gdzie faktycznie biegną kontenery, oraz warstwę sterującą (control plane), która podejmuje decyzje. Najmniejszą jednostką, którą zarządza Kubernetes, jest pod - opakowanie wokół jednego lub kilku ściśle powiązanych kontenerów.

Kluczowa różnica filozoficzna: w Dockerze mówisz jak coś uruchomić (krok po kroku). W Kubernetesie deklarujesz jaki ma być efekt końcowy, a klaster sam do tego stanu dąży i go pilnuje. Opisujesz to w pliku YAML. Oto Deployment - obiekt, który mówi: „utrzymuj trzy działające kopie tej aplikacji":

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sklep-api
spec:
  replicas: 3                       # zawsze utrzymuj 3 instancje
  selector:
    matchLabels: { app: sklep-api }
  strategy:
    type: RollingUpdate              # aktualizacja bez przestoju
  template:
    metadata: { labels: { app: sklep-api } }
    spec:
      containers:
        - name: api
          image: registry.example.com/sklep-api:1.0
          ports:
            - containerPort: 8000
          resources:
            requests: { cpu: "100m", memory: "128Mi" }
            limits:   { cpu: "500m", memory: "256Mi" }
          livenessProbe:                 # jak sprawdzić, czy aplikacja żyje
            httpGet: { path: /healthz, port: 8000 }
            initialDelaySeconds: 5
            periodSeconds: 10

Trzy repliki to fundament odporności, ale potrzebny jest jeszcze jeden element: stały adres, pod którym aplikacja jest dostępna, oraz rozkładanie ruchu między te repliki. Robi to obiekt Service:

apiVersion: v1
kind: Service
metadata:
  name: sklep-api
spec:
  selector:
    app: sklep-api               # kieruj ruch do podów z tą etykietą
  ports:
    - port: 80                   # port usługi w klastrze
      targetPort: 8000           # port kontenera
  type: ClusterIP                # wewnętrzny równoważnik obciążenia

Te dwa pliki wdrażasz na klaster narzędziem kubectl - i od tej chwili Kubernetes sam dba o resztę. Zobacz, jak wygląda samonaprawa (self-healing) w praktyce: gdy ręcznie usuniesz jeden z podów (symulując awarię), klaster natychmiast tworzy nowy, żeby wrócić do zadeklarowanych trzech replik:

devops@k8s:~$ kubectl apply -f sklep-api.yaml
deployment.apps/sklep-api created
service/sklep-api created

devops@k8s:~$ kubectl get pods -l app=sklep-api
NAME                         READY   STATUS    RESTARTS   AGE
sklep-api-6c8d4f9b7-2xk4p    1/1     Running   0          40s
sklep-api-6c8d4f9b7-9qm7t    1/1     Running   0          40s
sklep-api-6c8d4f9b7-h5rng    1/1     Running   0          40s

# Symulujemy awarię - kasujemy jeden pod
devops@k8s:~$ kubectl delete pod sklep-api-6c8d4f9b7-2xk4p
pod "sklep-api-6c8d4f9b7-2xk4p" deleted

# Kilka sekund później - Kubernetes już dostawił nowy pod
devops@k8s:~$ kubectl get pods -l app=sklep-api
NAME                         READY   STATUS    RESTARTS   AGE
sklep-api-6c8d4f9b7-9qm7t    1/1     Running   0          70s
sklep-api-6c8d4f9b7-h5rng    1/1     Running   0          70s
sklep-api-6c8d4f9b7-tn4wz    1/1     Running   0          6s

To samo deklaratywne podejście daje resztę „supermocy". Skalowanie do dziesięciu instancji to jedna komenda, a podmiana wersji obrazu uruchamia aktualizację bez przestoju (rolling update) - Kubernetes wymienia pody po kolei, cały czas utrzymując usługę dostępną:

# Skaluj do 10 replik jedną komendą - klaster sam rozłoży je po węzłach
devops@k8s:~$ kubectl scale deploy/sklep-api --replicas=10
deployment.apps/sklep-api scaled

# Wdróż nową wersję bez przerwy w działaniu (rolling update)
devops@k8s:~$ kubectl set image deploy/sklep-api api=registry.example.com/sklep-api:1.1
deployment.apps/sklep-api image updated

devops@k8s:~$ kubectl rollout status deploy/sklep-api
Waiting for rollout: 6 of 10 updated replicas are available...
deployment "sklep-api" successfully rolled out

Tego sam Docker nie zrobi - i właśnie dlatego Kubernetes powstał. Skalowanie pod ruch, samonaprawa, aktualizacje bez przestoju i rozkładanie obciążenia (load balancing) między repliki to jego rdzeń.

Różnica skali na jednym diagramie

Najprościej zobaczyć tę różnicę obrazowo. Po lewej Docker: jeden host, na nim Twoje kontenery. Po prawej Kubernetes: warstwa sterująca dyrygująca wieloma węzłami, a na każdym z nich pody rozmieszczane i przenoszone automatycznie.

Docker - jeden host
host-01
A
B
db
Ty decydujesz, co i gdzie uruchomić. Host pada - aplikacja znika razem z nim.
Kubernetes - klaster
control plane · scheduler
node-1
A
A
node-2
A
B
Klaster sam rozmieszcza pody, skaluje i przenosi je z padłych węzłów.
Docker działa w obrębie jednego hosta. Kubernetes spina wiele węzłów w jeden klaster i automatycznie rozkłada na nich pody - to właśnie ta różnica skali decyduje o tym, którego narzędzia potrzebujesz.

Docker vs Kubernetes - tabela porównawcza

Zestawienie na sucho, żeby uporządkować, co należy do której warstwy:

Cecha / zadanieSam DockerKubernetes
Pakowanie aplikacji w kontener✅ to jego rola❌ korzysta z gotowych obrazów
Uruchomienie na jednym hoście✅ (przesada dla 1 hosta)
Wiele usług na jednym hoście✅ docker compose
Wiele węzłów (klaster)✅ rdzeń działania
Automatyczne skalowanie pod ruch✅ autoskalowanie podów
Samonaprawa (restart padłych instancji)❌ tylko polityka restartu na 1 hoście✅ na całym klastrze
Aktualizacja bez przestoju✅ rolling update
Równoważenie ruchu (load balancing)❌ (wymaga osobnego narzędzia)✅ wbudowane przez Service
Próg wejścia i koszt utrzymania✅ niski❌ wysoki

Kiedy wystarczy sam Docker (i nie potrzebujesz Kubernetesa)

To najważniejsza i najczęściej pomijana sekcja, bo Kubernetes bywa wybierany z mody, a nie z potrzeby. W wielu sytuacjach sam Docker - najczęściej z docker compose - to optymalny, dojrzały wybór:

  • Aplikacja działa na jednym lub dwóch serwerach. Klaster dla jednego hosta to jak ciężarówka do przewiezienia roweru.
  • Ruch jest przewidywalny. Nie ma nagłych skoków wymagających automatycznego skalowania w sekundach.
  • Krótka przerwa przy wdrożeniu jest akceptowalna. Wewnętrzne narzędzie czy panel administracyjny nie potrzebuje zera przestoju.
  • Zespół jest mały i nie ma dedykowanej osoby od infrastruktury. Ktoś musiałby ten klaster utrzymywać - a to pełnoetatowa kompetencja.
  • Używasz zarządzanej platformy (PaaS). Usługi typu Render, Railway czy Fly.io biorą orkiestrację na siebie - dajesz im kontener, a one robią resztę.
Uczciwie: Kubernetes to potężne narzędzie, ale jego utrzymanie kosztuje - czas, kompetencje i pieniądze. Klaster trzeba aktualizować, zabezpieczać, monitorować i debugować, gdy coś pójdzie nie tak (a sieć w Kubernetesie potrafi być nieoczywista). Wdrożenie K8s tam, gdzie wystarczyłby docker compose, to jeden z najdroższych „technologicznych" błędów - płacisz złożonością za możliwości, których nie używasz.

Kiedy Kubernetes naprawdę się opłaca

Są jednak sytuacje, w których ta złożoność zwraca się z nawiązką. Kubernetes ma sens, gdy:

  • Potrzebujesz wysokiej dostępności bez przestojów. Sklep, który traci pieniądze za każdą minutę niedostępności, nie może sobie pozwolić na ręczne wdrożenia z przerwą.
  • Ruch jest mocno zmienny. Promocje, sezonowość, wirusowe skoki - autoskalowanie podaje i zabiera moc samo, płacisz tylko za to, czego realnie używasz.
  • Masz architekturę mikroserwisów. Kilkanaście czy kilkadziesiąt współpracujących usług to dokładnie scenariusz, do którego K8s został stworzony.
  • Działasz na wielu serwerach lub w wielu chmurach. Kubernetes daje jednolitą warstwę zarządzania niezależnie od tego, gdzie stoją maszyny.
  • Masz kogoś, kto ten klaster utrzyma. To warunek konieczny - bez kompetencji DevOps lub Platform Engineering K8s staje się ciężarem, nie ułatwieniem.

Prosta zasada decyzyjna: jeśli czytasz tę listę i przy większości punktów myślisz „to nie o nas" - prawdopodobnie Kubernetes jest dla Ciebie przedwczesny. Jeśli przytakujesz przy kilku - czas zacząć się nim poważnie interesować.

Alternatywy - nie tylko Kubernetes

Między „sam docker run" a „pełny Kubernetes" jest całe spektrum opcji o różnym progu złożoności. Warto je znać, zanim sięgniesz po najcięższe narzędzie:

  • docker compose - wiele kontenerów na jednym hoście, definiowanych jednym plikiem. Najprostszy krok wzwyż. Idealny dla środowisk deweloperskich i niewielkich wdrożeń produkcyjnych.
  • Docker Swarm - wbudowana w Dockera lekka orkiestracja na klastrze. Dużo prostsza od Kubernetesa, choć z mniejszym ekosystemem i wolniej rozwijana. Dobra, gdy chcesz wielu węzłów bez ciężaru K8s.
  • HashiCorp Nomad - lekki orkiestrator, który potrafi uruchamiać nie tylko kontenery, ale i zwykłe procesy czy maszyny wirtualne. Prostszy operacyjnie od Kubernetesa, ceniony tam, gdzie zespół szuka mniejszej złożoności.
  • Zarządzany Kubernetes (usługi K8s u dostawców chmury) - jeśli już wiesz, że potrzebujesz K8s, ale nie chcesz sam utrzymywać warstwy sterującej, chmura zrobi to za Ciebie. Płacisz za wygodę, a po Twojej stronie jest mniej rzeczy, które mogą się zepsuć.

Realny próg złożoności - i naturalna kolejność nauki

Z perspektywy nauki i wdrażania kolejność jest niemal zawsze ta sama, bo każda warstwa opiera się na poprzedniej. Próba przeskoczenia od razu do Kubernetesa to najczęstszy powód frustracji - K8s zakłada, że rozumiesz już kontenery, sieci i obrazy.

  1. Docker - obrazy i kontenery. Dockerfile, docker build, docker run, wolumeny, sieci. Po tym etapie umiesz skonteneryzować dowolną aplikację.
  2. docker compose - wiele usług na jednym hoście. Aplikacja plus baza plus cache, podnoszone jedną komendą. Większość projektów może się tu zatrzymać.
  3. Kubernetes - wiele hostów. Pody, Deployment, Service, Ingress, ConfigMap, Secret, a potem Helm i autoskalowanie. Wchodzisz tu, gdy realnie przerosłeś jeden host.

Dobra wiadomość jest taka, że ta droga jest powtarzalna i da się jej nauczyć w przewidywalnym czasie - pod warunkiem, że idziesz warstwami i ćwiczysz na prawdziwym sprzęcie, a nie tylko czytasz dokumentację. Lokalny klaster (na przykład w narzędziu typu kind albo minikube) postawisz na laptopie w minutę i przećwiczysz na nim wszystko, co opisaliśmy wyżej, nie płacąc ani złotówki za chmurę.

Podsumowanie

Docker i Kubernetes nie konkurują - uzupełniają się. Docker pakuje pojedynczą aplikację w przenośny kontener, który działa tak samo wszędzie. Kubernetes bierze wiele takich kontenerów i zarządza nimi na klastrze maszyn: skaluje, naprawia, aktualizuje bez przestoju i rozkłada ruch. Sam Docker (z docker compose) wystarcza zaskakująco często - na jednym czy dwóch hostach, przy przewidywalnym ruchu, w małym zespole. Kubernetes opłaca się dopiero przy wysokiej dostępności, zmiennym ruchu, mikroserwisach i obecności kogoś, kto klaster utrzyma. Wybieraj narzędzie do problemu, nie problem do modnego narzędzia - a naukę prowadź w kolejności: najpierw pudełko, potem flota.

Szkolenie: Docker i Kubernetes od zera

Szkolenie Docker i Kubernetes od zera -->

Szkolenie: Kubernetes - orkiestracja kontenerów

Szkolenie Kubernetes - orkiestracja kontenerów -->

Najczęściej zadawane pytania

Czy Docker i Kubernetes to konkurenci?
Nie. To dwie różne technologie rozwiązujące różne problemy, które bardzo dobrze ze sobą współpracują. Docker to platforma do pakowania aplikacji w kontenery - izolowane środowiska zawierające aplikację z jej zależnościami. Kubernetes to system orkiestracji, który zarządza wieloma takimi kontenerami na wielu serwerach: rozmieszcza je, restartuje gdy padną, skaluje i równoważy ruch. Mówiąc obrazowo: Docker pakuje aplikację, a Kubernetes zarządza setkami spakowanych aplikacji na klastrze maszyn.
Czego Docker nie potrafi sam?
Sam Docker działa w obrębie jednego hosta. Nie decyduje, na którym z wielu serwerów uruchomić kontener, nie zastępuje automatycznie maszyny, która padła, nie skaluje aplikacji w odpowiedzi na ruch i nie wdraża nowej wersji bez przerwy w działaniu na całym klastrze. Te zadania - rozkładanie obciążenia (load balancing), samonaprawa (self-healing), automatyczne skalowanie i aktualizacje bez przestoju (rolling update) na wielu węzłach - dokłada dopiero Kubernetes lub inny system orkiestracji.
Kiedy wystarczy sam Docker, a kiedy potrzebny jest Kubernetes?
Sam Docker (najczęściej z docker compose) wystarcza, gdy aplikacja działa na jednym lub dwóch serwerach, ruch jest przewidywalny, krótka przerwa przy wdrożeniu jest akceptowalna, a zespół jest mały. Kubernetes opłaca się, gdy potrzebujesz wysokiej dostępności bez przestojów, automatycznego skalowania pod zmienny ruch, masz wiele współpracujących usług (mikroserwisy) i kogoś, kto będzie ten klaster utrzymywał. Kubernetes to potężne, ale i kosztowne w utrzymaniu narzędzie - nie każdy projekt go potrzebuje.
Czy muszę znać Docker, żeby nauczyć się Kubernetes?
Praktycznie tak. Kubernetes orkiestruje kontenery, więc bez rozumienia, czym jest obraz, czym kontener, jak pisać Dockerfile i jak składać usługi w docker compose, nauka Kubernetesa jest walką z abstrakcjami, których nie rozumiesz. Naturalna kolejność to: najpierw Docker (obrazy, kontenery, sieci, wolumeny), potem docker compose dla wielu usług na jednym hoście, a dopiero na końcu Kubernetes dla wielu hostów. Próba zaczynania od Kubernetesa bez Dockera to najczęstszy błąd początkujących.

Komentarze (0)

Musisz być zalogowany by móc dodać komentarz. Zaloguj się przez Google

Brak komentarzy...