How to Deploy Bun Applications to Production: Docker and Lambda Guide

Bun applications deploy to production either as minimal Docker containers using the official Debian-slim image or as AWS Lambda layers via the bun-lambda package, both leveraging the same pre-built binary without requiring compilation.

To deploy Bun applications to production, you can leverage the officially supported container templates and serverless runtime layers maintained in the oven-sh/bun repository. These deployment methods utilize the verified Bun binary with cryptographic signature checking, ensuring that your production environment matches your local development setup without requiring manual compilation.

Deploy with Docker

The repository provides a production-hardened Docker configuration in dockerhub/debian-slim/Dockerfile that implements a multi-stage build pattern. This approach separates the binary download and verification process from the final runtime image, resulting in a minimal attack surface.

Multi-Stage Build Architecture

The build stage (lines 1-57 of dockerhub/debian-slim/Dockerfile) handles downloading the specified Bun release, verifying its GPG signature and SHA-256 checksum, and extracting the binary to /usr/local/bin/bun. This stage accepts a BUN_VERSION build argument supporting specific versions (e.g., v1.1.30), latest, or canary tags.

The runtime stage (lines 58-89) starts from a clean debian:trixie-slim base and copies only the verified binary. Key security features include:

  • A non-root user bun with UID 1000
  • Environment variable BUN_RUNTIME_TRANSPILER_CACHE_PATH=0 to disable caching (since containers are immutable)
  • The dockerhub/debian-slim/docker-entrypoint.sh entrypoint script that intelligently forwards commands to bun

Building and Running Production Containers

To build the production image:

git clone --filter=blob:none --sparse https://github.com/oven-sh/bun.git
git -C bun sparse-checkout set dockerhub/debian-slim
cd bun/dockerhub/debian-slim
docker build -t myapp:bun --build-arg BUN_VERSION=v1.1.30 .

To run your application:

docker run --rm -v "$(pwd)":/home/bun/app -w /home/bun/app myapp:bun bun run index.ts

For HTTP servers, expose the appropriate port:

docker run -d -p 3000:3000 -v "$(pwd)":/home/bun/app -w /home/bun/app myapp:bun bun run server.ts

Deploy to AWS Lambda

For serverless deployments, the packages/bun-lambda directory provides a custom runtime layer that translates Lambda events into standard Web API Request objects.

Building and Publishing the Layer

The package includes scripts to compile and publish the runtime. Execute these commands from the packages/bun-lambda directory:

bun install
bun run build-layer -- --arch x64 --release latest --output ./bun-lambda-layer.zip
bun run publish-layer -- --arch x64 --release latest --output ./bun-lambda-layer.zip --region us-east-1

The build-layer command supports both x64 and aarch64 architectures, allowing you to target specific AWS instance types.

Lambda Handler Configuration

Write handlers using the standard Web API fetch pattern:

// handler.ts
export default {
  async fetch(request: Request): Promise<Response> {
    return new Response("Hello from Bun Lambda!", {
      status: 200,
      headers: { "content-type": "text/plain" },
    });
  },
};

When configuring the Lambda function:

  1. Set Runtime to "Custom (Amazon Linux 2)"
  2. Set Handler to <filename>.fetch (e.g., handler.fetch if your file is handler.ts)
  3. Attach the Bun layer published via bun run publish-layer

This setup allows the shim in the layer to translate API Gateway events into Request objects and route them to your handler's fetch method.

CI/CD Integration

Integrate these deployment methods into your pipeline using standard Docker build steps or the bun-lambda CLI. A typical GitHub Actions workflow builds the Debian-slim image and pushes to a container registry:

name: Deploy Bun App
on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build production image
        run: |
          docker build -t ghcr.io/${{ github.repository }}/app:${{ github.sha }} \
            --build-arg BUN_VERSION=latest \
            -f dockerhub/debian-slim/Dockerfile .
      - name: Push to registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
          docker push ghcr.io/${{ github.repository }}/app:${{ github.sha }}

Summary

  • Use dockerhub/debian-slim/Dockerfile for containerized production deployments on Kubernetes, Fly.io, or similar orchestration platforms.
  • Set BUN_RUNTIME_TRANSPILER_CACHE_PATH=0 in production containers to disable the transpiler cache, as containers are immutable and short-lived.
  • Leverage packages/bun-lambda to build custom runtime layers for AWS Lambda serverless deployment using bun run build-layer and bun run publish-layer.
  • Target x64 or aarch64 architectures when building Lambda layers to match your AWS instance configuration.
  • Write handlers using the export default { async fetch(request) {...} } pattern for seamless compatibility between local bun run and Lambda execution environments.

Frequently Asked Questions

How do I pin a specific Bun version in Docker production deployments?

Pass the version identifier via --build-arg BUN_VERSION=v1.1.30 when building from dockerhub/debian-slim/Dockerfile. The build script supports semantic versions (with or without the v prefix), latest, or canary tags, and automatically resolves these to the correct release artifact while verifying cryptographic signatures.

What architectures does the Bun Lambda layer support?

The bun-lambda package supports both x64 (AMD64) and aarch64 (ARM64) architectures. Specify your target using the --arch flag when running bun run build-layer. Choose the architecture that matches your AWS Lambda function's configuration for optimal performance.

Why is the transpiler cache disabled in the production Docker image?

The Dockerfile explicitly sets BUN_RUNTIME_TRANSPILER_CACHE_PATH=0 because containers are designed to be immutable and ephemeral. Since the container filesystem is destroyed after each execution, caching transpiled JavaScript provides no performance benefit and avoids unnecessary writes to the overlay filesystem.

Can I use the same Bun code for local development and AWS Lambda?

Yes. The packages/bun-lambda runtime translates Lambda events into standard Request objects, allowing you to use the export default { async fetch(request) {...} } pattern. Test your handlers locally with bun run handler.ts, then deploy the identical file to Lambda with the custom runtime layer attached.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →