feat: 적용 무중단 배포 시스템 (Blue-Green Deployment)
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 51s

This commit is contained in:
jade
2026-07-24 08:51:01 +09:00
parent 60a7226199
commit 8b11c1aae8
8 changed files with 489 additions and 80 deletions

View File

@@ -22,7 +22,7 @@ jobs:
- name: Deploy Task on Host
run: |
echo "Starting Standard CI/CD Deploy pipeline..."
echo "Starting Blue-Green CI/CD Deploy pipeline..."
# 1. gradle 공식 이미지로 바로 컴파일 빌드!
docker run --rm \
@@ -36,22 +36,59 @@ jobs:
# 2. 빌드 결과 plain jar 아카이브 정리
find /app -name "*-plain.jar" -delete
# 3. 좀비 컨테이너 청소 (현재 우리가 쓸 포트를 점유 중인 옛날 컨테이너들만 정확히 색출해서 사살)
echo "Finding and killing zombie containers holding our ports..."
for port in 6379 8080 8089 8281 8282 8283 8284 8285 8288; do
cid=$(docker ps -q --filter "publish=$port")
if [ ! -z "$cid" ]; then
echo "Force killing container $cid using port $port"
docker rm -f $cid
fi
done
# 4. 마운트된 /app 디렉토리로 이동하여 호스트의 도커 컴포즈 제어!
cd /app
docker system prune -f
ACTIVE_PROFILE=dev docker compose up -d --build gateway redis mci-mock dozzle tool-sms tool-email tool-other tool-payment
# 4. 배포 후 대롱대롱 매달려 있는 가비지 이미지 자동 소거 청소!
# 3. 블루/그린 타겟 식별
IS_BLUE_RUNNING=$(docker ps --filter "name=ax_hub_mcp_tool-gateway-blue-1" --filter "status=running" -q)
if [ ! -z "$IS_BLUE_RUNNING" ]; then
echo "Current active color is BLUE. Deploying to GREEN..."
TARGET="green"
OLD_TARGET="blue"
else
echo "Current active color is GREEN (or none). Deploying to BLUE..."
TARGET="blue"
OLD_TARGET="green"
fi
# 공통 인프라 (DB, Redis 등) 띄우기
ACTIVE_PROFILE=dev docker compose up -d redis mci-mock dozzle nginx
# 4. 신규 버전(TARGET) 컨테이너 기동
echo "Building and starting $TARGET containers..."
ACTIVE_PROFILE=dev docker compose up -d --build \
gateway-$TARGET \
tool-sms-$TARGET \
tool-email-$TARGET \
tool-other-$TARGET \
tool-payment-$TARGET
# 5. 헬스 체크 대기 (Spring Boot 기동 시간 확보)
echo "Waiting 30 seconds for Spring Boot to start..."
sleep 30
# 신규 컨테이너가 죽지 않고 살아있는지 확인
IS_TARGET_ALIVE=$(docker ps --filter "name=ax_hub_mcp_tool-gateway-${TARGET}-1" --filter "status=running" -q)
if [ -z "$IS_TARGET_ALIVE" ]; then
echo "Health Check Failed! $TARGET container crashed. Rollback."
echo "Stopping failed $TARGET containers..."
docker compose stop gateway-$TARGET tool-sms-$TARGET tool-email-$TARGET tool-other-$TARGET tool-payment-$TARGET
exit 1 # 파이프라인 실패 처리 (구버전은 그대로 유지됨)
fi
# 6. 트래픽 전환 (Nginx 설정 스위칭)
echo "Health Check Passed! Switching traffic to $TARGET..."
mkdir -p ./nginx/conf.d
cp ./nginx/${TARGET}.conf ./nginx/conf.d/default.conf
docker compose exec -T nginx nginx -s reload
# 7. 구버전 종료
echo "Traffic switched. Stopping old $OLD_TARGET containers..."
docker compose stop gateway-$OLD_TARGET tool-sms-$OLD_TARGET tool-email-$OLD_TARGET tool-other-$OLD_TARGET tool-payment-$OLD_TARGET
# 가비지 청소
docker system prune -f
docker image prune -f
echo "CI/CD Deploy Success!"
echo "Blue-Green CI/CD Deploy Success! Currently running: $TARGET"

