Docker Compose i Kubernetes nie są prostymi zamiennikami
| Kryterium | Docker Compose | Kubernetes | Komentarz |
|---|---|---|---|
| Development lokalny | Bardzo dobry | Możliwy, zwykle cięższy | Compose ma niższy koszt wejścia |
| Produkcja na jednym hoście | Bardzo dobry | Często nadmiarowy | Docker oficjalnie opisuje ten scenariusz dla Compose |
| Wielowęzłowe HA | Brak natywnego schedulera klastra | Bardzo dobry | Kubernetes utrzymuje workload na węzłach klastra |
| Self-healing | Restart na hoście | Bardzo dobry | Kubernetes dodatkowo zastępuje Pody i reaguje na awarie węzłów |
| Autoscaling | Wymaga procesu wdrożeniowego | HPA | Kubernetes może skalować na podstawie metryk |
| Rolling updates | Wymaga procesu wdrożeniowego | HPA | Deployment ma wbudowany RollingUpdate i rollback |
| Koszt operacyjny | Niższy | Wyższy | Klaster wymaga dodatkowej platformy i kompetencji |
Docker Compose służy do deklaratywnego opisywania usług, sieci, wolumenów, konfiguracji i sekretów aplikacji kontenerowej. Compose Specification jest obecnie rekomendowanym formatem pliku Compose. [1]
Kubernetes jest platformą do zarządzania konteneryzowanymi workloadami i usługami w klastrze. Jego główne funkcje obejmują między innymi service discovery, load balancing, storage orchestration, rollouty, rollbacki, skalowanie i utrzymywanie deklarowanego stanu. [8]
Najważniejsze pytanie brzmi więc nie: który system jest lepszy, tylko: czy projekt potrzebuje orkiestracji klastra, czy wystarczy mu dobrze zarządzany pojedynczy host.
Co Docker Compose robi dobrze
Compose pozwala utrzymywać konfigurację wielu usług w jednym modelu: obrazy, zmienne środowiskowe, sieci, wolumeny, healthchecki, zależności, sekrety i konfiguracje. [1][3]
Ta sama definicja może być używana w development, CI, staging i produkcji, z dodatkowymi plikami nadpisującymi ustawienia środowiskowe. Docker oficjalnie dokumentuje taki model dla wdrożeń produkcyjnych. [2]
Dla zespołu oznacza to niski próg wejścia, mało obiektów infrastrukturalnych i prosty proces typu `docker compose up -d`.
Compose w produkcji: pojedynczy serwer jest scenariuszem oficjalnie wspieranym
Dokumentacja Docker wprost opisuje uruchamianie Compose w produkcji i wskazuje pojedynczy serwer jako najprostszy sposób wdrożenia aplikacji. [2]
W produkcji zwykle warto oddzielić konfigurację bazową od `compose.production.yaml`, usunąć bind mounty z kodem, dobrać porty i zmienne środowiskowe, ustawić restart policy oraz dodać potrzebne usługi pomocnicze. [2]
Najważniejsze ograniczenie architektoniczne jest proste: jeżeli wszystkie kontenery działają na jednym hoście, awaria tego hosta pozostaje wspólną domeną awarii. Restart kontenera nie naprawi fizycznie niedostępnego serwera.
Healthcheck, zależności i restart w Compose
Compose potrafi uruchamiać usługi w kolejności zależności. Przy `depends_on` z `condition: service_healthy` może także czekać, aż healthcheck zależnej usługi przejdzie poprawnie. [3][4]
Pole `restart` obsługuje między innymi `no`, `always`, `on-failure` i `unless-stopped`. Docker daemon może dzięki temu ponownie uruchomić zakończony kontener. [3][7]
To jest wartościowy mechanizm odporności na awarie procesu, ale nadal działa w granicach tego samego Docker hosta. Nie jest odpowiednikiem planowania workloadu na inny węzeł klastra.
Skalowanie w Compose: repliki to nie to samo co klaster
`docker compose up --scale SERVICE=N` oraz `docker compose scale` pozwalają uruchomić wiele instancji usługi. [6]
W standardowym scenariuszu opisanym przez Docker Compose działa na pojedynczym serwerze. Dokumentacja produkcyjna wskazuje osobny mechanizm klastrowy, Docker Swarm, gdy aplikacja ma być skalowana poza pojedynczy host. [2]
Compose Deploy Specification definiuje pola takie jak `replicas`, `placement`, `resources`, `update_config` i `rollback_config`, ale część `deploy` jest opcjonalna. Implementacja, która jej nie obsługuje, może ją zignorować. [5][3]
Co Kubernetes dodaje ponad pojedynczy Docker host
Kubernetes utrzymuje deklarowany stan workloadów za pomocą kontrolerów. Deployment jest typowym mechanizmem dla aplikacji bezstanowych i automatycznie zarządza Podami poprzez ReplicaSet. [10]
Platforma jest zaprojektowana do działania jako system rozproszony. Może rozmieszczać repliki na dostępnych węzłach, utrzymywać ich liczbę, zapewniać stały endpoint sieciowy przez Service i reagować na awarie. [8][10][15]
To właśnie ten zestaw mechanizmów, a nie sam format YAML, jest największą różnicą względem Compose.
Self-healing: awaria procesu kontra awaria węzła
| Funkcja | Docker Compose | Kubernetes | Różnica |
|---|---|---|---|
| Restart kontenera | Tak | Tak | Oba systemy potrafią ponawiać uruchomienie procesu |
| Odtworzenie po awarii węzła | Nie | Tak | Kubernetes może zaplanować Pod na innym węźle |
| Utrzymywanie replik | Ręcznie | Deklaratywnie | Kubernetes kontroluje stan zadany przez kontrolery |
| Autoscaling z metryk | Nie | Tak | HPA okresowo dostosowuje liczbę replik |
| Stały endpoint dla dynamicznych replik | Sieć Compose | Service | Kubernetes Service abstrahuje zmieniające się Pody |
| Planowanie CPU/RAM | W obrębie hosta | Scheduler klastra | Kubernetes scheduler bierze pod uwagę requests |
W Compose restart policy potrafi odtworzyć kontener, gdy proces zakończy się na działającym Docker hoście. [7]
Kubernetes rozszerza ten model. Może restartować kontenery, zastępować uszkodzone Pody, utrzymywać zadaną liczbę replik oraz przenosić workload, gdy węzeł stanie się niedostępny. [12]
Readiness probe może usunąć niedostępny Pod z backendów Service, a liveness probe może spowodować restart kontenera. Te mechanizmy mają różne cele i błędna konfiguracja liveness może sama powodować awarie. [16]
Networking i service discovery
Compose tworzy sieci aplikacji i pozwala usługom komunikować się po nazwach usług. To wystarcza dla wielu aplikacji działających na jednym Docker hoście. [1]
Kubernetes Service zapewnia stabilny adres IP lub nazwę hosta dla grupy Podów, mimo że same Pody są dynamicznie tworzone i usuwane. Warstwa Service i EndpointSlice kieruje ruch do aktualnych backendów. [15]
W klastrze wielowęzłowym ta abstrakcja ma większe znaczenie, ponieważ instancje aplikacji mogą zmieniać węzeł i adres IP bez zmiany endpointu używanego przez klientów.
Autoscaling i zarządzanie zasobami
Compose umożliwia ręczne skalowanie liczby kontenerów. Nie jest jednak odpowiednikiem kontrolera autoskalującego workload na podstawie metryk klastra. [6]
Kubernetes HorizontalPodAutoscaler może okresowo zmieniać liczbę replik Deploymentu lub StatefulSet na podstawie obserwowanych metryk, na przykład CPU, pamięci albo metryk niestandardowych. [13]
Kubernetes obsługuje także `requests` i `limits` dla CPU, pamięci i innych zasobów. Scheduler bierze requests pod uwagę przy wyborze węzła dla Poda. [14]
Wdrożenia, rolling updates i rollback
W Compose typowe wdrożenie zmiany polega na zbudowaniu lub pobraniu nowego obrazu i odtworzeniu odpowiednich kontenerów. Docker dokumentuje na przykład `docker compose up --no-deps -d web` dla aktualizacji pojedynczej usługi. [2]
Kubernetes Deployment ma wbudowaną strategię RollingUpdate. Nowe Pody są stopniowo tworzone, stare usuwane, a parametry rollout można kontrolować. Kubernetes obsługuje również historię rewizji i `kubectl rollout undo`. [11]
Jeśli projekt wymaga częstych wdrożeń z kontrolą dostępności wielu replik i łatwego rollbacku, Kubernetes daje gotowy mechanizm na poziomie orkiestratora.
Bazy danych i workloady stanowe
Compose dobrze nadaje się do lokalnego uruchamiania baz danych i może również utrzymywać je produkcyjnie na wolumenach, jeśli zespół akceptuje model jednego hosta i sam odpowiada za backup, replikację oraz odtwarzanie.
Kubernetes ma StatefulSet, który utrzymuje stabilną tożsamość Podów i może powiązać je z trwałym storage. Jest przeznaczony dla workloadów wymagających stabilnej tożsamości sieciowej lub trwałych danych. [17]
StatefulSet nie sprawia jednak, że baza danych automatycznie staje się wysoko dostępna. Replikacja, spójność danych, backupy i procedury disaster recovery nadal zależą od konkretnego systemu bazodanowego i architektury.
Koszt operacyjny Kubernetes jest realną częścią decyzji
Dokumentacja Kubernetes podkreśla, że produkcyjny klaster wymaga planowania i przygotowania, szczególnie w zakresie odporności, dostępu użytkowników, dostępności i zasobów. [9]
Kubernetes nie jest kompletnym PaaS. Obserwowalność, logowanie, alerty i wiele elementów platformy pozostają rozwiązaniami opcjonalnymi i rozszerzalnymi. [8]
Managed Kubernetes może przenieść część odpowiedzialności za control plane na dostawcę, ale zespół nadal zarządza workloadami, konfiguracją zasobów, siecią aplikacji, politykami wdrożeń, storage i diagnostyką.
Microservices nie są automatycznym argumentem za Kubernetes
Kubernetes został zaprojektowany z myślą o luźno powiązanych i dynamicznie zarządzanych workloadach, ale sam fakt podziału aplikacji na kilka usług nie tworzy jeszcze potrzeby klastra. [8]
API, frontend, worker, Redis i PostgreSQL mogą być sensownie uruchomione w Compose, jeśli całość mieści się na jednym hoście i wymagania dostępności na to pozwalają.
Lepszym kryterium niż liczba usług jest odpowiedź na pytania o awarie hostów, wymaganą liczbę replik, automatyczne skalowanie, SLO, częstotliwość wdrożeń oraz liczbę zespołów współdzielących platformę.
Kiedy naprawdę przejść z Compose na Kubernetes
| Pytanie | Compose jest rozsądny, gdy | Kubernetes ma sens, gdy |
|---|---|---|
| Awaria hosta | Dopuszczasz odtworzenie lub failover poza Compose | Workload ma automatycznie przeżyć awarię węzła |
| Skala | Mieści się na jednym hoście | Potrzebujesz wielu węzłów i autoscalingu |
| Wdrożenia | Proste recreate lub własny proces jest wystarczający | Potrzebujesz kontrolowanych rolloutów wielu replik |
| Zespół | Jeden lub kilka zespołów utrzymuje prosty stack | Wiele zespołów potrzebuje wspólnej platformy |
| Liczba usług | Liczba usług sama nie tworzy problemu klastra | Operacje na usługach wymagają standaryzacji i automatyzacji |
| Platforma | Minimalizm operacyjny jest priorytetem | Potrzebujesz polityk, schedulingu i abstrakcji klastra |
Migracja jest uzasadniona, gdy pojedynczy host staje się problemem operacyjnym, a nie tylko wtedy, gdy plik `compose.yaml` staje się długi.
Typowe realne sygnały to wymóg dalszej pracy aplikacji po awarii węzła, automatyczne rozmieszczanie wielu replik, dynamiczny autoscaling, kontrolowane rollouty dużej liczby usług, potrzeba wspólnej platformy dla wielu zespołów albo standaryzacja polityk zasobów i sieci. [8][9][12][13]
Jeżeli tych wymagań nie ma, Kubernetes może zwiększyć liczbę ruchomych części bez proporcjonalnej korzyści.
Praktyczna ścieżka dla projektu
Najczęściej rozsądna ścieżka wygląda tak: Dockerfile dla każdej aplikacji, Compose dla development i integracji, następnie Compose także w produkcji, dopóki pojedynczy serwer spełnia wymagania.
Jeżeli pojawia się potrzeba klastra, przygotuj aplikację do stateless działania tam, gdzie to możliwe, przenieś sesje i pliki poza lokalny filesystem kontenera, dodaj poprawne health endpointy, zdefiniuj requests i limits oraz zaprojektuj sposób zarządzania sekretami i storage przed migracją.
Compose może nadal zostać narzędziem lokalnym nawet wtedy, gdy produkcja działa na Kubernetes. Nie ma potrzeby wymuszać identycznego orkiestratora w laptopie dewelopera i na produkcji.
- Zacznij od wymagań dostępności i SLO, nie od technologii.
- Jeżeli jeden host wystarcza, najpierw rozważ Compose.
- Jeżeli awaria hosta nie może zatrzymać aplikacji, potrzebujesz architektury wielowęzłowej.
- Jeżeli skala zmienia się dynamicznie, oceń HPA i architekturę Kubernetes.
- Jeżeli rollout wielu replik musi być automatyczny i kontrolowany, Kubernetes daje gotowe kontrolery.
- Nie przenoś bazy danych do Kubernetes tylko dlatego, że aplikacja tam działa.
- Policz koszt utrzymania klastra, obserwowalności, sieci i aktualizacji.
- Wybierz najprostszy model, który rzeczywiście spełnia wymagania.

