Skip to Content
DocumentationReferenceDynamic compose

Dynamic Compose Reference

Dynamic compose is Runtipi’s app definition format for describing services, ports, volumes, and routing metadata. The preferred format is a standard docker-compose.yml file enhanced with x-runtipi metadata.

Quick Example

services: myapp: image: myapp:latest volumes: - ${APP_DATA_DIR}/data:/data environment: - FOO=bar - PASSWORD=${MYAPP_PASSWORD} x-runtipi: is_main: true internal_port: 80 x-runtipi: schema_version: 2

This is all you need to deploy a web app with automatic Traefik routing, networking, and data persistence.

x-runtipi Metadata Reference

Runtipi extends standard Docker Compose with x-runtipi metadata at two levels: top-level (document root) and service-level (per service).

Top-level x-runtipi

Placed at the root of docker-compose.yml, alongside services:

OptionTypeRequiredDescription
schema_versionnumberYesMust be 2
overridesarrayNoArchitecture-specific service overrides (see Architecture Overrides)
x-runtipi: schema_version: 2

Service-level x-runtipi

Placed inside a service definition:

OptionTypeRequiredDescription
is_mainbooleanNoMarks this service as the main app entry point (receives Traefik routing labels)
internal_portnumber | stringNoThe port the service listens on (used for Traefik routing)
add_to_main_networkbooleanNoAdds the service to Runtipi’s shared network for cross-app communication
services: app: image: myapp:latest x-runtipi: is_main: true internal_port: 8080

Standard Docker Compose Features

Everything else in your docker-compose.yml uses standard Docker Compose syntax. You don’t need to learn any custom format for volumes, environment variables, ports, healthchecks, etc. Here are some commonly used options:

Volumes

services: app: image: myapp:latest volumes: - ${APP_DATA_DIR}/config:/config - ${APP_DATA_DIR}/data:/data:ro

Use ${APP_DATA_DIR} for app-specific persistent data and ${RUNTIPI_MEDIA_DIR} for shared media directories.

Environment Variables

services: app: image: myapp:latest environment: - TZ=${TZ} - DB_PASSWORD=${MYAPP_DB_PASSWORD}

You can reference variables defined in the app’s config.json form fields using ${VARIABLE_NAME}.

Ports

For additional ports beyond the main internal_port (which is handled by Traefik), expose them directly:

services: app: image: myapp:latest ports: - "${APP_PORT}:8080/tcp" - "25565:25565/udp"

Health Checks

services: app: image: myapp:latest healthcheck: test: curl --fail http://localhost:8080 || exit 1 interval: 30s timeout: 10s retries: 3 start_period: 30s

Dependencies

services: app: image: myapp:latest depends_on: db: condition: service_healthy db: image: postgres:16 healthcheck: test: pg_isready -U postgres interval: 10s timeout: 5s retries: 5

Resource Limits

services: app: image: myapp:latest deploy: resources: limits: cpus: "0.5" memory: 512M reservations: devices: - capabilities: [gpu] driver: nvidia count: 1

Security Options

services: app: image: myapp:latest privileged: true cap_add: - NET_ADMIN cap_drop: - ALL security_opt: - no-new-privileges read_only: true user: "1000:1000"

Other Options

All standard Docker Compose options are supported, including command, entrypoint, working_dir, network_mode, extra_hosts, hostname, dns, tty, stdin_open, stop_signal, stop_grace_period, pid, sysctls, logging, devices, labels, shm_size, ulimits, and more. Refer to the Docker Compose documentation  for the full specification.

Architecture Overrides

You can provide architecture-specific service overrides in the top-level x-runtipi metadata. This is useful when you need different Docker images or settings for arm64 vs amd64.

services: media-server: image: mediaserver:latest volumes: - ${APP_DATA_DIR}/config:/config - ${RUNTIPI_MEDIA_DIR}:/media environment: - TZ=UTC x-runtipi: is_main: true internal_port: 8096 x-runtipi: schema_version: 2 overrides: - architecture: arm64 services: media-server: image: mediaserver:arm64-latest environment: - ARM_SPECIFIC_VAR=enabled - architecture: amd64 services: media-server: image: mediaserver:amd64-latest deploy: resources: reservations: devices: - capabilities: [gpu]

How Overrides Work

  • Runtipi detects the system architecture and applies matching overrides
  • Service names in overrides must match the base service names
  • Only specify properties that differ per architecture
  • Properties are deep-merged with the base configuration
  • Array properties (like volumes or ports) in overrides replace the base arrays entirely

Supported Architectures

  • amd64: Standard 64-bit x86 (x86_64)
  • arm64: 64-bit ARM (aarch64)

