home / skills / daleseo / bun-skills / bun-deploy

bun-deploy skill

/skills/bun-deploy

This skill generates optimized Bun Docker images, guiding multi-stage layouts, CI/CD integration, and Kubernetes deployment to minimize size and improve

npx playbooks add skill daleseo/bun-skills --skill bun-deploy

Review the files below or copy the command above to add this skill to your agents.

Files (5)
SKILL.md
7.6 KB
---
name: bun-deploy
description: Generate optimized Docker images for Bun applications. Use when deploying to containers, minimizing image sizes, setting up CI/CD pipelines, or deploying to Kubernetes.
compatibility: Requires Bun 1.0+ and Docker
allowed-tools: ["Bash", "Write", "Read"]
metadata:
  author: dale
  category: bun-runtime
  tags: [bun, docker, deployment, containers, kubernetes]
---

# Bun Docker Deployment

Create optimized Docker images for Bun applications. Bun's small runtime and binary compilation reduce image sizes by 88MB+ compared to Node.js.

## Quick Reference

For detailed patterns, see:
- **Dockerfile Templates**: [dockerfile-templates.md](references/dockerfile-templates.md) - 12+ optimized templates
- **Kubernetes**: [kubernetes.md](references/kubernetes.md) - K8s manifests, HPA, ingress
- **CI/CD**: [ci-cd.md](references/ci-cd.md) - GitHub Actions, GitLab CI, build scripts
- **Multi-Platform**: [multi-platform.md](references/multi-platform.md) - ARM64/AMD64 builds

## Core Workflow

### 1. Check Prerequisites

```bash
# Verify Docker is installed
docker --version

# Verify Bun is installed locally
bun --version

# Check if project is ready for deployment
ls -la package.json bun.lockb
```

### 2. Determine Deployment Strategy

Ask the user about their needs:

- **Application Type**: Web server, API, worker, or CLI
- **Image Size Priority**: Minimal size (40MB binary) vs. debugging tools (90MB Alpine)
- **Platform**: Single platform or multi-platform (AMD64 + ARM64)
- **Orchestration**: Docker Compose, Kubernetes, or standalone containers

### 3. Create Production Dockerfile

Choose the appropriate template based on needs:

**Standard Multi-Stage (Recommended)**

```dockerfile
# syntax=docker/dockerfile:1

FROM oven/bun:1-alpine AS deps
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile --production

FROM oven/bun:1-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN bun run build

FROM oven/bun:1-alpine AS runtime
WORKDIR /app

RUN addgroup --system --gid 1001 bunuser && \
    adduser --system --uid 1001 bunuser

COPY --from=deps --chown=bunuser:bunuser /app/node_modules ./node_modules
COPY --from=builder --chown=bunuser:bunuser /app/dist ./dist
COPY --from=builder --chown=bunuser:bunuser /app/package.json ./

USER bunuser
EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD bun run healthcheck.ts || exit 1

CMD ["bun", "run", "dist/index.js"]
```

**Minimal Binary (40MB)**

For smallest possible images:

```dockerfile
FROM oven/bun:1-alpine AS builder
WORKDIR /app

COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile

COPY . .
RUN bun build ./src/index.ts --compile --outfile server

FROM gcr.io/distroless/base-debian12
COPY --from=builder /app/server /server
EXPOSE 3000
ENTRYPOINT ["/server"]
```

**For other scenarios** (monorepo, database apps, CLI tools, etc.), see [dockerfile-templates.md](references/dockerfile-templates.md).

### 4. Create .dockerignore

```dockerignore
node_modules
bun.lockb
dist
*.log
.git
.env
.env.local
tests/
*.test.ts
coverage/
.vscode/
.DS_Store
Dockerfile
docker-compose.yml
```

### 5. Create Health Check Script

Create `healthcheck.ts`:

```typescript
#!/usr/bin/env bun

const port = process.env.PORT || 3000;
const healthEndpoint = process.env.HEALTH_ENDPOINT || '/health';

try {
  const response = await fetch(`http://localhost:${port}${healthEndpoint}`, {
    method: 'GET',
    timeout: 2000,
  });

  if (response.ok) {
    process.exit(0);
  } else {
    console.error(`Health check failed: ${response.status}`);
    process.exit(1);
  }
} catch (error) {
  console.error('Health check error:', error);
  process.exit(1);
}
```

Add health endpoint to your server:

```typescript
app.get('/health', (req, res) => {
  res.json({
    status: 'ok',
    timestamp: Date.now(),
    uptime: process.uptime(),
  });
});
```

### 6. Build and Test Image

```bash
# Build image
docker build -t myapp:latest .

# Check image size
docker images myapp:latest

# Run container
docker run -p 3000:3000 myapp:latest

