- Container dependency health check for missing containers:
waitForHealthy()now fails fast withContainerNotFoundErrorwhen a dependency container doesn't exist, instead of hanging indefinitely. Provides clear error message explaining the issue and suggesting either removingdepends_on: condition: service_healthyor ensuring the container exists with the expected name. - Documentation: Clarified that
service_healthydependencies should only be used for containers managed by compose. For externally managed dependencies, use short-formdepends_on: [service_name]instead.
- External dependency health-gating (crash recovery): When
container-compose upencounters adepends_on: { condition: service_healthy }against a container that is already running (started outside compose or by a previous run), it now skips the health wait and emits a warning. This prevents hangs on externally managed containers — critical for crash recovery scenarios where services like honcho-db and honcho-hub survive a Mac crash and compose is re-run. The newexternallyPresentServicesset tracks pre-existing running containers and skipswaitForHealthy()for their dependents.
- Registry environment variable: Database tests now require
OCI_REGISTRY_URLenvironment variable (wasOCI_REGISTRY_URL). Tests fail fast with clear instructions if not set. Apple Container does not support HTTP for RFC1918 private IPs, so an HTTPS-accessible registry is required for container image tests. - Test documentation: Added
docs/DYNAMIC_TEST_PATTERNS.mddocumenting container orchestration challenges discovered through dynamic testing.
- Registry access via Cloudflare tunnel: Documented workaround for Apple Container's inability to pull from IP-address registries. Private Zot registry now accessible via Cloudflare tunnel with IP-based bypass authentication. See
managing-container-registryskill for Cloudflare Access configuration details.
- YAML string interpolation in database tests: Fixed malformed multi-line string syntax where
\\(should be\(for proper Swift string interpolation. TeststestDatabaseContainerStartsandtestThreeTierWithDatabasenow correctly substituteOCI_REGISTRY_URLenvironment variable. - Test suite stability: All 164 tests now pass with proper registry URL configuration via
OCI_REGISTRY_URLenvironment variable.
- Registry URL configuration: Database tests now use
getZotRegistryURL()helper function that readsOCI_REGISTRY_URLenvironment variable (defaults to192.168.1.86:30500). Users can override with custom registry URLs for different deployment scenarios. - YAML formatting: Standardized indentation in test YAML strings (2 spaces for services, 4 spaces for nested fields) matching Docker Compose conventions.
- Environment variable injection: Tests now support
OCI_REGISTRY_URL=registry.example.com swift testpattern for custom registry configurations. - Full test suite: 164 tests passing (1 skipped - known YAML parsing issue in bind mount test).
- Service-level volume mapping:
service.volumesentries now generate-vflags incontainer runcommands. Bind mounts (paths with/or starting with.) and named volumes are supported. - Pre-decode
${VAR}substitution: Environment variables (${VAR},${VAR:-default},${VAR:?error}) are now resolved in raw YAML before decode, matching Docker Compose behavior. This resolves${VAR}inimage:,volumes:,command:, and all other compose fields — not justenvironment:values. $$escaping support: Users can write$$in compose YAML to produce a literal$for shell interpreters (e.g.,command: ["sh", "-c", "echo $$HOME"]→ shell sees$HOME).resolveYamlVariables()function: New helper inHelper Functions.swiftthat wrapsresolveVariable()with$$sentinel escaping for safe pre-decode substitution.__SERVICE_HOST__/__SERVICE_PORT__placeholder resolution: Runtime container IPs and ports are resolved for__{SERVICE_NAME}_HOST__and__{SERVICE_NAME}_PORT__patterns in environment variable values, with fuzzy matching (case-insensitive, strips hyphens/underscores).- Container runtime diagnostics:
ContainerDependentTraitnow pings the container API server on test startup and reports version, commit, and EUID status. - Idempotent
compose up: Added--force-recreateand--no-recreateflags to control whether running containers are recreated. - Integration tests for Feature 1 and Feature 2: Static tests verify pre-decode substitution through the full YAML decode pipeline; dynamic tests verify
${VAR}resolution in running containers andservice_healthydependency enforcement. - Volume mapping tests: Added
testBindMountMapping,testNamedVolumeMapping,testAbsolutePathBindMountMappingWithinCwd,testOutsidePathSecuritySkippedto verify-vflag generation. - Container polling helpers: New
TestHelpersmodule withContainerPollingHelpersfor async container state verification:waitForNetworks()- polls until container networks populate (Apple Container networks are async)waitForAllNetworks()- waits for all project containers to have networkswaitForContainers()- waits for containers to be createdContainerTestHelpers.assertHasNetworks()- safe network assertions without force unwraps
- Three-tier web application test: Re-enabled
testThreeTierWebApp()(formerly commented) using postgres:14-alpine, nginx:alpine, node:18-alpine, redis:alpine with network polling validation.
- Dead code removal: Removed unused
configVolume()function atComposeUp.swift:839that was never called; volume handling is now properly integrated intomakeRunArgs(). - Service volume mounting: Previously
service.volumeswas parsed from YAML but never generated-vflags forcontainer run. Now properly wired to create bind mounts and named volume mappings. - Test suite stabilization:
- Fixed WordPress test to check for IP pattern instead of
networks.firstwhich may be empty (race condition in container runtime API) - Added polling wait for container startup in
testUpAndDownComplex testUpAndDownComplexuses busybox/nginx instead of MySQL/WordPress (MySQL 8.0 initialization takes 30-60s and often times out)- Note:
testWordPressComposestill tests WordPress/MySQL functionality; only the compose down complex test was simplified
- Fixed WordPress test to check for IP pattern instead of
${VAR}resolution in env pipeline: Replaced naive${string stripping withresolveVariable()for proper${VAR:-default}and${VAR:?error}support in post-decode environment values.- Test container name limit: Shortened test container prefix (
CCT_instead ofContainerComposeTest_) to avoid the macOS 63-character container name limit. container start -dflag: Removed unsupported-dflag fromcontainer startcalls.- Build tooling: Updated
build-sign-install.shto maintain/usr/local/binsymlink and auto-inject git commit hash during build.
.envloading order:.envfile is now loaded before YAML decode (moved up in pipeline) so environment variables are available for pre-decode substitution.- Post-decode
resolveVariable(): Retained as idempotent safety net; no longer the primary resolution point.
- Shorthand
env:Key Support: Fixed critical bug where the shorthandenv:key (e.g.,env: MY_VAR=value) was not being decoded. - Environment Variable Test Fix: Fixed
HOSTenvironment variable conflict in tests by using unique variable names. - Volume Creation Idempotency: Fixed volume creation to gracefully handle "already exists" errors.
- Command String Parsing: Fixed parsing of string-form commands to properly split into executable and arguments.
- Environment Variable Mapping: Added missing
--envflag mapping inmakeRunArgs. - Port Mapping: Added missing
--publishflag mapping inmakeRunArgs. - macOS Container Name Limit: Implemented proactive validation and warnings for the 64-character container name limit on macOS.
- Test Suite Stabilization: Achieved 100% test pass rate (92/92 tests) on macOS by:
- Transitioning WordPress tests to
wordpress:fpm-alpinefor runtime compatibility. - Implementing unique port assignments (18080-18085) for all dynamic tests to prevent parallel execution collisions.
- Hardening
run-tests.shwith build directory ownership checks and automated container pruning.
- Transitioning WordPress tests to
- Security-Compliant Installation: Updated
build-and-install.shto target~/binwith ad-hoc code signing to bypass macOS Gatekeeper and provenance restrictions.
This release includes critical fixes from adversarial code review, silent failure remediation, and missing field mappings.
-
Adversarial Review Fixes - Comprehensive code review identified and fixed 63 confirmed issues:
- Fixed silent failures where streamCommand results were discarded (volume creation, container start, checkpoint)
- Fixed file handle resource leaks in Helper Functions with proper cleanup
- Added timeout mechanism to streamCommand (default 300s) to prevent indefinite hangs
- Fixed loadEnvFile to properly propagate errors instead of silently swallowing
-
Stopped container restart: When a container exists but is not running (e.g., stopped),
container-compose upnow starts the existing container instead of failing with an error message.- Previously: Container existed with status: stopped. Error was printed and command returned without starting the container.
- Now: Container is automatically started using
container start <name> -d, then waits for it to be running and updates service IPs.
-
Missing Field Mappings - Added support for compose fields that were parsed but never mapped to container run flags:
--userfor service.user--hostnamefor service.hostname--workdirfor service.working_dir--privilegedfor service.privileged--read-onlyfor service.read_only--networkfor service.networks (supports multiple networks)-tfor service.tty-ifor service.stdin_open
-
Checkpoint Command Improvements:
- Added pre-flight checks to verify container exists before checkpointing
- Added validation that container is running (with --force flag to override)
- Added exit code validation to ensure commit succeeded
This release bundles several upstream fixes and improvements merged into this fork. Highlights and user-facing notes:
-
dnsSearch support
- Commit: https://github.com/Mcrich23/Container-Compose/commit/d509f8af30f9d2382c1804f575ea0f22eb4e5734
- User note: Services can now specify dns_search/dnsSearch entries so containers can resolve each other by name using custom DNS search domains. Configure in your service's networks or service definition.
-
Multi-stage Docker build target support
- Commit: https://github.com/Mcrich23/Container-Compose/commit/02ca6462b84121c1553bd7adb862ee22aabc4997
- User note: When using build: with Dockerfiles that include multiple stages, the
targetfield is respected so you can build a specific stage (e.g.,build: { context: ".", target: "release" }).
-
Improved volume handling and named-volume destination preservation
- Commits/PRs: https://github.com/Mcrich23/Container-Compose/commit/b1badf86a4faf5c6ed512643e255760073d38988, Mcrich23#32, Mcrich23#42
- User note: Named volumes now preserve full destination paths (e.g.,
- elasticsearch-data:/usr/share/elasticsearch/data), and relative host paths are normalized to absolute paths for bind mounts.
-
Correct --entrypoint placement
- Commit: https://github.com/Mcrich23/Container-Compose/commit/84201f9416f4a5f1bd383763679f8e2fd7579e94
- User note: Entrypoint overrides in compose files are now passed to the container run command properly (as
--entrypoint <cmd>before the image), preventing unexpected immediate container exit.
-
Startup/wait fixes and improved command debugging
- Commits: https://github.com/Mcrich23/Container-Compose/commit/8a4e5bb0e634155d122ac5d93905a75dcbf5b3da, https://github.com/Mcrich23/Container-Compose/commit/eeddb266a45686c99f53f300c2c5d049b1f3b157, https://github.com/Mcrich23/Container-Compose/commit/4968a8669babe7822ada82cc90328f102edfd02e
- User note: Waiting logic no longer times out incorrectly when a container is already running; the tool prints the exact container run command being executed to aid debugging.
-
CI and release automation (fork-specific)
- Origin commits: https://github.com/explicitcontextualunderstanding/Container-Compose/commit/3f20dbf6a6268a93fa196632caa2c178214892f7 and https://github.com/explicitcontextualunderstanding/Container-Compose/commit/98b7fc4a50467067158d15eb47d9acca78121719
- User note: This fork adds GitHub Actions for release automation used by the maintainers of this fork.
For full details and links to the source commits/PRs, see FORK_CHANGES.md.