Uruchomienie backendu w kontenerze nie musi oznaczać utrzymywania własnych maszyn, aktualizowania systemu i pilnowania pojemności klastra. Amazon ECS z Fargate pozwala skupić się na obrazie aplikacji, konfiguracji zasobów i wdrożeniu, a infrastrukturę obliczeniową oddaje pod opiekę AWS. Pokażę, jak działa ten model, ile może kosztować, jak wdrożyć aplikację Python oraz gdzie kryją się jego ograniczenia.
Fargate upraszcza kontenery, ale nie zwalnia z projektowania infrastruktury
- Brak serwerów do utrzymania oznacza, że nie zarządzasz hostami EC2, ich aktualizacjami ani pojemnością.
- Task definition określa obraz kontenera, CPU, pamięć, porty, zmienne środowiskowe i logowanie.
- Sieć awsvpc daje każdemu zadaniu własny interfejs sieciowy oraz security group.
- Rozliczenie za sekundę obejmuje vCPU, pamięć i dodatkowy storage, ale osobno płacisz między innymi za NAT, logi i load balancer.
- Najlepsze zastosowanie to API, mikroserwisy, zadania asynchroniczne i aplikacje o zmiennym obciążeniu.
Co naprawdę dostajesz w ECS z Fargate
Amazon ECS to orkiestrator kontenerów, czyli usługa, która uruchamia, zatrzymuje, monitoruje i skaluje zadania. Fargate jest jednym ze sposobów ich uruchamiania. Najprościej wyobrazić to sobie tak: ECS podejmuje decyzje, a Fargate dostarcza środowisko, w którym kontener faktycznie działa.
W wariancie EC2 sam utrzymujesz instancje, na których ECS umieszcza kontenery. Przy Fargate nie wybierasz hosta ani nie instalujesz agenta na maszynie. Podajesz wymagania aplikacji, na przykład 0,5 vCPU i 1 GB RAM, a AWS uruchamia zadanie na zarządzanej infrastrukturze.
To nie jest jednak pełna ucieczka od DevOps. Nadal odpowiadasz za obraz Dockera, konfigurację VPC, security groups, role IAM, sekrety, logi, health checki i politykę skalowania. W praktyce Fargate usuwa sporą część pracy operacyjnej, ale nie usuwa potrzeby świadomego projektowania systemu.
Najważniejsze elementy modelu
- Cluster to logiczne miejsce grupowania usług i zadań.
- Task definition jest wersjonowanym opisem uruchomienia kontenera.
- Task to konkretna uruchomiona instancja definicji.
- Service pilnuje, aby działała określona liczba zadań i uruchamia nowe po awarii.
- Amazon ECR przechowuje obrazy kontenerów, choć można korzystać także z innych rejestrów.
Moja praktyczna zasada jest prosta: dla publicznego API niemal zawsze tworzę service, a pojedyncze taski zostawiam do migracji baz danych, zadań jednorazowych i procesów uruchamianych przez harmonogram.

