Docs / Deployment
Production Deployment
Same pier.yml, real domains, Let's Encrypt certs. Deploy via SSH or CI/CD.
SSH Deploy
The simplest path. Pier SSHs into your server, syncs pier.yml and your build context, then runs pier up remotely.
# First time: set up the remote pier remote add prod root@your-vps.com # Deploy pier deploy prod ✓ Syncing pier.yml to root@your-vps.com ✓ Building api on remote... ✓ Starting services... ✓ Health check passed: api → 200 OK ✓ Let's Encrypt cert issued for api.yourapp.com ✓ Deploy complete (38s) # Rollback pier deploy prod --rollback
Production pier.yml
Use pier.prod.yml or environment overrides. The main difference: real domains instead of .dock domains.
pier.prod.yml
name: myapp
services:
api:
build: ./api
port: 3000
domain: api.yourapp.com # Real domain → Let's Encrypt
health: /api/health
restart: always
env:
NODE_ENV: production
DATABASE_URL: ${SECRET:DATABASE_URL}
web:
build: ./web
port: 3000
domain: yourapp.com
depends_on: [api]
db:
image: postgres:16
volumes:
- pg_data:/var/lib/postgresql/data
env:
POSTGRES_PASSWORD: ${SECRET:DB_PASSWORD}CI/CD Integration
.github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Pier
run: curl -fsSL https://pier.wejoona.com/install.sh | bash
- name: Deploy
run: pier deploy prod
env:
PIER_SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
PIER_SECRETS_KEY: ${{ secrets.PIER_SECRETS_KEY }}Zero-Downtime Deploys
Pier uses rolling restarts by default. For services with health checks, the new container must pass health before the old one is stopped. If health fails, the deploy rolls back automatically. No manual intervention needed.
Back to Docs