Dlaczego zbudowaliśmy własne Cloud Native Buildpacks na Ubuntu 26.04
W skrócie
- Nodion buduje aplikacje z repozytoriów Git za pomocą własnych Cloud Native Buildpacks na stacku nodion-26 opartym na Ubuntu 26.04 LTS; to nie są buildpacki Paketo, Heroku ani Google.
- Dwanaście buildpacków napisanych w Go: Node.js, strony statyczne, Ruby, Python, PHP, Go, Rust, Elixir, Java i .NET, a do tego pliki Procfile i dodatkowe pakiety Debiana.
- Nodion utrzymuje linię wersji języka do końca okresu wsparcia i jeszcze przez trzy miesiące, a do wskazanej wersji minor trafia najnowsza opublikowana poprawka.
- Wykrywanie sprawdza po kolei 14 grup i obsługuje aplikacje w kilku językach, takie jak Laravel z Vite czy Rails z JS; szczegóły znajdziesz w dokumentacji buildpacków.
Nodion buduje aplikacje z repozytoriów Git za pomocą własnych Cloud Native Buildpacks. Trzymamy się specyfikacji Cloud Native Buildpacks dla faz detect, build i launch, ale stack, buildpacki językowe i wersje runtime'ów są nasze. Stack nazywa się nodion-26 i bazuje na Ubuntu 26.04 LTS. To nie są buildpacki Paketo, Heroku ani Google. Wyjaśniamy, dlaczego je zbudowaliśmy i co to oznacza dla Twoich buildów.
Buildpacki w 30 sekund
Buildpack zamienia kod źródłowy w obraz kontenera bez pliku Dockerfile. Rozpoznaje język, instaluje runtime i zależności, buduje aplikację i ustawia polecenie startowe. Cloud Native Buildpacks to otwarty standard dla tego procesu. Builder łączy buildpacki, lifecycle, który je uruchamia, oraz obrazy bazowe do budowania i uruchamiania. Dopiero zaczynasz? Przeczytaj najpierw Cloud Native Buildpacks: czym są i jak działają.
Dlaczego nie użyć istniejącego buildera?
Paketo, Heroku i Google publikują Cloud Native Buildpacks i są to solidne projekty. Sięgnięcie po jeden z nich byłoby drogą na skróty.
Zdecydowaliśmy inaczej, bo dla platformy builder nie jest szczegółem. To on decyduje, na jakim systemie operacyjnym działa Twoja aplikacja, jakie wersje runtime'ów są dostępne, jak wybierana jest wersja i co się dzieje, gdy wersja osiąga koniec wsparcia (end of life). To decyzje produktowe, które nasi użytkownicy odczuwają przy każdym wdrożeniu. Chcieliśmy mieć je we własnych rękach, spisane w jednym miejscu i jednakowe dla wszystkich języków.
Co zbudowaliśmy
Jeden stack na Ubuntu 26.04 LTS
Stack nodion-26 składa się z dwóch obrazów. Obraz buildu zawiera kompilatory i pliki nagłówkowe. Obraz uruchomieniowy (run image) zawiera biblioteki klienckie, których aplikacje często potrzebują, takie jak klienty Postgres i MySQL, ImageMagick oraz certyfikaty CA. Twój proces działa jako użytkownik bez uprawnień roota.
Wybraliśmy Ubuntu 26.04, bo to najnowsze wydanie LTS. Canonical wydał je w kwietniu 2026 roku i zapewnia standardowe wsparcie bezpieczeństwa do maja 2031 roku. Dzięki temu obraz bazowy Twojej aplikacji przez długi czas nie będzie wymagać większej zmiany.
Dwanaście buildpacków, jedna baza kodu
Buildpacków jest dwanaście: Node.js, strony statyczne, Ruby, Python, PHP, Go, Rust, Elixir, Java i .NET, a do tego jeden dla plików Procfile i jeden dla dodatkowych pakietów Debiana. Wszystkie są napisane w Go z użyciem libcnb, biblioteki Go projektu Cloud Native Buildpacks, i znajdują się w jednym module. Korzystają ze wspólnej biblioteki do dobierania wersji, pobierania i logowania, więc przypięcie wersji, komunikat błędu czy weryfikacja pobranego pliku działają tak samo w każdym języku.
Wykrywanie, które radzi sobie z aplikacjami w kilku językach
Builder sprawdza 14 grup od góry do dołu i wygrywa pierwsza grupa, której wszystkie wymagane pliki są obecne. W prawdziwych projektach kolejność ma znaczenie:
- Statyczny frontend w JavaScripcie jest budowany przez Node.js, a potem serwowany przez buildpack dla stron statycznych.
composer.jsonrazem zpackage.jsondaje PHP i Node.js w jednym buildzie (na przykład Laravel z Vite).Gemfilerazem zpackage.jsondaje Ruby i Node.js (Rails z pipeline'em JS).- Dalej sprawdzane są pojedyncze języki, samodzielny serwer Node.js, strona wyłącznie statyczna, a na końcu aplikacja, która ma tylko Procfile.
Dodatkowe pakiety Debiana są opcjonalną częścią każdej grupy, więc każda aplikacja może je dodać.
Własny pipeline runtime'ów
Dostępne runtime'y są zdefiniowane w jednej macierzy wersji w naszym repozytorium. Zadanie uruchamiane co godzinę sprawdza daty końca wsparcia i nowe wydania, stosuje politykę wsparcia i otwiera pull request, który aktualizuje macierz. Po jego scaleniu każda brakująca wersja runtime'u jest budowana i publikowana, a aplikacje dostają ją przy następnym buildzie.
Ruby, Python, PHP i Erlang są kompilowane ze źródeł na naszym obrazie buildu. Pozostałe runtime'y są przepakowywane z plików binarnych publikowanych przez same projekty. Gdy build pobiera runtime, przed rozpakowaniem sprawdza plik z opublikowaną sumą kontrolną.
Co zyskujesz
Polityka wersji, która mieści się w jednym akapicie
Utrzymujemy linię wersji języka, dopóki nie osiągnie końca wsparcia, i jeszcze do trzech miesięcy później. Jeśli wskażesz wersję minor, dostaniesz najnowszy opublikowany patch tej wersji. Build z wersją starszą niż najstarsza opublikowana linia kończy się błędem, bo wersja nie jest już wspierana, a z wersją nowszą niż wszystko, co dotąd zbudowaliśmy, bo nie jest jeszcze dostępna. W obu przypadkach build zatrzymuje się z jasnym komunikatem, zamiast po cichu użyć innej wersji.
Wyjątkiem są Go i Rust: aplikację buduje najnowszy opublikowany toolchain, a kod ze starszymi wartościami w go.mod lub rust-version nadal się kompiluje.
| Język | Domyślnie | Dostępne linie wersji (wrzesień 2026) |
|---|---|---|
| Node.js | 24 | 22, 24, 25, 26 |
| Python | 3.13 | 3.10 do 3.14 |
| PHP | 8.3 | 8.2 do 8.5 |
| Ruby | 3.4 | 3.3, 3.4, 4.0 |
| Go | 1.26 | Najnowszy toolchain (1.25 do 1.27) |
| Rust | 1.96 | Najnowszy toolchain (1.95 do 1.98) |
| Java | 21 | 11, 17, 21, 25, 26 |
| .NET | 10 | 8, 9, 10 |
| Elixir | 1.20 | 1.15 do 1.20 (Erlang/OTP 26 do 29) |
Numery wersji patch zmieniają się w miarę publikowania kolejnych wersji. Strona każdego języka wyjaśnia, jak przypiąć wersję, na przykład za pomocą .node-version lub .python-version.
Własna konfiguracja, gdy jej potrzebujesz
- Procfile: zdefiniuj własne typy procesów. Każdy typ staje się osobnym procesem aplikacji, a domyślne ustawienia języka obowiązują tylko wtedy, gdy nie ma pliku Procfile.
- Dodatkowe pakiety systemowe: wypisz pakiety Debiana w
project.toml(albo wAptfile). Są rozpakowywane do obrazu; skrypty maintainera nie są uruchamiane. - Monorepo: ustaw Base directory na folder aplikacji.
[com.nodion.buildpacks.deb-packages]
install = ["ffmpeg", "pandoc"] Czego nie zmieniliśmy
Specyfikacji. Detect, build i launch działają tak jak na każdej platformie Cloud Native Buildpacks, a wynikiem jest zwykły obraz OCI. Nodion domyślnie używa własnego buildera, ale jeśli wolisz, możesz wybrać inny. Jeśli Twoje repozytorium ma już Dockerfile albo nie jest projektem w obsługiwanym języku, użyj Dockerfile. Nie wiesz, co wybrać? Przeczytaj Dockerfile vs buildpacki.
Aby to wypróbować, połącz repozytorium w Applications → New, wybierz Buildpacks i upewnij się, że Twoja aplikacja nasłuchuje na PORT. Wszystko inne znajdziesz w dokumentacji buildpacków.
Najczęściej zadawane pytania
Jakich buildpacków używa Nodion?
Własnych Cloud Native Buildpacks Nodion na stacku nodion-26 (Ubuntu 26.04 LTS). Są zgodne ze specyfikacją Cloud Native Buildpacks, ale buildpacki językowe, stack i wersje runtime'ów pochodzą od Nodion, a nie od Paketo, Heroku czy Google.
Jakie języki obsługują buildpacki Nodion?
Node.js, Python, Ruby, PHP, Go, Rust, Elixir, Java, .NET i strony statyczne, a także aplikacje z samym plikiem Procfile. Dodatkowe pakiety Debiana można dodać przez project.toml lub plik Aptfile.
Jak długo Nodion wspiera wersję języka?
Linia wersji języka pozostaje dostępna do końca okresu wsparcia i jeszcze przez trzy miesiące. Aplikacje w Go i Rust są zawsze budowane najnowszym opublikowanym toolchainem, który kompiluje też starszy kod.
Czy na Nodion mogę użyć Dockerfile zamiast buildpacków?
Tak. Użyj Dockerfile, gdy Twoje repozytorium już go ma lub nie jest projektem w obsługiwanym języku, a Nodion zbuduje i uruchomi ten obraz.