comparisons

Nixpacks vs Docker: The Ultimate Guide to Size, Speed, and Why Railway Moved On

Written by Mert Batur
Feb 16, 2026
16 read
Nixpacks vs Docker: The Ultimate Guide to Size, Speed, and Why Railway Moved On

The Nixpacks vs Docker decision used to be simple: trade control for convenience. But in 2025, Railway, the team that built Nixpacks, put it in maintenance mode and shipped Railpack as its replacement. That changes the calculus entirely. This is the full docker vs nixpacks comparison with real image sizes, build speed data, side-by-side code, and a decision framework that accounts for where things actually stand in 2026.

Nixpacks vs Docker at a Glance

If you need to deploy without a Dockerfile and your stack is supported, Nixpacks (or its successor Railpack) gets you running in seconds. If you care about image size, build speed, or production optimization, a custom Dockerfile wins every time.

FeatureNixpacksDocker (Dockerfile)
ConfigurationZero-config auto-detectionManual Dockerfile
Setup EffortSeconds (just push code)Minutes to hours (write + optimize)
Image Size800MB-1.3GB typical50-150MB with Alpine + multi-stage
Build Speed (first)Slower (Nix package download)Faster with cached base images
Build Speed (cached)Inconsistent cachingPredictable layer caching
Language Support~20 auto-detected languagesAnything you can containerize
Version PinningCommit-based (no semver)Exact version control
Production ReadinessDevelopment/stagingProduction-grade
Learning CurveNear zeroModerate (Dockerfile syntax)
CustomizationLimited (nixpacks.toml)Complete control
Current StatusMaintenance mode (deprecated)Actively developed
Best ForRapid prototyping, hackathonsProduction apps, optimized deploys

One thing worth understanding upfront: Nixpacks doesn't replace Docker. It generates a Dockerfile under the hood and uses Docker's BuildKit to produce OCI-compliant images. It's an abstraction layer on top of Docker, not an alternative to it.

What Is Nixpacks? (And How It Differs from Nix)

Nixpacks is a build tool created by Railway that auto-detects your app's language and framework, then generates a container image without any configuration. You push code, Nixpacks figures out the rest. That's the pitch, and for simple apps, it genuinely delivers.

Here's what a Nixpacks build looks like:

bash
# Zero config -- Nixpacks detects your stack automatically
nixpacks build . --name my-app

# Or with a custom start command
nixpacks build . --name my-app --start-cmd "node dist/index.js"

Nixpacks scans your source for files like package.json, requirements.txt, or go.mod and picks the right "provider", its term for language-specific build recipes. It was designed to be faster and simpler than Heroku-style buildpacks, and for a while it was Railway's default builder.

How Nixpacks Detects Your Stack

The detection pipeline is straightforward: Nixpacks walks your project root looking for known config files. Found a package.json? Node.js provider. Found requirements.txt or pyproject.toml? Python provider. It even handles monorepos to some extent, though things get messy with non-standard project layouts.

Nix vs Nixpacks: Not the Same Thing

This trips up almost everyone (including most articles ranking for this query). Nix is a functional package manager and build system focused on reproducible builds. Nixpacks is a specific tool that uses Nix packages internally to resolve dependencies. They're related but different, like saying "npm" and "create-react-app" are the same thing because one uses the other.

The critical context for 2026: Nixpacks is in maintenance mode. Railway stopped adding features and built Railpack to address fundamental limitations. Existing projects still work, but there's no roadmap for improvements.

Docker and Dockerfiles: The Industry Standard

You know Docker. So let's skip the "Docker is a containerization platform" paragraph and focus on what matters for this comparison.

A Dockerfile gives you explicit, layer-by-layer control over your container image. You choose the base image, control which files get copied, specify exactly which dependencies get installed, and optimize the final result with multi-stage builds. Here's a production-ready example:

dockerfile
# Multi-stage Node.js Dockerfile -- optimized for size
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/index.js"]

The key Docker features relevant to this comparison: multi-stage builds let you separate build-time dependencies from the runtime image. Layer caching through BuildKit makes subsequent builds fast and predictable. And base image selection (Alpine, distroless, scratch) gives you direct control over image size and attack surface.

Docker knowledge is also universally transferable. Every cloud provider, every CI/CD platform, every deployment target understands a Dockerfile.

Nixpacks vs Docker: Head-to-Head Comparison

Setup and Configuration

Nixpacks' biggest selling point is zero-config deployment. For a standard Node.js app, you literally don't need any configuration file. Push code, get a container. With Docker, you need to write and maintain a Dockerfile.

