fix: apply Docker 24 network workaround and smoke tests to production deploy

- Add SECRET_KEY env to deploy job for compose variable expansion
- Replace simple docker compose up with network stripping workaround
  (Docker 24 compose fails on external networks during container creation)
- Connect containers to networks manually after compose creates them
- Add smoke tests via docker exec against localhost:4000
- Create internal network manually when compose skips it

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Gan, Jimmy
2026-05-17 23:33:00 +08:00
parent deb049c889
commit d5faa14d07
+66 -6
View File
@@ -171,6 +171,8 @@ jobs:
name: Deploy to Production name: Deploy to Production
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [backend-tests, frontend-tests] needs: [backend-tests, frontend-tests]
env:
SECRET_KEY: test-secret-key-for-ci-environment-32chars-minimum
container: container:
volumes: volumes:
- /var/packages/ContainerManager/target/usr/bin/docker:/usr/bin/docker - /var/packages/ContainerManager/target/usr/bin/docker:/usr/bin/docker
@@ -237,24 +239,82 @@ jobs:
- name: Sync runtime compose file - name: Sync runtime compose file
run: cp dashboard/docker-compose.yml /nas-dashboard/docker-compose.yml run: cp dashboard/docker-compose.yml /nas-dashboard/docker-compose.yml
- name: Deploy - name: Deploy and verify
run: | run: |
set -e set -e
export DOCKER_API_VERSION=1.43 export DOCKER_API_VERSION=1.43
docker compose -f /nas-dashboard/docker-compose.yml up -d --pull never
- name: Wait for container to be healthy # Docker 24 compose fails when it can't connect external networks
run: | # during container creation. Try compose first; if the container
# isn't created, strip networks from compose file and retry.
docker compose -f /nas-dashboard/docker-compose.yml up -d --pull never 2>&1 || true
if ! docker container inspect nas-dashboard >/dev/null 2>&1; then
echo "Compose failed to create container, stripping networks from compose file..."
python3 -c "
import os
lines = open('/nas-dashboard/docker-compose.yml').readlines()
out = []
skip_net = False
for l in lines:
stripped = l.strip()
if stripped == 'networks:' and not l[0].isspace():
skip_net = True
continue
if skip_net:
if l[0].isspace():
continue
skip_net = False
if stripped == 'networks:' and l[:4].strip() == '':
skip_net = True
continue
if skip_net:
if l.startswith(' '):
continue
skip_net = False
out.append(l)
open('/tmp/prod-ci.yml','w').writelines(out)
"
docker compose -f /tmp/prod-ci.yml up -d --pull never
fi
# Create the internal network if compose didn't create it
docker network create internal 2>/dev/null || true
# Connect docker-socket-proxy to networks
docker network connect internal docker-socket-proxy 2>/dev/null || true
docker network connect nas-dashboard_internal docker-socket-proxy 2>/dev/null || true
# Connect dashboard to networks
docker network connect internal nas-dashboard 2>/dev/null || true
docker network connect nas-dashboard_internal nas-dashboard 2>/dev/null || true
docker network connect gitea_gitea nas-dashboard 2>/dev/null || true
# Verify network connections
echo "=== Network connections ==="
docker inspect nas-dashboard --format '{{json .NetworkSettings.Networks}}' | python3 -c 'import json,sys;nets=json.load(sys.stdin);[print(f" Connected to {n}") for n in nets];assert "nas-dashboard_internal" in nets, "Missing nas-dashboard_internal";print("All network connections established")'
# Wait for container to be healthy
echo "Waiting for container to be healthy..." echo "Waiting for container to be healthy..."
for i in {1..30}; do for i in {1..30}; do
STATUS=$(docker inspect --format='{{.State.Health.Status}}' nas-dashboard 2>/dev/null || echo "starting") STATUS=$(docker inspect --format='{{.State.Health.Status}}' nas-dashboard 2>/dev/null || echo "starting")
if [ "$STATUS" = "healthy" ]; then if [ "$STATUS" = "healthy" ]; then
echo "✅ Container is healthy" echo "✅ Container is healthy"
exit 0 break
fi fi
echo "Waiting... ($i/30) Status: $STATUS" echo "Waiting... ($i/30) Status: $STATUS"
sleep 2 sleep 2
done done
echo "❌ Container failed to become healthy" STATUS=$(docker inspect --format='{{.State.Health.Status}}' nas-dashboard 2>/dev/null || echo "unknown")
if [ "$STATUS" != "healthy" ]; then
echo "❌ Container failed to become healthy: $STATUS"
docker logs nas-dashboard --tail 50 docker logs nas-dashboard --tail 50
exit 1 exit 1
fi
# Run smoke tests via docker exec
echo "=== Running smoke tests ==="
docker exec nas-dashboard python3 -c "import urllib.request,json; d=json.loads(urllib.request.urlopen('http://localhost:4000/api/health',timeout=5).read()); assert d['status']=='ok', f'unexpected: {d}'" && echo "✅ Health check passed" || { echo "❌ Health check failed"; docker logs nas-dashboard --tail 50; exit 1; }
docker exec nas-dashboard python3 -c "import urllib.request; html=urllib.request.urlopen('http://localhost:4000/',timeout=5).read().decode(); assert 'NAS Dashboard' in html, f'missing NAS Dashboard'" && echo "✅ Frontend loads" || { echo "❌ Frontend failed to load"; exit 1; }
echo ""
echo "=== All deployment checks passed! ==="