1. ๊ฐ์
github action, docker์ nginx๋ฅผ ์ฌ์ฉํด ๋ฌด์ค๋จ ๋ฐฐํฌ CI/CD๋ฅผ ๊ตฌ์ถํด๋์๋ค. ๋๋ BLUE/GREEN ๋ฐฉ์์ ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ์ ์ฉํด๋๋๋ฐ, ์ ์ฉ ํ ์๋ก์ด ์ปจํ ์ด๋๊ฐ ์คํ๋๊ณ ์คํ๋ง ์๋ฒ๊ฐ ๋ค ์ผ์ก๋ค๋ฉด, ๊ธฐ์กด ์ปจํ ์ด๋๋ฅผ ์ข ๋ฃ์ํค๋ ๊ฒ ๊น์ง ํ์ธํ๊ธฐ์ ์ ๊ตฌ์ถ๋๋ค ์๊ฐํ๋ค.
๋ฉฐ์น ์ ํ๋ก ํธ์๋ ํ์์ ์๋ฒ ์ฐ๋ ํ ์คํธ๋ฅผ ํด๋ณด๊ฒ ๋ค๋ ์์ฒญ์ด ๋ค์ด์๊ณ ํธ๋ฆฌ๊ฑฐ๋ฅผ ๊ฑธ์ด๋ ๋ธ๋์น์ push ํด์ฃผ์ด ๋ฐฐํฌ๋ฅผ ์๋ํ์ง๋ง, ๋ณ๊ฒฝ์ฌํญ์ด ์ ๋๋ก ์ ์ฉ๋์ง ์์๋ค.
ec2์ ๋ค์ด๊ฐ ์์ธ์ ์ดํด๋ณด์๋ค.
Nginx config ํ์ผ์ port๋ ์ ๋ณ๊ฒฝ๋์๊ณ , ์ปจํ ์ด๋๋ ์ ์คํ๋๊ณ ์ข ๋ฃ๋๋๊ฑธ ํ์ธํ๋๋ฐ ๋ณ๊ฒฝ ์ฝ๋๊ฐ ์ ์ฉ๋์ง ์์ ์ด๋ฏธ์ง๊ฐ ๋ฌธ์ ์ธ๊ฐ ํ๊ณ ์ด๋ฏธ์ง ๋ชฉ๋ก์ ์กฐํํ๋๋ ์ด๋ฏธ์ง๊ฐ ์ ๋ฐ์ดํธ ๋์ง ์์๋ค.
์์ธ๊ณผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๊ธฐ๋กํด๋๋ ค ํ๋ค.
2. ์์ธ
์๋๋ ๊ธฐ์กด์ ์์ฑํ๋ ๋ฌด์ค๋จ ๋ฐฐํฌ ๊ด๋ จ ์ฝ๋๋ค์ด๋ค.
- deploy.yml (์ผ๋ถ)
- name: Build jikgong-a Docker Image
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/jikgong .
- name: Push jikgong-a Docker Image
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/jikgong
- deploy.sh
RUNNING_CONTAINER=$(sudo docker ps)
echo "์คํ์ค์ธ ์ปจํ
์ด๋ ๋ชฉ๋ก: ${RUNNING_CONTAINER}"
# ์คํ ์ค์ธ ๋์ปค ์ปดํฌ์ฆ ํ์ธ
EXIST_A=$(sudo docker ps -q -f name=jikgong-a)
echo "EXIST_A ๊ฐ: ${EXIST_A}"
if [ -z "${EXIST_A}" ] # -z๋ ๋ฌธ์์ด ๊ธธ์ด๊ฐ 0์ด๋ฉด true. A๊ฐ ์คํ ์ค์ด์ง ์๋ค๋ ์๋ฏธ.
then
# B๊ฐ ์คํ ์ค์ธ ๊ฒฝ์ฐ
START_CONTAINER=a
TERMINATE_CONTAINER=b
START_PORT=8080
TERMINATE_PORT=8081
else
# A๊ฐ ์คํ ์ค์ธ ๊ฒฝ์ฐ
START_CONTAINER=b
TERMINATE_CONTAINER=a
START_PORT=8081
TERMINATE_PORT=8080
fi
echo "jikgong-${START_CONTAINER} up"
# ์คํํด์ผํ๋ ์ปจํ
์ด๋ docker-compose๋ก ์คํ. -p๋ docker-compose ํ๋ก์ ํธ์ ์ด๋ฆ์ ๋ถ์ฌ
# -f๋ docker-composeํ์ผ ๊ฒฝ๋ก๋ฅผ ์ง์
sudo docker pull ${DOCKERHUB_USERNAME}/jikgong
sudo docker-compose -f docker-compose.${START_CONTAINER}.yml up -d --build
RUNNING_CONTAINER=$(sudo docker ps)
echo "์คํ์ค์ธ ์ปจํ
์ด๋ ๋ชฉ๋ก: ${RUNNING_CONTAINER}"
for cnt in {1..10} # 10๋ฒ ์คํ
do
echo "check server start.."
# ์คํ๋ง๋ถํธ์ ๋ฑ๋กํ๋ actuator๋ก ์คํ๋์๋์ง ํ์ธ
UP=$(curl -s http://127.0.0.1:${START_PORT}/jikgong/health | grep 'UP')
if [ -z "${UP}" ] # ์คํ๋์๋ค๋ฉด break
then
echo "server not start.."
else
break
fi
echo "wait 10 seconds" # 10 ์ด๊ฐ ๋๊ธฐ
sleep 10
done
if [ $cnt -eq 10 ] # 10๋ฒ๋์ ์คํ์ด ์๋์์ผ๋ฉด ๋ฐฐํฌ ์คํจ, ๊ฐ์ ์ข
๋ฃ
then
echo "deployment failed."
exit 1
fi
echo "server start!"
echo "change nginx server port"
# sed ๋ช
๋ น์ด๋ฅผ ์ด์ฉํด์ ์๊น ์ง์ ํด์คฌ๋ service-url.inc์ url๊ฐ์ ๋ณ๊ฒฝํด์ค๋๋ค.
# sed -i "s/๊ธฐ์กด๋ฌธ์์ด/๋ณ๊ฒฝํ ๋ฌธ์์ด" ํ์ผ๊ฒฝ๋ก ์
๋๋ค.
# ์ข
๋ฃ๋๋ ํฌํธ๋ฅผ ์๋ก ์์๋๋ ํฌํธ๋ก ๊ฐ์ ๋ณ๊ฒฝํด์ค๋๋ค.
sudo sed -i "s/${TERMINATE_PORT}/${START_PORT}/" /etc/nginx/conf.d/service-url.inc
# ์๋ก์ด ํฌํธ๋ก ์คํ๋ง๋ถํธ๊ฐ ๊ตฌ๋ ๋๊ณ , nginx์ ํฌํธ๋ฅผ ๋ณ๊ฒฝํด์ฃผ์๋ค๋ฉด, nginx ์ฌ์์ํด์ค๋๋ค.
echo "nginx reload.."
sudo service nginx reload
# ๊ธฐ์กด์ ์คํ ์ค์ด์๋ docker-compose๋ ์ข
๋ฃ์์ผ์ค๋๋ค.
echo "jikgong-${TERMINATE_CONTAINER} down"
sudo docker-compose -f docker-compose.${TERMINATE_CONTAINER}.yml down --rmi all
# ์ปจํ
์ด๋์ ์ฌ์ฉ๋์ง ์๋ ์ด๋ฏธ์ง ์ ๋ถ ์ ๊ฑฐ
sudo docker image prune -af
EXIST_IMAGES=$(sudo docker images)
echo "ํ์ฌ ์ด๋ฏธ์ง ๋ฆฌ์คํธ: ${EXIST_IMAGES}"
echo "success deployment"
- docker-compose-a.yml
version: "3.8"
services:
jikgong-a:
container_name: jikgong-a
image: ${DOCKERHUB_USERNAME}/jikgong
volumes:
- ./logs:/logs
env_file:
- .env
ports:
- "8080:8080"
restart: always
networks:
default:
external:
name: jikgongnet
- docker-compose.b.yml
version: "3.8"
services:
jikgong-b:
container_name: jikgong-b
image: ${DOCKERHUB_USERNAME}/jikgong
volumes:
- ./logs:/logs
env_file:
- .env
ports:
- "8081:8080"
restart: always
networks:
default:
external:
name: jikgongnet
์ ์ฝ๋๋ฅผ ๊ฐ๋จํ๊ฒ ์์ฝํ๋ฉด
docker compose ํ์ผ์ด ๋ ๊ฐ๊ฐ ์๊ณ , ๊ธฐ์กด์ A๊ฐ ์คํ ์ค์ด์๋ค๋ฉด, B๋ฅผ ์คํ์ํจ๋ค.
B์ ์ดํ๋ฆฌ์ผ์ด์ ์๋ฒ๊ฐ ๋ค ์ผ์ง๋ฉด nginx์ ํฌ์๋ฉ ํฌํธ๋ฅผ B๋ก ๋ฐ๊ฟ์ฃผ๊ณ ์ปจํ ์ด๋ A๋ฅผ ์ข ๋ฃ์ํจ๋ค.
์ข ๋ฃ ์ํจ ํ ์ฌ์ฉํ์ง ์๋ ์ด๋ฏธ์ง๋ฅผ ์ ๋ถ ์ ๊ฑฐํ๋ค.
์ธ๋ป๋ณด๋ฉด ์ ์์ ์ธ ๋ก์ง ๊ฐ์ง๋ง ํ๊ฐ์ง ๋ฌธ์ ์ ์ด ์๋ค.
deploy.yml์์ image๋ฅผ buildํ ๋ ์ด๋ฆ์ jikgong์ผ๋ก ์ธํ ํ๋ค.
์ด๋๋ก docker hub์ ํธ์ฌํ๋ฉด ์ ์์ ์ผ๋ก ์๋ก์ด ์ด๋ฏธ์ง๋ก ์ ๋ฐ์ดํธ ๋์ง๋ง, docker-compose.yml์ ์คํ ์ค image๋ฅผ pull ๋ฐ์ ๋ ์ด๋ฏธ ์ด์ ์ ๊ฐ์ ์ด๋ฆ์ image๊ฐ ์กด์ฌํด pull์ ๋ฐ์ง ๋ชป ํ๋ค.
์๋ image๊ฐ ๊ธฐ์กด์ ์๋๋ผ๋ ์๋กญ๊ฒ pull ๋ฐ์ผ๋ฉด ๋ก์ปฌ์ image๊ฐ ์ ๋ฐ์ดํธ ๋๋๊ฒ ๋ง์ง๋ง, ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ์ ์ฉํ์ ๋ ์กฐ๊ธ ๋ค๋ฅด๋ค.
๊ธฐ์กด image๋ก ์ปจํ ์ด๋๋ฅผ ์คํ์ค์ด๊ธฐ ๋๋ฌธ์ ์ด image๋ฅผ ์ ๋ฐ์ดํธ ํ๋ ๊ฑด ๋ถ๊ฐ๋ฅํ ๊ฒ ๊ฐ์๋ค.
3. ํด๊ฒฐ ๋ฐฉ์
์ด๋ฏธ์ง ์ด๋ฆ์ด ๊ฐ๊ณ , ๊ธฐ์กด ์ด๋ฏธ์ง๋ก ์ปจํ ์ด๋๊ฐ ์คํ ์ค์ด๋ผ ์ ๋ฐ์ดํธ๋ฅผ ์ํค์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ์ด๋ฆ์ด ์๋ก ๋ค๋ฅธ 2๊ฐ์ ์ด๋ฏธ์ง๋ฅผ ๊ฐ๊ฐ docker hub์ pushํ๊ณ docker-compose.yml ํ์ผ์์ ํ๋์ฉ ๋ถ๋ฌ์ค๋๋ก ์์ ํด์ฃผ์๋ค.
- deploy.yml (์ผ๋ถ)
# ๋ฌด์ค๋จ ๋ฐฐํฌ ์ ๊ธฐ์กด ์ด๋ฏธ์ง๋ก ์คํ๋๋ ๊ฒ์ ๋ง๊ธฐ ์ํด a, b๋ก ๋๋
- name: Build jikgong-a Docker Image
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/jikgong-a .
- name: Push jikgong-a Docker Image
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/jikgong-a
- name: Build jikgong-b Docker Image
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/jikgong-b .
- name: Push jikgong-b Docker Image
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/jikgong-b
image pull ๋ถ๋ถ ์์
- docker-compose-a.yml
version: "3.8"
services:
jikgong-a:
container_name: jikgong-a
image: ${DOCKERHUB_USERNAME}/jikgong-a
volumes:
- ./logs:/logs
env_file:
- .env
ports:
- "8080:8080"
restart: always
networks:
default:
external:
name: jikgongnet
- docker-compose.b.yml
version: "3.8"
services:
jikgong-b:
container_name: jikgong-b
image: ${DOCKERHUB_USERNAME}/jikgong-b
volumes:
- ./logs:/logs
env_file:
- .env
# logging:
# driver: awslogs
# options:
# awslogs-group: "jikgong-logs"
# awslogs-region: "ap-northeast-2"
# awslogs-stream: "jikgong-stream"
ports:
- "8081:8080"
restart: always
networks:
default:
external:
name: jikgongnet
4. ๊ฒฐ๋ก
github action, nginx, docker ์กฐํฉ์ผ๋ก ๋ฌด์ค๋จ ๋ฐฐํฌ CI/CD๋ฅผ ๊ตฌ์ถํ๋ ๊ฐ๋ฐ์๋ค์ด ๊ฝค๋ ๋ง๋ค๊ณ ์๊ฐํ๊ณ , ๊ทธ ๋ถ๋ค๋ ๋ค๋ค ๋์ ๊ฐ์ ๋ฌธ์ ๋ฅผ ๊ฒช์ง ์์์๊น? ์ถ์๋๋ฐ ์์ง ๊ทธ๋ฐ ๋ธ๋ก๊ทธ ๊ธ์ ์ฐพ์ง ๋ชปํ๋ค.
์ฌ์ค ๋ด๊ฐ ํด๊ฒฐํ ๋ฐฉ์์ธ ๋ ๊ฐ์ image๋ฅผ buildํ๊ณ ๊ฐ๊ฐ push ํ๋ ๊ฑด ๊ทธ๋ ๊ฒ ์ข์ ํด๊ฒฐ ๋ฐฉ์์ด๋ผ๊ณค ์๊ฐ๋ค์ง ์๋๋ค.
๋ค๋ฅธ ๋ ์ข์ ๋ฐฉ๋ฒ์ด ์๋ ๊ตฌ๊ธ๋ง, ํ์ง์ ๋ถ๋ค ์๊ฒ๋ ์ฌ์ญค๋ดค์ง๋ง, ํน๋ณํ ๋ค๋ฅธ ๋ฐฉ์์ด ์๋ ๊ฒ ๊ฐ๋ค.
์ ํจ์ค ์ฌ์ฉ ์ jenkinsfile ์คํฌ๋ฆฝํธ๋ก ํด๊ฒฐํ ์ ์์ ๊ฒ ๊ฐ๋ค๋ ๋ถ์ ๊ณ์ จ์ง๋ง, ํ ์ด ํ๋ก์ ํธ์ github action์ผ๋ก๋ ์ถฉ๋ถํ๋ค ์๊ฐ์ด ๋ค์ด ์ฐ์ ์ ์ ๋ฐฉ๋ฒ์ผ๋ก ํด๊ฒฐํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ค.