# Test health endpoint
curl http://localhost:3000/health
```

### 7. Setup for Environment

**For Local Development with Docker Compose:**

Create `docker-compose.yml`:

```yaml
version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
    depends_on:
      - db
      - redis

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: mydb
    ports:
      - "5432:5432"

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
```

Run with: `docker-compose up`

**For Kubernetes Deployment:**

See [kubernetes.md](references/kubernetes.md) for complete manifests including:
- Deployment configuration
- Service and Ingress
- Secrets and ConfigMaps
- Horizontal Pod Autoscaling
- Resource limits optimized for Bun

**For CI/CD:**

See [ci-cd.md](references/ci-cd.md) for:
- GitHub Actions workflow
- GitLab CI configuration
- Build and push scripts
- Automated deployments

**For Multi-Platform (ARM64 + AMD64):**

See [multi-platform.md](references/multi-platform.md) for:
- Multi-platform Dockerfile
- Buildx configuration
- Testing on different architectures

### 8. Update package.json

Add Docker scripts:

```json
{
  "scripts": {
    "docker:build": "docker build -t myapp:latest .",
    "docker:run": "docker run -p 3000:3000 myapp:latest",
    "docker:dev": "docker-compose up",
    "docker:clean": "docker system prune -af"
  }
}
```

## Image Size Comparison

Bun produces significantly smaller images:

| Configuration | Size | Use Case |
|--------------|------|----------|
| **Bun Binary (distroless)** | ~40 MB | Production (minimal) |
| **Bun Alpine** | ~90 MB | Production (standard) |
| **Node.js Alpine** | ~180 MB | Baseline comparison |

**88MB+ savings with Bun!**

## Security Best Practices

1. **Use non-root user** (included in Dockerfiles above)
2. **Scan for vulnerabilities**: `docker scan myapp:latest`
3. **Use official base images**: `oven/bun` is official
4. **Keep images updated**: Rebuild regularly with latest Bun
5. **Never hardcode secrets**: Use environment variables or secret managers

## Optimization Tips

**Layer caching:**
```dockerfile
# Copy dependencies first (changes less often)
COPY package.json bun.lockb ./
RUN bun install

# Copy source code last (changes more often)
COPY . .
RUN bun run build
```

**Reduce layer count:**
```dockerfile
# Combine RUN commands
RUN bun install && \
    bun run build && \
    rm -rf tests/
```

**Minimize final image:**
```dockerfile
# Only copy what's needed in runtime
COPY --from=builder /app/dist ./dist
# Don't copy: src/, tests/, .git/, node_modules (if using binary)
```

## Completion Checklist

- ✅ Dockerfile created (multi-stage or binary)
- ✅ .dockerignore configured
- ✅ Health check implemented
- ✅ Non-root user configured
- ✅ Image built and tested locally
- ✅ Image size verified (<100MB for Alpine, <50MB for binary)
- ✅ Environment configuration ready (docker-compose or K8s)
- ✅ CI/CD pipeline configured (if needed)

## Next Steps

After basic deployment:

1. **Monitoring**: Add Prometheus metrics endpoint
2. **Logging**: Configure structured logging
3. **Secrets**: Set up proper secret management
4. **Scaling**: Configure horizontal pod autoscaling (K8s)
5. **CI/CD**: Automate builds and deployments
6. **Multi-region**: Deploy to multiple regions for redundancy

For detailed implementations, see the reference files linked above.

Overview

This skill generates optimized Docker images and deployment patterns for Bun applications to minimize image size and speed up CI/CD. It provides production-ready Dockerfile templates, .dockerignore guidance, health checks, and platform or orchestration patterns for Docker Compose and Kubernetes. Use it to produce tiny runtime images, multi-platform builds, and repeatable pipelines for container deployments.

How this skill works

The skill inspects project layout and deployment goals (app type, size vs. debugging tradeoffs, target platforms, orchestration) and selects a tailored Dockerfile template: a recommended multi-stage Alpine flow or a minimal compiled binary image. It supplies Dockerfile snippets, a .dockerignore, a healthcheck script, and CI/CD and Kubernetes patterns. It also includes optimization and security best-practices (non-root user, vulnerability scanning, caching).

When to use it

  • Deploy a Bun web server, API, worker, or CLI into containers
  • Minimize container image size for production (distroless binary or Alpine)
  • Set up CI/CD pipelines that build and push Bun images
  • Target multi-platform images (AMD64 and ARM64) for cloud or edge
  • Migrate from Node.js to Bun to reduce image footprint and startup time

Best practices

  • Use multi-stage builds: install deps, build, then copy only runtime artifacts
  • Run as a non-root user in the final image to improve security
  • Keep a focused .dockerignore to reduce build context and avoid leaking secrets
  • Add a lightweight HTTP healthcheck and expose a /health endpoint
  • Leverage layer caching by copying package.json and bun.lockb before source files

Example use cases

  • Build a 40MB distroless binary image for production microservices
  • Create a 90MB Alpine image when debugging tools are needed in the runtime
  • Add GitHub Actions that build multi-platform images and push to a registry
  • Deploy to Kubernetes with resource limits, HPA, Service, and Ingress manifests
  • Run a local development stack with docker-compose mounting source and node_modules

FAQ

How much smaller are Bun images compared to Node.js?

Typical Bun images are ~40–90 MB depending on the template; Node.js Alpine images are often ~180 MB, so Bun can save 88 MB or more.

When should I use the minimal binary image vs Alpine runtime?

Use the minimal compiled binary for smallest production images and fastest startup; use Alpine when you need runtime tooling, shell access, or easier debugging.