A general-purpose build pack that automatically detects your application type, generates optimized Dockerfiles, and builds production-ready container images.
- Auto-detection - Automatically detects language, framework, and package manager
- Optimized Dockerfiles - Generates multi-stage builds with security best practices
- BuildKit caching - Framework-specific cache mounts for faster rebuilds
- Non-root containers - Runs as unprivileged user by default
- Native dependency support - Automatically installs required system packages
- Static site support - Serves static builds with Caddy (default) or nginx
More coming soon, we will support a bunch of them, not just Javascript based.
| Framework | Output Types |
|---|---|
| Next.js | Server (SSR) / Static |
| Nuxt | Server (SSR) / Static |
| Remix / React Router | Server (SSR) / Static |
| Astro | Server (SSR) / Static |
| SvelteKit | Server (SSR) / Static |
| Solid Start | Server (SSR) / Static |
| TanStack Start | Server (SSR) / Static |
| Vite | Static |
| Gatsby | Static |
| Angular | Server (SSR) / Static |
| Express | Server |
| Fastify | Server |
| NestJS | Server |
| AdonisJS | Server |
curl -fsSL https://raw.githubusercontent.com/coollabsio/coolpack/main/install.sh | bashgit clone https://github.com/coollabsio/coolpack.git
cd coolpack
./build.shThe binary will be created at ./coolpack.
- Docker with BuildKit support (for building images)
- Go 1.21+ (only for building from source)
# Navigate to your project
cd my-app
# See what Coolpack detects
coolpack plan
# Generate Dockerfile
coolpack prepare
# Build container image
coolpack build
# Run the container (development only)
coolpack runAnalyze and display the build plan without generating any files.
coolpack plan # Current directory
coolpack plan ./my-app # Specific path
coolpack plan --json # Output as JSON
coolpack plan --out # Save to coolpack.json
coolpack plan --out custom.json # Save to custom file
coolpack plan --packages curl --packages wget # Add custom packages
coolpack plan --build-env NEXT_PUBLIC_API_URL=https://api.example.com # Add build envFlags:
| Flag | Description |
|---|---|
--json |
Output as JSON |
-o, --out |
Write plan to file (default: coolpack.json) |
--packages |
Additional APT packages to install |
--build-env |
Build-time env vars (KEY=value or KEY) |
Generate a Dockerfile in the .coolpack/ directory.
If a coolpack.json file exists in the project root, it will be used instead of running detection.
coolpack prepare
coolpack prepare --static-server nginx # Use nginx instead of Caddy
coolpack prepare --build-cmd "npm run build:prod"
coolpack prepare --plan coolpack.json # Use specific plan file
coolpack prepare --packages curl # Add custom APT packagesFlags:
| Flag | Description |
|---|---|
-i, --install-cmd |
Override install command |
-b, --build-cmd |
Override build command |
-s, --start-cmd |
Override start command |
--static-server |
Static server: caddy (default), nginx |
--output-dir |
Override static output directory (e.g., dist, build) |
--spa |
Enable SPA mode (serves index.html for all routes) |
--no-spa |
Disable SPA mode (overrides auto-detection) |
--build-env |
Build-time env vars (KEY=value or KEY) |
--packages |
Additional APT packages to install |
--plan |
Use plan file instead of detection |
Generate Dockerfile and build the container image.
If a coolpack.json file exists in the project root, it will be used instead of running detection.
coolpack build
coolpack build -n my-app -t v1.0.0
coolpack build --build-env NEXT_PUBLIC_API_URL=https://api.example.com
coolpack build --no-cache
coolpack build --plan coolpack.json # Use specific plan file
coolpack build --packages ffmpeg # Add custom APT packagesFlags:
| Flag | Description |
|---|---|
-n, --name |
Image name (defaults to directory name) |
-t, --tag |
Image tag (default: latest) |
--no-cache |
Build without Docker cache |
-i, --install-cmd |
Override install command |
-b, --build-cmd |
Override build command |
-s, --start-cmd |
Override start command |
--static-server |
Static server: caddy (default), nginx |
--output-dir |
Override static output directory (e.g., dist, build) |
--spa |
Enable SPA mode (serves index.html for all routes) |
--no-spa |
Disable SPA mode (overrides auto-detection) |
--build-env |
Build-time env vars |
--packages |
Additional APT packages to install |
--plan |
Use plan file instead of detection |
Build and run the container locally. For development only.
coolpack run
coolpack run -e DATABASE_URL=postgres://localhost/dbFlags:
| Flag | Description |
|---|---|
-n, --name |
Image name |
-t, --tag |
Image tag |
-e, --env |
Runtime env vars (KEY=value) |
Print version information.
coolpack versionOverride Coolpack behavior with environment variables:
| Variable | Description | Default |
|---|---|---|
COOLPACK_INSTALL_CMD |
Override install command | Auto-detected |
COOLPACK_BUILD_CMD |
Override build command | Auto-detected |
COOLPACK_START_CMD |
Override start command | Auto-detected |
COOLPACK_BASE_IMAGE |
Override base Docker image | Provider-specific |
COOLPACK_NODE_VERSION |
Override Node.js version | Auto-detected or 24 |
COOLPACK_STATIC_SERVER |
Static file server | caddy |
COOLPACK_SPA_OUTPUT_DIR |
Override static output directory | Framework-specific |
COOLPACK_SPA |
Enable SPA mode | Auto-detected |
COOLPACK_NO_SPA |
Disable SPA mode | false |
COOLPACK_PACKAGES |
Additional APT packages (comma-separated) | - |
NODE_VERSION |
Alternative to COOLPACK_NODE_VERSION (legacy) |
- |
Priority: CLI flags > Environment variables > Auto-detected
Default Base Images by Provider:
| Provider | Default Base Image |
|---|---|
| Node.js | node:<version>-slim |
| Node.js (bun) | oven/bun:<version>-slim |
Build-time variables are baked into the image during build:
coolpack build --build-env NEXT_PUBLIC_API_URL=https://api.example.comUse for:
- Next.js
NEXT_PUBLIC_*variables - Vite
VITE_*variables - Any
process.envaccessed during build
Runtime variables are passed when running the container:
docker run -e DATABASE_URL=postgres://... -e API_KEY=... my-app:latestUse for:
- Secrets that shouldn't be in the image
- Config that changes per environment
Add custom cache directories in package.json:
{
"cacheDirectories": [
".cache",
"tmp/build-cache"
]
}Coolpack detects Node.js version from (in priority order):
COOLPACK_NODE_VERSIONenv varengines.nodein package.json.nvmrcfile.node-versionfile.tool-versionsfile (asdf)mise.tomlfile- Default:
24
Detected from (in priority order):
packageManagerfield in package.json- Lock files (
pnpm-lock.yaml,bun.lockb,yarn.lock,package-lock.json) enginesfield in package.json- Default:
npm
cd my-nextjs-app
coolpack build -n my-app -t latest
docker run -p 3000:3000 my-app:latestcd my-vite-app
coolpack build
docker run -p 80:80 my-vite-app:latestcoolpack build \
--install-cmd "pnpm install --frozen-lockfile" \
--build-cmd "pnpm build:production" \
--start-cmd "node dist/server.js"coolpack build \
--build-env NEXT_PUBLIC_API_URL=https://api.example.com \
--build-env NEXT_PUBLIC_GA_ID=UA-123456coolpack build --static-server nginxFor Single Page Applications, Coolpack auto-detects client-side routers (vue-router, react-router-dom, etc.) and configures the server to serve index.html for all routes:
# Auto-detected when vue-router, react-router-dom, etc. is found
coolpack build
# Manual override
coolpack build --spaSave a build plan and reuse it for reproducible builds:
# Generate and save plan
coolpack plan --out
# Edit coolpack.json to customize settings...
# Build using the plan file (auto-detected)
coolpack build
# Or specify explicitly
coolpack build --plan coolpack.jsonAdd system packages that aren't auto-detected:
# Via CLI flag
coolpack build --packages ffmpeg --packages curl
# Via environment variable
COOLPACK_PACKAGES=ffmpeg,curl coolpack build
# Via plan file (add to metadata.custom_packages)- Go 1.21+
- Docker (for testing builds)
git clone https://github.com/coollabsio/coolpack.git
cd coolpack
go mod download./build.shcoolpack/
├── main.go # Entry point
├── build.sh # Build script
├── cmd/coolpack/
│ ├── root.go # Root CLI command
│ ├── plan.go # Plan subcommand
│ ├── prepare.go # Prepare subcommand
│ ├── build.go # Build subcommand
│ └── run.go # Run subcommand
└── pkg/
├── app/
│ ├── context.go # App context (path, env, file helpers)
│ └── plan.go # Plan struct
├── detector/
│ ├── detector.go # Main detector, registers providers
│ └── types.go # Provider interface
├── generator/
│ └── generator.go # Dockerfile generation
└── providers/node/
├── node.go # Node.js provider
├── package_json.go # package.json parsing
├── package_manager.go # Package manager detection
├── version.go # Node version detection
├── framework.go # Framework detection
├── config_parser.go # JS/TS config parsing
└── native_deps.go # Native dependency detection
- Create
pkg/providers/<name>/<name>.go - Implement the
Providerinterface:
type Provider interface {
Name() string
Detect(ctx *app.Context) (bool, error)
Plan(ctx *app.Context) (*app.Plan, error)
}- Register in
pkg/detector/detector.go:
func (d *Detector) registerProviders() {
d.providers = append(d.providers, node.New())
d.providers = append(d.providers, yourprovider.New())
}For Node.js frameworks, edit pkg/providers/node/framework.go:
- Add framework constant
- Add detection logic in
DetectFramework() - Add output type determination
- Add default build/start commands
Test against example projects:
# Test detection
./coolpack plan /path/to/test-project
# Test Dockerfile generation
./coolpack prepare /path/to/test-project
cat /path/to/test-project/.coolpack/Dockerfile
# Test full build
./coolpack build /path/to/test-projectgithub.com/spf13/cobra- CLI frameworkgithub.com/smacker/go-tree-sitter- AST parsing for JS/TS config files
- Detection - Scans project files to identify language, framework, and package manager
- Planning - Creates a build plan with install, build, and start commands
- Generation - Produces an optimized multi-stage Dockerfile
- Building - Runs
docker buildwith BuildKit cache mounts
- Multi-stage builds (builder + runner)
- BuildKit cache mounts for dependencies and build artifacts
- Non-root user (
cooluser, UID 1001) - Production-optimized Node.js settings
- Framework-specific output copying
- Automatic native dependency installation
MIT
Contributions are welcome! Please feel free to submit issues and pull requests.