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
bunwith UID 1000 - Environment variable
BUN_RUNTIME_TRANSPILER_CACHE_PATH=0to disable caching (since containers are immutable) - The
dockerhub/debian-slim/docker-entrypoint.shentrypoint script that intelligently forwards commands tobun
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:
- Set Runtime to "Custom (Amazon Linux 2)"
- Set Handler to
<filename>.fetch(e.g.,handler.fetchif your file ishandler.ts) - 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/Dockerfilefor containerized production deployments on Kubernetes, Fly.io, or similar orchestration platforms. - Set
BUN_RUNTIME_TRANSPILER_CACHE_PATH=0in production containers to disable the transpiler cache, as containers are immutable and short-lived. - Leverage
packages/bun-lambdato build custom runtime layers for AWS Lambda serverless deployment usingbun run build-layerandbun run publish-layer. - Target
x64oraarch64architectures when building Lambda layers to match your AWS instance configuration. - Write handlers using the
export default { async fetch(request) {...} }pattern for seamless compatibility between localbun runand 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →