Skip to content

Commit 70d7e82

Browse files
ImTotemclaude
andcommitted
refactor(infra): switch from Docker nginx to host nginx
- Remove nginx/certbot Docker services (port conflict with host nginx) - Add infra/nginx/bcsd-api.conf for host nginx sites-enabled - API containers expose host ports (8001/8002 for blue/green) - deploy.sh copies conf to /etc/nginx/sites-enabled/ and reloads host nginx - Health check uses curl on host port instead of docker exec - init-ssl.sh uses host certbot instead of Docker certbot Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 36279b0 commit 70d7e82

File tree

5 files changed

+41
-64
lines changed

5 files changed

+41
-64
lines changed

.env.example

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,12 @@ MONGO_PORT=27017
3939
MONGO_VOLUME_PATH=/home/ubuntu/bcsd-data/mongo
4040

4141
# === Deployment ===
42-
# Blue-green 배포 시 graceful shutdown 대기 시간 (초)
42+
# Blue-green API 호스트 포트 (호스트 nginx에서 프록시)
43+
API_BLUE_PORT=8001
44+
API_GREEN_PORT=8002
45+
# n8n 호스트 포트
46+
N8N_PORT=5678
47+
# Graceful shutdown 대기 시간 (초)
4348
GRACEFUL_TIMEOUT=10
4449

4550
# === Infrastructure ===

infra/docker/docker-compose.yml

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,27 @@ services:
88
- ../../.env
99
volumes:
1010
- ../../${GOOGLE_SERVICE_ACCOUNT_FILE}:/app/${GOOGLE_SERVICE_ACCOUNT_FILE}:ro
11-
expose:
12-
- "8000"
11+
ports:
12+
- "${API_BLUE_PORT}:8000"
1313
command: ["uvicorn", "bcsd_api.main:app", "--host", "0.0.0.0", "--port", "8000", "--timeout-graceful-shutdown", "${GRACEFUL_TIMEOUT}"]
1414
stop_grace_period: ${GRACEFUL_TIMEOUT}s
1515
networks:
1616
- bcsd
1717

1818
api-green:
1919
<<: *api
20+
ports:
21+
- "${API_GREEN_PORT}:8000"
2022

2123
n8n:
2224
image: n8nio/n8n:latest
2325
restart: unless-stopped
24-
expose:
25-
- "5678"
26+
ports:
27+
- "${N8N_PORT}:5678"
2628
environment:
27-
N8N_HOST: n8n.bcsdlab.com
29+
N8N_HOST: "${N8N_DOMAIN}"
2830
N8N_PROTOCOL: https
29-
WEBHOOK_URL: https://n8n.bcsdlab.com/
31+
WEBHOOK_URL: "https://${N8N_DOMAIN}/"
3032
N8N_BASIC_AUTH_ACTIVE: "true"
3133
N8N_BASIC_AUTH_USER: "${N8N_AUTH_USER}"
3234
N8N_BASIC_AUTH_PASSWORD: "${N8N_AUTH_PASSWORD}"
@@ -36,39 +38,8 @@ services:
3638
networks:
3739
- bcsd
3840

39-
nginx:
40-
image: nginx:alpine
41-
restart: unless-stopped
42-
ports:
43-
- "80:80"
44-
- "443:443"
45-
volumes:
46-
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
47-
- certbot-webroot:/var/www/certbot:ro
48-
- certbot-certs:/etc/letsencrypt:ro
49-
depends_on:
50-
- api-blue
51-
- api-green
52-
- n8n
53-
networks:
54-
- bcsd
55-
56-
certbot:
57-
image: certbot/certbot:latest
58-
volumes:
59-
- certbot-webroot:/var/www/certbot
60-
- certbot-certs:/etc/letsencrypt
61-
- ../scripts/certbot_slack.py:/usr/local/bin/certbot_slack.py:ro
62-
environment:
63-
SLACK_BOT_TOKEN: "${SLACK_BOT_TOKEN}"
64-
SLACK_CERTBOT_CHANNEL: "${SLACK_CERTBOT_CHANNEL}"
65-
SLACK_SERVER_NAME: "${SLACK_SERVER_NAME}"
66-
entrypoint: /bin/sh -c "trap exit TERM; while :; do python /usr/local/bin/certbot_slack.py; sleep 12h & wait $${!}; done"
67-
6841
volumes:
6942
n8n-data:
70-
certbot-webroot:
71-
certbot-certs:
7243

7344
networks:
7445
bcsd:
Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@ map $http_upgrade $connection_upgrade {
44
}
55

66
upstream api_blue {
7-
server api-blue:8000;
7+
server 127.0.0.1:8001;
88
}
99

1010
upstream api_green {
11-
server api-green:8000;
11+
server 127.0.0.1:8002;
12+
}
13+
14+
upstream n8n {
15+
server 127.0.0.1:5678;
1216
}
1317

1418
upstream frontend {
15-
server frontend:8080;
19+
server 127.0.0.1:8080;
1620
}
1721

1822
# --- HTTP: ACME + redirect ---
@@ -148,7 +152,7 @@ server {
148152
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
149153

150154
location / {
151-
proxy_pass http://n8n:5678;
155+
proxy_pass http://n8n;
152156
proxy_http_version 1.1;
153157
proxy_set_header Host $host;
154158
proxy_set_header X-Real-IP $remote_addr;

infra/scripts/deploy.sh

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ set -euo pipefail
33

44
COMPOSE="sudo docker compose --env-file .env -f infra/docker/docker-compose.yml"
55
COMPOSE_DB="sudo docker compose --env-file .env -f infra/docker/docker-compose.db.yml"
6-
NGINX_CONF="infra/docker/nginx.conf"
6+
NGINX_CONF="infra/nginx/bcsd-api.conf"
7+
NGINX_DEST="/etc/nginx/sites-enabled/bcsd-api.conf"
78
HEALTH_PATH="/openapi.json"
89
MAX_RETRIES=10
910

@@ -16,12 +17,11 @@ next_slot() {
1617
}
1718

1819
health_check() {
19-
local container="api-${1}"
20+
local port
21+
port=$(grep -m1 "^API_$(echo "$1" | tr '[:lower:]' '[:upper:]')_PORT=" .env | cut -d= -f2-)
2022
local retries=0
2123
while [ $retries -lt $MAX_RETRIES ]; do
22-
if $COMPOSE exec "$container" python -c \
23-
"import urllib.request; urllib.request.urlopen('http://localhost:8000${HEALTH_PATH}')" \
24-
> /dev/null 2>&1; then
24+
if curl -sf "http://localhost:${port}${HEALTH_PATH}" > /dev/null 2>&1; then
2525
return 0
2626
fi
2727
retries=$((retries + 1))
@@ -63,8 +63,8 @@ echo "Current: $CURRENT → Deploying: $NEXT"
6363
echo "1. Building $NEXT..."
6464
$COMPOSE build "api-${NEXT}"
6565

66-
echo "2. Starting $NEXT + nginx..."
67-
$COMPOSE up -d "api-${NEXT}" nginx
66+
echo "2. Starting $NEXT..."
67+
$COMPOSE up -d "api-${NEXT}"
6868

6969
echo "3. Health check on api-${NEXT}..."
7070
if ! health_check "$NEXT"; then
@@ -77,8 +77,9 @@ if ! health_check "$NEXT"; then
7777
fi
7878

7979
echo "4. Switching nginx → $NEXT"
80-
sed -i "s/proxy_pass http:\/\/api_${CURRENT}/proxy_pass http:\/\/api_${NEXT}/" "$NGINX_CONF"
81-
$COMPOSE exec nginx nginx -s reload
80+
sed -i "s/proxy_pass http:\/\/api_${CURRENT}/proxy_pass http:\/\/api_${NEXT}/g" "$NGINX_CONF"
81+
sudo cp "$NGINX_CONF" "$NGINX_DEST"
82+
sudo nginx -t && sudo nginx -s reload
8283

8384
echo "5. Stopping old ($CURRENT)..."
8485
$COMPOSE stop "api-${CURRENT}"

infra/scripts/init-ssl.sh

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,23 @@ if [ -f .env ]; then
55
set -a; source .env; set +a
66
fi
77

8-
COMPOSE="sudo docker compose --env-file .env -f infra/docker/docker-compose.yml"
98
DOMAIN="${DOMAIN:?Set DOMAIN in .env}"
109
N8N_DOMAIN="${N8N_DOMAIN}"
1110
FRONTEND_DOMAIN="${FRONTEND_DOMAIN}"
1211

1312
echo "=== Initial SSL Certificate Setup ==="
1413

15-
echo "1. Starting nginx for ACME challenge..."
16-
$COMPOSE up -d nginx
17-
18-
echo "2. Requesting certificate for $DOMAIN..."
19-
$COMPOSE run --rm certbot certonly \
14+
echo "1. Requesting certificate for $DOMAIN..."
15+
sudo certbot certonly \
2016
--webroot \
2117
-w /var/www/certbot \
2218
-d "$DOMAIN" \
2319
--register-unsafely-without-email \
2420
--agree-tos
2521

2622
if [ -n "$N8N_DOMAIN" ]; then
27-
echo "3. Requesting certificate for $N8N_DOMAIN..."
28-
$COMPOSE run --rm certbot certonly \
23+
echo "2. Requesting certificate for $N8N_DOMAIN..."
24+
sudo certbot certonly \
2925
--webroot \
3026
-w /var/www/certbot \
3127
-d "$N8N_DOMAIN" \
@@ -34,8 +30,8 @@ if [ -n "$N8N_DOMAIN" ]; then
3430
fi
3531

3632
if [ -n "$FRONTEND_DOMAIN" ]; then
37-
echo "4. Requesting certificate for $FRONTEND_DOMAIN (+ internal.bcsdlab.com)..."
38-
$COMPOSE run --rm certbot certonly \
33+
echo "3. Requesting certificate for $FRONTEND_DOMAIN (+ internal.bcsdlab.com)..."
34+
sudo certbot certonly \
3935
--webroot \
4036
-w /var/www/certbot \
4137
-d "$FRONTEND_DOMAIN" \
@@ -44,8 +40,8 @@ if [ -n "$FRONTEND_DOMAIN" ]; then
4440
--agree-tos
4541
fi
4642

47-
echo "5. Reloading nginx with SSL..."
48-
$COMPOSE exec nginx nginx -s reload
43+
echo "4. Reloading nginx..."
44+
sudo nginx -t && sudo nginx -s reload
4945

5046
echo "=== SSL setup complete ==="
51-
echo "Auto-renewal is handled by the certbot container."
47+
echo "Auto-renewal: sudo certbot renew (via system cron/timer)"

0 commit comments

Comments
 (0)