CI CD
무중단 배포 (Github Actions, Code Deploy) - 2
붓 필
2025. 1. 23. 00:36

이번엔 CodeDeploy에서 ec2 인스턴스에 자동 배포하는 것을 설정해보려 한다.
1. docker-compose파일 생성
docekr-compose 작성법과 문법 설명은 생략하겠다.
아래처럼 yaml파일을 작성한다. 경로는 프로젝트 최상위 경로에 있다.
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- '80:80'
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- /dev/null:/etc/nginx/conf.d/default.conf # default.conf 무효화
networks:
- app-network
restart: always
nest-green:
build: .
container_name: nest-green
restart: always
ports:
- '3001:3000'
volumes:
- ./src:/app/src
networks:
- app-network
nest-blue:
build: .
container_name: nest-blue
restart: always
ports:
- '3002:3000'
volumes:
- ./src:/app/src
networks:
- app-network
networks:
app-network:
driver: bridge
2. 쉘 스크립트 파일 생성
최상위 프로젝트의 scripts폴더에 exec.sh, docker-script.sh파일을 생성해 준다.
권한 문제 삽질로 파일을 두 개로 나누었고, 로그를 보면서 해볼 길 바란다.
###### =>>>>>> exec.sh 파일
#!/bin/bash
# Docker 권한 문제 해결을 위해 ssm-user를 docker 그룹에 추가
sudo usermod -aG docker ubuntu
sudo usermod -aG docker ssm-user
echo "Current user: $(whoami)"
echo "Current directory: $(pwd)"
ls -l /home/ubuntu/my-nest-app
echo "Switching to project directory..."
cd /home/ubuntu/my-nest-app || exit 1
echo "Running docker script..."
sh /home/ubuntu/my-nest-app/scripts/docker-script.sh
###### =>>>>>> docker-script.sh 파일
#!/bin/bash
# Nginx와 현재 구동 중인 애플리케이션의 상태 확인
EXIST_GREEN=$(docker ps | grep nest-green)
EXIST_BLUE=$(docker ps | grep nest-blue)
DOCKER_APP_NAME=nest
# Nginx 설정 파일 경로
NGINX_CONF=<nginx 파일 경로>
NGINX_CONF_BACKUP="${NGINX_CONF}.backup"
# 현재 설정 백업
cp $NGINX_CONF $NGINX_CONF_BACKUP
# 이번 배포 타겟 결정
TARGET_PORT=0
CURRENT_CONTAINER=""
NEW_CONTAINER=""
# Green이 없으면 Green을 시작하고 Blue가 없으면 Blue를 시작, Green을 종료
if [ -z "$EXIST_GREEN" ]; then
echo "> Green container is not running. Starting Green container..."
TARGET_PORT=3001
CURRENT_CONTAINER="nest-blue"
NEW_CONTAINER="nest-green"
# Green 컨테이너 시작
docker-compose up -d nest-green
elif [ -z "$EXIST_BLUE" ]; then
echo "> Blue container is not running. Starting Blue container..."
TARGET_PORT=3002
CURRENT_CONTAINER="nest-green"
NEW_CONTAINER="nest-blue"
# Blue 컨테이너 시작
docker-compose up -d nest-blue
else
echo "> Both Green and Blue containers are running. Updating configuration..."
TARGET_PORT=3001
CURRENT_CONTAINER="nest-blue"
NEW_CONTAINER="nest-green"
# Green 컨테이너 다시 시작
docker-compose up -d nest-green
fi
echo "> Health check of New WAS at 'http://127.0.0.1:${TARGET_PORT}'..."
# 헬스 체크
for RETRY_COUNT in {1..10}
do
echo "> Retrying health check... (${RETRY_COUNT})"
RESPONSE_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:${TARGET_PORT})
if [ ${RESPONSE_CODE} -eq 200 ]; then
echo "> New WAS successfully running"
# Nginx upstream 설정 업데이트
# 현재 실행 중인 컨테이너를 새로운 컨테이너로 변경
sed -i.bak "s/server ${CURRENT_CONTAINER}:3000/server ${NEW_CONTAINER}:3000/g" $NGINX_CONF
# Nginx 설정 리로드
docker exec nginx nginx -s reload
echo "> Nginx reloaded with new configuration"
# 이전 컨테이너 종료 (Green 또는 Blue 컨테이너 종료)
if [ ! -z "$CURRENT_CONTAINER" ]; then
echo "> Stopping previous container: $CURRENT_CONTAINER"
docker-compose stop $CURRENT_CONTAINER
docker-compose rm -f $CURRENT_CONTAINER
fi
break
elif [ ${RETRY_COUNT} -eq 10 ]; then
echo "> Health check failed."
# 새 컨테이너 종료
docker-compose stop $NEW_CONTAINER
docker-compose rm -f $NEW_CONTAINER
# Nginx 설정 복구
cp $NGINX_CONF_BACKUP $NGINX_CONF
docker exec nginx nginx -s reload
exit 1
fi
sleep 10
done
# Nginx 컨테이너가 여전히 실행 중이라면, 재시작
docker-compose up -d nginx
# 불필요한 도커 리소스 정리
echo "Prune Docker System"
docker system prune -af
# 백업 파일 제거
rm -f $NGINX_CONF_BACKUP
exit 0
CodeDeploy가 s3에서 압축파일을 가져와 서버에 아축파일을 풀고 exec.sh 스크립트를 실행하게 된다.
자 여기서 push하고 테스트해보면 정상적으로 동작하는게 보인다.