How to Deploy Bun to Docker Without Writing a Dockerfile

M
Miget Team
Writer
January 24, 2026
4 min read

You can containerize any Bun application without writing a Dockerfile using migetpacks. It auto-detects your Bun version from .bun-version or bunfig.toml, caches dependencies with bun install, detects your entry point automatically, and produces an optimized slim image. One command, zero configuration.


Why Is Writing a Dockerfile for Bun So Complicated?

A production-ready Bun Dockerfile requires:

  • Choosing between oven/bun and oven/bun:slim images
  • Proper layer ordering for bun install caching
  • Handling both bun.lock (text) and bun.lockb (binary) formats
  • Entry point detection for TypeScript files
  • Running build scripts if present
  • Bun-specific environment configuration

Bun is new and tutorials are often outdated or miss caching best practices.

How Do I Containerize a Bun App Without a Dockerfile?

Open your terminal, navigate to your Bun project, and run:

cd ~/projects/my-bun-api

docker run --rm \
  -v "$PWD":/workspace/source \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OUTPUT_IMAGE=my-bun-api:latest \
  miget/migetpacks:latest

That's it. migetpacks will:

  1. Detect Bun from bun.lock, bun.lockb, bunfig.toml, or .bun-version
  2. Read version from .bun-version or bunfig.toml
  3. Run bun install with caching
  4. Run bun run build if a build script exists
  5. Output a slim production image

How Does migetpacks Detect Bun?

migetpacks detects Bun when any of these signals are present:

PrioritySignal
1bun.lock or bun.lockb (lockfiles)
2bunfig.toml (config file)
3.bun-version (version file)
4bun-types in package.json dependencies

Bun detection runs after backend frameworks (Ruby, Python, Go, etc.) but before Node.js.

How Is the Bun Version Detected?

PrioritySourceExample
1BUN_VERSION env varBUN_VERSION=1.3.4
2.bun-version file1.3.4
3version in bunfig.tomlversion = "1.3.4"
4DefaultLatest stable

How Is the Entry Point Detected?

The entry point is automatically detected in this order:

  1. .ts/.js file referenced in scripts.start of package.json
  2. Common file patterns: index.ts, server.ts, app.ts, main.ts, src/index.ts, src/server.ts, index.js, server.js
  3. Falls back to index.ts

What Does the Generated Dockerfile Look Like?

# Builder stage
FROM oven/bun:1.3.4 AS builder
WORKDIR /build

COPY package.json bun.lock ./

RUN bun install

COPY . .

RUN bun run build

# Runtime stage
FROM oven/bun:1.3.4-slim
WORKDIR /app
COPY --from=builder /build /app

You never write or maintain this file - migetpacks handles it automatically.

What Run Command Is Used?

The default run command:

bun run {entrypoint}

Override with RUN_COMMAND or a Procfile:

web: bun run server.ts

What About the Build Script?

If package.json contains a "build" script, bun run build is automatically executed after dependency installation. Override with BUILD_COMMAND:

docker run --rm \
  -v "$PWD":/workspace/source \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OUTPUT_IMAGE=my-bun:latest \
  -e BUILD_COMMAND="bun run build:prod" \
  miget/migetpacks:latest

How Do I Build Secure Distroless Images?

Enable Docker Hardened Images for minimal containers:

docker run --rm \
  -v "$PWD":/workspace/source \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OUTPUT_IMAGE=my-app:latest \
  -e USE_DHI=true \
  miget/migetpacks:latest

DHI images for Bun are available starting from version 1.3.6. The runtime image is distroless with no shell.

What's the Difference Between Bun, Node.js, and Deno?

RuntimePackage ManagerTypeScriptSpeed
Bunbun (built-in)NativeFastest
Node.jsnpm/yarn/pnpmVia build stepStandard
Denodeno (built-in)NativeFast

Next Steps

Stay UpdatedWith Latest Posts

Subscribe to our newsletter and never miss a new blog post, update, or special offer from the Miget team.