Skip to content

Commit d93523b

Browse files
m4dm4rtig4nClément VALENTINclaude
authored
fix(conductor): support multi-instance deployment with external services (#79)
Create a dedicated docker-compose.conductor.yml for Conductor that only runs frontend and backend services, using external Redis and PostgreSQL. Remove static container names to avoid conflicts between instances, and move port definitions to docker-compose.override.yml for dynamic port allocation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Clément VALENTIN <[email protected]> Co-authored-by: Claude <[email protected]>
1 parent e15ba72 commit d93523b

File tree

4 files changed

+88
-33
lines changed

4 files changed

+88
-33
lines changed

docker-compose.conductor.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Docker Compose pour Conductor (multi-instances)
2+
# Utilise Redis et PostgreSQL externes configurés via .env.local
3+
# Les ports sont définis dynamiquement dans docker-compose.override.yml
4+
5+
services:
6+
7+
# Backend FastAPI
8+
backend:
9+
build:
10+
context: ./apps/api
11+
dockerfile: Dockerfile
12+
restart: unless-stopped
13+
env_file:
14+
- ./.env.api
15+
environment:
16+
- PYTHONUNBUFFERED=1
17+
- WATCHFILES_FORCE_POLLING=true
18+
- WATCHFILES_POLL_INTERVAL=1000
19+
- TZ=Europe/Paris
20+
extra_hosts:
21+
- "host.docker.internal:host-gateway"
22+
volumes:
23+
- ./apps/api/data:/app/data
24+
- ./apps/api/src:/app/src
25+
- ./apps/api/static:/app/static
26+
- backend_logs:/logs
27+
command: ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload", "--reload-dir", "/app/src"]
28+
healthcheck:
29+
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/ping')"]
30+
interval: 30s
31+
timeout: 10s
32+
retries: 3
33+
start_period: 40s
34+
35+
# Frontend React/Vite
36+
frontend:
37+
build:
38+
context: ./apps/web
39+
dockerfile: Dockerfile.dev
40+
restart: unless-stopped
41+
volumes:
42+
- ./apps/web/src:/app/src
43+
- ./apps/web/public:/app/public
44+
- ./apps/web/index.html:/app/index.html
45+
- ./apps/web/vite.config.ts:/app/vite.config.ts
46+
- ./apps/web/tsconfig.json:/app/tsconfig.json
47+
- ./apps/web/tsconfig.node.json:/app/tsconfig.node.json
48+
- ./apps/web/tailwind.config.js:/app/tailwind.config.js
49+
- ./apps/web/postcss.config.js:/app/postcss.config.js
50+
- /app/node_modules
51+
depends_on:
52+
- backend
53+
54+
volumes:
55+
backend_logs:
56+
driver: local

docker-compose.yml

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ services:
33
# Redis
44
redis:
55
image: redis:7-alpine
6-
container_name: myelectricaldata-redis
76
restart: unless-stopped
87
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
98
volumes:
@@ -16,13 +15,10 @@ services:
1615
timeout: 5s
1716
retries: 3
1817

19-
# PostgreSQL (optionnel, activable via DATABASE_TYPE=postgresql)
18+
# PostgreSQL
2019
postgres:
2120
image: postgres:16-alpine
22-
container_name: myelectricaldata-postgres
2321
restart: unless-stopped
24-
env_file :
25-
- ./.env.api
2622
environment:
2723
POSTGRES_DB: myelectricaldata
2824
POSTGRES_USER: myelectricaldata
@@ -40,7 +36,6 @@ services:
4036
# pgAdmin - Interface web PostgreSQL
4137
pgadmin:
4238
image: dpage/pgadmin4:latest
43-
container_name: myelectricaldata-pgadmin
4439
restart: unless-stopped
4540
environment:
4641
PGADMIN_DEFAULT_EMAIL: [email protected]
@@ -61,7 +56,6 @@ services:
6156
build:
6257
context: ./apps/api
6358
dockerfile: Dockerfile
64-
container_name: myelectricaldata-backend
6559
restart: unless-stopped
6660
env_file:
6761
- ./.env.api
@@ -70,6 +64,8 @@ services:
7064
- WATCHFILES_FORCE_POLLING=true
7165
- WATCHFILES_POLL_INTERVAL=1000
7266
- TZ=Europe/Paris
67+
extra_hosts:
68+
- "host.docker.internal:host-gateway"
7369
volumes:
7470
- ./apps/api/data:/app/data
7571
- ./apps/api/src:/app/src
@@ -80,8 +76,7 @@ services:
8076
- myelectricaldata
8177
depends_on:
8278
- redis
83-
ports:
84-
- "8081:8000"
79+
# ports définis dans docker-compose.override.yml pour support multi-instances
8580
healthcheck:
8681
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/ping')"]
8782
interval: 30s
@@ -94,7 +89,6 @@ services:
9489
build:
9590
context: ./apps/web
9691
dockerfile: Dockerfile.dev
97-
container_name: myelectricaldata-frontend
9892
restart: unless-stopped
9993
volumes:
10094
- ./apps/web/src:/app/src
@@ -106,8 +100,7 @@ services:
106100
- ./apps/web/tailwind.config.js:/app/tailwind.config.js
107101
- ./apps/web/postcss.config.js:/app/postcss.config.js
108102
- /app/node_modules
109-
ports:
110-
- "8000:5173"
103+
# ports définis dans docker-compose.override.yml pour support multi-instances
111104
networks:
112105
- myelectricaldata
113106
depends_on:
@@ -118,7 +111,6 @@ services:
118111
build:
119112
context: ./apps/docs
120113
dockerfile: Dockerfile
121-
container_name: myelectricaldata-docs
122114
restart: unless-stopped
123115
volumes:
124116
- ./docs:/app/docs:ro
@@ -130,10 +122,6 @@ services:
130122
- docs
131123

132124
volumes:
133-
caddy_data:
134-
driver: local
135-
caddy_config:
136-
driver: local
137125
redis_data:
138126
driver: local
139127
postgres_data:

scripts/conductor-start.sh

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,19 @@ export BACKEND_PORT
6363
log_info "Port Frontend: $FRONTEND_PORT"
6464
log_info "Port Backend: $BACKEND_PORT"
6565

66-
# Vérifier la configuration Redis/PostgreSQL
66+
# Vérifier la configuration Redis/PostgreSQL (services externes)
67+
# Remplacer localhost par host.docker.internal pour l'accès depuis les conteneurs
6768
REDIS_URL="${REDIS_URL:-redis://localhost:6379/0}"
6869
DATABASE_URL="${DATABASE_URL:-sqlite+aiosqlite:///./data/myelectricaldata.db}"
6970

70-
log_info "Redis: $REDIS_URL"
71-
log_info "Database: $(echo $DATABASE_URL | sed 's/:.*@/:***@/')"
71+
# Convertir les URLs pour Docker (localhost -> host.docker.internal)
72+
REDIS_URL_DOCKER=$(echo "$REDIS_URL" | sed 's/localhost/host.docker.internal/g')
73+
DATABASE_URL_DOCKER=$(echo "$DATABASE_URL" | sed 's/localhost/host.docker.internal/g')
74+
75+
log_info "Redis (host): $REDIS_URL"
76+
log_info "Redis (docker): $REDIS_URL_DOCKER"
77+
log_info "Database (host): $(echo $DATABASE_URL | sed 's/:.*@/:***@/')"
78+
log_info "Database (docker): $(echo $DATABASE_URL_DOCKER | sed 's/:.*@/:***@/')"
7279

7380
# Créer le fichier .env.api à partir du template si nécessaire
7481
if [ ! -f ".env.api" ]; then
@@ -78,20 +85,20 @@ if [ ! -f ".env.api" ]; then
7885
fi
7986
fi
8087

81-
# Mettre à jour les URLs dans .env.api
88+
# Mettre à jour les URLs dans .env.api (utiliser les URLs Docker)
8289
if [ -f ".env.api" ]; then
83-
# Mettre à jour REDIS_URL
90+
# Mettre à jour REDIS_URL (version Docker)
8491
if grep -q "^REDIS_URL=" .env.api; then
85-
sed -i.bak "s|^REDIS_URL=.*|REDIS_URL=$REDIS_URL|" .env.api
92+
sed -i.bak "s|^REDIS_URL=.*|REDIS_URL=$REDIS_URL_DOCKER|" .env.api
8693
else
87-
echo "REDIS_URL=$REDIS_URL" >> .env.api
94+
echo "REDIS_URL=$REDIS_URL_DOCKER" >> .env.api
8895
fi
8996

90-
# Mettre à jour DATABASE_URL
97+
# Mettre à jour DATABASE_URL (version Docker)
9198
if grep -q "^DATABASE_URL=" .env.api; then
92-
sed -i.bak "s|^DATABASE_URL=.*|DATABASE_URL=$DATABASE_URL|" .env.api
99+
sed -i.bak "s|^DATABASE_URL=.*|DATABASE_URL=$DATABASE_URL_DOCKER|" .env.api
93100
else
94-
echo "DATABASE_URL=$DATABASE_URL" >> .env.api
101+
echo "DATABASE_URL=$DATABASE_URL_DOCKER" >> .env.api
95102
fi
96103

97104
# Mettre à jour FRONTEND_URL et BACKEND_URL pour le dev
@@ -108,17 +115,20 @@ VITE_APP_NAME=MyElectricalData
108115
EOF
109116

110117
# Générer le docker-compose.override.yml avec les ports dynamiques
118+
# et sans dépendances vers redis/postgres (services externes)
111119
cat > docker-compose.override.yml <<EOF
112120
# Fichier généré automatiquement par conductor-start.sh
113121
# Ne pas éditer manuellement - les modifications seront écrasées
122+
# Mode Conductor: utilise Redis/PostgreSQL externes
114123
115124
services:
116125
backend:
126+
depends_on: []
117127
ports:
118128
- "${BACKEND_PORT}:8000"
119129
environment:
120-
- REDIS_URL=${REDIS_URL}
121-
- DATABASE_URL=${DATABASE_URL}
130+
- REDIS_URL=${REDIS_URL_DOCKER}
131+
- DATABASE_URL=${DATABASE_URL_DOCKER}
122132
- FRONTEND_URL=http://localhost:${FRONTEND_PORT}
123133
- BACKEND_URL=http://localhost:${BACKEND_PORT}
124134
@@ -138,8 +148,9 @@ EOF
138148

139149
log_info "Démarrage des services..."
140150

141-
# Démarrer uniquement frontend et backend (sans redis, postgres, pgadmin, docs)
142-
docker compose up -d --build frontend backend
151+
# Utiliser docker-compose.conductor.yml (sans redis, postgres, pgadmin, docs)
152+
# + docker-compose.override.yml pour les ports dynamiques
153+
docker compose -f docker-compose.conductor.yml -f docker-compose.override.yml up -d --build
143154

144155
# Attendre que les services soient prêts
145156
log_info "Attente du démarrage des services..."

scripts/conductor-stop.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ fi
3232

3333
log_info "Arrêt des services pour: $COMPOSE_PROJECT_NAME"
3434

35-
# Arrêter les conteneurs
36-
docker compose down
35+
# Arrêter les conteneurs (utiliser docker-compose.conductor.yml + override)
36+
docker compose -f docker-compose.conductor.yml -f docker-compose.override.yml down 2>/dev/null || docker compose -f docker-compose.conductor.yml down
3737

3838
# Nettoyer les fichiers temporaires
3939
rm -f .conductor-ports

0 commit comments

Comments
 (0)