Skip to content

starter-series/docker-deploy-starter

Docker Deploy Starter

Docker + GitHub Actions CI/CD + one-click deploy to any VPS.

Build your app. Push to deploy.

CI License: MIT Docker GHCR

English | 한국어


Part of Starter Series — Stop explaining CI/CD to your AI every time. Clone and start.

Docker Deploy · Discord Bot · Telegram Bot · Browser Extension · Electron App · npm Package · React Native · VS Code Extension · MCP Server · Python MCP Server · Cloudflare Pages


Quick Start

Via create-starter (recommended):

npx @starter-series/create my-service --template docker-deploy
cd my-service
# Add your app's Dockerfile + code, then:
docker compose up

Or clone directly:

git clone https://github.com/starter-series/docker-deploy-starter my-service
cd my-service
docker compose up

Full setup (bring your own app):

# 1. Click "Use this template" on GitHub (or clone)
git clone https://github.com/starter-series/docker-deploy-starter.git my-app
cd my-app

# 2. Replace app/ with your application
rm -rf app/
# Copy your app files here

# 3. Update Dockerfile for your language
# See docs/DOCKERFILE_EXAMPLES.md for Python, Go, Rust, Java, etc.

# 4. Test locally
cp .env.example .env
docker compose up

What's Included

├── app/                        # Example app (replace with yours)
│   ├── server.js               # Minimal Node.js HTTP server
│   └── package.json
├── Dockerfile                  # Example build (swap for your language)
├── docker-compose.yml          # Local development
├── .github/
│   ├── workflows/
│   │   ├── ci.yml              # Lint, compose validate, build test, JS tests
│   │   ├── cd.yml              # Build → GHCR push → VPS deploy via SSH
│   │   └── setup.yml           # Auto setup checklist on first use
│   └── PULL_REQUEST_TEMPLATE.md
├── docs/
│   ├── DOCKERFILE_EXAMPLES.md  # Dockerfiles for Node, Python, Go, Rust, Java
│   ├── GHCR_SETUP.md           # GitHub Container Registry setup
│   ├── HTTPS_SETUP.md          # HTTPS with Caddy reverse proxy
│   └── VPS_DEPLOY.md           # VPS SSH deployment guide
├── scripts/
│   ├── bump-version.js         # Version bump utility (validates VERSION)
│   └── deploy-with-rollback.sh # Health-checked deploy + auto rollback
├── tests/                      # node:test suites + rollback integration test
├── package.json                # `npm test` runner
└── VERSION                     # Current version

Features

  • Language agnostic — Swap the Dockerfile for any language (Node, Python, Go, Rust, Java, static)
  • CI Pipeline — Dockerfile lint (hadolint), docker-compose validation, build verification, Trivy CVE scan, plus node:test suites (version-bump + /health) on every push
  • CD Pipeline — Build → push to GHCR → health-checked deploy to VPS via docker compose + auto GitHub Release
  • Real health checks/health reflects a readiness signal and can return 503; wire your own dependency probes (DB, cache, …) so failed deploys actually roll back
  • Dockerfile examples — Multi-stage builds for Node, Python, Go, Rust, Java in docs
  • Version managementnode scripts/bump-version.js patch/minor/major (validates VERSION, fails loudly on a malformed file instead of writing garbage)
  • Local devdocker compose up with volume mounts for live reload
  • HTTPS guide — Caddy reverse proxy with automatic TLS
  • Deploy guides — Step-by-step docs for GHCR and VPS setup
  • Template setup — Auto-creates setup checklist issue on first use

Health checks (/health)