When you do need to customize Nixpacks, you use nixpacks.toml:

toml
# nixpacks.toml -- customize Nixpacks behavior
[phases.setup]
nixPkgs = ["...", "ffmpeg"]  # Add system dependencies

[phases.build]
cmds = ["npm run build"]

[start]
cmd = "node dist/index.js"

The equivalent Dockerfile is more verbose but far more explicit:

dockerfile
FROM node:20-alpine
RUN apk add --no-cache ffmpeg
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
CMD ["node", "dist/index.js"]

For a hackathon or prototype, Nixpacks saves you real time. For anything you'll maintain longer than a weekend, that Dockerfile pays for itself in debuggability and optimization potential.

Verdict: Draw. Nixpacks wins for speed-to-deploy. Docker wins for long-term maintainability. Pick based on your timeline.

Image Size

This is where the comparison gets brutal. Nixpacks images are big. Not "slightly larger" big, we're talking 10-17x larger than an optimized Dockerfile for the same application.

One well-documented case: a developer migrated a Next.js app from Nixpacks to a custom Dockerfile and saw the image shrink from 1.3GB to 76.83MB, a 17x reduction. That's not unusual.

FrameworkNixpacks ImageOptimized DockerReduction
Node.js (Express)~900MB~80MB (Alpine)11x
Python (FastAPI)~1.1GB~90MB (slim)12x
Go (net/http)~800MB~15MB (scratch)53x
Static HTML~600MB~5MB (nginx-alpine)120x
Next.js~1.3GB~77MB (Alpine multi-stage)17x

The reason comes down to architecture. Nixpacks dumps everything into /nix/store, build tools, compilers, debug symbols, libraries you'll never need at runtime, all in one massive layer. Docker's multi-stage builds let you throw away everything except the actual runtime artifacts.

Verdict: Docker wins decisively. This isn't a close call. If image size matters to your project, and it almost always does for production, Docker is the only real option.

Build Speed and Caching

First builds with Nixpacks are typically slower because it downloads Nix packages from scratch. According to Railway's own data, a typical Nixpacks build takes around 1 minute 27 seconds, versus 15 seconds for a Dockerfile build and 6 seconds for a pre-built image.

Subsequent builds tell a more nuanced story. Nix binary caching can speed things up, but it's less predictable than Docker's layer caching. A change to your package.json invalidates the Nix cache broadly, while Docker layer caching only rebuilds layers from the changed step forward.

Docker layer caching is also more transparent. You can see exactly which layers changed and why. Nixpacks caching is more of a black box, it either hits or it doesn't, and debugging cache misses in the Nix store requires expertise most teams don't have.

Verdict: Docker wins. More predictable, faster for both first and cached builds, and easier to debug when caching breaks.

Language and Framework Support

Nixpacks auto-detects around 20 languages and frameworks: Node.js, Python, Go, Rust, Java, Ruby, PHP, .NET, Elixir, and more. For supported stacks, the detection is genuinely impressive, it picks the right runtime version, sets up the build command, and configures the start command automatically.

Docker supports anything you can write a Dockerfile for. That's effectively unlimited. Exotic runtimes, custom toolchains, multi-language monorepos, if it runs on Linux, Docker handles it.

The version pinning difference matters more than you'd think. Nixpacks uses commit-based versioning for Nix packages. You can't say "Python 3.11.4", you get whatever version the Nix commit provides. Docker gives you exact version control: FROM python:3.11.4-slim is deterministic.

Verdict: Docker wins for flexibility. Nixpacks is convenient if your stack is on the supported list. Docker handles everything, with precise version control.

Production Readiness and Security

Nixpacks images include far more packages than your app actually needs. That translates to a larger attack surface, more binaries means more potential vulnerabilities. The bloated /nix/store layer contains compilers, build tools, and libraries that have no business in a production image.

Docker gives you options like Alpine (minimal), distroless (no shell, no package manager), or even FROM scratch for compiled languages. These minimal images contain only what your app needs to run, drastically reducing the attack surface.

Debugging is another gap. Nixpacks images have an unfamiliar directory structure centered around /nix/store with hash-based paths. If something goes wrong in production, you'll spend time figuring out the filesystem layout before you can even start troubleshooting.

Verdict: Docker wins for production. Smaller attack surface, familiar debugging tools, and established security scanning pipelines all favor Docker.

Developer Experience

Here's where Nixpacks genuinely shines. For a developer who's never written a Dockerfile, going from code to running container in one command is magical. nixpacks build ., done. No syntax to learn, no base image to choose, no layer ordering to think about.

