github action, docker, nginx๋ฅผ ํ™œ์šฉํ•œ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ์‹œ Docker Image๊ฐ€ ์—…๋ฐ์ดํŠธ ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ

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์œผ๋กœ๋„ ์ถฉ๋ถ„ํ•˜๋‹ค ์ƒ๊ฐ์ด ๋“ค์–ด ์šฐ์„ ์€ ์œ„ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•ด๊ฒฐํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ๋‹ค.