Jak wygląda wdrożenie backendu krok po kroku
Typowy przepływ zaczyna się od aplikacji, na przykład API stworzonego we Flasku lub FastAPI. Kod trafia do obrazu Dockera, obraz do rejestru, a ECS otrzymuje definicję zadania i informację, ile jego kopii ma działać.
- Zbuduj obraz i uruchom go lokalnie, sprawdzając port, zmienne środowiskowe oraz obsługę sygnału zakończenia.
- Wyślij obraz do ECR lub prywatnego rejestru.
- Zarejestruj task definition z parametrami CPU, pamięci, sieci i logowania.
- Utwórz usługę ECS z żądaną liczbą zadań.
- Dodaj Application Load Balancer, jeśli backend ma obsługiwać ruch HTTP lub HTTPS.
- Połącz wdrożenie z CI/CD, aby każda zatwierdzona wersja mogła przejść przez testy i automatyczny deployment.
Dla aplikacji Python szczególnie ważny jest sposób startu procesu. Kontener powinien uruchamiać serwer produkcyjny, taki jak Gunicorn lub Uvicorn, a nie wbudowany serwer developerski. Przykładowo API FastAPI może działać z kilkoma workerami, ale ich liczbę trzeba dobrać do przydzielonego CPU i charakteru żądań.
Minimalny fragment definicji zadania
{
"family": "backend-api",
"requiresCompatibilities": ["FARGATE"],
"networkMode": "awsvpc",
"cpu": "512",
"memory": "1 GB",
"containerDefinitions": [
{
"name": "api",
"image": "rejestr/backend-api:1.4.0",
"portMappings": [
{
"containerPort": 8000,
"protocol": "tcp"
}
],
"essential": true
}
]
}
Sam fragment nie wystarczy do produkcji. Dodałbym jeszcze log driver, health check, limit zasobów kontenera, role IAM oraz bezpieczne przekazywanie sekretów. Wersjonowanie obrazu konkretnym tagiem albo digestem jest rozsądniejsze niż używanie etykiety latest, która utrudnia odtworzenie konkretnego wdrożenia.
CPU, pamięć i sieć decydują o powodzeniu
Fargate wymaga zdefiniowania CPU i pamięci na poziomie całego taska. Nie można dobrać dowolnej pary wartości. Przykładowo 0,25 vCPU obsługuje 512 MB, 1 GB lub 2 GB RAM, a przy 1 vCPU można wybrać od 2 do 8 GB pamięci.
| CPU | Dostępna pamięć | Typowe zastosowanie |
|---|---|---|
| 0,25 vCPU | 0,5-2 GB | Małe API, webhooki, zadania pomocnicze |
| 0,5 vCPU | 1-4 GB | Niewielki backend Python |
| 1 vCPU | 2-8 GB | Typowe API z umiarkowanym ruchem |
| 2 vCPU | 4-16 GB | Cięższe endpointy i procesy obliczeniowe |
| 4 vCPU | 8-30 GB | Wymagające usługi backendowe |
Nie zaczynałbym od dużego pakietu „na zapas”. Lepszy punkt wyjścia to mała konfiguracja, test obciążeniowy i obserwacja metryk CPU oraz pamięci. Jeśli kontener kończy się z błędem Out of memory, zwiększasz RAM. Jeśli CPU długo utrzymuje się blisko limitu, zwiększasz vCPU albo liczbę replik.
Sieć prywatna czy publiczna
Taski Fargate korzystają z trybu awsvpc, więc każdy otrzymuje własny interfejs sieciowy. Musisz wskazać subnety oraz security groups. Dla aplikacji produkcyjnej zwykle wybieram prywatne subnety w co najmniej dwóch Availability Zones, a ruch z Internetu kieruję przez load balancer w subnetach publicznych.
Task w prywatnym subnecie potrzebuje drogi do pobrania obrazu i komunikacji z usługami zewnętrznymi. Najczęściej oznacza to NAT Gateway albo endpointy VPC dla ECR i innych usług. Publiczny adres IP upraszcza start, ale zwiększa powierzchnię ataku i nie powinien być domyślną decyzją dla backendu.
Storage nie zastępuje bazy danych
Każde zadanie ma domyślnie 20 GB efemerycznego storage. To dobre miejsce na pliki tymczasowe, cache lub rozpakowanie danych, ale zawartość może zniknąć po wymianie taska. Dane użytkowników powinny trafić do trwałego magazynu, takiego jak S3, EFS, EBS albo zarządzana baza danych.
Ile kosztuje uruchomienie aplikacji
Rozliczenie obejmuje osobno przydzielone vCPU, pamięć i dodatkową przestrzeń efemeryczną. Opłata nalicza się od momentu pobierania obrazu do zakończenia taska, z minimalnym czasem jednej minuty dla kontenerów Linux. Dla Windows obowiązuje minimalny czas pięciu minut.
Dobrym przykładem skali jest kalkulacja dla regionu US East. Pięć tasków działających przez 10 minut dziennie, każdy z 1 vCPU, 2 GB RAM i 30 GB storage, daje około 1,26 USD miesięcznie za samą moc obliczeniową w wariancie Linux x86. Dla architektury ARM podobny przykład wynosi około 1,02 USD. To nie jest końcowy rachunek całej architektury.
| Element | Za co płacisz | Co często zaskakuje |
|---|---|---|
| Fargate | vCPU, RAM i dodatkowy storage | Większy task kosztuje także wtedy, gdy zasoby są niewykorzystane |
| NAT Gateway | Godziny działania i transfer | Przy małym backendzie może kosztować więcej niż same taski |
| Load balancer | Czas działania i jednostki przetworzonego ruchu | Jeden ALB jest wspólnym kosztem dla wielu usług |
| CloudWatch | Logi, metryki i retencja | Debugowanie bez limitu retencji potrafi podnieść rachunek |
| Publiczne IPv4 | Przypisane adresy publiczne | Warto ich unikać, jeśli nie są potrzebne |
Jeżeli obciążenie jest stałe, można rozważyć Savings Plans. Dla zadań przerywalnych, takich jak batch processing albo testy, Fargate Spot może obniżyć koszt nawet o 70%, ale trzeba zaakceptować możliwość przerwania zadania. Przy kosztorysie dla Polski sprawdziłbym konkretny region, transfer, NAT, logi i load balancer w kalkulatorze cenowym, zamiast przeliczać wyłącznie stawkę za kontener.
Fargate czy EC2, Lambda albo Kubernetes
Fargate nie jest automatycznie najlepszym wyborem dla każdego kontenera. Ja patrzę przede wszystkim na kontrolę nad infrastrukturą, przewidywalność obciążenia, czas działania procesu i koszty stałe.
| Rozwiązanie | Największa zaleta | Główne ograniczenie | Kiedy wybrać |
|---|---|---|---|
| ECS z Fargate | Kontenery bez zarządzania hostami | Mniejsza kontrola i koszt zależny od przydzielonych zasobów | API, mikroserwisy, zmienne obciążenie |
| ECS na EC2 | Większa kontrola i możliwość upakowania tasków | Samodzielne aktualizacje, skalowanie i utrzymanie instancji | Duże, stałe obciążenie lub niestandardowe wymagania |
| AWS Lambda | Uruchamianie funkcji bez ciągłego procesu | Ograniczenia modelu funkcji, czasu i środowiska | Zdarzenia, krótkie operacje, automatyzacja |
| EKS z Fargate | Kubernetes bez zarządzania częścią workerów | Większa złożoność operacyjna Kubernetes | Organizacje już używające Kubernetes |
Fargate wygrywa, gdy zespół chce używać Dockera i ECS, ale nie chce budować kompetencji wokół hostów. EC2 może być tańsze przy całodobowym, stabilnym obciążeniu, szczególnie gdy potrafisz dobrze wykorzystać instancje. Lambda będzie prostsza dla pojedynczych funkcji, lecz nie zastąpi wygodnie długo działającego API z własnym środowiskiem systemowym.
Pułapki produkcyjne i dobre praktyki
Najczęstszy błąd polega na traktowaniu Fargate jak „serwera bez SSH”. To zupełnie inny model pracy. Nie zakładasz, że wejdziesz do hosta i ręcznie naprawisz problem, dlatego logi, metryki i health checki muszą być gotowe przed wdrożeniem.
Stabilne wdrożenia
- Przechowuj obrazy pod niezmiennymi tagami lub digestami.
- Włącz deployment circuit breaker, aby wadliwa wersja mogła automatycznie się wycofać.
- Ustaw health check aplikacji, który sprawdza rzeczywistą gotowość, a nie tylko fakt działania procesu.
- Rozłóż minimum 2 taski w 2 strefach, jeśli usługa ma być odporna na awarię jednej strefy.
- Obsługuj SIGTERM i kończ połączenia łagodnie podczas wymiany kontenera.
Bezpieczeństwo i sekrety
Nie umieszczaj haseł w obrazie ani w repozytorium. Sekrety trzymaj w Secrets Manager lub Parameter Store, a taskowi nadaj tylko uprawnienia, których naprawdę potrzebuje. Osobno skonfiguruj execution role do pobrania obrazu i wysyłania logów oraz task role używaną przez kod aplikacji.
Przeczytaj również: API first - Szybciej, lepiej, bez błędów? Sprawdź, jak!
Wydajność obrazu
Duży obraz wydłuża start taska i może pogorszyć autoskalowanie. W Pythonie ograniczam rozmiar obrazu przez wieloetapowy Docker build, pliki .dockerignore, lekką bazę i usunięcie narzędzi developerskich z finalnej warstwy. Dla obrazów większych niż około 250 MiB po kompresji można rozważyć lazy loading SOCI, ale najpierw sprawdziłbym, czy odchudzenie obrazu nie rozwiązuje problemu prościej.
Do skalowania usługi użyj metryk, a nie przeczucia. Dla API sensowne mogą być CPU, pamięć, liczba żądań na target albo opóźnienie p95. Zadania workerów lepiej skalować według długości kolejki, bo niskie użycie CPU nie oznacza, że system szybko opróżnia kolejkę.
Jak podejść do pierwszego wdrożenia
Na początek wybrałbym prosty backend, prywatny subnet, ECR, jedną usługę ECS i ALB. Konfigurację trzymałbym w Terraformie, AWS CDK albo CloudFormation, ponieważ ręczne klikanie w konsoli szybko prowadzi do różnic między środowiskiem testowym i produkcyjnym.
Minimalny test powinien obejmować wdrożenie nowej wersji, restart taska, skalowanie do zera i z powrotem, utratę jednego taska oraz odczyt logów. Dopiero gdy te scenariusze są przewidywalne, dodawałbym bardziej zaawansowane strategie, takie jak blue-green deployment czy Fargate Spot.
Najlepszą miarą sukcesu nie jest to, że kontener wystartował. Liczy się także czas wdrożenia, możliwość odtworzenia środowiska, widoczność błędów i rachunek, który nie rośnie bez kontroli.
Fargate jako rozsądny pierwszy krok w stronę produkcyjnego DevOps
Amazon ECS z Fargate dobrze sprawdza się jako warstwa uruchomieniowa dla backendów, które mają działać w kontenerach, ale nie wymagają własnego klastra maszyn. Daje szybkie wdrożenie, automatyczne odtwarzanie zadań i wygodne skalowanie, pod warunkiem że poprawnie zaprojektujesz sieć, role, logowanie i koszty.
Jeżeli budujesz API w Pythonie, zacznij od małego obrazu, jasno określonych zasobów i dwóch replik w różnych strefach. Dopiero później optymalizuj architekturę pod obciążenie. Taka kolejność zwykle daje więcej niż przedwczesne komplikowanie infrastruktury.
