This document summarizes all changes in this fork (explicitcontextualunderstanding/Container-Compose) relative to the upstream repository (Mcrich23/Container-Compose).
Current Release: v0.11.0 Container Runtime: v0.11.0 Last Updated: 2026-04-03
Release Date: 2026-04-03
New Features:
- Build secrets support —
build.secretsin compose files withid+env/srcfields - CONTAINER_DEFAULT_PLATFORM — env var fallback for platform resolution
- Registry protocol control —
--schemeflag for HTTP/HTTPS/auto registry access
Implementation Status:
- Build secrets: YAML parsing complete (7 tests), CLI wiring blocked on upstream mcrich23/container
- Platform fallback: Complete and tested
- Registry scheme: Complete and wired
Test Results: 200/200 tests passing (199 existing + 1 placeholder for blocked integration test)
There is a clinical 64-character limit for guest process labels in the macOS container runtime. When using long project names or UUID-based prefixes (common in test suites), service names must be kept short to avoid Invalid argument (Code 22) errors.
-
Proactive Validation: The orchestrator now warns users if a container name exceeds 63 characters during
upand provides a detailed discussion in--help. -
Port Isolation: Dynamic tests now use a dedicated, non-overlapping port range (18080–18085) to prevent "Address already in use" errors during parallel execution.
-
Image Compatibility: WordPress tests have been transitioned to
wordpress:fpm-alpineto bypassVirtualization.frameworksyscall limitations. -
Security Compliance: Installation now targets
~/binwith ad-hoc signing to ensure stability under macOS security policies. -
Recommended Names:
wp,db,web. -
Avoid: Long descriptive names like
wordpress-application-serviceif the combined length exceeds ~63 characters.
The test suite supports custom container registries via the OCI_REGISTRY_URL environment variable:
# Use custom registry (e.g., Cloudflare tunnel to bypass Apple Container RFC1918 HTTP downgrade)
OCI_REGISTRY_URL=registry.example.com swift testThis is particularly useful when working around Apple Container's HTTP auto-downgrade bug for private IP addresses (RFC1918). Database tests require OCI_REGISTRY_URL to be set because Apple Container does not support HTTP for private IPs.
Apple Container cannot pull images from registries using IP addresses (RFC1918 private IPs). It only supports domain names. This fork uses a Cloudflare tunnel with IP-based bypass authentication to route a domain to the local Zot registry:
Apple Container → registry.example.com → Cloudflare Tunnel → Zot (internal IP)
Cloudflare Access Configuration:
| Setting | Value |
|---|---|
| Application | Zot Registry Secure (your domain) |
| Policy | Service Token Bypass |
| Action | BYPASS |
| IP Ranges | Your local network ranges (e.g., 192.168.1.0/24, IPv6 prefix) |
Usage:
# Set registry URL for database tests
OCI_REGISTRY_URL=your-registry.example.com swift test --filter ComposeAdvancedTests
# Pull images via domain (works with Apple Container)
container run your-registry.example.com/your-image:latest echo "test"Troubleshooting 403 Errors:
- Verify your public IP:
curl -s ifconfig.me - Check Cloudflare Access policy includes your IP range
- IPv6 users need
/64prefix (not/128single address) - Policy changes take 30-60 seconds to propagate
| Status | File | Change Summary |
|---|---|---|
| Added | .github/workflows/release.yml |
Automated release workflow |
| Modified | .github/workflows/tests.yml |
Enhanced CI workflow, added static test filtering |
| Added+Modified | CHANGELOG.md |
Version changelog |
| Added | FORK_CHANGES.md |
This file — fork change tracking |
| Added | VERIFICATION.md |
Verification procedures and testing guidelines |
| Added+Modified | build-release.sh |
Release build script with conda/xattr cleanup |
| Added+Modified | build-sign-install.sh |
Build, sign, install with auto git hash injection and /usr/local/bin symlink |
| Added+Modified | install.sh |
Installation script with macOS provenance handling |
| Added+Modified | run-tests.sh |
Test runner with conda environment cleanup |
| Added+Modified | scripts/env-setup.sh |
Shared conda environment cleanup for build and test scripts |
| Modified | Sources/Container-Compose/Application.swift |
Added checkpoint command registration, git hash in version string |
| Modified | Sources/Container-Compose/Codable Structs/Build.swift |
Added target field for multi-stage builds |
| Modified | Sources/Container-Compose/Codable Structs/Network.swift |
Enhanced network synchronization |
| Modified | Sources/Container-Compose/Codable Structs/Service.swift |
Added dns_search array support, validation for restart/platform/runtime/volumes/ports |
| Added+Modified | Sources/Container-Compose/Commands/CheckpointCommand.swift |
Checkpoint command using container commit; post-creation P0 error handling fixes |
| Modified | Sources/Container-Compose/Commands/ComposeDown.swift |
Added try/throw support for deriveProjectName, -f flag with absolute/relative path handling, --timeout-seconds with graceful→force escalation, .container-compose.state for idempotent teardown, DownResult exit codes (0=clean, 1=timeout, 2=fatal) |
| Modified | Sources/Container-Compose/Commands/ComposeUp.swift |
Refactored with makeRunArgs, added 8 field mappings, StopOldStuffError, VolumeConfigError, CPU validation, pre-decode ${VAR} substitution, --force-recreate/--no-recreate, __SERVICE_HOST__/__SERVICE_PORT__ resolution, -f flag, --recover mode with drift detection, waitForCompletedSuccessfully() for service_completed_successfully, virtiofs database path warnings |
| Modified | Sources/Container-Compose/Commands/Version.swift |
Version display with git commit hash |
| Modified | Sources/Container-Compose/Errors.swift |
Added invalidResourceConfig, DependencyFailedError error cases |
| Added | Sources/Container-Compose/Commands/ComposePs.swift |
container-compose ps command: service-to-container matching, table/JSON output, service filter, exit codes |
| Added | Sources/Container-Compose/Commands/HealthCommand.swift |
container-compose health command: container health polling via container exec, table/JSON/watch output, service filtering |
| Modified | Sources/Container-Compose/Helper Functions.swift |
P0/P2 fixes: safe regex handling, VariableResolutionError, deriveProjectName sanitization, env_file error handling, resolveYamlVariables() with $$ escaping |
| Added | Tests/Container-Compose-StaticTests/CheckpointCommandTests.swift |
Unit tests for checkpoint command |
| Added+Modified | Tests/Container-Compose-StaticTests/ComposeUpMappingTests.swift |
Mapping tests for makeRunArgs flag generation, -f path resolution, --recover mutual exclusivity. |
| Added | Tests/Container-Compose-StaticTests/NetworkVolumeMappingTests.swift |
Network and volume synchronization tests |
| Modified | Tests/Container-Compose-DynamicTests/ComposeDownTests.swift |
Updated for 3-container WordPress setup |
| Modified | Tests/Container-Compose-DynamicTests/ComposeUpTests.swift |
Updated for WordPress FPM variant, port-agnostic assertions, Feature 1 & 2 integration tests |
| Modified | Tests/Container-Compose-DynamicTests/ComposeAdvancedTests.swift |
Fixed YAML string interpolation, added getZotRegistryURL() helper for custom registry configuration |
| Modified | Tests/Container-Compose-StaticTests/BuildConfigurationTests.swift |
Added build target tests |
| Modified | Tests/Container-Compose-StaticTests/DockerComposeParsingTests.swift |
Replaced force unwraps with guard statements |
| Modified | Tests/Container-Compose-StaticTests/EnvFileLoadingTests.swift |
.env file loading tests |
| Modified | Tests/Container-Compose-StaticTests/EnvironmentVariableTests.swift |
Environment variable tests |
| Modified | Tests/Container-Compose-StaticTests/HealthcheckConfigurationTests.swift |
Healthcheck configuration tests |
| Modified | Tests/Container-Compose-StaticTests/HelperFunctionsTests.swift |
deriveProjectName tests |
| Modified | Tests/Container-Compose-StaticTests/ServiceDependencyTests.swift |
Service dependency tests |
| Modified | Tests/TestHelpers/DockerComposeYamlFiles.swift |
Configurable test ports via environment variables |
| Added | Tests/Container-Compose-StaticTests/ComposePsMappingTests.swift |
40 static tests: PsStatus model, service-to-container matching, table/JSON formatting, summary |
| Added | Tests/Container-Compose-DynamicTests/ComposePsTests.swift |
8 dynamic tests: real container ps output, filter, JSON, exit codes |
| Added | Tests/Container-Compose-DynamicTests/HealthCommandTests.swift |
Dynamic tests: health polling, watch mode, service filtering |
| Added | Tests/TestHelpers/ContainerPollingHelpers.swift |
Async container state polling helpers for robust network validation |
| Added | Tests/compose_static_checks.sh |
Static validation script for compose files |
| Added | Tests/network_reachability.sh |
Network connectivity testing script |
| Added | docs/checkpoint.md |
Documentation for checkpoint feature |
| File | Reason |
|---|---|
ADVERSARIAL_REVIEW_FIXES.md |
Audit findings resolved, folded into codebase |
DYNAMIC_TEST_ANALYSIS.md |
Analysis superseded by stabilized test suite |
build-and-install.sh |
Consolidated into build-sign-install.sh |
docs/FORK_README_UPDATE.md |
Merged into FORK_CHANGES.md |
-
fix: remove RuntimeStatus type that doesn't exist (commit: c509a2f)
- Removes a reference to a RuntimeStatus type that wasn't present in the container library
-
fixed incorrect waiting for running container (commit: 8a4e5bb)
- Upstream commit
- Fixes wait logic so waiting for container startup no longer always times out
-
removed 30 second timeout when container already started (commit: eeddb26)
- Upstream commit
- Removes unnecessary fixed timeout when container is already running
-
added support for dnsSearch (commit: d509f8a)
- Upstream commit
- Adds dns_search/dnsSearch support for service name resolution with custom DNS search domains
-
added support for multi stage build target (commit: 02ca646)
- Upstream commit
- Adds support for specifying a build target (multi-stage Dockerfile target)
-
added information about what command is being run (commit: 4968a86)
- Upstream commit
- Outputs the exact container tool command being executed for debugging
-
fix: place --entrypoint flag before image name (commit: 84201f9)
- Upstream commit
- Ensures --entrypoint is passed before the image name for proper interpretation
-
test: add named volume full path preservation test (commit: 8edb8a9)
- Upstream commit
- Adds unit/regression tests to preserve full destination paths for named volumes
-
fix: use full destination path for named volumes (commit: b1badf8)
- Upstream commit
- Corrects handling of named volume destination paths
-
CI / release workflow additions (commits: 3f20dbf, 98b7fc4, 1d284fb)
- GitHub Actions workflows for release automation
-
v0.10.0 Features:
- Standardized Argument Construction: Refactored
ComposeUp.swiftwith centralizedmakeRunArgshelper - Entrypoint Positioning: Fixed
--entrypointplacement relative to image name - Shared Utilities: Extracted
streamCommandandderiveProjectNameintoHelper Functions.swift - Service Property Restoration: Restored
runtime,init, andinit_imagesupport inService.swift - Checkpoint Subcommand: Added
container-compose checkpoint <service>usingcontainer commit - Mapping Tests: Added
ComposeUpMappingTestsfor flag generation validation - Network/Volume Sync: Improved synchronization of network and volume definitions
- Standardized Argument Construction: Refactored
-
Unreleased Features & Fixes:
- Pre-decode
${VAR}substitution:resolveYamlVariables()resolves environment variables in raw YAML before decode, enabling${VAR}inimage:,volumes:,command:, etc. Supports${VAR:-default}and${VAR:?error}with Docker Compose-compatible$$escaping for literal$. __SERVICE_HOST__/__SERVICE_PORT__resolution: Runtime container IPs and ports resolved for__{NAME}_HOST__and__{NAME}_PORT__patterns in env values with fuzzy matching.- Container runtime diagnostics: Test trait reports API server version, commit, and EUID.
- Idempotent compose up:
--force-recreateand--no-recreateflags. - Build tooling: Auto git hash injection in
build-sign-install.sh,/usr/local/binsymlink maintenance. - Test improvements: Shortened container prefix, 128 static tests + 9 dynamic tests passing.
${VAR}pipeline fix: Replaced naive${stripping withresolveVariable()for proper default/error syntax.
- Pre-decode
-
v0.10.2 Fixes:
-
Service-level volume mapping: Fixed critical bug where
service.volumesentries were parsed from YAML but never generated-vflags forcontainer run. Integrated volume handling intomakeRunArgs()with support for bind mounts and named volumes. Removed deadconfigVolume()function. Added 4 new mapping tests. -
Healthcheck-aware depends_on: Implemented
waitForHealthy()inComposeUp.swiftthat polls a dependency's healthcheck command viacontainer execbefore starting dependent services. Supports CMD, CMD-SHELL, and NONE formats with configurable interval/timeout/retries/start_period. -
Container polling helpers: Added
ContainerPollingHelpers.swifttoTestHelpersmodule providing async polling for container state verification (networks, status) with proper error handling and timeouts. Re-enabledtestThreeTierWebApp()with safe network assertions replacing force unwraps.- Fixed
container execsyntax: Apple'scontainer execdoes not use--separator (unlike Docker). Updated exec arg construction to match Apple CLI format. - Shorthand
env:Key Support: Fixed critical bug whereenv:shorthand was not decoded. Now properly recognized as alias forenvironment:(env takes precedence when both present) - Environment Variable Test Fix: Fixed
HOSTvariable conflict in tests by using unique names (DB_HOST,DB_PORT,DB_NAME) - Volume Creation Idempotency: Gracefully handle "already exists" errors during volume creation
- Command String Parsing: Split string-form commands into proper executable + arguments array
- Environment Variable Mapping: Added
--envflag mapping to pass service env vars to containers - Port Mapping: Added missing
--publishflag mapping inmakeRunArgsfor service port mappings - Test Suite Stabilization: Achieved 100% test pass rate (141/141 static + 9/9 dynamic) by resolving naming, port, image compatibility, and volume mapping issues.
- Fixed
-
v0.10.1 Fixes:
- Restart stopped containers on compose up: When containers exist but are stopped, automatically start them instead of returning an error
- Static checks: Added
compose_static_checks.shfor compose file validation - Network reachability: Added
network_reachability.shfor DNS and connectivity testing
-
v0.10.3 — Orchestration Hardening (Plan 65):
- Phase 1 —
--recovermode: Crash recovery for compose projects. Detects existing containers, skips running ones, starts stopped ones, creates missing ones, respects dependency order. Replaces 200-line orchestrator scripts withcontainer-compose up --recover -f compose.yml. - Phase 2a — Dependency chain halt:
waitForCompletedSuccessfully()blocks dependents when a container exits with non-zero code. 6 static tests. - Phase 2b —
service_completed_successfullycondition: Compose file support fordepends_on: { service: { condition: service_completed_successfully } }. 8 static tests. - Phase 3 — Virtiofs database path warnings: Warns on named volumes with DB-like paths (
postgres,mysql,mongodb,data) under virtiofs, wherechmod/chownwill fail. - Phase 4 —
container-compose healthcommand: Container health polling viacontainer exec, table/JSON/watch output modes, service filtering, exit codes (0=healthy, 1=unhealthy, 2=error). - Phase 5a —
container-compose downtimeout hardening:--timeout-seconds Nflag with graceful→force escalation..container-compose.statefile for idempotent teardown across interrupted runs.DownResultexit codes (0=clean, 1=timeout, 2=fatal). - Phase 6 —
container-compose pscommand: Service-to-container matching bycontainer_nameoverride or{project}-{service}convention. Table/JSON output, service filter, exit codes, summary line. 40 static tests + 8 dynamic tests. - Test suite: 188 total tests (141 static + 8 dynamic passing + 1 skip + 1 disabled).
- Phase 1 —
These features are present in this fork but not in apple/container v0.10.0:
- RuntimeStatus type removal (c509a2f)
- Container wait logic fixes (8a4e5bb, eeddb26)
- dnsSearch / dns_search support (d509f8a)
- Multi-stage build target support (02ca646)
- Debug output for CLI commands (4968a86)
- Entrypoint flag positioning fix (84201f9)
- Named volume full-path preservation (b1badf8, 8edb8a9)
- Checkpoint command (v0.10.0)
- Restart stopped containers (v0.10.1)
--recovermode (v0.10.3) — crash recovery: skip running, start stopped, create missing, respect dependency orderservice_completed_successfullycondition (v0.10.3) — halt dependency chain on non-zero container exitcontainer-compose healthcommand (v0.10.3) — container health polling viacontainer exec, table/JSON/watch outputcontainer-compose pscommand (v0.10.3) — service status table, JSON output, service filter, exit codescontainer-compose downtimeout (v0.10.3) —--timeout-secondswith graceful→force escalation,.container-compose.statefor idempotent teardown- Virtiofs database path warnings (v0.10.3) — warn on named volumes with DB-like paths under virtiofs
Based on analysis of apple/container v0.11.0 upcoming features and current fork capabilities.
container-compose distinguishes dependencies by ownership:
| Type | Ownership | Lifecycle | Gating | Pattern |
|---|---|---|---|---|
| Internal | Managed by compose | Create/Start/Destroy | service_healthy supported |
Orchestrator verifies readiness |
| External | Host/Another project/Hardware | Persistent, independent | Addressable-only | App-level retries |
| Component | Change | UX Impact |
|---|---|---|
| Parser | external: true strips healthcheck blocks |
Prevents accidental hang |
| Dependency Engine | condition: service_healthy → error/warning for externals |
Fail-fast behavior |
| Resolver | __SERVICE_HOST__ resolved before runtime |
Enables late-binding |
| CLI/Logs | [WARN] 'db' is external. Ignoring health-gate; ensure app-level retries. |
Educates user |
For external services, use pre-processing to resolve host-specific endpoints:
# Before render (template)
services:
app:
environment:
DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@${EXTERNAL_DB_HOST}:${DB_PORT}/mydb
depends_on:
- db # Short form only - no health gating
# render-script.py resolves ${EXTERNAL_DB_HOST} before compose upSoft check with short timeout:
- Logic:
nc -z ${HOST} ${PORT}(500ms timeout) - Result: Log
[INFO] External service 'db' not reachable on port 15432. Proceeding anyway... - Rationale: Don't block deployment for momentary network issues; app handles retries
| Feature | Status | Upstream Version | Production Validated |
|---|---|---|---|
init/init_image support |
✅ Complete | v0.10.0 | Yes |
runtime flag |
✅ Complete | v0.10.0 | Yes |
| Checkpoint command | ✅ Complete | v0.10.0 | No |
| Restart stopped containers | ✅ Complete | v0.10.1 | Yes (post-crash) |
| Multi-stage build target | ✅ Complete | Fork-only | No |
dns_search support |
✅ Complete | Fork-only | Yes |
Pre-decode ${VAR} substitution |
✅ Complete | Unreleased | Yes (replaces renderer) |
service_healthy dependency enforcement |
✅ Complete | Unreleased | Yes (compose-managed only) |
__SERVICE_HOST__/__SERVICE_PORT__ resolution |
✅ Complete | Unreleased | Yes |
| External dependency fail-fast | ✅ Complete | v0.10.3 | Yes |
| External dependency health-gating skip (crash recovery) | ✅ Complete | Unreleased | Yes (post-crash) |
-f / --file flag |
✅ Complete | Unreleased | Yes (use long form) |
--recover mode |
✅ Complete | Fork-only | Yes (post-crash) |
service_completed_successfully condition |
✅ Complete | Fork-only | Yes (Phase 2b) |
container-compose health command |
✅ Complete | Fork-only | Yes (Phase 4) |
container-compose ps command |
✅ Complete | Fork-only | Yes (Phase 6) |
container-compose down timeout + state file |
✅ Complete | Fork-only | Yes (Phase 5a) |
| Virtiofs database path warnings | ✅ Complete | Fork-only | Yes (Phase 3) |
| File volume mounts | — | Warning logged, mount attempted | |
--env-file support |
❌ Missing | — | Workaround: render env vars |
| Named volume recreation (skip if exists) | ❌ Error | — | Workaround: pre-create |
| Multi-service changed-only restart | ❌ All restart | — | Workaround: per-service render |
| Named volume virtiofs chmod/chown | ❌ Permission denied | — | Workaround: container run for DB |
Release notes — no breaking CLI or API changes.
| Feature | Upstream PR | Compose Impact | Fork Action |
|---|---|---|---|
| Build secrets support | #1300 | Add secrets: to build: config |
Extend Build.swift with secrets array |
| Network MTU configuration | #1267 | Add mtu: to network definitions |
Update Network.swift with MTU field |
| Default CPUs/memory (container) | #1266 | System properties set defaults | May affect makeRunArgs() resource flags |
| Default CPUs/memory (builder) | #1293 | System properties set defaults | May affect build resource allocation |
| CONTAINER_DEFAULT_PLATFORM | #1286 | Default image platform selection | Evaluate if fork needs explicit arch flag |
| Checkpoint export as OCI tar | #1303 | Breaking change to checkpoint format | Update CheckpointCommand.swift |
| Dockerfile ignore files | #1273 | .dockerignore per Dockerfile |
No compose change needed |
| ARG parsing fixes | #1342 | Build arg resolution | Verify existing ${VAR} handling |
| Auto-remove container prune on start | #1290 | Reaps orphaned auto-remove containers | No compose change needed |
| Rootfs override | #1323 | Custom init filesystem per service | Evaluate for compose integration |
| Registry resource (auth) | #1195 | Native registry authentication | Spike to deprecate fork registry handling |
| Volumes allow "." | #1326 | Current directory as volume source | No compose change needed |
| Container lifecycle hang fixes | Multiple | Addresses XPC timeout issues | May reduce need for --timeout-seconds |
| CLI stop/delete error on not found | #878 | container stop/delete error instead of silent fail |
Scripts should handle exit codes explicitly |
| Containerization 0.29.0 | #1327 | Runtime dependency bump | Required for build secrets |
| Feature | Upstream PR | Notes |
|---|---|---|
| High-Performance File Transfer | #1190 | container cp for sync/hot-reload |
| Advanced Networking | #1151 | Multi-plugin network support |
| Auto-Start (LaunchAgent) | #1176, #1201 | Boot service installation |
| Robust Service Lifecycle (Restart Policies) | #1258 | restart: always/on-failure/unless-stopped |
Implemented in v0.10.3 (Plan 65 Phase 1). See container-compose up --recover --help for usage.
The --recover flag is the single highest-impact feature for production use. After a macOS crash, the current recovery path requires a 200-line orchestrator script that checks each container individually, skips running ones, starts missing ones, and manages startup order manually.
| Behavior | Description |
|---|---|
| Detect existing containers | Scan for containers with matching project+service names |
| Skip running containers | Don't attempt to recreate or restart already-running services |
| Start stopped containers | container start for containers that exist but are stopped |
| Create missing containers | container run for services with no existing container |
| Respect dependency order | Topological sort ensures dependencies start before dependents |
| Skip health-gates for externals | Don't wait for service_healthy on pre-existing containers (v0.10.3 already does this partially) |
| Idempotent | Safe to run multiple times — no-op if all services are running |
| Step | Current (orchestrator script) | With --recover |
|---|---|---|
| 1 | Check if DB exists → container run or skip |
container-compose up --recover -f compose.yml |
| 2 | Check if hub exists → container-compose up |
Single command handles all services |
| 3 | Check if hermes exists → container-compose up |
Automatic dependency ordering |
| 4 | Start 4 derivers individually | All services recovered in one pass |
| 5 | Verify all running | Built-in status reporting |
| Lines of code | ~200 (shell script) | 1 command |
Features currently worked around in external orchestrator scripts (e.g., apple-container-honcho-compose.sh).
Updated 2026-04-02 after macOS crash recovery effort revealed critical gaps in crash resilience.
| Gap | Current Workaround | Impact | Priority |
|---|---|---|---|
--recover mode |
container-compose up --recover -f compose.yml detects existing containers, skips running ones, starts stopped ones, creates missing ones, respects dependency order. Replaces the 200-line orchestrator script with one command. See Plan 65 Phase 1. |
||
container restart |
External watchdog scripts | No native restart policy enforcement after crashes; restart: always/on-failure is parsed but cannot be delegated to runtime |
High |
| Digest-pinned images | Zot mirror with stable tag (honcho-hub:stable) |
container-compose strips @sha256:... suffix from image references and pulls :latest instead, defeating digest-based pinning. Workaround: copy pinned image to local Zot with a stable tag and reference that tag. This breaks on Zot registries that return HTTP 400 for Docker v2 pull API. |
High |
| Service bind-mount volumes | Render compose with patches in command |
configVolume() function exists as dead code in ComposeUp.swift:839 (parses paths, validates traversal, generates -v args) but is never called from makeRunArgs(). Service-level volumes: entries are parsed into service.volumes but zero -v/--mount flags are generated for container run. File mounts are explicitly skipped with a warning (line 880). Directory mounts generate -v but mode (:ro) is stripped. All bind mounts silently ignored. Workaround pattern: A Python render script (render-honcho-compose.py) injects live-patches into the compose command: block before container-compose up. This enables a "Circuit Breaker" that skips Alembic migrations when the database schema already exists, preventing data loss on image updates. To force migrations when needed, set HONCHO_FORCE_MIGRATION=1 on the hub service. |
High |
container cp |
Volume mounts for all file sharing | No hot-reload or file sync capability; limits dev workflow | High |
container wait |
Polling with container list |
Cannot efficiently block until a container exits; adds latency to shutdown orchestration | Medium |
container-compose down XPC timeout |
container stop + container rm manually |
container-compose down fails with internalError: "XPC timeout"container-compose down --timeout-seconds 30 uses graceful→force escalation. .container-compose.state file tracks teardown state for idempotent recovery. See Plan 65 Phase 5a. |
|
| Multi-service restart scope | Per-service rendered compose | container-compose up restarts ALL services in the compose file even when only one changed. docker compose only restarts changed services. Workaround: Render per-service compose files (one service per file) and run container-compose up -d <service> individually. The orchestrator's render_compose() function strips all non-target services. |
Medium |
| File volume mount (single file) | container run instead of compose |
container-compose logs a warning and attempts the mount anyway: Warning: Volume mount source '/path/to/file' is a file. The 'container' tool does not support direct file mounts. Skipping this volume. Hermes kubeconfig still requires container run workaround. |
High |
| Named volume recreation error | container volume create before compose |
container-compose errors when a named volume already exists. docker compose gracefully skips. Workaround: Run container volume create <name> before container-compose up in the orchestrator. |
Medium |
--env-file support |
Render env vars into compose file | container-compose does not support --env-file for loading .env files. All env vars must be in the compose file's environment: block or host env. Workaround: Python render_compose() resolves secrets from 1Password Connect and bakes them into the rendered YAML. |
Medium |
| Named volume virtiofs chmod failure | container run for DB (Phase 1) |
container-compose converts named volumes to host directory bind mounts via virtiofs, where chmod/chown fails. PostgreSQL's entrypoint requires chmod/chown on the data directory. container run uses the native ext4 volume driver where this works. Workaround: Two-phase startup — DB via container run, all other services via container-compose. This is the single biggest architectural constraint on the Honcho stack. |
High |
The orchestrator script works around several features that container-compose already implements natively:
| Feature | Container-Compose Support | Orchestrator Workaround (unnecessary) |
|---|---|---|
-f flag |
-f on ComposeUp and ComposeDown; accepts absolute or relative paths, skips CWD scanning when explicit |
Symlink desired file to compose.yml before each call |
${VAR} interpolation |
resolveYamlVariables() in Helper Functions.swift resolves ${VAR}, ${VAR:-default}, ${VAR:?error} on raw YAML before decode (Docker Compose compatible with $$ escaping) |
Python pre-renders compose file with os.environ substitution |
depends_on ordering |
Service.topoSortConfiguredServices() does topological sort at ComposeUp.swift:147; waitForHealthy() gates service_healthy dependencies |
Manual sequential container-compose up -d <service> calls |
service_healthy on externally managed containers |
waitForHealthy() now verifies container exists before health polling (v0.10.3) |
Mitigated: Now fails fast with ContainerNotFoundError if dependency container doesn't exist. Root cause remains: For externally managed containers (started outside compose), use depends_on: [service_name] (short form) instead of depends_on: { service_name: { condition: service_healthy } }. The service_healthy condition assumes compose owns the dependency's lifecycle and healthcheck configuration. |
| Partial compose / volumes | setupVolume() handles "already exists" gracefully; top-level named volumes created idempotently per compose file. Service-level volumes: are parsed but never wired to container run args (dead code configVolume() at line 839) |
Regex-based stripping of volumes: and single-service extraction; orchestrator renders patches into command instead |
No breaking CLI or API changes. Safe to upgrade with containers running — existing containers continue on the old runtime until stopped and restarted.
Behavioral Changes:
- Checkpoint export format changes (#1303) — checkpoint files may need migration
container stop/deletenow error on not-found containers (#878) — scripts should handle exit codes explicitly- Default CPUs/memory set via system properties (#1266, #1293) — may affect resource allocation on next
container run/container-compose up - Auto-remove containers reaped on system start (#1290) — orphaned auto-remove containers cleaned up
New Capabilities Available:
- Build secrets via
container build --secret(#1300) - Network MTU via
--network ...mtu=N(#1267) CONTAINER_DEFAULT_PLATFORMenv var for image arch selection (#1286)- Rootfs override per container (#1323)
- Registry resource for authentication (#1195)
- Volumes allow "." as source (#1326)
Deprecations:
- Evaluate removing fork registry auth if #1195 meets needs
New Dependencies:
- Containerization 0.29.0 (bundled with v0.11.0)
- Swift tools version unchanged (v5.9+)
| Feature | Test Priority | Type |
|---|---|---|
| Build secrets | High | Integration |
| Network MTU | Medium | Unit + Network |
| Resource limits | High | Resource validation |
| Checkpoint export | High | Migration/compat |
| RegistryResource | Medium | Auth flows |
| Rootfs override | Low | Integration |
| v0.11.0 compat | High | Full suite |
Ready to upstream:
-
dns_searchsupport (if not in v0.11.0) - Build
targetfield - Named volume full-path preservation
Blocked on upstream:
- Restart policies (waiting for #1258)
container cpintegration (waiting for #1190)
Fork-only:
- Checkpoint command (compose-specific)
- Restart stopped containers (compose lifecycle)
- Debug output formatting
| Feature | Test Coverage | Priority |
|---|---|---|
| Persistence | Named volumes, full path preservation | High |
| Security | SELinux compatibility, build secrets | High |
| Reliability | Memory validation, restart policies, stopped container restart | High |
| Networking | DNS search, network reachability, MTU configuration | Medium |
| Build | Multi-stage targets, build secrets, resource limits | High |
| Lifecycle | Checkpoint export/import, container restart | High |
| Orchestration | healthcheck-aware depends_on |
High |
| Registry | Authentication, push/pull | Medium |
| Test Infrastructure | Container polling helpers, async state verification | High |
- Create detailed CHANGELOG.md with migration notes
- Update README and CLI --help strings for fork-only features
- Audit tests for upstream v0.11.0 compatibility
- Add build secrets support to
Build.swift(v0.11.0 upstream #1300) - Add network MTU to
Network.swift(v0.11.0 upstream #1267) - Spike RegistryResource (#1195) to evaluate deprecating fork registry auth
- Update
CheckpointCommand.swiftfor OCI tar export format (v0.11.0 #1303) - Consider upstreaming: dns_search, build.target, entrypoint fix, named-volume behavior
- Implement healthcheck-aware
depends_on(wait for dependency healthy before starting dependents) - Fix
service_healthyhandling for externally managed existing containers (v0.10.3: crash recovery detection skips health-gates) - Implement
--recovermode (v0.10.3 Plan 65 Phase 1) — detect existing running containers, skip them, start missing ones, respect dependency order - Fix XPC timeout on
container-compose downfor long-running containers (v0.10.3 Plan 65 Phase 5a — graceful→force escalation, state file) - Add file volume mount support (v0.10.3 — warning logged, mount attempted)
- Add
container-compose healthcommand (v0.10.3 Plan 65 Phase 4) - Add
container-compose pscommand (v0.10.3 Plan 65 Phase 6) - Add
service_completed_successfullycondition (v0.10.3 Plan 65 Phase 2b) - Add virtiofs database path warnings (v0.10.3 Plan 65 Phase 3)
- Add
--env-filesupport for.envfile loading - Implement changed-service-only restart (skip services with identical config)
- Fix named volume "already exists" error (skip gracefully like docker compose)
-
Investigate virtiofs chmod/chown failure for named volumes— RESOLVED: Apple Container 0.11.0 (kernel 6.18.5) no longer EPERMs on virtiofs.chmodworks,chownis silent no-op (exit 0). PostgreSQL (walg-db/dark-db entrypoint) runs correctly on virtiofs named volumes. See Plan 95 Phase 11.
Features missing or incompatible in Apple's container CLI relative to Docker that block or complicate compose orchestration.
| Feature | Docker CLI | Apple container CLI |
Impact on Compose |
|---|---|---|---|
exec -- separator |
docker exec <id> -- cmd args |
No -- support; args go directly after container ID: container exec <id> cmd args |
Compose healthcheck execution must strip -- from exec args (worked around in fork) |
container wait |
docker wait <id> returns exit code |
Not implemented (Plugin 'container-wait' not found) |
No way to block until a container exits; forces polling with container list |
container cp |
docker cp <id>:src dest |
Not implemented (Plugin 'container-cp' not found) |
No file sync or hot-reload; must use volume mounts for all file sharing |
container restart |
docker restart <id> |
Not implemented (Plugin 'container-restart' not found) |
Restart policies (restart: always/on-failure) cannot trigger restarts after crashes |
container attach |
docker attach <id> |
Not implemented (Plugin 'container-attach' not found) |
Cannot reconnect to a container's stdin/stdout after detach |
| Feature | Docker CLI | Apple container CLI |
Impact on Compose |
|---|---|---|---|
container rename |
docker rename <old> <new> |
Not implemented (Plugin 'container-restart' not found) |
Cannot rename containers; must track original names |
container health / health status in inspect |
docker inspect returns Health.Status |
No health status field in container metadata | Compose must exec healthcheck commands manually via container exec (works, but native health state would avoid exec overhead per poll) |
container logs --since / --tail |
docker logs --tail 100 --since 1m |
container logs lacks filtering flags |
Cannot efficiently fetch recent logs for debugging |
--restart policy on run/create |
docker run --restart=always |
Not present on container run |
Compose restart: key cannot delegate to runtime; needs external watchdog |
--hostname on run/create |
docker run --hostname foo |
Not present on container run |
Compose hostname: key must be handled via /etc/hosts volume mount workaround |
| Feature | Docker CLI | Apple container CLI |
Impact on Compose |
|---|---|---|---|
--cap-add / --cap-drop |
docker run --cap-add SYS_PTRACE |
Not present on container run |
Cannot configure Linux capabilities |
--security-opt |
docker run --security-opt seccomp=... |
Not present on container run |
Cannot configure seccomp/AppArmor profiles |
--pid (PID sharing) |
docker run --pid=container:id |
Not present on container run |
Cannot share PID namespace between containers |
--shm-size |
docker run --shm-size=256m |
Not present on container run |
Cannot configure shared memory size |
--tmpfs with options |
docker run --tmpfs /run:rw,noexec |
container run --tmpfs supports path only |
Cannot set tmpfs mount options |
--gpus |
docker run --gpus all |
Not present on container run |
No GPU passthrough support |
| Feature | Docker Syntax | Apple container Syntax |
Workaround in Fork |
|---|---|---|---|
exec argument separation |
docker exec <id> -- cmd args |
container exec <id> cmd args |
Strip -- before passing to exec |
| Volume bind mount format | docker run -v src:dest:ro |
container run --mount type=bind,source=src,target=dest,readonly |
Convert -v format to --mount format in makeRunArgs |
| Network attach format | docker run --network foo |
container run --network foo[,mac=XX:XX:XX:XX:XX:XX] |
Direct mapping, no issue |
| Port publish format | docker run -p 127.0.0.1:8080:80 |
container run --publish 8080:80 (no bind address in older versions) |
Verified: --publish 127.0.0.1:8080:80 works in current version |
- Tests overhaul: Mcrich23#22
- Named volume fixes: Mcrich23#32, Mcrich23#42
- ComposeDown tests: Mcrich23#50