Architecture
ShipFree uses a multi-stage build pattern optimized for Next.js applications:- Base Stage: Sets up Bun runtime and creates non-root user for security
- Dependencies Stage: Installs project dependencies using Bun
- Builder Stage: Compiles and builds the Next.js application
- 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 fromdocker/Dockerfile:
docker/Dockerfile
Environment-Specific Deployments
ShipFree provides separate Docker configurations for different environments:Development Environment
docker/development/Dockerfile):
- Copies
.env.development.sampleto.env.production - Exposed on port 3001
- Optimized for development workflows
Staging Environment
docker/staging/Dockerfile):
- Copies
.env.staging.sampleto.env.production - Exposed on port 3002
- Production-like environment for testing
Production Environment
docker/production/Dockerfile):
- Copies
.env.production.sampleto.env.production - Exposed on port 3003
- Full production optimizations
Docker Compose Configuration
Example productioncompose.yaml:
docker/production/compose.yaml
Port Mapping
Default port mappings:| Environment | Host Port | Container Port |
|---|---|---|
| Development | 3001 | 3000 |
| Staging | 3002 | 3000 |
| Production | 3003 | 3000 |
compose.yaml files.
Environment Variables
Using .env Files
Each environment expects a.env.*.sample file:
.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/standalonedirectory - Includes only required files and dependencies
- Significantly reduces Docker image size
- Improves container startup time
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: Ensurebun.lock exists in your project root:
Container Exits Immediately
Check logs:- Missing environment variables
- Database connection issues
- Port conflicts
Permission Denied Errors
Rebuild with no cache:Database Connection Issues
Verify DATABASE_URL: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
- Run database migrations
- Deploy to Vercel (alternative to Docker)
- Configure environment variables