The deploy pipeline rolls back when the new container fails its health check (docker compose up -d --wait). That safety net only works if /health can actually report failure — a /health that always returns 200 makes every deploy look healthy and silently disables rollback.

  • Currently implementedapp/server.js exposes /health backed by a list of async readiness checks. All checks passing → 200 {"status":"ok"}. Any check returning falsy or throwing → 503 {"status":"unavailable"}. Unknown paths return 404 (the example server is not a catch-all). The default check only confirms the HTTP listener is bound.

  • Design intent — fail-closed: a dependency outage should surface as an unhealthy container so the orchestrator stops routing traffic and the CD rollback triggers, rather than serving a broken app behind a green check.

  • You must wire real checks. Replace the example app and register probes for the dependencies your app actually needs:

    const { createApp } = require('./server.js');
    const { server } = createApp({
      readinessChecks: [
        async () => { await db.query('SELECT 1'); return true; },
        async () => (await redis.ping()) === 'PONG',
      ],
    });
    server.listen(process.env.PORT || 3000);
  • Non-goals — this is not a metrics/liveness framework. It is the minimal readiness contract the rollback logic depends on; swap in your stack's health library if you need more.

CI/CD

CI (every PR + push to main)

Step What it does
Lint Dockerfile Hadolint checks for best practices
Validate compose Verifies docker-compose.yml syntax
Build test Builds the Docker image to catch build errors
Scan image Trivy scans for CRITICAL CVEs

Security & Maintenance

Workflow What it does
CodeQL (codeql.yml) Static analysis for security vulnerabilities (push/PR + weekly)
Maintenance (maintenance.yml) Weekly CI health check — auto-creates issue on failure
Stale (stale.yml) Labels inactive issues/PRs after 30 days, auto-closes after 7 more

CD (manual trigger or tag push)

Step What it does
Version guard Fails if git tag already exists for this version
Build & push Builds image and pushes to GitHub Container Registry
Deploy SSHs into your VPS, pulls new image, health-checked restart via docker compose
Image cleanup Prunes old images on VPS + keeps last 10 versions on GHCR
GitHub Release Creates a tagged release with auto-generated notes

How to deploy:

  1. Set up GitHub Secrets (see below)
  2. Bump version: node scripts/bump-version.js patch
  3. Manual: Go to Actions tab → DeployRun workflow
  4. Auto: Push a version tag — git tag v$(cat VERSION) && git push --tags

GitHub Secrets

Secret Description
VPS_HOST Your server IP or domain
VPS_USER SSH username
VPS_SSH_KEY SSH private key

See docs/VPS_DEPLOY.md for a detailed setup guide.

Note: GHCR authentication uses GITHUB_TOKEN automatically — no extra secrets needed.

Development

# Start locally with Docker
docker compose up

# Rebuild after Dockerfile changes
docker compose up --build

# Bump version (fails loudly if VERSION is malformed — never writes 1.2.NaN)
node scripts/bump-version.js patch   # 1.0.0 → 1.0.1
node scripts/bump-version.js minor   # 1.0.0 → 1.1.0
node scripts/bump-version.js major   # 1.0.0 → 2.0.0

Tests

# Node tests: version-bump validation + /health (200) and unknown path (404)
npm test

# Rollback integration test (needs Docker; also run in CI)
bash tests/rollback-integration.sh

Switching Languages

  1. Replace app/ with your application code
  2. Pick a Dockerfile from docs/DOCKERFILE_EXAMPLES.md (Python, Go, Rust, Java, static)
  3. Update docker-compose.yml ports if needed
  4. Update .env.example with your app's environment variables
  5. Test: docker compose up --build

Why VPS?

Platforms like Railway/Render/Vercel are great for single apps. But when you need more, VPS wins:

  • One server, everything — Run app + DB + cache on one machine instead of paying per service
  • No vendor lock-in — Standard Docker + SSH. Move between any VPS provider
  • Full system access — GPU, custom packages, compliance, any OS-level config
  • Always on — No cold starts, no spin-down, no sleep timers
  • Predictable cost — Flat monthly price, no usage-based surprises

Use Railway/Render/Vercel instead if:

  • You're deploying a single web app and want zero infrastructure management
  • You need managed databases with automatic backups

Why This Over Blog Tutorials?

Every "Docker + GitHub Actions" tutorial teaches the same steps. You end up copy-pasting YAML, debugging GHCR auth, wiring SSH keys, and setting up health checks — every single time.

This template gives you the entire pipeline, tested and ready. git clone → replace app/ → push → deployed.

Contributing

PRs welcome. Please use the PR template.

License

MIT

Releases

No releases published

Packages

 
 
 

Contributors