Skip to main content
ShipFree includes production-ready Docker configurations for containerized deployments. All Dockerfiles use Bun as the runtime for optimal performance.

Architecture

ShipFree uses a multi-stage build pattern optimized for Next.js applications:
  1. Base Stage: Sets up Bun runtime and creates non-root user for security
  2. Dependencies Stage: Installs project dependencies using Bun
  3. Builder Stage: Compiles and builds the Next.js application
  4. Runner Stage: Creates minimal production image with only runtime files

Benefits of Multi-Stage Builds

  • Smaller Image Size: Final image contains only runtime dependencies
  • Better Security: Build tools and dev dependencies are excluded
  • Faster Deployments: Smaller images transfer and start faster
  • Layer Caching: Optimized for Docker’s build cache

Quick Start

General Purpose Dockerfile

The main Dockerfile is suitable for most use cases:

Dockerfile Configuration

Here’s the main Dockerfile from docker/Dockerfile:
docker/Dockerfile

Environment-Specific Deployments

ShipFree provides separate Docker configurations for different environments:

Development Environment

Development Dockerfile (docker/development/Dockerfile):
  • Copies .env.development.sample to .env.production
  • Exposed on port 3001
  • Optimized for development workflows

Staging Environment

Staging Dockerfile (docker/staging/Dockerfile):
  • Copies .env.staging.sample to .env.production
  • Exposed on port 3002
  • Production-like environment for testing

Production Environment

Production Dockerfile (docker/production/Dockerfile):
  • Copies .env.production.sample to .env.production
  • Exposed on port 3003
  • Full production optimizations

Docker Compose Configuration

Example production compose.yaml:
docker/production/compose.yaml

Port Mapping

Default port mappings: Customize ports by editing the respective compose.yaml files.

Environment Variables

Using .env Files

Each environment expects a .env.*.sample file:
These files are copied to .env.production during the Docker build process.

Runtime Environment Variables

For production, pass environment variables at runtime:

Using .env File with Docker Compose

Create a .env file and reference it in compose.yaml:

Production Deployment

Build Optimized Image

Run in Production

Using Docker Compose for Production

Next.js Standalone Output

ShipFree is configured for standalone output mode, which:
  • Creates a minimal .next/standalone directory
  • Includes only required files and dependencies
  • Significantly reduces Docker image size
  • Improves container startup time
Note: The output: 'standalone' option is commented out in next.config.ts. Uncomment it for production deployments:
next.config.ts

Security Best Practices

Non-Root User

All Dockerfiles run the application as a non-root user (nextjs):

Minimal Permissions

Files are copied with proper ownership:

No Build Tools in Production

The final image excludes build dependencies for a smaller attack surface.

Troubleshooting

Build Fails with “Lockfile not found”

Solution: Ensure bun.lock exists in your project root:

Container Exits Immediately

Check logs:
Common causes:
  • Missing environment variables
  • Database connection issues
  • Port conflicts

Permission Denied Errors

Rebuild with no cache:

Database Connection Issues

Verify DATABASE_URL:
For local PostgreSQL: Use host.docker.internal instead of localhost:

Advanced Usage

Multi-Container Setup with PostgreSQL

Create a complete stack with database:
compose.yaml

Health Checks

Add health checks to your containers:

Custom Build Arguments

Pass build-time variables:

Container Registry

Push to Docker Hub

Push to GitHub Container Registry

Next Steps

Resources