coolify-compose
npx skills add https://github.com/cachemoney/agent-toolkit --skill coolify-compose
Agent 安装分布
Skill 文档
Coolify Docker Compose
Convert standard Docker Compose files into Coolify-compatible templates with automatic credential generation, dynamic URLs, and one-click deployment.
Two Deployment Modes
Coolify supports two ways to deploy compose files with different capabilities:
1. Raw Compose (Paste Content)
Paste compose YAML directly into Coolify’s UI. Limited feature set:
| Feature | Supported |
|---|---|
image: |
â Yes |
build: |
â No – must use pre-built images |
| External config files | â No – must use inline content: |
YAML anchors (&, *) |
â Yes – resolved by YAML parser |
| Coolify magic variables | â Yes |
content: for inline files |
â Yes |
Use when: Quick deployments, simple services, no custom images needed.
2. Repository Mode (Git URL)
Point Coolify to a Git repository containing your compose file. Full Docker Compose features:
| Feature | Supported |
|---|---|
image: |
â Yes |
build: |
â Yes – builds from Dockerfile in repo |
| External config files | â Yes – relative paths work |
| Coolify magic variables | â Yes |
content: for inline files |
â Yes |
Use when: Custom images needed, complex multi-file setups, existing docker-compose.yml in a repo.
Repository setup:
my-service/
âââ compose.yml # or docker-compose.yml
âââ custom-image/
â âââ Dockerfile
â âââ config.sql
âââ other-files/
# compose.yml - can use build:
services:
app:
build:
context: ./custom-image
dockerfile: Dockerfile
Which Mode to Use?
| Original compose has… | Recommended mode |
|---|---|
Only image: references |
Either works |
build: directives |
Repository mode |
| External config files to mount | Repository mode (or use content: in raw) |
| Single simple service | Raw mode is faster |
Quick Start
Every Coolify template needs a header and magic variables:
# documentation: https://example.com/docs
# slogan: Brief description of the service
# category: backend
# tags: api, database, docker
# logo: svgs/myservice.svg
# port: 3000
services:
app:
image: myapp:latest
environment:
- SERVICE_URL_APP_3000 # Generates URL, routes proxy to port 3000
- DATABASE_URL=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@db:5432/mydb
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3000/health"]
interval: 5s
timeout: 10s
retries: 10
db:
image: postgres:16-alpine
environment:
- POSTGRES_USER=$SERVICE_USER_POSTGRES
- POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER}"]
interval: 5s
timeout: 10s
retries: 10
Conversion Checklist
When converting a standard docker-compose.yml:
0. Check for build: Directives
If the compose has build: entries:
- Repository mode: Keep them. Coolify will build from the Dockerfile.
- Raw mode: Replace with pre-built
image:references or find equivalent images.
# Original with build:
services:
custom-db:
build: ./custom-postgres
# Raw mode: find or create pre-built image
custom-db:
image: your-registry.com/custom-postgres:latest
# Repository mode: keep build:, include Dockerfile in repo
custom-db:
build:
context: ./custom-postgres
dockerfile: Dockerfile
1. Add Header Metadata
# documentation: https://... # Required: URL to official docs
# slogan: ... # Required: One-line description
# category: ... # Required: backend, cms, monitoring, etc.
# tags: ... # Required: Comma-separated search terms
# logo: svgs/....svg # Required: Path in Coolify's svgs/ folder
# port: ... # Recommended: Main service port
2. Replace Hardcoded Credentials
# â Before
POSTGRES_PASSWORD=mysecretpassword
POSTGRES_USER=admin
# â
After
POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES
POSTGRES_USER=$SERVICE_USER_POSTGRES
3. Replace URLs with Magic Variables
# â Before
APP_URL=https://myapp.example.com
# â
After
- SERVICE_URL_APP_3000 # Declares URL + proxy routing
- APP_URL=$SERVICE_URL_APP # References it
4. Remove ports: for Proxied Services
Coolify’s Traefik proxy handles routing. Only keep ports: for SSH, UDP, or proxy bypass.
# â Before
ports:
- "3000:3000"
# â
After
environment:
- SERVICE_URL_APP_3000 # Proxy routes to container port 3000
# No ports: needed
5. Add Health Checks
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 5s
timeout: 10s
retries: 10
6. Use depends_on with Conditions
depends_on:
db:
condition: service_healthy
Magic Variables Reference
Coolify generates values using SERVICE_<TYPE>_<IDENTIFIER>:
| Type | Example | Result |
|---|---|---|
PASSWORD |
SERVICE_PASSWORD_DB |
Random password |
PASSWORD_64 |
SERVICE_PASSWORD_64_KEY |
64-char password |
USER |
SERVICE_USER_ADMIN |
Random 16-char string |
BASE64_64 |
SERVICE_BASE64_64_SECRET |
64-char random string |
REALBASE64_64 |
SERVICE_REALBASE64_64_JWT |
Actual base64-encoded string |
HEX_32 |
SERVICE_HEX_32_KEY |
64-char hex string |
URL |
SERVICE_URL_APP_3000 |
https://app-uuid.example.com + proxy |
FQDN |
SERVICE_FQDN_APP |
app-uuid.example.com (no scheme, no port suffix) |
Declaration vs Reference (Critical)
For SERVICE_URL, the port suffix configures proxy routing but is not part of the variable name:
# Declare WITH port suffix (configures proxy to route to port 3000)
- SERVICE_URL_MYAPP_3000
# Reference WITHOUT port suffix (gets the URL value)
- APP_URL=$SERVICE_URL_MYAPP
- WEBHOOK_URL=${SERVICE_URL_MYAPP}/webhooks
SERVICE_FQDN is automatically available when SERVICE_URL is declared â no separate declaration needed:
# This single declaration...
- SERVICE_URL_MYAPP_3000
# ...makes BOTH of these available:
- FULL_URL=$SERVICE_URL_MYAPP # https://myapp-uuid.example.com
- HOSTNAME=${SERVICE_FQDN_MYAPP} # myapp-uuid.example.com
â ï¸ Important: Use hyphens, not underscores, before port numbers:
SERVICE_URL_MY_SERVICE_3000 # â Breaks parsing
SERVICE_URL_MY-SERVICE_3000 # â
Works
See references/magic-variables.md for complete list.
Coolify-Specific Extensions
Create Directory
volumes:
- type: bind
source: ./data
target: /app/data
is_directory: true # Coolify creates this
Create File with Content
Useful in raw mode when you can’t reference external files. In repository mode, you can just mount files normally.
# Raw mode: embed file content inline
volumes:
- type: bind
source: ./config.json
target: /app/config.json
content: |
{"key": "${SERVICE_PASSWORD_APP}"}
# Repository mode: reference actual file in repo
volumes:
- ./config/settings.json:/app/config.json:ro
Exclude from Health Checks
For migration/init containers that exit after running:
services:
migrate:
command: ["npm", "run", "migrate"]
exclude_from_hc: true
Common Patterns
Database Connection
environment:
- DATABASE_URL=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@db:5432/${POSTGRES_DB:-myapp}
Shared Credentials
Same SERVICE_PASSWORD_* identifier = same value across all services:
services:
app:
environment:
- DB_PASS=$SERVICE_PASSWORD_POSTGRES
db:
environment:
- POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES # Same value
Multi-Service URLs
services:
frontend:
environment:
- SERVICE_URL_FRONTEND_3000
- API_URL=$SERVICE_URL_API
api:
environment:
- SERVICE_URL_API_8080=/api # Path suffix
Health Check Patterns
# HTTP
test: ["CMD", "wget", "--spider", "-q", "http://localhost:8080"]
# PostgreSQL
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
# MySQL/MariaDB
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
# Redis
test: ["CMD", "redis-cli", "ping"]
# Always pass (use sparingly)
test: ["CMD", "echo", "ok"]
Environment Variable Syntax
environment:
- NODE_ENV=production # Hardcoded, hidden from UI
- API_KEY=${API_KEY} # Editable in UI (empty)
- LOG_LEVEL=${LOG_LEVEL:-info} # Editable with default
- SECRET=${SECRET:?} # Required - blocks deploy if empty
Troubleshooting
| Problem | Solution |
|---|---|
| “No Available Server” error | Check docker ps for unhealthy containers; verify healthcheck passes |
| Variables not in Coolify UI | Use ${VAR} syntax; hardcoded VAR=value won’t appear |
| Magic variables not generating | Check spelling; ensure SERVICE_ prefix; verify Coolify v4.0.0-beta.411+ |
| Port routing broken | Use SERVICE_URL_NAME_PORT; avoid underscores before port; remove ports: |
Examples
First, check for an official template: Many popular services have official Coolify templates at github.com/coollabsio/coolify/tree/main/templates/compose. If one exists, use it as the reference for correct patterns.
When converting a compose file without an official template, analyze it and use the matching example:
| Compose file has… | Use example |
|---|---|
| 1 service, no database | examples/simple/ |
| 2 services: app + database (postgres/mysql/mariadb) | examples/with-database/ |
| 3+ services, or mounted config files, or multiple databases | examples/multi-service/ |
Quick analysis:
- Count the
services:â if just 1, usesimple/ - Look for
postgres,mysql,mariadb,mongoimages â if 1 database, usewith-database/ - Look for mounted
.xml,.json,.ymlconfig files â if present, usemulti-service/ - Look for
clickhouse,redis, multiple databases â usemulti-service/
References
- references/magic-variables.md â Complete variable type reference
- references/categories.md â Valid category values
- Official Coolify Compose Docs â Authoritative documentation
- Official Service Templates â Reference implementations for correct patterns