View File

@@ -8,6 +8,7 @@ import io.shinhanlife.glow.communication.dto.HeaderDefaults;
import io.shinhanlife.glow.communication.dto.Transfer;
import io.shinhanlife.glow.communication.module.mci.component.GlowMciComponent;
import io.shinhanlife.glow.communication.util.CommonHeaderFactory;
import io.shinhanlife.dap.common.integration.mci.enums.IndvCtinRoleTyp;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@@ -56,7 +57,7 @@ public class AxhubMciComponent {
commonHeaderMap.put(HeaderDefaults.SCRN_ID, sessionDto.getPrgrId());
}
commonHeaderMap.put(HeaderDefaults.INDV_CTIN_ROLE_CD, io.shinhanlife.dap.common.integration.mci.enums.IndvCtinRoleTyp.CD_Z99.getCode());
commonHeaderMap.put(HeaderDefaults.INDV_CTIN_ROLE_CD, IndvCtinRoleTyp.CD_Z99.getCode());
commonHeaderMap.put(HeaderDefaults.TGRM_CREA_CHNN_TYPE_CD, TGRM_CREA_CHNN_TYPE_CD_1);
if (communicationProperties != null && communicationProperties.getCommon() != null) {

View File

@@ -0,0 +1,69 @@
package io.shinhanlife.dap.dapmt.infra.itrf.mci.cfp.a.io;
import io.shinhanlife.dap.common.integration.mci.component.AxhubMciComponent;
import io.shinhanlife.dap.dapmt.dto.Onnba3011Req;
import io.shinhanlife.glow.communication.dto.Transfer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @package io.shinhanlife.dap.dapmt.infra.itrf.mci.cfp.a.io
* @className MciCfpaClient
* @description 보장분석결과조회 MCI 호출 클라이언트
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class MciCfpaClient {
private final AxhubMciComponent mci;
// 인터페이스 코드 상수
private static final String INTERFACE_CODE = "CLCNNB00001"; // CLCCFP00001 (Onnba용 코드 유지)
// 정상 응답 코드 상수
private static final String SUCCESS_CODE_COM = "COM00139";
private static final String SUCCESS_CODE_CFP = "CFP00000";
private static final String NO_DATA_CODE = "COM00150";
// 예외 코드 상수
private static final String ERROR_CODE_PROCESS = "CLC00007";
private static final String ERROR_CODE_MESSAGE = "CLC00043";
/**
* 보장분석결과조회
*
* @param inDto 입력 DTO
* @return 출력 객체
*/
public Object callCfpa0001(Onnba3011Req inDto) throws Exception {
// 인터페이스 호출
Transfer<Object> resTransfer = mci.callTo(INTERFACE_CODE, inDto, Object.class);
// 응답 검증
validateResponse(resTransfer);
// 메시지 검증
validateMessage(String.valueOf(resTransfer.getMessage()));
return resTransfer.getBody();
}
private void validateResponse(Transfer<Object> resTransfer) {
log.info("응답 검증 로직 수행");
}
private void validateMessage(String message) {
log.info("메시지 검증 로직 수행: {}", message);
}
}

View File

@@ -1,6 +1,6 @@
package io.shinhanlife.dap.dapmt.service.impl;
import io.shinhanlife.dap.common.integration.mci.component.AxhubMciComponent;
import io.shinhanlife.dap.dapmt.infra.itrf.mci.cfp.a.io.MciCfpaClient;
import io.shinhanlife.dap.dapmt.annotation.McpFunction;
import io.shinhanlife.dap.dapmt.annotation.McpTool;
import io.shinhanlife.dap.dapmt.service.OnnbaMciToolService;
@@ -33,8 +33,8 @@ public class OnnbaMciToolServiceImpl implements OnnbaMciToolService {
private static final String INTERFACE_CODE_3011 = "CLCNNB00001";
// Glow 기반의 AxhubMciComponent 주입
private final AxhubMciComponent mci;
// 공통 MCI Client 주입
private final MciCfpaClient mciCfpClient;
/**
* AI Agent가 호출하게 될 메서드입니다.
@@ -53,18 +53,13 @@ public class OnnbaMciToolServiceImpl implements OnnbaMciToolService {
log.info("[MCI Tool] 보종By가입설계한도계산조회 요청 수신.");
try {
// GlowMciComponent 표준 방식 (Transfer 객체 이용)
Transfer<Object> resTransfer = mci.callTo(
INTERFACE_CODE_3011,
null, // rcvSvcId
req,
Object.class
);
// MciCfpaClient를 통한 호출
Object response = mciCfpClient.callCfpa0001(req);
log.info("[MCI Tool] Glow 기반 MCI 연동 성공.");
// 결과 반환 (실제로는 resTransfer.getBody() 리턴)
return resTransfer.getBody() != null ? resTransfer.getBody() : "{\"status\":\"SUCCESS\", \"message\":\"GlowMciComponent 통신 완료\"}";
// 결과 반환
return response != null ? response : "{\"status\":\"SUCCESS\", \"message\":\"GlowMciComponent 통신 완료\"}";
} catch (Exception e) {
log.error("[MCI Tool] MCI 연동 중 오류 발생: {}", e.getMessage(), e);

View File

@@ -11,12 +11,59 @@ services:
timeout: 3s
retries: 5
gateway:
mci-mock:
image: wiremock/wiremock:latest
ports:
- "8089:8080"
volumes:
- ./mci-mock:/home/wiremock
dozzle:
image: amir20/dozzle:latest
ports:
- "8288:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /home/ubuntu/app/ax_hub_mcp_tool:/app
restart: always
gitea-runner:
image: gitea/act_runner:latest
environment:
- GITEA_INSTANCE_URL=https://git.devjun.net
- GITEA_RUNNER_REGISTRATION_TOKEN=2N7ciuFIp6Jm29ewtzfl9ruQtpwGgB4ngFcXC2lF
- GITEA_RUNNER_NAME=ociwp-runner
- GLOW_COMMUNICATION_EXTMCI_PORT=8080
- GITEA_RUNNER_LABELS=ubuntu-latest,ubuntu-22.04,linux-arm64
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /home/ubuntu/app/ax_hub_mcp_tool:/app
- ./act_runner_data:/data
- ./bin/docker:/usr/bin/docker
- /usr/libexec/docker/cli-plugins/docker-compose:/usr/libexec/docker/cli-plugins/docker-compose
restart: always
nginx:
image: nginx:latest
ports:
- "8281:8281"
- "8282:8282"
- "8283:8283"
- "8284:8284"
- "8285:8285"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
depends_on:
redis:
condition: service_healthy
# ==========================================
# BLUE SERVICES
# ==========================================
gateway-blue:
build:
context: .
dockerfile: dap-gateway/Dockerfile
ports:
- "8281:8081"
volumes:
- ./:/src
depends_on:
@@ -32,19 +79,10 @@ services:
- JAVA_TOOL_OPTIONS=-Xms64m -Xmx384m
- SPRING_PROFILES_ACTIVE=${ACTIVE_PROFILE:-local}
mci-mock:
image: wiremock/wiremock:latest
ports:
- "8089:8080"
volumes:
- ./mci-mock:/home/wiremock
tool-sms:
tool-sms-blue:
build:
context: .
dockerfile: dap-tool-sms/Dockerfile
ports:
- "8282:8082"
depends_on:
- redis
environment:
@@ -52,9 +90,9 @@ services:
- SPRING_REDIS_HOST=redis
- SPRING_REDIS_PORT=6379
- SPRING_DATA_REDIS_PORT=6379
- AXHUB_GATEWAY_URL=http://gateway:8081
- AXHUB_GATEWAY_URL=http://gateway-blue:8081
- AXHUB_SOURCE_DIR=/src
- AXHUB_TOOL_URL=http://tool-sms:8082
- AXHUB_TOOL_URL=http://tool-sms-blue:8082
- GLOW_COMMUNICATION_MCI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_MCI_PORT=8080
- GLOW_COMMUNICATION_EXTMCI_HOMT=http://mci-mock
@@ -63,12 +101,10 @@ services:
- GLOW_COMMUNICATION_EAI_PORT=8080
- SPRING_PROFILES_ACTIVE=${ACTIVE_PROFILE:-local}
tool-email:
tool-email-blue:
build:
context: .
dockerfile: dap-tool-email/Dockerfile
ports:
- "8283:8083"
depends_on:
- redis
environment:
@@ -76,8 +112,8 @@ services:
- SPRING_REDIS_HOST=redis
- SPRING_REDIS_PORT=6379
- SPRING_DATA_REDIS_PORT=6379
- AXHUB_GATEWAY_URL=http://gateway:8081
- AXHUB_TOOL_URL=http://tool-email:8083
- AXHUB_GATEWAY_URL=http://gateway-blue:8081
- AXHUB_TOOL_URL=http://tool-email-blue:8083
- GLOW_COMMUNICATION_MCI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_MCI_PORT=8080
- GLOW_COMMUNICATION_EXTMCI_HOMT=http://mci-mock
@@ -86,12 +122,10 @@ services:
- GLOW_COMMUNICATION_EAI_PORT=8080
- SPRING_PROFILES_ACTIVE=${ACTIVE_PROFILE:-local}
tool-other:
tool-other-blue:
build:
context: .
dockerfile: dap-tool-other/Dockerfile
ports:
- "8284:8084"
depends_on:
- redis
environment:
@@ -99,8 +133,8 @@ services:
- SPRING_REDIS_HOST=redis
- SPRING_REDIS_PORT=6379
- SPRING_DATA_REDIS_PORT=6379
- AXHUB_GATEWAY_URL=http://gateway:8081
- AXHUB_TOOL_URL=http://tool-other:8084
- AXHUB_GATEWAY_URL=http://gateway-blue:8081
- AXHUB_TOOL_URL=http://tool-other-blue:8084
- GLOW_COMMUNICATION_MCI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_MCI_PORT=8080
- GLOW_COMMUNICATION_EXTMCI_HOMT=http://mci-mock
@@ -109,12 +143,10 @@ services:
- GLOW_COMMUNICATION_EAI_PORT=8080
- SPRING_PROFILES_ACTIVE=${ACTIVE_PROFILE:-local}
tool-payment:
tool-payment-blue:
build:
context: .
dockerfile: dap-tool-payment/Dockerfile
ports:
- "8285:8085"
depends_on:
- redis
environment:
@@ -122,8 +154,8 @@ services:
- SPRING_REDIS_HOST=redis
- SPRING_REDIS_PORT=6379
- SPRING_DATA_REDIS_PORT=6379
- AXHUB_GATEWAY_URL=http://gateway:8081
- AXHUB_TOOL_URL=http://tool-payment:8085
- AXHUB_GATEWAY_URL=http://gateway-blue:8081
- AXHUB_TOOL_URL=http://tool-payment-blue:8085
- GLOW_COMMUNICATION_MCI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_MCI_PORT=8080
- GLOW_COMMUNICATION_EXTMCI_HOMT=http://mci-mock
@@ -132,28 +164,109 @@ services:
- GLOW_COMMUNICATION_EAI_PORT=8080
- SPRING_PROFILES_ACTIVE=${ACTIVE_PROFILE:-local}
dozzle:
image: amir20/dozzle:latest
ports:
- "8288:8080"
# ==========================================
# GREEN SERVICES
# ==========================================
gateway-green:
build:
context: .
dockerfile: dap-gateway/Dockerfile
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /home/ubuntu/app/ax_hub_mcp_tool:/app
restart: always
gitea-runner:
image: gitea/act_runner:latest
- ./:/src
depends_on:
redis:
condition: service_healthy
environment:
- GITEA_INSTANCE_URL=https://git.devjun.net
- TZ=Asia/Seoul
- SPRING_REDIS_HOST=redis
- SPRING_REDIS_PORT=6379
- SPRING_DATA_REDIS_HOST=redis
- SPRING_DATA_REDIS_PORT=6379
- AXHUB_SOURCE_DIR=/src
- JAVA_TOOL_OPTIONS=-Xms64m -Xmx384m
- SPRING_PROFILES_ACTIVE=${ACTIVE_PROFILE:-local}
- GITEA_RUNNER_REGISTRATION_TOKEN=2N7ciuFIp6Jm29ewtzfl9ruQtpwGgB4ngFcXC2lF
- GITEA_RUNNER_NAME=ociwp-runner
tool-sms-green:
build:
context: .
dockerfile: dap-tool-sms/Dockerfile
depends_on:
- redis
environment:
- TZ=Asia/Seoul
- SPRING_REDIS_HOST=redis
- SPRING_REDIS_PORT=6379
- SPRING_DATA_REDIS_PORT=6379
- AXHUB_GATEWAY_URL=http://gateway-green:8081
- AXHUB_SOURCE_DIR=/src
- AXHUB_TOOL_URL=http://tool-sms-green:8082
- GLOW_COMMUNICATION_MCI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_MCI_PORT=8080
- GLOW_COMMUNICATION_EXTMCI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_EXTMCI_PORT=8080
- GITEA_RUNNER_LABELS=ubuntu-latest,ubuntu-22.04,linux-arm64
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /home/ubuntu/app/ax_hub_mcp_tool:/app
- ./act_runner_data:/data
- ./bin/docker:/usr/bin/docker
- /usr/libexec/docker/cli-plugins/docker-compose:/usr/libexec/docker/cli-plugins/docker-compose
restart: always
- GLOW_COMMUNICATION_EAI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_EAI_PORT=8080
- SPRING_PROFILES_ACTIVE=${ACTIVE_PROFILE:-local}
tool-email-green:
build:
context: .
dockerfile: dap-tool-email/Dockerfile
depends_on:
- redis
environment:
- TZ=Asia/Seoul
- SPRING_REDIS_HOST=redis
- SPRING_REDIS_PORT=6379
- SPRING_DATA_REDIS_PORT=6379
- AXHUB_GATEWAY_URL=http://gateway-green:8081
- AXHUB_TOOL_URL=http://tool-email-green:8083
- GLOW_COMMUNICATION_MCI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_MCI_PORT=8080
- GLOW_COMMUNICATION_EXTMCI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_EXTMCI_PORT=8080
- GLOW_COMMUNICATION_EAI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_EAI_PORT=8080
- SPRING_PROFILES_ACTIVE=${ACTIVE_PROFILE:-local}
tool-other-green:
build:
context: .
dockerfile: dap-tool-other/Dockerfile
depends_on:
- redis
environment:
- TZ=Asia/Seoul
- SPRING_REDIS_HOST=redis
- SPRING_REDIS_PORT=6379
- SPRING_DATA_REDIS_PORT=6379
- AXHUB_GATEWAY_URL=http://gateway-green:8081
- AXHUB_TOOL_URL=http://tool-other-green:8084
- GLOW_COMMUNICATION_MCI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_MCI_PORT=8080
- GLOW_COMMUNICATION_EXTMCI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_EXTMCI_PORT=8080
- GLOW_COMMUNICATION_EAI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_EAI_PORT=8080
- SPRING_PROFILES_ACTIVE=${ACTIVE_PROFILE:-local}
tool-payment-green:
build:
context: .
dockerfile: dap-tool-payment/Dockerfile
depends_on:
- redis
environment:
- TZ=Asia/Seoul
- SPRING_REDIS_HOST=redis
- SPRING_REDIS_PORT=6379
- SPRING_DATA_REDIS_PORT=6379
- AXHUB_GATEWAY_URL=http://gateway-green:8081
- AXHUB_TOOL_URL=http://tool-payment-green:8085
- GLOW_COMMUNICATION_MCI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_MCI_PORT=8080
- GLOW_COMMUNICATION_EXTMCI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_EXTMCI_PORT=8080
- GLOW_COMMUNICATION_EAI_HOMT=http://mci-mock
- GLOW_COMMUNICATION_EAI_PORT=8080
- SPRING_PROFILES_ACTIVE=${ACTIVE_PROFILE:-local}

64
nginx/blue.conf Normal file
View File

@@ -0,0 +1,64 @@
upstream gateway {
server gateway-blue:8081;
}
upstream tool-sms {
server tool-sms-blue:8082;
}
upstream tool-email {
server tool-email-blue:8083;
}
upstream tool-other {
server tool-other-blue:8084;
}
upstream tool-payment {
server tool-payment-blue:8085;
}
server {
listen 8281;
location / {
proxy_pass http://gateway;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 8282;
location / {
proxy_pass http://tool-sms;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 8283;
location / {
proxy_pass http://tool-email;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 8284;
location / {
proxy_pass http://tool-other;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 8285;
location / {
proxy_pass http://tool-payment;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

64
nginx/green.conf Normal file
View File

@@ -0,0 +1,64 @@
upstream gateway {
server gateway-green:8081;
}
upstream tool-sms {
server tool-sms-green:8082;
}
upstream tool-email {
server tool-email-green:8083;
}
upstream tool-other {
server tool-other-green:8084;
}
upstream tool-payment {
server tool-payment-green:8085;
}
server {
listen 8281;
location / {
proxy_pass http://gateway;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 8282;
location / {
proxy_pass http://tool-sms;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 8283;
location / {
proxy_pass http://tool-email;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 8284;
location / {
proxy_pass http://tool-other;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 8285;
location / {
proxy_pass http://tool-payment;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

66
scratch_rewrite.py Normal file
View File

@@ -0,0 +1,66 @@
import yaml
import copy
with open('docker-compose.yml', 'r') as f:
compose = yaml.safe_load(f)
services = compose['services']
new_services = {}
# Services to duplicate
app_services = ['gateway', 'tool-sms', 'tool-email', 'tool-other', 'tool-payment']
for name, svc in services.items():
if name in app_services:
# Create blue
blue_svc = copy.deepcopy(svc)
if 'ports' in blue_svc:
del blue_svc['ports'] # Nginx will handle ports
# Update AXHUB_GATEWAY_URL and AXHUB_TOOL_URL to point to blue if they refer to the base name
if 'environment' in blue_svc:
env = blue_svc['environment']
for i, e in enumerate(env):
if isinstance(e, str):
env[i] = e.replace('http://gateway:8081', 'http://gateway-blue:8081')
env[i] = env[i].replace(f'http://{name}:', f'http://{name}-blue:')
new_services[f'{name}-blue'] = blue_svc
# Create green
green_svc = copy.deepcopy(svc)
if 'ports' in green_svc:
del green_svc['ports']
if 'environment' in green_svc:
env = green_svc['environment']
for i, e in enumerate(env):
if isinstance(e, str):
env[i] = e.replace('http://gateway-blue:8081', 'http://gateway-green:8081') # replace from previous
env[i] = e.replace('http://gateway:8081', 'http://gateway-green:8081')
env[i] = env[i].replace(f'http://{name}:', f'http://{name}-green:')
new_services[f'{name}-green'] = green_svc
else:
new_services[name] = svc
# Add nginx
new_services['nginx'] = {
'image': 'nginx:latest',
'ports': [
'8281:8281',
'8282:8282',
'8283:8283',
'8284:8284',
'8285:8285'
],
'volumes': [
'./nginx/conf.d:/etc/nginx/conf.d'
],
'depends_on': ['redis']
}
compose['services'] = new_services
with open('docker-compose.yml', 'w') as f:
yaml.dump(compose, f, sort_keys=False, default_flow_style=False)