Docker Compose
DevPanel uses standard Docker Compose v2 syntax. Any valid compose.yml file works without modification.
Tips & best practices
Use named volumes
Persistent data survives redeploys. Without named volumes, data is lost on container recreation.
Avoid hardcoding secrets
Use environment variables managed in DevPanel instead of baking secrets into your Compose file.
Pin image tags
Use specific tags like postgres:16-alpine to prevent unexpected upgrades on redeploy.
Use restart: unless-stopped
Ensures containers come back up after server reboots or crashes.
Use depends_on
Control startup order so your app doesn't start before its database is ready.
Using environment variables
Variables added in the DevPanel UI are injected as a .env file alongside your Compose file at deploy time. Reference them with ${VAR_NAME}.
services:
app:
image: myapp:latest
environment:
DATABASE_URL: ${DATABASE_URL}
SECRET_KEY: ${SECRET_KEY}
NODE_ENV: productionNetworking
Each service stack gets an isolated Docker network by default. Services within the same Compose file can reach each other by container name:
services:
app:
image: myapp:latest
environment:
# "db" resolves to the postgres container's IP
DATABASE_URL: postgresql://user:pass@db:5432/mydb
depends_on: [db]
db:
image: postgres:16-alpine
# No "ports:" needed — only app can reach dbFull example stack
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on: [app]
restart: unless-stopped
app:
image: ghcr.io/youruser/myapp:latest
environment:
DATABASE_URL: ${DATABASE_URL}
SECRET_KEY: ${SECRET_KEY}
depends_on: [db]
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASS}
POSTGRES_DB: ${DB_NAME}
volumes:
- pgdata:/var/lib/postgresql/data
restart: unless-stopped
volumes:
pgdata: