Waarom we onze eigen Cloud Native Buildpacks op Ubuntu 26.04 bouwden
In het kort
- Nodion bouwt Git-apps met eigen Cloud Native Buildpacks op de stack nodion-26, gebaseerd op Ubuntu 26.04 LTS; het zijn geen buildpacks van Paketo, Heroku of Google.
- Twaalf buildpacks, geschreven in Go, dekken Node.js, statische sites, Ruby, Python, PHP, Go, Rust, Elixir, Java en .NET, plus Procfiles en extra Debian-pakketten.
- Nodion ondersteunt een versielijn van een taal zolang die niet end-of-life is en tot drie maanden daarna, en een gevraagde minor-versie krijgt de nieuwste gepubliceerde patch.
- Bij de detectie worden 14 groepen in volgorde geprobeerd, ook voor polyglotte apps zoals Laravel met Vite of Rails met JS; details staan in de documentatie over buildpacks.
Nodion bouwt Git-apps met eigen Cloud Native Buildpacks. We volgen de specificatie van Cloud Native Buildpacks voor detect, build en launch, maar de stack, de taalbuildpacks en de runtimeversies zijn van ons. De stack heet nodion-26 en is gebaseerd op Ubuntu 26.04 LTS. Het zijn geen buildpacks van Paketo, Heroku of Google. Hier lees je waarom we ze hebben gebouwd en wat dat betekent voor je builds.
Buildpacks in 30 seconden
Een buildpack maakt van broncode een containerimage zonder Dockerfile. Het herkent de taal, installeert een runtime en de afhankelijkheden, bouwt de app en stelt een startcommando in. Cloud Native Buildpacks zijn daarvoor de open standaard. Een builder bundelt de buildpacks, de lifecycle die ze uitvoert en de basisimages voor de build en de runtime. Nieuw in dit onderwerp? Begin met Cloud Native Buildpacks uitgelegd.
Waarom geen bestaande builder hergebruiken?
Paketo, Heroku en Google publiceren allemaal Cloud Native Buildpacks, en het zijn degelijke projecten. Een van die builders overnemen was eenvoudiger geweest.
We hebben daarvan afgezien, want voor een platform is de builder geen detail. Die bepaalt op welk besturingssysteem je app draait, welke runtimeversies beschikbaar zijn, hoe een versie wordt gekozen en wat er gebeurt als een versie end-of-life is. Dat zijn productbeslissingen die onze gebruikers bij elke deploy merken. We wilden ze in eigen hand houden, op één plek vastgelegd en gelijk voor alle talen.
Wat we hebben gebouwd
Eén stack op Ubuntu 26.04 LTS
De stack nodion-26 bestaat uit twee images. De build-image bevat compilers en headerbestanden. De run-image bevat de clientbibliotheken die apps vaak nodig hebben, zoals de clients voor Postgres en MySQL, ImageMagick en CA-certificaten. Je proces draait als gebruiker zonder rootrechten.
We kozen voor Ubuntu 26.04 omdat dit de nieuwste LTS-release is. Canonical bracht deze uit in april 2026 en vermeldt standaard beveiligingsonderhoud tot mei 2031, dus de basis onder je app kan nog lang mee voordat de volgende grote overstap nodig is.
Twaalf buildpacks, één codebase
Er zijn twaalf buildpacks: Node.js, statische sites, Ruby, Python, PHP, Go, Rust, Elixir, Java en .NET, plus één voor Procfiles en één voor extra Debian-pakketten. Ze zijn allemaal in Go geschreven op basis van libcnb, de Go-bibliotheek van het project Cloud Native Buildpacks, en staan in één module. Ze delen één bibliotheek voor het bepalen van versies, downloads en logging. Daardoor werken het vastzetten van een versie, foutmeldingen en downloadcontroles in elke taal op dezelfde manier.
Detectie die overweg kan met polyglotte apps
De builder probeert 14 groepen van boven naar beneden, en de eerste groep waarvoor alle vereiste bestanden aanwezig zijn, wordt gekozen. Bij echte projecten doet de volgorde ertoe:
- Een statische JavaScript-frontend wordt gebouwd met Node.js en daarna geserveerd door het buildpack voor statische sites.
composer.jsonpluspackage.jsonlevert PHP en Node.js in één build op (bijvoorbeeld Laravel met Vite).Gemfilepluspackage.jsonlevert Ruby en Node.js op (Rails met een JS-pipeline).- Daarna losse talen, een zelfstandige Node.js-server, een puur statische site en tot slot een app met alleen een Procfile.
Extra Debian-pakketten zijn een optioneel onderdeel van elke groep, dus elke app kan ze toevoegen.
Onze eigen runtimepipeline
Welke runtimes er zijn, staat in één versiematrix in onze repository. Een job die elk uur draait, controleert end-of-life-datums en nieuwe releases, past het supportbeleid toe en opent een pull request die de matrix bijwerkt. Zodra die is gemerged, wordt elke ontbrekende runtimeversie gebouwd en gepubliceerd, en gebruiken apps ze bij hun volgende build.
Ruby, Python, PHP en Erlang worden vanaf de broncode gecompileerd op onze build-image. De andere runtimes worden opnieuw verpakt vanuit de binaries die de projecten zelf publiceren. Als een build een runtime downloadt, controleert die het bestand tegen de gepubliceerde checksum voordat het wordt uitgepakt.
Wat het je oplevert
Een versiebeleid dat in één alinea past
We ondersteunen een versielijn van een taal zolang die niet end-of-life is, en tot drie maanden daarna. Vraag je een minor-versie aan, dan krijg je de nieuwste gepubliceerde patch van die minor. Een versie die ouder is dan de oudste gepubliceerde lijn, mislukt omdat die end-of-life is, en een versie die nieuwer is dan alles wat we al hebben gebouwd, mislukt omdat die nog niet beschikbaar is. In beide gevallen stopt de build met een duidelijke melding, in plaats van stilletjes een andere versie te gebruiken.
Go en Rust zijn de uitzondering: de nieuwste gepubliceerde toolchain bouwt de app, en code met oudere waarden in go.mod of rust-version compileert nog steeds.
| Taal | Standaard | Gepubliceerde lijnen (september 2026) |
|---|---|---|
| Node.js | 24 | 22, 24, 25, 26 |
| Python | 3.13 | 3.10 t/m 3.14 |
| PHP | 8.3 | 8.2 t/m 8.5 |
| Ruby | 3.4 | 3.3, 3.4, 4.0 |
| Go | 1.26 | Nieuwste toolchain (1.25 t/m 1.27) |
| Rust | 1.96 | Nieuwste toolchain (1.95 t/m 1.98) |
| Java | 21 | 11, 17, 21, 25, 26 |
| .NET | 10 | 8, 9, 10 |
| Elixir | 1.20 | 1.15 t/m 1.20 (Erlang/OTP 26 t/m 29) |
Patchversies worden bijgewerkt zodra we ze publiceren. Op de pagina van elke taal lees je hoe je een versie vastzet, bijvoorbeeld met .node-version of .python-version.
Uitwijkmogelijkheden waar je ze nodig hebt
- Procfile: definieer je eigen procestypes. Elk type wordt een eigen proces van de app, en de standaardinstellingen van de taal gelden alleen als er geen Procfile is.
- Extra systeempakketten: zet Debian-pakketten in
project.toml(of eenAptfile). Ze worden in de image uitgepakt; maintainerscripts worden niet uitgevoerd. - Monorepo's: laat Base directory naar de map van de app wijzen.
[com.nodion.buildpacks.deb-packages]
install = ["ffmpeg", "pandoc"] Wat hetzelfde is gebleven
De specificatie. Detect, build en launch werken zoals op elk platform voor Cloud Native Buildpacks, en het resultaat is een gewone OCI-image. Nodion gebruikt standaard de eigen builder, en je kunt een andere builder kiezen als je dat liever hebt. Heeft je repository al een Dockerfile, of is het geen project in een ondersteunde taal, gebruik dan die Dockerfile. Twijfel je wat past? Lees Dockerfile vs buildpacks.
Om het te proberen koppel je een repository via Applications → New, kies je Buildpacks en zorg je dat je app luistert op PORT. Al het andere staat in de documentatie over buildpacks.
Veelgestelde vragen
Welke buildpacks gebruikt Nodion?
De eigen Cloud Native Buildpacks van Nodion op de stack nodion-26 (Ubuntu 26.04 LTS). Ze volgen de specificatie van Cloud Native Buildpacks, maar de taalbuildpacks, de stack en de runtimeversies zijn van Nodion, geen buildpacks van Paketo, Heroku of Google.
Welke talen ondersteunen de buildpacks van Nodion?
Node.js, Python, Ruby, PHP, Go, Rust, Elixir, Java, .NET en statische sites, plus apps met alleen een Procfile. Extra Debian-pakketten voeg je toe met project.toml of een Aptfile.
Hoe lang ondersteunt Nodion een taalversie?
Een versielijn van een taal blijft beschikbaar zolang die niet end-of-life is en tot drie maanden daarna. Go en Rust bouwen altijd met de nieuwste gepubliceerde toolchain, die ook oudere code compileert.
Kan ik op Nodion een Dockerfile gebruiken in plaats van buildpacks?
Ja. Gebruik een Dockerfile als je repository er al een heeft of geen project in een ondersteunde taal is; Nodion bouwt en draait dan die image.