Docker's learning curve isn't steep, but it's real. Writing an efficient Dockerfile requires understanding layer caching, multi-stage builds, .dockerignore, and the distinction between COPY and ADD. It's knowledge that pays off, but it takes time to acquire.

The long-term trade-off is worth considering. Nixpacks knowledge is platform-specific, it's useful on Railway, Coolify, and a handful of other platforms. Docker knowledge is universal and transferable to any job, any cloud provider, any deployment target.

Verdict: Nixpacks wins for getting started. Docker wins for career-long utility. If you're learning, start with Nixpacks to ship fast, then learn Docker for production.

Side-by-Side: Same App, Both Ways

Let's see the practical difference. Here's a Node.js Express API configured for both tools.

Nixpacks (zero config, no file needed):

bash
# Nixpacks auto-detects Node.js from package.json
# No configuration file required
nixpacks build . --name express-api

# Result: ~900MB image

For Nixpacks, you don't even need a nixpacks.toml if your app is standard. It reads package.json, detects the build script, and sets up the start command.

Docker (optimized multi-stage Dockerfile):

dockerfile
# Dockerfile for the same Express API
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:20-alpine
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY ./src ./src
EXPOSE 3000
CMD ["node", "src/index.js"]

Now a Python FastAPI app:

Nixpacks (zero config):

bash
# Nixpacks detects Python from requirements.txt
nixpacks build . --name fastapi-app

# Result: ~1.1GB image

Docker (optimized Dockerfile):

dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY ./app ./app
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

Here's the output side by side:

bash
# Image size comparison
$ docker images
REPOSITORY          TAG       SIZE
express-api-nix     latest    924MB    # Nixpacks build
express-api         latest    83MB     # Docker multi-stage
fastapi-nix         latest    1.12GB   # Nixpacks build
fastapi-app         latest    92MB     # Docker slim

The Nixpacks version "just works" with zero effort. The Docker version takes 10-15 minutes to write but produces an image that's 10x smaller, deploys faster, and costs less to store and transfer.

The Image Size Problem: Why Nixpacks Creates 800MB Containers

The image bloat isn't a bug you can configure away, it's a fundamental consequence of how Nix works under the hood.

What's Actually Inside a 1.3GB Image

When Nixpacks builds your app, the Nix package manager resolves every dependency (including build-time ones) and copies them into /nix/store. That store becomes a single massive layer in your container image. Inside a typical Nixpacks-built Node.js image, you'll find:

  • Build compilers (gcc, g++) that were only needed during npm install
  • Development headers for native modules you may not even use
  • Debug symbols that add hundreds of MB
  • Unused system libraries pulled in as transitive Nix dependencies
  • The entire Nix store metadata, hashes, derivation references, and dependency graphs

Why You Can't Just Optimize It Away

Docker solves this with multi-stage builds: compile in one stage, copy only the output to a clean runtime stage. Nixpacks has no equivalent mechanism. The /nix/store architecture treats all packages as a single atomic unit. You can't cherry-pick which Nix packages make it into the final image.

You can try limiting packages in nixpacks.toml by being explicit about aptPkgs and Nix packages, but the core Nix runtime dependencies still get included. The practical ceiling for Nixpacks optimization still leaves you with images 5-8x larger than an equivalent Docker build.

The real-world cost of 800MB+ images: slower deployments, higher container registry storage costs, longer cold starts on serverless platforms, and more bandwidth consumption every time a node pulls the image. For a startup running 10 replicas with frequent deploys, those extra gigabytes add up in both time and money.

When image size matters, and it matters for anything beyond a prototype, the answer is straightforward: write a Dockerfile.

The Railpack Factor: Why Railway Abandoned Nixpacks

This is the context that changes everything about the nixpacks vs docker debate. In March 2025, Railway, the team that built Nixpacks and deployed it across 14 million app builds, announced they were moving on.

Their reasons were specific and technical:

  1. Commit-based versioning, Nix packages don't use semver. You can't request "Node 20.11.1." You get whatever version a specific Nix commit provides, making reproducible builds harder than they should be.
  2. Massive image sizes, The /nix/store architecture made optimization structurally impossible. Railway's 200,000+ users were deploying unnecessarily bloated images.
  3. Unpredictable caching, Nix binary caching worked inconsistently, leading to slow builds that frustrated developers.

What Railpack Improves Over Nixpacks

Railpack ditches Nix entirely. It uses an Ubuntu base with standard package managers (apt, language-specific tooling) and proper multi-phase builds. The results are significant:

  • Node.js images: 38% smaller than Nixpacks
  • Python images: 77% smaller than Nixpacks
  • Proper semver support: request node@20 or [email protected] and get exactly that
  • Predictable caching: standard layer-based caching that developers understand

