Dockerfile vs buildpacki: co wybrać dla Twojej aplikacji?
W skrócie
- W Dockerfile samodzielnie opisujesz każdy krok builda; Cloud Native Buildpacks wykrywają Twój język i budują obraz z kodu źródłowego bez Dockerfile.
- Buildpacki pasują do standardowych aplikacji w obsługiwanych językach i zostawiają utrzymanie obrazu bazowego builderowi; Dockerfile sprawdza się przy niestandardowych pakietach systemowych, nietypowych stackach i pełnej kontroli nad obrazem.
- Oba podejścia dają obraz kontenera, więc możesz zacząć od jednego i później przejść na drugie.
- Na Nodion wybierasz Buildpacks albo Dockerfile dla każdej aplikacji: aplikacje z buildpackami nasłuchują na porcie PORT ustawianym przez Nodion, aplikacje z Dockerfile na porcie z EXPOSE lub z zakładki Processes.
Zarówno Dockerfile, jak i buildpacki zamieniają Twój kod źródłowy w obraz kontenera. Różnica polega na tym, kto określa kroki builda: w Dockerfile robisz to Ty, a buildpack ustala je na podstawie Twojego kodu. Wybierz buildpacki dla typowej aplikacji webowej w obsługiwanym języku, a Dockerfile, gdy potrzebujesz pełnej kontroli nad obrazem albo używasz technologii, których nie wykrywa żaden buildpack.
Czym jest Dockerfile
Jak ujmuje to dokumentacja Dockera, Dockerfile to „a text document that contains all the commands a user could call on the command line to assemble an image”, czyli plik tekstowy zawierający polecenia potrzebne do zbudowania obrazu. Wybierasz obraz bazowy, instalujesz pakiety systemowe, kopiujesz kod, instalujesz zależności i ustawiasz polecenie startowe. Każdą instrukcję określasz samodzielnie: masz pełną kontrolę, ale też odpowiadasz za utrzymanie pliku.
FROM node:24-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"] W praktyce przy pisaniu Dockerfile znaczenie mają dwie funkcje:
- Cache warstw: obraz jest budowany warstwami, a Docker zapisuje je w cache. Gdy zmieni się jedna warstwa, wszystkie kolejne też są budowane od nowa. Dlatego przykład kopiuje
package.jsoni instaluje zależności, zanim skopiuje resztę kodu. - Buildy wieloetapowe (multi-stage): kilka instrukcji
FROMw jednym pliku, z których każda rozpoczyna nowy etap. Kompilujesz w jednym etapie i kopiujesz tylko wynik do małego obrazu końcowego, a kompilatory i narzędzia do builda zostają poza nim.
Czym są buildpacki
Buildpack to oprogramowanie, które analizuje Twój kod źródłowy i ustala, jak go zbudować. Cloud Native Buildpacks to otwarty standard w tym zakresie. Build przechodzi przez stałe fazy: detect znajduje buildpacki pasujące do Twojego kodu, build zamienia kod źródłowy w artefakty gotowe do uruchomienia (na przykład instalując runtime i zależności, a potem kompilując), a export zapisuje końcowy obraz OCI. Nie potrzebujesz Dockerfile; opcjonalne pliki, takie jak Procfile czy project.toml, pozwalają skonfigurować build i procesy.
Buildpacki wyróżniają trzy cechy:
- Osobne obrazy do builda i do uruchamiania: kompilatory i pliki nagłówkowe są w obrazie build, a aplikacja działa na obrazie uruchomieniowym (run image), już bez nich.
- Rebase: gdy obraz uruchomieniowy dostaje aktualizację,
pack rebaseprzepina obraz aplikacji na nową bazę bez ponownego budowania aplikacji. - Powtarzalność: lifecycle ustawia znaczniki czasu warstw na stałą datę, więc ten sam kod źródłowy, builder i buildpacki dają ten sam obraz, o ile same buildpacki za każdym razem generują ten sam wynik.
Więcej tła znajdziesz w artykule Czym są Cloud Native Buildpacks.
Dockerfile vs buildpacki w skrócie
| Dockerfile | Buildpacki | |
|---|---|---|
| Kontrola | Pełna: obraz bazowy, pakiety, użytkownicy, układ plików | W ramach opcji buildpacka: przypięte wersje, Procfile, dodatkowe pakiety |
| Utrzymanie | Samodzielnie aktualizujesz obraz bazowy i każdą instrukcję | Opiekun buildera aktualizuje stack i buildpacki języków |
| Aktualizacje bezpieczeństwa | Nowy build z poprawionym obrazem bazowym; musisz tego pilnować samodzielnie | Aktualizacje buildera wprowadzają poprawione obrazy bazowe do następnego builda; istniejący obraz wymaga nowego builda albo jawnego rebase |
| Powtarzalność | Zależy od tego, jak ściśle przypinasz obrazy i pakiety | Wbudowana przy tych samych danych wejściowych, ze stałymi znacznikami czasu warstw |
| Szybkość builda | Szybki przy dobrze uporządkowanym cache warstw; zmiana na początku przebudowuje wszystko, co po niej następuje | Warstwy z cache, np. zależności, są przywracane między buildami |
| Multi-stage | Tak, kilka etapów FROM | Niepotrzebne: narzędzia do builda zostają w obrazie build |
| Nietypowe stacki | Wszystko, co da się zainstalować w obrazie | Tylko to, co wykrywa builder |
Kiedy wybrać buildpacki
- Twoja aplikacja jest napisana w języku obsługiwanym przez builder, np. Node.js, Python, Ruby, PHP, Go, Rust, Java, .NET lub Elixir, albo jest stroną statyczną.
- Nie chcesz samodzielnie utrzymywać obrazów bazowych i pakietów systemu operacyjnego.
- Uruchamiasz wiele usług i chcesz, żeby wszystkie były budowane w ten sam sposób.
- Twój zespół zna język programowania, ale nie zna Dockera.
Kiedy wybrać Dockerfile
- Potrzebujesz konkretnego obrazu bazowego, pakietów systemowych wykraczających poza to, co instaluje buildpack, albo własnego użytkownika.
- Builder nie wykrywa Twojego języka ani frameworka.
- Projekt ma już działający Dockerfile, jak wiele aplikacji open source.
- Chcesz uzyskać bardzo mały obraz dzięki buildowi wieloetapowemu albo używać dokładnie tego samego obrazu lokalnie, w CI i na produkcji.
Jak Nodion obsługuje oba podejścia
W Applications → New łączysz repozytorium Git i wybierasz Buildpacks albo Dockerfile. Jeśli skanowanie znajdzie Dockerfile, wybiera go w pierwszej kolejności. Strategię możesz później zmienić w Settings; zmiana obowiązuje od następnego wdrożenia. Jeśli budujesz gdzie indziej, wdróż zamiast tego gotowy obraz.
Buildpacki na Nodion
- Własne Cloud Native Buildpacks Nodion na stacku
nodion-26(Ubuntu 26.04 LTS). Wykrywają Node.js, Python, Ruby, PHP, Go, Rust, Elixir, Java, .NET i strony statyczne. - Proces działa jako użytkownik bez uprawnień roota. Dodatkowe pakiety Debiana deklarujesz w
project.tomlalbo wAptfile; ich skrypty instalacyjne nie są uruchamiane. Procfiledefiniuje typy procesów; bez niego proceswebdostaje domyślne polecenie dla danego języka.- Port: Nodion ustawia
PORT. Nasłuchuj na nim; większość domyślnych poleceń używa portu 8080, jeśli zmienna nie jest ustawiona.
web: gunicorn myapp.wsgi --bind 0.0.0.0:$PORT
worker: python worker.py Dockerfile na Nodion
- Katalog ustawiony jako Base directory jest kontekstem builda, a znajdujący się w nim
.dockerignorejest uwzględniany. - Pliki multi-stage działają. Nie ma wyboru etapu, więc uruchamiany jest ostatni etap.
- Zmienne środowiskowe oznaczone jako Build są przekazywane jako build args (
ARG). Sekrety BuildKit nie są przekazywane. - Port: Nodion nie ustawia
PORTdla aplikacji z Dockerfile. Powiąż aplikację z portem procesu web, który jest wstępnie uzupełniany na podstawieEXPOSEi który możesz zmienić w zakładce Processes; jeśli ta lista jest pusta, Nodion używaEXPOSEz obrazu, a w ostateczności portu 8080. Nasłuchuj na wszystkich interfejsach, nie tylko na localhost. - Health check: gotowość (readiness) sprawdza żądanie HTTP GET na ścieżkę health checka ustawioną w Settings (domyślnie
/). Odpowiedź 2xx lub 3xx oznacza, że aplikacja działa poprawnie.HEALTHCHECKw obrazie jest ignorowany. USERz obrazu jest respektowany.
Wszystkie szczegóły znajdziesz w dokumentacji buildpacków i w dokumentacji Dockerfile. Nie wiesz jeszcze, co wybrać? Zacznij od buildpacków, a Dockerfile dodaj wtedy, gdy będziesz potrzebować czegoś, czego one nie potrafią.
Najczęściej zadawane pytania
Czy do wdrożenia kontenera potrzebuję Dockerfile?
Nie. Buildpacki budują obraz kontenera bezpośrednio z kodu źródłowego, bez Dockerfile w repozytorium. Możesz też wdrożyć gotowy obraz z rejestru (registry).
Czy buildpacki są lepsze od Dockerfile?
Żadne z tych rozwiązań nie jest lepsze w każdym przypadku. Buildpacki wymagają mniej utrzymania przy standardowych aplikacjach w obsługiwanych językach, a Dockerfile daje Ci pełną kontrolę nad obrazem i działa z każdym stackiem.
Czy mogę użyć wieloetapowego Dockerfile (multi-stage) na Nodion?
Tak. Wieloetapowe Dockerfile działają. Nie ma wyboru etapu, więc uruchamiany obraz to ostatni etap.
Na jakim porcie powinna nasłuchiwać moja aplikacja?
Z buildpackami nasłuchuj na porcie ze zmiennej środowiskowej PORT, którą ustawia Nodion. Przy Dockerfile Nodion nie ustawia PORT: powiąż aplikację z portem procesu web, pobranym z EXPOSE lub ustawionym w zakładce Processes, i nasłuchuj na wszystkich interfejsach.