Skip to main content
[ PIER ]
Au

Auto-build (Railpack)

Push code, get a container — no Dockerfile required.

Application #auto#buildpack#railpack#git

Railpack is a modern build-pack-style image builder that auto-detects your language and framework, generates a BuildKit plan, and produces a production OCI image. Pier wraps it so you can ship Node, Python, Go, Rust, Ruby, PHP, Java, Deno, Bun, Elixir and more directly from a Git URL — no Dockerfile, no Nixpacks lock-in, no manual config.

Deploy with Pier

  1. 1 Open the Pier dashboard and click Add service.
  2. 2 Pick Auto-build (Railpack) from the template list.
  3. 3 Choose the version, set a service name, and Pier provisions the container, storage, and ports automatically.
  4. 4 Attach a domain if you want HTTPS. Traefik auto-provisions the Let's Encrypt certificate.

What is Railpack?

Railpack is an open-source image builder developed by Railway and released in 2024 as the successor to Nixpacks. It inspects a Git repository, identifies the language and framework, and produces a production-ready OCI image using BuildKit — without requiring a Dockerfile.

The result is the “push code, get a container” experience pioneered by Heroku and Railway, but built on modern infrastructure: BuildKit’s parallel LLB execution, granular layer caching, and minimal language-specific base images instead of the heavy Nix store that Nixpacks shipped. Typical Railpack images are 20–80% smaller than the equivalent Nixpacks output and rebuild 2–5× faster on cache hits.

Pier wraps Railpack as the “Auto-build” service template. You give it a Git URL, a port, and (optionally) a start command — Pier clones the repo, runs Railpack, builds the image, and ships it under Traefik with TLS. The whole loop, from git push to live URL, takes 30–120 seconds depending on the project size and cache state.

How Pier deploys it

When you create an Auto-build service, Pier:

  1. Clones the configured Git URL at the chosen branch.
  2. Runs railpack build on the source — Railpack inspects, plans, and generates an OCI image tagged for your service.
  3. Stores the image in Pier’s local registry and starts a container on the exposed port.
  4. Wires Traefik so the service is reachable at its assigned domain (with automatic Let’s Encrypt TLS if a custom domain is attached).

A railpack.json at the repo root lets you override anything Railpack auto-detects — language version, system packages, install/build/start commands, build-time env vars. Most projects need zero config.

Webhook redeploys: configure your Git host to POST to the Pier redeploy webhook for the service, and every push to the watched branch rebuilds and rolls out automatically.

When NOT to use Railpack

If you already have a Dockerfile that works, keep it — use the Dockerfile template. Hand-tuned Dockerfiles beat any auto-builder on image size, layer control, and security review surface for a specific app.

If your build needs exotic system packages, custom multi-stage logic, or non-OCI artifacts (init systems, supervisord stacks, multi-binary distroless), Dockerfile is also the right answer.

For pre-built images from a registry — use the Docker Image template. For multi-container stacks defined together — Docker Compose. Railpack shines specifically for “I have a repo, I want a container, I don’t want to write Dockerfile lines.”

Key features

Zero-config language detection

Detects Node, Python, Go, Rust, Ruby, PHP, Java, Deno, Bun, Elixir, Static and more from package files (package.json, requirements.txt, go.mod, Cargo.toml, Gemfile, composer.json). No buildpacks list to memorize.

BuildKit-native

Generates an LLB (low-level build) plan that BuildKit executes — parallel stages, granular layer cache, frontend isolation. 30–80% faster repeat builds vs classic buildpacks.

Smaller images than Nixpacks

Typical Railpack image is 20–80% smaller than the equivalent Nixpacks output by skipping the Nix store layer and using minimal Debian or Alpine bases per language.

Framework-aware

Knows Next.js, Astro, Vite, Nuxt, Remix, SvelteKit, Django, Flask, FastAPI, Rails, Laravel, Phoenix — picks the right install / build / start commands automatically.

Static site mode

Detects pure static output (Astro, Vite, Hugo, Jekyll) and ships an `nginx` runtime instead of a Node server — 5 MB image, microsecond cold start.

Override-friendly

Drop a `railpack.json` in repo root to pin versions, add system packages, override install/build/start commands, set env vars. Override only what you need; defaults handle the rest.

Use cases

Push-to-deploy workflows

Wire your repo to Pier, push to main → Railpack auto-builds → service rolls out. No CI YAML, no Dockerfile maintenance.

Polyglot teams

One template handles every service in a multi-language monorepo. Backend Go service, frontend Next.js, ML Python worker — same builder, same UX.