Railpack is still in beta. It currently supports Node.js, Python, Go, PHP, and static HTML. Rust, Ruby, Java, and several other languages Nixpacks handles aren't available in Railpack yet.

Docker vs Nixpacks vs Railpack: Summary Table

FeatureDockerNixpacksRailpack
ConfigurationManual DockerfileZero-config / nixpacks.tomlZero-config / railpack.json
Image SizeSmallest (with optimization)Largest (800MB-1.3GB)Medium (38-77% smaller than Nixpacks)
Version PinningExact (e.g., node:20.11.1)Commit-based (no semver)Semver (e.g., node@20)
Language SupportUnlimited~20 languages5 languages (beta)
CachingPredictable layer cachingInconsistent Nix cachingStandard layer caching
Learning CurveModerateNear zeroNear zero
Production ReadyYesLimitedMaturing
Current StatusActively developedMaintenance modeBeta (actively developed)
Best ForProduction, optimizationLegacy projectsNew Railway projects
Base SystemYour choice (Alpine, distroless)Nix storeUbuntu-based

Platform Support: Where Each Tool Works

Your containerization choice depends partly on where you're deploying. Here's which modern deployment platforms support which build tools:

PlatformNixpacksDockerRailpackBuildpacks
RailwayLegacy supportYesDefaultNo
RenderNoYesNoNo
Fly.ioNoDefaultNoNo
CoolifyYesYesRequestedYes
DokployYesYesNoNo
KinstaDefaultYesNoNo
DokkuVia pluginYesNoDefault

A few takeaways: Docker is the only build tool supported everywhere. If platform portability matters, a Dockerfile is your safest bet. Nixpacks support is concentrated in self-hosted PaaS tools (Coolify, Dokploy) and a few managed platforms (Kinsta). Railpack is Railway-exclusive for now.

When to Use Each: Decision Framework

Here's the decision matrix. If your situation matches a row, the recommendation has been tested across real projects.

If Your Project Needs...Best ChoiceWhy
Ship a prototype in 10 minutesNixpacks or RailpackZero config gets you deployed instantly
Production app with SLADockerFull control over size, security, and caching
Smallest possible imageDocker (Alpine/distroless)Multi-stage builds, minimal base images
Fastest CI/CD pipelineDocker (pre-built base)Layer caching is predictable and granular
New project on RailwayRailpackIt's the default, and it's better than Nixpacks
Existing Nixpacks project on RailwayRailpack or DockerMigrate when ready, Nixpacks still works but gets no updates
Multi-language monorepoDockerFull control over each service's build
Team with zero Docker experienceNixpacks/Railpack to startLearn Docker later for production
Deploying across multiple cloud infrastructure providersDockerUniversal support, portable everywhere
Maximum reproducibilityDocker (pinned digests)Exact image hashes guarantee identical builds

Three rules of thumb:

  1. Prototyping? Use zero-config tools (Nixpacks, Railpack). Don't waste time writing a Dockerfile for something you might throw away.
  2. Going to production? Write a Dockerfile. The 30 minutes you invest saves hours of debugging bloated images and unpredictable builds.
  3. Already on Nixpacks? Don't panic-migrate. Plan a switch to Railpack or Docker when your project naturally reaches a milestone.

How Techsy Approaches Container Deployments

We've shipped production apps with both Nixpacks and custom Dockerfiles, so here's our honest take.

For client prototypes and MVPs, we often start with zero-config builders. They remove friction during the phase where you're iterating on features daily and don't yet know if the project has legs. Nixpacks (or now Railpack on Railway) is perfect for this, deploy in seconds, focus on the product.

The moment a project reaches production, we switch to optimized Dockerfiles. Our process looks like this:

  1. Audit the current image, check size, identify unnecessary packages, scan for vulnerabilities
  2. Write a multi-stage Dockerfile, separate build dependencies from runtime
  3. Set up proper layer caching, order COPY instructions to maximize cache hits
  4. Choose the right base image, Alpine for most apps, distroless for security-critical services
  5. Integrate into CI/CD, build, test, push to registry, deploy

We've helped startups go from 1GB+ Nixpacks images to sub-100MB Docker images, cutting deploy times by 5x and saving meaningful money on container registry costs.

Building something and not sure about your deployment setup? Get a free consultation, we'll help you pick the right approach for your project.

Frequently Asked Questions

Is Nixpacks deprecated?

