Staging Stack - Staging Environment
Overview
Separate staging environment for testing features before production deployment.
URL: https://staging.michaelschiemer.de
Features:
- Separate containers and volumes from production
- Auto-deployment from
stagingbranch - Shared Traefik network (same SSL certificates)
- Separate Redis instance
- Can use separate database or share with production
Services
- staging-app (PHP-FPM) - Application runtime
- staging-nginx (Nginx) - Web server for staging.michaelschiemer.de
- staging-redis (Redis 7) - Separate cache/session/queue backend
- staging-queue-worker - Background job processor
- staging-scheduler - Cron job executor
Prerequisites
- Traefik Stack Running (shared with production)
- DNS Configuration:
staging.michaelschiemer.depoints to server IP - Docker Networks:
docker network create traefik-public # Shared with production docker network create staging-internal # Staging-only
Configuration
1. Create Environment File
cp .env.example .env
2. Configure Environment Variables
# Staging-specific
APP_ENV=staging
APP_DEBUG=true
APP_URL=https://staging.michaelschiemer.de
# Database (can use separate staging DB or share)
DB_DATABASE=michaelschiemer_staging
DB_HOST=postgres
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=<password>
# Redis (separate instance)
REDIS_PASSWORD=<password>
CACHE_PREFIX=staging
# Git
GIT_REPOSITORY_URL=https://git.michaelschiemer.de/michael/michaelschiemer.git
GIT_BRANCH=staging
GIT_TOKEN=<token>
Deployment
Initial Setup
# Create staging stack directory on server
mkdir -p ~/deployment/stacks/staging
# Copy docker-compose.yml from repository
cp deployment/stacks/staging/docker-compose.yml ~/deployment/stacks/staging/
# Create .env file
cd ~/deployment/stacks/staging
cp .env.example .env
# Edit .env with staging-specific values
# Ensure networks exist
docker network create traefik-public 2>/dev/null || true
docker network create staging-internal 2>/dev/null || true
# Start staging stack
docker compose up -d
Auto-Deployment
Automatic: Push to staging branch triggers build, then auto-deploys to staging.
Manual: Use "Deploy to Staging" workflow in Gitea Actions.
Verify Deployment
# Check container status
cd ~/deployment/stacks/staging
docker compose ps
# Test staging URL
curl https://staging.michaelschiemer.de/health
# View logs
docker compose logs -f staging-app
docker compose logs -f staging-nginx
Differences from Production
| Aspect | Production | Staging |
|---|---|---|
| Domain | michaelschiemer.de | staging.michaelschiemer.de |
| Branch | main | staging |
| APP_ENV | production | staging |
| APP_DEBUG | false | true |
| Redis | Separate instance | Separate instance |
| Database | michaelschiemer | michaelschiemer_staging |
| Volumes | app-* | staging-* |
| Network | app-internal | staging-internal |
Workflow
- Development: Feature branch → merge to
staging - Auto-Build: Push to
stagingtriggersbuild-image.yml - Auto-Deploy: Successful build auto-deploys to staging (via
deploy-staging.yml) - Testing: Test on https://staging.michaelschiemer.de
- Production: Merge
staging→main→ deploy to production
Troubleshooting
Staging not accessible
# Check Traefik routing
docker logs traefik | grep staging
# Verify container is running
docker ps | grep staging
# Check nginx logs
docker logs staging-nginx
Code not updating
# Force code pull in staging-app
docker exec staging-app bash -c "cd /var/www/html && git pull origin staging"
docker compose restart staging-app staging-nginx
Cleanup
To remove staging environment:
cd ~/deployment/stacks/staging
docker compose down -v # Removes volumes too
docker network rm staging-internal