Migrating off Heroku / Render / Railway

Apps already designed for Heroku / Render / Railway buildpacks port to Railpack with zero or near-zero changes. Same conventions (Procfile, package.json scripts, requirements.txt).

SSR + static side-by-side

An Astro site with `output: 'server'` runs Node SSR; the same repo as `output: 'static'` ships an nginx container — Railpack picks correctly based on the build output.

Quick demos & prototypes

Spin up a working URL from any GitHub repo in under a minute. Useful for PR previews, hackathons, customer demos.

Code examples

Deploy a Next.js app (no config) bash
# In Pier:
# 1. New service → Auto-build (Railpack)
# 2. Git URL: https://github.com/you/my-next-app.git
# 3. Branch: main
# 4. Port: 3000
# 5. Deploy.
#
# Railpack detects Next.js, runs:
#   npm ci → npm run build → npm run start
# Result: production OCI image, ~120 MB.
railpack.json overrides json
{
  "$schema": "https://schema.railpack.com",
  "provider": "node",
  "packages": {
    "node": "22",
    "pnpm": "9"
  },
  "aptPackages": ["ffmpeg", "imagemagick"],
  "buildCommand": "pnpm run build",
  "startCommand": "pnpm start",
  "env": {
    "NODE_ENV": "production"
  }
}
Multi-language monorepo (root config) json
{
  "provider": "python",
  "packages": { "python": "3.12" },
  "installCommand": "pip install -r requirements.txt",
  "startCommand": "uvicorn app:app --host 0.0.0.0 --port $PORT"
}
Static site shortcut json
{
  "provider": "static",
  "buildCommand": "npm run build",
  "outputDirectory": "dist"
}

How it compares

vs Dockerfile (this catalog) Dockerfile gives you 100% control but you write and maintain the build logic. Railpack writes it for you and stays out of the way until you need an override. Use Dockerfile when you need exotic system packages or multi-arch builds; use Railpack for everything else.
vs Nixpacks (Railway's previous builder) Nixpacks pioneered the auto-detect-and-build pattern but produces large images by shipping a Nix store. Railpack is the successor — smaller images, faster cache, simpler overrides, modern BuildKit frontend.
vs Heroku Buildpacks / Cloud Native Buildpacks CNB is an open standard with a rich ecosystem but slower builds and a steeper override curve (project.toml, buildpack ordering). Railpack is simpler, faster, opinionated.
vs Manual Docker image A hand-tuned Dockerfile will always win on size + boot time for the specific app it targets. Railpack wins on iteration speed and uniformity across services.

Frequently asked questions

What languages does Railpack support?
Node, Python, Go, Rust, Ruby, PHP, Java (Maven/Gradle), Deno, Bun, Elixir, and a "static" provider for pre-built site output. New providers ship regularly.
Where do I put a railpack.json?
In the repo root (next to package.json / pyproject.toml / etc.). Railpack reads it before language detection and uses its fields as overrides. Everything in the file is optional.
How do I set runtime environment variables?
Use Pier's env-vars UI on the service — they're injected at container start. `railpack.json`'s `env` block is for build-time variables only.
Does it support private packages (npm, PyPI, etc.)?
Yes — set NPM_TOKEN / PIP_INDEX_URL / etc. as build-time env vars in Pier. Railpack passes them into the BuildKit build context as secrets, not baked into the final image.
What's the build cache behavior?
BuildKit layer cache lives on the Pier host. First build is full; subsequent builds reuse install/build layers as long as the lockfile and source hash match. Typical 80%+ cache hit on incremental pushes.
How do I trigger rebuilds?
Push to the configured branch and Pier's webhook (if wired) triggers a rebuild. Or hit the "Redeploy" button in the service UI — it pulls the latest commit and rebuilds.
Can I see what Railpack decided to do?
Yes — the build log prints the detected provider, install/build/start commands, and the LLB plan. If detection picks the wrong stack, override in `railpack.json`.
Difference from "Deploy from Dockerfile"?
With Dockerfile you write the build recipe. With Railpack the recipe is inferred. If you already have a working Dockerfile, use the Dockerfile template — no reason to switch.

Related services

Deploy on your VPS

Railpack is a modern build-pack-style image builder that auto-detects your language and framework, generates a BuildKit plan, and produces a production OCI image. Pier wraps it so you can ship Node, Python, Go, Rust, Ruby, PHP, Java, Deno, Bun, Elixir and more directly from a Git URL — no Dockerfile, no Nixpacks lock-in, no manual config.

Deploy this service →