Yes. Nixpacks is in maintenance mode as of 2025. Railway (its creator) built Railpack as the successor. Existing Nixpacks projects still work and receive critical bug fixes, but no new features or language providers are being added. For new projects, consider Railpack or a custom Dockerfile.

What replaced Nixpacks?

Railpack, built by Railway (the same team behind Nixpacks). It drops the Nix dependency entirely, using Ubuntu-based builds with standard package managers. The result: 38% smaller Node.js images and 77% smaller Python images compared to Nixpacks, with proper semver version support.

Why are Nixpacks images so large?

The Nix store architecture copies all packages, including build-time dependencies like compilers and debug symbols, into a single large layer. There's no equivalent of Docker's multi-stage builds to strip out unnecessary files. A simple Node.js app typically produces an 800MB-1.3GB image via Nixpacks versus 50-100MB with an optimized Dockerfile.

Should I use Nixpacks or Docker?

For rapid prototyping on supported platforms, Nixpacks gets you deployed with zero configuration. For production apps where image size, security, and build performance matter, a custom Dockerfile gives you 10-50x smaller images and far more control. Given Nixpacks' deprecated status, Docker is the safer long-term investment.

Can Nixpacks and Docker be used together?

Yes. Nixpacks generates a Dockerfile under the hood and uses Docker's BuildKit engine to produce images. Many teams use Nixpacks for development and staging environments (fast iteration, zero config) while maintaining a custom Dockerfile for production deployments.

What is the difference between Nix and Nixpacks?

Nix is a functional package manager and build system focused on reproducible builds. Nixpacks is a build tool created by Railway that uses Nix packages to auto-detect languages and containerize applications. They're related but different tools, Nix is the underlying technology, Nixpacks is the opinionated wrapper built on top of it.

Does Railway still support Nixpacks?

Railway still supports Nixpacks for existing projects, but the default builder for new projects is now Railpack. You can also use a custom Dockerfile on Railway. To switch, simply add a Dockerfile to your project root, Railway auto-detects it and uses it instead of Nixpacks.

Is Nixpacks faster than Docker?

Generally no. First builds with Nixpacks are slower due to Nix package downloads (about 1 minute 27 seconds versus 15 seconds for a Dockerfile build, per Railway's benchmarks). Cached builds can be comparable for simple changes, but Docker layer caching is more predictable and granular overall.

How do I switch from Nixpacks to a Dockerfile on Railway?

Add a Dockerfile to your project root. Railway auto-detects it and prioritizes it over Nixpacks, no settings changes needed. Write a multi-stage Dockerfile optimized for your stack, push it, and Railway handles the rest.

What platforms use Nixpacks?

Coolify, Dokploy, Kinsta, and Dokku (via plugin) still actively use Nixpacks. Railway has transitioned to Railpack as the default. Render, Fly.io, and Vercel use their own proprietary build systems. Docker is the only build approach supported across every platform.

Is Nixpacks good for production?

Nixpacks is better suited for development and staging than production. The large image sizes (800MB+), limited optimization options, and deprecated status make it a risky choice for production workloads. For production, a custom Dockerfile or Railpack (if on Railway) are both stronger options.

Final Verdict

CategoryWinnerKey Reason
Setup SpeedNixpacksZero-config deployment in seconds
Image SizeDocker10-50x smaller images with multi-stage builds
Build SpeedDockerFaster first builds, more predictable caching
Language SupportDockerUnlimited versus ~20 auto-detected
Production ReadinessDockerMinimal base images, better security posture
Developer ExperienceNixpacksLower barrier to entry for beginners
Long-Term ViabilityDockerIndustry standard; Nixpacks is deprecated

Docker is the better choice for most developers who care about production quality. It wins five of seven categories, and the two categories Nixpacks wins (setup speed, beginner DX) matter most during prototyping, a phase that's temporary by definition.

Nixpacks served a real purpose: it proved that zero-config containerization is possible and valuable. But its fundamental limitations, bloated images, unpredictable caching, commit-based versioning, led its own creators to build something better. Railpack may eventually offer the best of both worlds (zero-config with reasonable image sizes), but it's still in beta with limited language support.

Here's the practical recommendation: if you're starting a new project on Railway, let Railpack handle your builds. If you're deploying anywhere else, or if you're heading toward production, invest the 30 minutes to write a proper Dockerfile. That small upfront cost saves you from debugging 1GB images, slow deploys, and a build tool that's no longer evolving.

Sources

Tags

nixpacks vs dockernixpacksdockerrailpackcontainerizationrailwayzero-config deploymentdockerfile

Share this article

Start Your Project

Ready to build something extraordinary?

Let's turn your vision into reality. Our team is ready to help you create software that makes a difference.