Skip to main content
BunShip includes a production-ready Docker setup with a multi-stage Dockerfile, development and production Compose files, and health checks for every service.

Dockerfile Overview

The Dockerfile at docker/Dockerfile.api uses four stages to produce a small, secure image: Key security properties of the final image:
  • Runs as user bunship (UID 1001), not root
  • Alpine base for minimal attack surface (~5 MB base layer)
  • dumb-init as PID 1 for proper signal handling
  • Built-in HEALTHCHECK against /health

Development with Docker Compose

The development Compose file (docker/docker-compose.yml) starts three services: the API, a background worker, and Redis.
In development mode, source directories are mounted as read-only volumes so code changes reflect without rebuilding:

Services

Runs the Elysia API on port 3000. Depends on Redis being healthy before starting.

Production with Docker Compose

The production override file (docker/docker-compose.prod.yml) layers on top of the development file to add resource limits, replica counts, log rotation, and Redis authentication.

What changes in production

Resource Limits

Adjust these in docker-compose.prod.yml based on your workload.

Building and Running

Build the Image

Run Database Migrations

Run migrations before starting the application for the first time, or after schema changes:

Push to a Registry

Volume Management

BunShip uses two named volumes:
The db-data volume is only relevant when using a file-based SQLite database (TURSO_DATABASE_URL=file:../../local.db). In production with Turso Cloud, no local database volume is needed.

Environment Variables

Pass environment variables through an .env file or your orchestrator’s secrets system.
Inside Docker Compose, service-level environment entries override values from env_file. The Compose files set REDIS_HOST=redis so the API connects to the Redis container by service name rather than localhost.

Scaling

Multiple API Instances

Scale the API horizontally with Docker Compose:
When running multiple instances, place a reverse proxy (Nginx, Caddy, or Traefik) in front to distribute traffic. BunShip is stateless — sessions are validated via JWT and jobs are coordinated through Redis — so any instance can handle any request.

Worker Scaling

Scale workers independently from the API:
BullMQ distributes jobs across worker instances automatically. Add workers when your queue depth grows or job processing time increases.

Zero-Downtime Updates

The production Compose file configures rolling updates with a start-first strategy:
To deploy a new version:

Troubleshooting

Container won’t start

Redis connection refused

Build is slow

Enable BuildKit and layer caching:
The Dockerfile copies package.json and bun.lockb before source code, so dependency installation is cached unless lockfile changes.