AgentSkillsCN

compose-check

针对 Phala Cloud CVM 的 docker-compose.yml 与 Docker 构建进行部署前验证。 检查架构、文件大小、密钥泄露、卷挂载,以及单文件约束。 适用于:用户在将 docker-compose.yml 或 Dockerfile 提交至 Phala Cloud 部署前,希望对其进行审查时使用, 或当 CVM 部署因 compose/镜像问题而失败时使用。

SKILL.md
--- frontmatter
name: compose-check
description: |
  Pre-deploy validation for docker-compose.yml and Docker build targeting Phala Cloud CVMs.
  Checks architecture, file size, secrets leakage, volume mounts, and single-file constraints.
  Use when: user shares a docker-compose.yml or Dockerfile for review before deploying to Phala Cloud,
  or when a CVM deploy fails due to compose/image issues.

Compose Pre-Deploy Check

Validate docker-compose.yml and Docker build configuration before deploying to a Phala Cloud CVM.

When to Run

User saysAction
"review my compose", "check before deploy"Run Full Checklist
"deploy failed", "container won't start"Run Full Checklist + check serial logs (phala logs --serial)
"need TEE features", "dstack", "attestation in app"Run TEE Volume Check
"image pull error", "unauthorized"Jump to Image Accessibility
"compose too large", "payload size"Jump to File Size

Full Checklist

Run every check in order. Stop and report the first failure. Mark each as PASS/FAIL in output.

1. Single-File Constraint

Phala Cloud accepts one docker-compose.yml — no external file references.

FAIL if any of these appear:

FieldExampleWhy it fails
build with path contextbuild: ./appBuild context directory not available on CVM
build.dockerfiledockerfile: Dockerfile.prodExternal Dockerfile not uploaded
extendsextends: file: base.ymlExternal compose file not available
env_fileenv_file: .envExternal file not available — use phala deploy -e .env instead
configs / secrets (file-based)file: ./my_configExternal files not uploaded
volumes with host bind (source files)./src:/app/srcHost files don't exist on CVM

PASS if:

  • build with inline Dockerfile (multi-line dockerfile_inline) — allowed but check Step 2
  • image references only — preferred pattern
  • Named volumes — fine (data:/var/lib/db)

Inline build is allowed but discouraged for large builds. The entire inline content counts toward the 200KB size limit.

2. File Size

Combined size of docker_compose_file + pre_launch_script must be ≤ 200KB (200 × 1024 = 204,800 bytes).

Measure in UTF-8 bytes, not characters (CJK characters = 3 bytes each).

If close to limit: Inline Dockerfiles and long scripts are the usual culprits. Move the Dockerfile out — pre-build and push the image to a registry, then reference by image: tag.

3. Architecture — amd64 Only

Phala Cloud CVMs run on Intel TDX hardware (x86_64/amd64). ARM images will not work.

Check Dockerfile / build config:

PatternVerdict
FROM --platform=linux/amd64 ...PASS — explicit
FROM node:20 (no platform specified)WARN — works if built on amd64 host, fails if built on Apple Silicon / ARM
FROM --platform=linux/arm64 ...FAIL
GOARCH=arm64 or TARGETARCH=arm64FAIL

Recommendation: Always build with explicit platform:

bash
docker buildx build --platform linux/amd64 -t myimage:latest .

Or in docker-compose.yml inline build:

yaml
services:
  app:
    build:
      dockerfile_inline: |
        FROM --platform=linux/amd64 node:20-slim
        ...

If user builds on Apple Silicon (M1/M2/M3): They MUST use --platform linux/amd64 or docker buildx. Default build produces arm64 images that crash on CVM boot with no obvious error message — serial logs may show exec format errors.

4. Image Accessibility

Every image: in the compose file must be pullable from the CVM at boot time.

Image typeWhat to check
Public (Docker Hub, ghcr.io)Verify tag exists: docker manifest inspect <image>
Private registryUser must set DSTACK_DOCKER_USERNAME + DSTACK_DOCKER_PASSWORD in env file
AWS ECRUser must set DSTACK_AWS_ACCESS_KEY_ID + DSTACK_AWS_SECRET_ACCESS_KEY + DSTACK_AWS_REGION + DSTACK_AWS_ECR_REGISTRY in env file
localhost / 127.0.0.1 imageFAIL — no local Docker daemon on CVM

