Nixpacks: building a deployable image without writing a Dockerfile
Docker & Containers' own domain taught how to write a Dockerfile by hand, line by line. Railway's default build path skips that step entirely for most real projects — and understanding what it's actually doing under the hood is what lets you recognize the specific, real cases where you still need to write one yourself.
Intermediate
2 min read
What Nixpacks actually does: detect, then build, automatically
Railway sees: package.json with a "start" script
→ Nixpacks detects: this is a Node.js app
→ automatically: installs Node, runs `npm install`, runs the build
script, sets up the right start command — NO Dockerfile written
Nixpacks is Railway's own open-source build system that inspects a repository's files (package.json, requirements.txt, go.mod, Gemfile, and dozens of other signals) and automatically constructs a complete, correct container image — without a human writing a Dockerfile at all. This is a real, different approach from Docker & Containers' own domain, which taught Dockerfile best practices assuming you're the one writing every instruction; Nixpacks exists specifically to remove that step for the large fraction of projects that don't need anything unusual.
Nix packages: why this is more reliable than a naive "guess the framework" heuristic
Nixpacks is built on Nix, a package manager with a real, deliberate property this whole approach depends on: every package version is precisely pinned and reproducible, so the exact same build inputs always produce the exact same result — unlike a naive "install whatever apt-get happens to have today" approach, which can silently drift as upstream package versions change over time. This reproducibility is what makes trusting an automatically-generated build plan reasonable, rather than a risky black box.
railway.json / nixpacks.toml: customizing the automatic build when needed
[phases.build]cmds = ["npm run build", "npm run generate-sitemap"][start]cmd = "npm run start:production"
For cases where Nixpacks' automatic detection doesn't quite match what a project actually needs, a configuration file lets you override specific phases (install, build, start) without abandoning Nixpacks' automatic base-image selection entirely — a middle ground between "fully automatic" and "write the entire Dockerfile by hand."
When you should still bring your own Dockerfile
Railway sees a Dockerfile in the repo root → uses it directly,
skipping Nixpacks entirely
A project with genuinely unusual system dependencies (a specific native library version, a multi-stage build with steps Nixpacks has no detection heuristic for, an existing Dockerfile already tuned and tested for a different platform) should use its own Dockerfile directly — Railway detects one automatically and uses it in place of Nixpacks, no separate toggle required. This is exactly the judgment call Docker & Containers' own domain prepares you to make: Nixpacks removes the need to write a Dockerfile for the common case, not the option to write one when a project's actual requirements genuinely call for it.