Skip to content

Importing Docker Compose Files

Quant Cloud supports importing standard docker-compose.yml files, allowing you to leverage your existing Docker Compose definitions with minimal changes. The platform automatically translates compose syntax into optimized cloud configurations.

services:
web:
image: nginx:latest # External image
app:
image: latest # Internal registry (tag only)

A tag-only image: and a service with build: both use an image from your organisation’s internal Quant Cloud registry. The platform does not run docker build; your CI builds and pushes the image. See Image tags for internal images.

services:
app:
command: ["php", "artisan", "queue:work"]
# OR
command: php artisan queue:work
entrypoint: ["/usr/local/bin/entrypoint.sh"]
# OR
entrypoint: /usr/local/bin/entrypoint.sh

Supports both string and array formats.

services:
app:
environment:
- DATABASE_HOST=mysql
- DATABASE_PORT=3306
# OR
environment:
DATABASE_HOST: mysql
DATABASE_PORT: 3306

Supports both array and object formats.

services:
web:
ports:
- "80" # Container port only
- "8080:80" # Host:container mapping
volumes:
db-data:
uploads:
services:
db:
volumes:
- db-data:/var/lib/mysql
- uploads:/var/www/html/uploads

Referenced volumes are automatically created as persistent volumes if they don’t exist.

A relative path source such as ./src:/var/www/html is read as a logical volume name, so it also becomes a persistent volume mounted over that path, and it hides the files that your image has at that path. Keep source-code bind mounts for local development in docker-compose.override.yml.

services:
app:
depends_on:
- db
- redis
# OR with conditions
depends_on:
db:
condition: service_healthy
redis:
condition: service_started

Supported conditions: START, HEALTHY, COMPLETE, SUCCESS

services:
web:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 40s
services:
app:
working_dir: /app
user: "1000:1000"

Using Standard Deploy Syntax:

services:
app:
deploy:
resources:
limits:
cpus: '1'
memory: 2048M
reservations:
memory: 1024M

deploy.replicas is ignored. The number of running copies comes from the environment’s minimum and maximum capacity (see scaling).

Using Quant Labels:

services:
app:
labels:
- "quant.cpu=1024"
- "quant.memory=2048"
- "quant.memory.reservation=1024"
x-quant-labels:
quant.task.cpu: "2048" # Total vCPU (1024 = 1 vCPU)
quant.task.memory: "4096" # Total memory in MiB
quant.architecture: "ARM64" # ARM64 or X86_64

If you do not set task-level resources, a new application gets the platform default of 256 CPU units (0.25 vCPU) and 512 MiB. That is too small for server-side rendering with image optimisation, or for most CMS sites: the task stops answering health checks and is replaced. Set at least 512/1024 for those workloads and adjust from the environment’s metrics.

quant.architecture must match the platform you build the image for (ARM64 with linux/arm64, X86_64 with linux/amd64). A mismatch stops the container at start.

volumes:
db-data:
cache-data:

Automatically created as persistent volumes with default paths.

  • Building images. A service with build: is not built by the platform; it uses an internal image (see Image tags for internal images)
  • networks (automatic service discovery provided)
  • secrets (use Quant Cloud secrets management)
  • configs (use environment variables or volumes)
  • Host network mode, privileged mode, device mappings

Exclude services from import:

services:
local-only:
image: mailhog/mailhog
labels:
- "quant.type=none"

Label a local database service with quant.type: mysql or quant.type: postgres. It is not deployed as a container. Use the managed database instead: enable it when you create the application, and Quant Cloud injects its connection variables.

services:
db:
image: mysql:8.4
labels:
quant.type: mysql

Task-level CPU and memory must follow the below combinations:

CPU (units) vCPU Memory Options (MiB)
256 0.25 512, 1024, 2048
512 0.5 1024, 2048, 3072, 4096
1024 1 2048-8192 (1024 MiB increments)
2048 2 4096-16384 (1024 MiB increments)
4096 4 8192-30720 (1024 MiB increments)

Invalid values are automatically adjusted with warnings.

version: "3.8"
x-quant-labels:
quant.task.cpu: "2048"
quant.task.memory: "4096"
quant.architecture: "X86_64"
volumes:
db-data:
uploads:
services:
web:
image: nginx:latest
ports:
- "80"
- "443"
labels:
- "quant.cpu=1024"
- "quant.memory=2048"
volumes:
- uploads:/var/www/html/uploads:ro
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 5s
retries: 3
depends_on:
app:
condition: service_healthy
app:
image: php:8.2-fpm
command: ["php-fpm", "-F"]
working_dir: /var/www/html
user: "www-data"
deploy:
resources:
limits:
cpus: '1'
memory: 1024M
volumes:
- uploads:/var/www/html/uploads
environment:
DB_HOST: db
REDIS_HOST: redis
depends_on:
- db
- redis
db:
image: mysql:8.0
volumes:
- db-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
command: ["redis-server", "--appendonly", "yes"]

An internal image is tagged <service>-<suffix>, where <service> is the compose service name. Production uses the suffix latest, so the service app runs the image tagged app-latest. Your CI must push exactly that tag. The Quant Cloud init action’s image_suffix_clean output gives the suffix for the current branch. If the tag starts with anything else (for example the framework name while the service is app), the image is not found and the deployment fails.

For feature branch deployments, append a suffix to internal image tags:

# Query parameter or JSON wrapper
imageSuffix: "feature-xyz"
# Transforms internal images
# "latest" becomes "web-feature-xyz"
# External images unchanged: "nginx:latest" stays "nginx:latest"

Perfect for PR previews and feature branch environments.

  1. Parse & Validate - YAML syntax and structure validation
  2. Translate - Convert to Quant Cloud’s internal format
  3. Volume Creation - Auto-create any missing volumes
  4. Task Configuration - Generate the task configuration
  5. Deploy - Update service and trigger deployment

The platform API is https://dashboard.quantcdn.io/api/v3 (QuantGov: https://dash.quantgov.cloud/api/v3). Authenticate with Authorization: Bearer <token>.

Validate and translate (no deploy):

Terminal window
POST /api/v3/organizations/{organisation}/compose/validate

The body is JSON with the file content in compose and an optional imageSuffix. The response contains translatedComposeDefinition and any translationWarnings.

Example:

Terminal window
jq -Rs '{compose: .}' docker-compose.yml | curl -sS -X POST \
-H "Authorization: Bearer $QUANT_API_KEY" \
-H "Content-Type: application/json" \
--data @- \
https://dashboard.quantcdn.io/api/v3/organizations/my-org/compose/validate

Send translatedComposeDefinition as composeDefinition when you create an application, or with PUT /api/v3/organizations/{organisation}/applications/{application}/environments/{environment} to replace an environment’s definition (this redeploys it).

  1. Start Simple - Test with basic compose files first
  2. Specify Resources - Always define x-quant-labels for CPU/memory
  3. Use Health Checks - Enable zero-downtime deployments
  4. Validate Locally - Run docker-compose config before importing
  5. Version Images - Use specific tags in production
  6. Use Secrets Management - Don’t hardcode credentials

“Invalid CPU/memory combination”

  • Check permitted combinations table above
  • Platform auto-corrects with warnings

“Volume not found”

  • Volumes auto-create with default paths
  • Create manually for custom paths

“Image not accessible”

  • Verify the internal tag exists in your registry and is <service>-<suffix>
  • Check external image names are correct

“Port mapping conflicts”

  • Ensure unique ports across containers