Complete Example

Here’s a full example of a web app with a database:

services: app: image: myapp:2.1.0 volumes: - ${APP_DATA_DIR}/data:/data environment: - DATABASE_URL=postgresql://postgres:${MYAPP_DB_PASSWORD}@myapp-db:5432/myapp - SECRET_KEY=${MYAPP_SECRET_KEY} healthcheck: test: curl --fail http://localhost:8080/health || exit 1 interval: 30s timeout: 10s retries: 3 depends_on: myapp-db: condition: service_healthy x-runtipi: is_main: true internal_port: 8080 myapp-db: image: postgres:16 volumes: - ${APP_DATA_DIR}/db:/var/lib/postgresql/data environment: - POSTGRES_DB=myapp - POSTGRES_PASSWORD=${MYAPP_DB_PASSWORD} healthcheck: test: pg_isready -U postgres interval: 10s timeout: 5s retries: 5 x-runtipi: schema_version: 2

Legacy JSON Format (docker-compose.json)

The JSON format (docker-compose.json) is legacy and maintained for backward compatibility only. Legacy files are automatically converted internally. New apps should use docker-compose.yml with x-runtipi metadata as documented above.

The legacy format uses a custom JSON structure instead of standard Docker Compose YAML. Key differences from the YAML format:

  • Uses camelCase property names (isMain, internalPort, addToMainNetwork) instead of x-runtipi metadata
  • Services are an array with a name field instead of a map
  • Environment variables use [{key, value}] array format instead of KEY=value strings
  • Volumes use {hostPath, containerPath} objects instead of host:container strings
  • Additional ports use addPorts with {containerPort, hostPort, tcp, udp} objects

Legacy JSON Validator

You can validate legacy JSON configurations using the validator below:

Legacy Configuration Options Reference

Schema Configuration

OptionTypeDescription
schemaVersionnumberSchema version (must be 2)
servicesarrayArray of service configurations
overridesarrayArchitecture-specific overrides

Basic Configuration

OptionTypeDescriptionExample
namestring (required)The name of the service and container"name": "nginx"
imagestring (required)The Docker image to use"image": "nginx:latest"
commandstring | string[]The command to run in the container"command": "/my/app" or "command": ["npm", "start"]
environmentarrayEnvironment variables[{"key": "FOO", "value": "bar"}]

Port Configuration

OptionTypeDescription
internalPortnumberThe main port exposed by the container
addPortsarrayAdditional ports to expose

Example addPorts:

"addPorts": [{ "containerPort": 8080, "hostPort": 8080, "tcp": true, "udp": false, "interface": "127.0.0.1" }]

Volume Configuration

"volumes": [{ "hostPath": "/host/path", "containerPath": "/container/path", "readOnly": false, "shared": false, "private": false, "bind": { "propagation": "rprivate" } }]

Network Configuration

OptionTypeDescription
networkModestringCustom network mode
addToMainNetworkbooleanAdd container to main network
extraHostsstring[]Additional /etc/hosts entries
hostnamestringContainer hostname
dnsstring | string[]Custom DNS servers

Health Check Configuration

"healthCheck": { "test": "curl --fail http://localhost", "retries": 3, "interval": "30s", "timeout": "10s", "startInterval": "5s", "startPeriod": "30s" }

Resource Configuration

OptionTypeDescription
deployobjectResource limits and reservations
ulimitsobjectResource limits
shmSizestringSize of /dev/shm

Security Configuration

OptionTypeDescription
privilegedbooleanRun container with elevated privileges
capAddstring[]Add container capabilities
capDropstring[]Drop container capabilities
securityOptstring[]Security options
readOnlybooleanMount root filesystem as read only
userstringUsername or UID

Advanced Configuration

OptionTypeDescription
entrypointstring | string[]Container entrypoint
workingDirstringWorking directory inside container
ttybooleanAllocate a pseudo-TTY
stdinOpenbooleanKeep STDIN open
stopSignalstringSignal to stop the container
stopGracePeriodstringTime to wait to stop container
pidstringPID namespace
sysctlsobjectSysctl settings
loggingobjectLogging configuration
devicesstring[]Device mappings
extraLabelsobjectAdditional container labels

Dependencies

OptionTypeDescription
dependsOnobject | string[]Service dependencies
isMainbooleanIndicates where traefik labels should be applied

Docker Compose to Legacy JSON Converter

If you need to convert an existing docker-compose.yml to the legacy JSON format:

Docker Compose YAML

Dynamic Compose Output

The converter works for most cases, but please review the converted configuration to ensure it meets your needs. Some advanced features may not be fully supported.

Last updated on