728x90
1.
https://soobysu.tistory.com/184
2.
https://soobysu.tistory.com/185
여기부턴 EC2 환경에서 작업 된다.
1. 포트 정리
사용 할 포트를 정의 해주어야 한다.
NginX 로 포트를 변경하여 무중단 배포를 구성한다.
2.Dockerfile 구성
FROM openjdk:17-alpine
ARG JAR_FILE=./*.jar
ENV TZ=Asia/Seoul
COPY ${JAR_FILE} /app/api.jar
ENTRYPOINT ["java", "-jar", "/app/api.jar"]
docker-compose 에 사용 될 Dockerfile 을 만들어 준다.
jdk 는 프로젝트에 맞는 jdk 를 설정 해준다.
2. docker-compose.yml 구성
구성해야 할 compose file 은 총 4가지 이다
docker-compose.dev.blue.yaml
docker-compose.dev.green.yaml
docker-compose.prd-blue.yaml
docker-compose.prd-green.yaml
한가지의 파일로 만들고 환경변수 설정해주는 방법도 있지만
직관적으로 파일을 구분하는게 좋아서 구별해 두었다.
version: '3.1'
services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: blue-dev
environment:
- JAVA_OPTS=-server -Xms512mb -Xmx512mb -Xss256k -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -Dfile.encoding=UTF-8
- TZ=Asia/Seoul
- SPRING_PROFILES_ACTIVE=dev
ports:
- '1110:9090'
volumes:
- springApp-logs:/logs
networks:
- service-network
volumes:
springApp-logs:
networks:
service-network:
external: true
version: '3.1'
services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: green-dev
environment:
- JAVA_OPTS=-server -Xms512mb -Xmx512mb -Xss256k -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -Dfile.encoding=UTF-8
- TZ=Asia/Seoul
- SPRING_PROFILES_ACTIVE=dev
ports:
- '1111:9090'
volumes:
- springApp-logs:/logs
networks:
- service-network
volumes:
springApp-logs:
networks:
service-network:
external: true
version: '3.1'
services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: blue-prd
environment:
- JAVA_OPTS=-server -Xms512mb -Xmx512mb -Xss256k -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -Dfile.encoding=UTF-8
- TZ=Asia/Seoul
- SPRING_PROFILES_ACTIVE=prd
ports:
- '1120:9091'
volumes:
- springApp-logs:/logs
networks:
- service-network
volumes:
springApp-logs:
networks:
service-network:
external: true
version: '3.1'
services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: green-prd
environment:
- JAVA_OPTS=-server -Xms512mb -Xmx512mb -Xss256k -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -Dfile.encoding=UTF-8
- TZ=Asia/Seoul
- SPRING_PROFILES_ACTIVE=prd
ports:
- '1121:9091'
volumes:
- springApp-logs:/logs
networks:
- service-network
volumes:
springApp-logs:
networks:
service-network:
external: true
4. NginX 설정
# vi /etc/nginx/nginx.conf
http {
##
# Basic Settings
##
.
.
.
include /your/path/nginx/*.conf;
4-1 채널 포트 설정 파일
nginx 설정 파일을 둘 디렉토리를 생상 해 준뒤 nginx 설정을 매핑 시킬 수 있게 작성 한다.
# nginx.dev.conf
server {
listen 1110;
server_name localhost;
location / {
proxy_pass http://127.0.0.1:1110;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# nginx.prd.conf
server {
listen 1120;
server_name localhost;
location / {
proxy_pass http://127.0.0.1:1120;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
8888 -> dev
8889 -> prd 채널로 매핑 될 수 있게 설정파일을 만들어 준다
4-2 변경 될 포트 파일
# service_url_dev.inc
set $service_url http://127.0.0.1:1110;
# service_url_prd.inc
set $service_url http://127.0.0.1:1120;
배포 쉘 스크립트에서 있을 포트 변경 파일을 만들어 준다.
5. deploy.sh 구성
마지막으로 github Actions 에서 실행 될 배포 쉘스크립트를 작성한다.
#!/bin/bash
export PATH="$PATH:/usr/local/bin"
MODE=${1:-dev}
if [ "$MODE" == "prd" ]; then
PORT1=1110 # Blue
PORT2=1111 # Green
else
PORT1=1120 # Blue
PORT2=1121 # Green
fi
echo "모드: $MODE, 포트1: $PORT1, 포트2: $PORT2"
# 현재 실행 중인 Blue 앱이 있는지 확인
EXIST_BLUE=$(docker ps --filter "name=blue-${MODE}" --format "{{.ID}}")
if [ -n "$EXIST_BLUE" ]; then
echo "Blue is running. Switching to Green on port $PORT2..."
docker-compose -p green-${MODE} -f docker-compose.${MODE}.green.yaml up -d
BEFORE_COLOR="blue"
AFTER_COLOR="green"
BEFORE_PORT=$PORT1
AFTER_PORT=$PORT2
else
echo "Green is running. Switching to Blue on port $PORT1..."
docker-compose -p blue-${MODE} -f docker-compose.${MODE}.blue.yaml up -d
BEFORE_COLOR="green"
AFTER_COLOR="blue"
BEFORE_PORT=$PORT2
AFTER_PORT=$PORT1
fi
echo "${AFTER_COLOR} server up (port: ${AFTER_PORT})"
# 서버 응답 확인
for cnt in {1..10}; do
echo "서버 응답 확인 중 (${cnt}/10)"
UP=$(curl -s http://localhost:${AFTER_PORT}/api/open/healthCheck)
if [ -n "${UP}" ]; then
echo "Server is up and healthy!"
break
fi
sleep 10
done
if [ $cnt -eq 10 ]; then
echo "서버가 정상적으로 구동되지 않았습니다."
exit 1
fi
echo "Nginx 설정 업데이트 및 재시작 ${MODE}..."
if [ "$MODE" == "prd" ]; then
CONFIG_FILE="/home/ubuntu/bin/nginx/service_url_prd.inc"
else
CONFIG_FILE="/home/ubuntu/bin/nginx/service_url_dev.inc"
fi
sudo sed -i "s|http://127.0.0.1:${BEFORE_PORT}|http://127.0.0.1:${AFTER_PORT}|" $CONFIG_FILE || { echo "Failed to update Nginx configuration"; exit 1; }
sudo nginx -s reload || { echo "Failed to reload Nginx"; exit 1; }
echo "Nginx reloaded with new configuration for ${MODE}."
# 이전 앱 종료 및 이미지 제거
echo "Stopping ${BEFORE_COLOR}-${MODE}..."
docker-compose -p ${BEFORE_COLOR}-${MODE} -f docker-compose.${MODE}.${BEFORE_COLOR}.yaml down || { echo "Failed to stop ${BEFORE_COLOR} app"; exit 1; }
# 이미지 제거 (이미 사용 중일 경우 오류 방지)
docker rmi ${BEFORE_COLOR}-${MODE} || echo "Image ${BEFORE_COLOR}-${MODE} is still in use or already removed."
echo "${BEFORE_COLOR}-${MODE} server down (port: ${BEFORE_PORT})"
2장에서 설명된 deploy.sh dev 명령어가 실행되면 MODE 환경변수에 dev 가 들어가서 실행된다
각 단계는 dev 와 prd 분기로 나눠져 docker-compose 파일로 이미지를 빌드하여 컨테이너화 시키게 된다.
echo "Nginx 설정 업데이트 및 재시작 ${MODE}..."
if [ "$MODE" == "prd" ]; then
CONFIG_FILE="/your/path/service_url_prd.inc"
else
CONFIG_FILE="/your/path/service_url_dev.inc"
fi
sudo sed -i "s|http://127.0.0.1:${BEFORE_PORT}|http://127.0.0.1:${AFTER_PORT}|" $CONFIG_FILE || { echo "Failed to update Nginx configuration"; exit 1; }
sudo nginx -s reload || { echo "Failed to reload Nginx"; exit 1; }
echo "Nginx reloaded with new configuration for ${MODE}."
컨테이너가 띄어지고 헬스체크가 완료되면 NginX 의 포트를 변경하여 요청을 After Color 의 컨테이너로 연결 될 수 있게 한다.
728x90