A Docker-native git-push deployment system for multi-language applications. No hard-coded app names, ports, or paths. Everything is configurable via gokku.yml.
Gokku = Go + Dokku - A lightweight alternative to Dokku, focused on containerized deployments with multi-language support.
Complete deployment in 4 steps:
From your local machine, run one-time command to setup everything:
gokku remote setup USER@SERVER_IPThis will:
- Install Gokku on the server
- Install essential plugins (nginx, letsencrypt, cron, postgres, redis)
- Configure SSH keys
- Verify installation
- Create default "gokku" remote for easy commands
From your local machine (no SSH needed):
gokku apps create api-production --remoteFrom your local machine:
gokku remote add api-production USER@SERVER_IPgit push api-production mainThat's it! Your app is live. 🎉
✅ Docker-Native - All applications run in containers with blue-green deployment
✅ Zero Hard-coding - Everything configured via gokku.yml
✅ Multi-Language - Go, Python, Node.js, Ruby (extensible)
✅ Blue-Green Deployments - Zero-downtime deployments with automatic rollback
✅ CLI Management - Comprehensive command-line interface for all operations
✅ Config-Driven - Apps, environments, ports all in config
✅ Auto Dockerfile - Generates Dockerfile if not exists
✅ Health Checks - Built-in health monitoring and restart policies
All project-specific settings are in one place.
Most fields are optional with sensible defaults:
apps:
api:
path: ./cmd/api
binary_name: apiThis minimal config will use defaults:
lang: go(default language)environments: [production](default environment)branch: main(default branch for production)deployment.keep_releases: 5(default)deployment.restart_policy: always(default)
apps:
api-server:
path: ./cmd/api
binary_name: api-server
workdir: .
go_version: "1.25"
environments:
- name: production
branch: main
default_env_vars:
LOG_LEVEL: info
- name: staging
branch: staging
default_env_vars:
LOG_LEVEL: debug
deployment:
keep_releases: 5
restart_policy: always
restart_delay: 5
worker:
path: ./cmd/worker
binary_name: worker
workdir: .
go_version: "1.25"
environments:
- name: production
branch: main
deployment:
keep_releases: 3
restart_policy: always
restart_delay: 5
ml-service:
lang: python
path: ./services/ml
dockerfile: ./services/ml/Dockerfile # optional
entrypoint: main.py
image: "python:3.11-slim"
port_strategy: manual # or 'auto' for sequential ports
docker:
registry: "" # empty = local, or docker.io, ghcr.io
base_images:
go: "golang:1.25-alpine"
python: "python:3.11-slim"
nodejs: "node:20-alpine"All configuration fields are optional with sensible defaults:
| Field | Default | Description |
|---|---|---|
lang |
go |
Programming language |
workdir |
. |
Working directory for build |
go_version |
1.25 |
Go version (for Go apps) |
entrypoint |
main.py (Python)index.js (Node.js) |
Application entrypoint |
image |
❌ No | Auto-detected |
The image field supports two modes:
Base Image (Local Build):
image: "python:3.11-slim" # Base image for local build
path: ./appPre-built Registry Image (Ultra-fast Deployment):
image: "ghcr.io/meu-org/api:latest" # Pre-built image from registryWhen using a registry image (ghcr.io, ECR, docker.io, etc.), Gokku will:
- Pull the pre-built image from the registry
- Tag it for the application
- Deploy directly (no build step required)
This enables ultra-fast deployments and integrates perfectly with CI/CD pipelines.
When build.image is not specified, Gokku automatically detects the version from project files:
Ruby:
.ruby-versionfile (e.g.,3.2.0)Gemfile(e.g.,ruby '3.1.0')- Fallback:
ruby:latest
Go:
go.modfile (e.g.,go 1.21)- Fallback:
golang:latest-alpine
Node.js:
.nvmrcfile (e.g.,18.17.0)package.jsonengines field (e.g.,"node": ">=18.0.0")- Fallback:
node:latest
Python:
- Always uses
python:latestas fallback
| Field | Default | Description |
|---|---|---|
environments |
[production] |
List of environments |
branch |
main (production)staging (staging)develop (dev) |
Git branch for environment |
| Field | Default | Description |
|---|---|---|
deployment.keep_releases |
5 |
Number of releases to keep |
deployment.keep_images |
5 |
Number of Docker images to keep |
deployment.restart_policy |
always |
Docker restart policy |
deployment.restart_delay |
5 |
Restart delay in seconds |
Minimal Go app (all defaults):
apps:
api:
path: ./cmd/api
binary_name: apiMinimal Python app:
apps:
ml-service:
lang: python
path: ./services/mlCustom everything:
apps:
custom-app:
path: ./cmd/custom
binary_name: custom
go_version: "1.24"gokku- CLI binary for managementgokku.yml- Main configuration filehooks/- Git hooks for automatic deployment
install- Universal installer (auto-detects server/client)
Gokku now features automatic setup on first deploy. No manual configuration required!
- First Push: When you push to a new app/environment for the first time
- Auto-Detection: Gokku detects it's a first deploy
- Config Reading: Reads your
gokku.ymlfrom the repository - Infrastructure Creation: Automatically creates:
- Git repository structure
- Docker containers
- Environment files
- Directory structure
- Deploy: Builds and deploys your application
- Zero Manual Setup: No need to run setup scripts
- Configuration-Driven: Uses your
gokku.ymlfor all settings - Consistent: Same setup process for all apps
- Error-Free: No manual steps to forget or get wrong
Edit gokku.yml with your apps and environments:
apps:
api:
build_path: ./cmd/api
binary_name: api
worker:
build_path: ./cmd/worker
binary_name: worker
environments:
- name: production
branch: main
- name: staging
branch: developThe server setup is now automatic! No manual setup required.
Simply push your code and Gokku will:
- Detect it's the first deploy
- Read your
gokku.ymlconfiguration - Create all necessary infrastructure
- Deploy your application
# Just push - setup happens automatically!
git push api-production main# First deploy - setup happens automatically
git push api-production main
git push worker-staging develop# List all applications
gokku apps
# Deploy applications
gokku deploy api-production
gokku deploy worker-staging
# Manage environment variables
gokku config set API_KEY=xxx -a api-production
gokku config list -a api-production
# View logs and status
gokku logs -a api-production
gokku status -a api-production
# Restart services
gokku restart -a api-production
# Rollback if needed
gokku rollback -a api-productionAdvantages:
- Full control
- Clear and explicit
- Easy to document
- No conflicts
Sequential ports assigned automatically:
port_strategy: auto
base_port: 8000Results in:
api-production→ 8000api-staging→ 8001worker-production→ 8002worker-staging→ 8003
Advantages:
- No manual assignment
- Predictable
- Quick setup
All applications run in Docker containers with blue-green deployment for zero-downtime updates:
apps:
api:
path: ./cmd/api
binary_name: api
go_version: "1.25"
goos: linux
goarch: amd64
cgo_enabled: 0
ml-service:
lang: python
path: ./services/ml
entrypoint: main.py
image: "python:3.11-slim"Go Apps:
FROM golang:1.25-alpine AS builder
WORKDIR /app
COPY go.mod go.sum* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o app ./cmd/api
FROM alpine:latest
RUN apk --no-cache add ca-certificates tzdata
WORKDIR /root/
COPY --from=builder /app/app .
EXPOSE ${PORT:-8080}
CMD ["./app"]Python Apps:
FROM python:3.11-slim
WORKDIR /app
RUN apt-get update && apt-get install -y gcc && rm -rf /var/lib/apt/lists/*
COPY requirements.txt* ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE ${PORT:-8080}
CMD ["python", "main.py"]Specify your own Dockerfile in the build config:
apps:
ml-service:
lang: python
path: ./services/ml
dockerfile: ./services/ml/Dockerfile # Use this instead of auto-generation
entrypoint: main.py- Push code:
git push ml-service-prod main - Hook extracts code to release directory
- Checks for Dockerfile:
- If exists: uses it
- If not: generates based on
lang
- Builds image:
ml-service:20250115-150405 - Tags as latest:
ml-service:latest - Blue-Green Deployment:
- Starts new container (green)
- Health checks new container
- Switches traffic from blue to green
- Stops old container (blue)
- Cleanup old images (keeps last 5)
Images are tagged with timestamps:
# Current
ml-service:latest → ml-service:20250115-150405
# Previous releases
ml-service:20250115-140305
ml-service:20250115-130200
# Rollback (manual for now)
docker stop ml-service-production
docker run --name ml-service-production ml-service:20250115-140305All applications use Docker containers, regardless of language:
apps:
api:
path: ./cmd/api
binary_name: api
worker:
path: ./cmd/worker
binary_name: worker
vad:
lang: python
path: ./services/vad
entrypoint: main.py# One-line install (future)
curl -fsSL https://gokku-vm.com/install | bash- Reusable - Use same deployer for all Go projects
- Versioned - Update deployment system independently
- Shareable - Teams can share deployment practices
- Maintainable - One place to fix bugs/add features
- Clean - Keep deployment separate from application code
Configure your project:
apps:
api:
build_path: ./cmd/api
binary_name: api
worker:
build_path: ./cmd/worker
binary_name: worker
environments:
- name: production
branch: main
- name: staging
branch: staging
workdir: . # or apps/trunk for your structure# First push automatically sets up everything
git push api-production mainThe first push will:
- Create the git repository
- Set up Docker containers
- Configure environment variables from
gokku.yml - Build and deploy your application
# Using gokku CLI
gokku config set PORT=8080 -a api-production
gokku config list -a api-productionapps:
app-name:
build_path: string # Path to main package (relative to workdir)
binary_name: string # Output binary name (defaults to app name)deployment:
keep_releases: number # Number of releases to keep (default: 5)
health_check_timeout: number # Seconds to wait for health check
restart_policy: string # Docker restart policy (default: unless-stopped)
restart_delay: number # Seconds between restarts (default: 5)User configuration is automatically detected from your git remote URL.
Example:
# Git remote format: user@host:path
git remote add production ubuntu@server:api
# The user 'ubuntu' is automatically extracted and usedNo configuration needed - Gokku automatically uses the user from your git remote.
Set via env-manager for each app/environment:
env-manager --app api --env production set \
API_KEY=xxx \
DATABASE_URL=postgres://... \
PORT=8080| Aspect | This System |
|---|---|
| Reusability | ✅ Any Go project |
| Portability | ✅ Separate repo ready |
| Configuration | ✅ Edit YAML |
| New App | ✅ Add to config |
| New Environment | ✅ Add to config |
| Documentation | ✅ In config file |
| Validation | ✅ Automatic |
| Errors | ✅ Early detection |
-
Binary Distribution
- Pre-compiled binaries for Linux/macOS
curl -fsSL https://... | shinstaller- GitHub releases with checksums
-
Config Validation
- JSON Schema for gokku.yml
- Linter for common mistakes
- Best practices checker
-
Multi-Language Support
- Node.js applications
- Python applications
- Any compiled language
-
Advanced Features
- Blue-green deployments
- Canary releases
- Load balancer integration
- Health check endpoints
- Metrics collection
-
Cloud Integrations
- AWS Systems Manager
- Parameter Store for secrets
- CloudWatch Logs
- Auto-scaling groups
# 1. Create fresh Ubuntu EC2
# 2. Install Gokku
curl -fsSL https://gokku-vm.com/install | bash
# 3. Create test project locally
mkdir test-project && cd test-project
git init
# 4. Create test config
cat > gokku.yml << EOF
apps:
test-app:
path: ./main.go
binary_name: test-app
EOF
# 5. Create simple Go app
cat > main.go << EOF
package main
import "fmt"
func main() { fmt.Println("Hello Gokku!") }
EOF
# 6. Add git remote and push (auto-setup happens)
git add .
git commit -m "Initial commit"
git remote add production ubuntu@ec2:test-app
git push production main
# 7. Verify
ssh ubuntu@ec2 "docker ps | grep test-app"Once you've made your great commits (include tests, please):
- Fork this repository
- Create a topic branch - git checkout -b my_branch
- Push to your branch - git push origin my_branch
- Create a pull request
- That's it!
Please respect the indentation rules and code style. And use 2 spaces, not tabs. And don't touch the version thing or distribution files; this will be made when a new version is going to be release
The Dockerfile and associated scripts and documentation in this project are released under the MIT License.
