coolify-compose

📁 cachemoney/agent-toolkit 📅 9 days ago
4
总安装量
4
周安装量
#47959
全站排名
安装命令
npx skills add https://github.com/cachemoney/agent-toolkit --skill coolify-compose

Agent 安装分布

gemini-cli 4
antigravity 4
claude-code 4
github-copilot 4
codex 4
opencode 4

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, use simple/
  • Look for postgres, mysql, mariadb, mongo images — if 1 database, use with-database/
  • Look for mounted .xml, .json, .yml config files — if present, use multi-service/
  • Look for clickhouse, redis, multiple databases — use multi-service/

References