Registry credentials go in the env file (phala deploy -e .env), NOT in docker-compose.yml. They are encrypted client-side before transmission.

5. Secrets Leakage

Scan docker-compose.yml for hardcoded secrets. FAIL if any found.

PatternExamples
Private keysPRIVATE_KEY=0x..., -----BEGIN RSA PRIVATE KEY-----
API keys / tokensAPI_KEY=sk-..., TOKEN=ghp_..., AWS_SECRET_ACCESS_KEY=...
PasswordsPASSWORD=..., DB_PASSWORD=..., REDIS_PASSWORD=...
Connection strings with credentialspostgres://user:pass@..., mongodb://user:pass@...
JWT secretsJWT_SECRET=..., SECRET_KEY=...

Fix: Move all secrets to the env file and deploy with phala deploy -e .env. Environment variables are encrypted client-side before reaching the API. The docker-compose.yml itself is stored as plaintext in the backend.

Acceptable in compose: variable references like ${DB_PASSWORD} (resolved from env file at runtime).

6. TEE Volume Mount

If the application needs TEE capabilities (key derivation, attestation quotes, TDX info), it must mount the dstack socket.

Check: Does any service have this volume?

yaml
volumes:
  - /var/run/dstack.sock:/var/run/dstack.sock
ScenarioVerdict
App uses dstack SDK / calls TEE APIFAIL if volume missing — app can't reach TEE
App is a plain web service, no TEE featuresPASS without volume — not needed
Volume uses legacy path /var/run/tappd.sockWARN — still works but recommend migrating to dstack.sock

Both sockets are available on the CVM. The dstack SDK tries dstack.sock first, falls back to tappd.sock. But the volume must be mounted for the container to access either.

7. Port and Network Sanity

Quick checks:

  • ports: with host binding (e.g., "8080:80") — fine, CVM maps these
  • network_mode: host — works but unusual for CVM
  • Multiple services exposing same host port — FAIL, port conflict at runtime

Output Format

After running all checks, report:

code
## Compose Pre-Deploy Check

| # | Check | Result | Detail |
|---|-------|--------|--------|
| 1 | Single-file constraint | PASS | No external file references |
| 2 | File size | PASS | 12KB (limit: 200KB) |
| 3 | Architecture | WARN | No --platform specified, verify build host is amd64 |
| 4 | Image accessibility | PASS | All images are public Docker Hub |
| 5 | Secrets leakage | FAIL | Line 15: hardcoded `PRIVATE_KEY=0x...` |
| 6 | TEE volume mount | PASS | dstack.sock mounted on service "app" |
| 7 | Port/network | PASS | No conflicts |

### Actions Required
- **[FAIL] Secrets leakage:** Move `PRIVATE_KEY` to env file, use `${PRIVATE_KEY}` reference in compose

Only list Actions Required for FAIL and WARN items. Skip if all PASS.


Gotchas

IssueDetail
Apple Silicon default builds arm64docker build on M1/M2/M3 without --platform linux/amd64 produces unusable images. Serial logs show exec format error.
env_file: in compose ≠ phala deploy -eCompose env_file: references a file that doesn't exist on CVM. Use phala deploy -e .env which encrypts and transmits vars separately.
Inline Dockerfile eats size budgetA 50-line Dockerfile inlined via dockerfile_inline can push compose over 200KB when combined with pre-launch script. Pre-build and push to registry instead.
docker-compose.yml is stored as plaintextThe compose content is visible in the backend. Only env vars (via -e) are encrypted. Never put secrets in the compose file.
Volume .:/app doesn't workHost bind mounts with relative paths reference the CVM filesystem, not the developer's machine. Only named volumes and specific system paths (like dstack.sock) are meaningful.
depends_on with condition: service_healthyHealth checks work normally but add boot latency. Keep health check intervals short for CVM startup.
restart: unless-stopped recommendedWithout restart policy, a crashed container stays down. CVM won't auto-heal.