fix: compose network bug - try up/direct, fallback to stripped config

Docker Compose v2.20.1 fails to create containers when external
networks can't be connected. First try compose directly; if container
isn't created, strip networks from resolved config via JSON processing
and retry. Connect networks manually in both paths.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Gan, Jimmy
2026-05-17 20:05:05 +08:00
parent 91769fe2c6
commit c7073377ca
+39 -9
View File
@@ -235,17 +235,47 @@ jobs:
docker network create nas-dashboard_internal
fi
# Create compose override with network_mode: none (Docker 24 compose
# fails to create containers when it can't connect external networks).
# We connect networks manually after container creation.
echo 'services:' > /tmp/docker-compose.ci-override.yml
echo ' dashboard-dev:' >> /tmp/docker-compose.ci-override.yml
echo ' network_mode: "none"' >> /tmp/docker-compose.ci-override.yml
# Docker 24 compose fails when it can't connect external networks
# during container creation. Try compose first; if the container
# isn't created, strip networks from the resolved config via
# docker compose config output (processed with Python json).
docker compose -f docker-compose.dev.yml -p nas-dashboard-dev up -d --pull never 2>&1 || true
# Deploy without networks in compose
docker compose -f docker-compose.dev.yml -f /tmp/docker-compose.ci-override.yml -p nas-dashboard-dev up -d --pull never
if ! docker inspect nas-dashboard-dev >/dev/null 2>&1; then
echo "Compose failed to create container, stripping networks from config..."
docker compose -f docker-compose.dev.yml config --format json 2>/dev/null | python3 -c "
import json, sys
cfg = json.load(sys.stdin)
cfg['services']['dashboard-dev']['networks'] = {}
cfg['networks'] = {}
with open('/tmp/no-network.yml', 'w') as f:
for k, v in cfg.items():
if k == 'services':
f.write('services:\n')
for svc, svc_cfg in v.items():
f.write(f' {svc}:\n')
for sk, sv in svc_cfg.items():
if sk == 'networks':
continue
elif isinstance(sv, dict):
f.write(f' {sk}:\n')
for dk, dv in sv.items():
f.write(f' {dk}: {json.dumps(dv) if not isinstance(dv, str) else dv}\n')
elif isinstance(sv, list):
f.write(f' {sk}:\n')
for e in sv:
f.write(f' {json.dumps(e) if not isinstance(e, str) else e}\n')
else:
f.write(f' {sk}: {json.dumps(sv) if not isinstance(sv, str) else sv}\n')
elif k == 'networks':
continue
else:
f.write(f'{k}: {json.dumps(v) if not isinstance(v, str) else v}\n')
"
docker compose -f /tmp/no-network.yml -p nas-dashboard-dev up -d --pull never
fi
# Manually connect to networks after container is created
# Connect networks after container is created (idempotent)
docker network connect nas-dashboard_internal nas-dashboard-dev 2>/dev/null || true
docker network connect gitea_gitea nas-dashboard-dev 2>/dev/null || true