[CI&CD] Github Action +Docker + EC2 + self hosted runner 로 React (front-end) CI&CD 구축하기
놀러가실 프로젝트는 Ec2 에서 jenkins + docker를 통해서 CI&CD 구축을 했었다. 하지만 젠킨스를 이용해서 배포했기 때문에 여러개의 인스턴스 사용이 불가피 했고, 이를 계속 유지하기에는 비용측면과 유지관리하는 데에 번거로움이 있었다. (젠킨스 서버 용량이 커서 한 개의 인스턴스에서 도커와 젠킨스를 함께 사용할 수 없었다. swap 도 사용하고, 프리티어 최대용량을 써도 계속 서버가 다운됐음. 그리고 비용문제로 프리티어 사용을 위해 각 인스턴스마다 팀원들 계정을 썼기 때문에 문제가 생겼을 때 해당 서버에 아이디랑 비번을 계속 찾아야하는 것도 번거로운 문제였음)
따라서, 배포 후에 서버 유지가 어려워서 바로 서버를 닫았다. 그런데 취준을 위해 따로 코드 리팩토링을 진행하던 중에 도메인으로 접속해서 실제 애플리케이션을 써볼 수 없다는 점이 아쉽기도 하고, 좀 더 쉽게 배포를 진행해보고 싶어서 CI&CD 를 다시 구축하기로 했다!
사실 리팩토링 진행하고 싶은 부분이 많은데.. 일단 그 부분은 좀 미뤄두고 배포 후에 빠르게 진행해보려고 한다..!
시각화에 취약한 인간이라 일단 눈에 보이는게 중요해...👀
일단 배포 방법에 대한 고민이 있었는데 제약 사항이 있었기에 이에 맞는 방법을 택해야했다.
사용할 수 있는 인스턴스는 한 개였고, 내가 배포해야할 될 서버는 '스프링부트 서버, 리액트 서버, 채팅 서버, 레디스 서버' 총 4개 였다.
프리티어로 사용해야 했기에 사용할 수 있는 최대 스토리지 30기가 + swap 까지 사용해서 최대한 사용해보려고 한다....
정 안되면 계정 하나 더 파야지 모.. 빌드는 깃허브 액션을 통해 진행하고, 빌드한 이미지를 도커허브에 올린 뒤 인스턴스에서 도커허브 이미지를 pull 받아 컨테이너로 띄우는 방식으로 배포를 진행하기로 하였다.
우선, 가비아에서 구매한 도메인을 ec2에 적용하려면 아래 방법대로 하면 된다.
1. ec2에 탄력적IP적용
2. ec2의 IP를 내 도메인의 A타입과 매핑해두기
🍄 Dockerfile 생성
# Stage 1: Build the React app
FROM node:18-alpine as build
WORKDIR /app
COPY package.json ./
# Update package list and install nodejs and npm
RUN npm install
COPY . ./
# React 앱 빌드
RUN npm run build
# Stage 2: Serve the React app using Nginx
FROM nginx:alpine
# Nginx 설정 파일을 이미지에 복사
COPY default.conf /etc/nginx/conf.d/default.conf
# React 앱을 빌드한 결과물을 Nginx의 정적 파일 서빙 디렉토리로 복사
COPY --from=build /app/build /usr/share/nginx/html
# Nginx가 리스닝할 포트 설정
EXPOSE 80
# Nginx를 실행하여 정적 파일 서빙
CMD ["nginx", "-g", "daemon off;"]
- node:-alpine 이미지를 베이스로 한다. WORKDIR을 /app으로 설정한다. 워킹 디렉토리는 이미지내에 생성되는 디렉토리이다.
- 워킹 디렉토리 내부로 package.json 파일을 복사한 뒤, 그 안에서 npm install & build 한다.
- Nginx 이미지를 베이스로 하여 프로젝트 내부의 default.conf 파일을 복사하고, 빌드 파일을 도커 내에 복사한 뒤, 80 포트를 열어준다.
🍄 .dockerignore 생성
node_modules
dist
.git
*.md
*.log
.env
README.md
.dockerignore
.gitignore
Jenkinsfile
이미지 생성시 용량을 줄이기 위해 프로젝트 내의 필요 없는 node_modules를 ignore 해주었다.
🍄 default.conf 생성
server {
listen 3000;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
- location / 블록은 루트 URL 경로(/)에서 발생하는 모든 요청을 처리한다.
- root /usr/share/nginx/html; 구문은 정적 파일이 위치한 디렉토리를 지정하고, 이 경우, Dockerfile에서 Nginx 이미지의 해당 위치로 빌드 결과물을 복사하게 된다.
- index index.html index.htm; 구문은 Nginx가 디렉토리를 제공할 때 사용할 기본 파일 이름을 지정한다.
- try_files $uri $uri/ /index.html; 구문은 Nginx가 요청을 처리하는 방식을 정의하는 부분이다. Nginx는 우선 $uri가 파일이나 디렉토리에 매핑되는지 확인하고, 그렇지 않은 경우 /index.html 파일을 제공한다.
- 이전의 과정(Dockerfile)에서 COPY --from=builder usr/src/app/build /usr/share/nginx/html 를 통해 빌드 파일을 usr/src/nginx/html로 복사하였기 때문에 root 경로를 위와 같이 설정했다
🍄 깃허브 액션 파일 설정(.github/workflows/npm-publish.yml)
name: Deploy
on:
push:
branches: [main] # main 브랜치에 push 발생하면 트리거
workflow_dispatch: # 디버깅용, actions 탭에서 직접 버튼 눌러서 트리거
jobs:
build:
runs-on: ubuntu-latest # ubuntu 최신 버전 환경에서 실행
steps:
# GitHub Actions는 해당 프로젝트를 만들어진 환경에 checkout하고 나서 실행한다.
# 마치 브랜치를 만들 때 checkout하는 것처럼 꼭 필요하다.
# 아래 코드는 누군가 만들어놓은 Action을 사용하는 것이다.
# 만들어놓은 Action을 사용할 때는 uses라는 키워드를 사용한다.
- name: Checkout
uses: actions/checkout@v3.5.2
# React 프로젝트이므로 해당 환경을 Node.js 위에서 실행하겠다고 명시한다.
# 마찬가지로 누군가 만들어 놓은 Action이다.
# node.js 18 버전을 사용하도록 설정
- name: Use Node.js 18
uses: actions/setup-node@v3
with:
node-version: 18
# push할 때마다 npm을 install 해야할까? 아니다.
# 해당 프로젝트의 node_modules가 변했는지 안 변했는지를 이용해서
# 모듈 변화가 있을 때만 npm install을 해줄 수도 있다.
- name: Cache node modules
# 그걸 제공하는 Action도 있다.
uses: actions/cache@v2.1.8
# 해당 step을 대표하는 id를 설정할 수도 있다. 해당 값은 뒤의 step에서 사용한다.
id: cache
with:
# node_modules라는 폴더를 검사하여
path: node_modules
# 아래 키값으로 cache가 돼있는지 확인한다.
key: npm-packages-${{ hashFiles('**/package-lock.json') }}
# 위 step에서 node_modules에 대한 cache 검사를 했다.
# 만약 모듈에 변한 게 있다면 `npm install`을 실행하고 아니면 해당 step을 건너뛰게 된다.
# if 키워드는 해당 스텝을 실행할지 말지를 결정할 수 있는 키워드이다.
# 위 step에서 정했던 cache라는 id를 steps.cache로 가져올 수 있다.
# cache라는 id 값을 가진 step에서는 cache-hit라는 output을 내뱉는다.
# 그걸로 cache가 hit 됐는지 안 됐는지를 알 수 있다.
# 그 값이 true가 아닐 때만 npm install을 한다.
# https://fe-developers.kakaoent.com/2022/220106-github-actions/
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: npm install
- name: Build
run: npm run build
# Docker에 연결하여 이미지를 빌드하고 Hub에 푸시한다.
# https://docs.docker.com/build/ci/github-actions/#step-three-define-the-workflow-steps
- name: Docker Build and push
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -t ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:server-prod-blue -f Dockerfile .
docker build -t ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:server-prod-green -f Dockerfile .
docker push ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:server-prod-blue
docker push ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:server-prod-green
deploy:
needs: build-and-test # build-and-test 작업이 성공적으로 수행되어야 실행된다.
runs-on: self-hosted # 지정된 Runner에서 동작한다. 등록한 self-hosted runner의 이름을 작성한다.
steps:
- name: Pull Docker image from DockerHub # docker image를 pull 해온다.
run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:server-prod-blue
- name: Pull Docker image from DockerHub # 실행중인 docker container가 있다면 중지한다.
run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:server-prod-green
- name: deploy.sh 적용
run: ./deploy.sh
- name: 사용하지 않는 docker image 지우기
run: sudo docker image prune -f
github action 파일을 작성해준 뒤, secret 값을 설정해준다.
그 다음 외부에서 인스턴스에 접속하지 못하게 할 것 이기 때문에 self-hosted-runner 를 통해서 ec2 환경에서 배포할 수 있게 설정해준다.
🕊️ Self-Hosted Runner 설정
Settings - Actions - Runners에서 runner를 등록한다.
원하는 image, architecture를 설정하고 생성된 명령어를 등록하려는 서버에서 실행하면 된다.
EC2를 사용하므로, ssh 접속 후 해당 명령어를 실행했다.
🕊️ EC2 접속 후 Docker, Docker-compose 설치
ec2 내에 docker 와 docker-compose 를 설치해준다.
이전에 용량 문제 예방을 위해 swap 설정도 해준다.
이후에, Docker를 이용하여 Nginx를 컨테이너로 실행하고 https를 적용하는 방법까지 알아보자.
docker-compose.yml 작성
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./data/nginx:/etc/nginx/conf.d
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
depends_on:
- certbot
certbot:
image: certbot/certbot
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
version 은 docker-compose 의 버전을 나타낸다. 그리고 nginx, cerbot 컨테이너를 띄우고 있으며, volumes 통해 ec2의 파일들을 컨테이너 내로 연동 시킨다. 예를 들어, ./data/nginx:/etc/nginx/conf.d 는 ec2 내에 있는 ./data/nginx 파일이 컨테이너의 /etc/nginx/conf.d 로 옮겨 진다고 보면 된다.
restar: unless-stopped 는 컨테이너가 수동으로 중지되지 않는 한 항상 자동으로 재시작되는 설정이다.
그리고 volumes 를 통해 호스트와 컨테이너 사이에 볼륨을 설정한다. 이렇게 볼륨마운트 설정을 하고나면, 로컬에서 nginx.conf를 편집해서 배포를 아무리해도, 배포된 Nginx 컨테이너 내부의 conf.d에는 방금 로컬에서 배포한 nginx.conf가 위치하는 것이 아니라, 무조건 EC2의 ./nginx/conf.d 환경으로 덮어지게 되는 것이다.
default.conf 파일을 작성
도커 컴포즈로 볼륨마운트 설정을 해둔 ec2 내 경로에 nginx conf 파일을 작성해준다.
server {
listen 80;
listen [::]:80;
server_name nolleogasil.com www.nolleogasil.com; #여기에는 본인의 도메인이 들어간다.
server_tokens off;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
Let’s Encrypt 유효성 검사를 완료하려면 Nginx가 필요하지만 인증서가 없으면 nginx가 시작되지 않는다.
그래서 임시로 https를 사용하지 않는 척 nginx를 실행한 다음 인증서를 발급받고 https를 사용한 nginx에 인증서를 적용하면 된다.
위에 작성한 것처럼 임시 HTTP 설정으로 Nginx 서버가 80번 포트만 리스닝하게 설정한다.
- location /.well-known/acme-challenge/
- 이 블록은 Let's Encrypt에서 SSL 인증서를 자동으로 발급받기 위한 설정인데, Let's Encrypt는 ACME(Automatic Certificate Management Environment) 프로토콜을 이용해서 도메인의 소유권을 확인한다.
- 이 과정에서 /.well-known/acme-challenge/ 경로에 특정한 정보를 배치하게 되는데, 이 설정은 그 요청을 처리하는 부분이라고 보면된다.
- return 301 https://$host$request_uri; 80포트로 들어오는 HTTP 요청을 HTTPS로 리다이렉트하는 부분이다. 이를 통해 모든 트래픽이 암호화되도록 강제하는 것이다. 301은 HTTP 상태 코드로 "Moved Permanently"를 나타내며, $host는 요청이 도착한 서버의 이름, $request_uri는 요청의 URI를 의미한다.
docker-compose를 실행.
docker-compose -f docker-compose.yml up -d
docker ps // nginx와 certbot 컨테이너가 살아있는지 확인
cerbot 으로 도메인에 대한 SSL/TLS 인증서를 생성
nginx, certbot 모두 잘 실행 되었다면, cerbot 을 이용하여 도메인에 대한 SSL/TLS 인증서를 생성해야 한다.
아래 명령어를 입력하여, certbot 인증서를 설치한다.
curl -L https://raw.githubusercontent.com/wmnnd/nginx-certbot/master/init-letsencrypt.sh > init-letsencrypt.sh
chmod +x init-letsencrypt.sh
vi init-letsencrypt.sh
sudo ./init-letsencrypt.sh
인증서 발급받는 스크립트를 다운로드하고 도메인, 이메일 주소, 디렉터리를 변경해야한다.
난 여기서 계속 오류가 났었다. 가비아에서 도메인의 네임서버를 Route 53 네임서버로 설정한 후 DNS 레코드를 Route 53에서 관리해야 하는데 계속 가비아의 A 레코드에만 ec2를 연결해놓아서 A레코드를 인식하지 못했기 때문이다.
도메인과 네임서버의 역할에 대해서 다시 한 번 상기할 수 있는 기회가 됐다..
Nginx conf 설정에 Https 리버스 프록시 설정
위와 같이 SSL/TLS 인증서 설치가 제대로 마쳤다면, 다시 Nginx conf 설정에 Https 리버스 프록시 설정을 해 준다.
또한 Let's Encrypt에서 발급받은 인증서는 30일후에 만료되기 때문에 자동 인증서 갱신이 필요하다.
# HTTPS 서버 블록: 443번 포트에서 SSL 인증서로 트래픽 처리
server {
listen 443 ssl;
server_name www.nolleogasil.com;
ssl_certificate /etc/letsencrypt/live/nolleogasil.com/fullchain.pem; # Let's Encrypt 인증서
ssl_certificate_key /etc/letsencrypt/live/nolleogasil.com/privkey.pem; # 개인 키
ssl_trusted_certificate /etc/letsencrypt/live/nolleogasil.com/chain.pem; # 체인 인증서
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers on;
# Upstream 블록을 통해 Blue/Green 컨테이너로 트래픽 전달
location / {
proxy_pass http://app; # upstream "app"으로 트래픽 전달
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
upstream app {
server blue-container:80; # 기본 blue-container 로 설정
#server green-container:80;
}
blue/green 컨테이너를 관리할 수 있도록 docker-compose.yml 을 수정해준다.
version: '3'
services:
nginx:
image: nginx:latest
restart: unless-stopped
container_name: nginx
ports:
- "80:80"
- "443:443"
volumes:
- /home/ubuntu/data/nginx:/etc/nginx/conf.d
- /home/ubuntu/build:/usr/share/nginx/html # React 빌드 파일을 Nginx에 매핑
- /home/ubuntu/data/certbot/conf:/etc/letsencrypt
- /home/ubuntu/data/certbot/www:/var/www/certbot
networks:
- app-network
blue-container:
image: ${DOCKER_USERNAME}/${DOCKER_REPOSITORY}:${DEPLOY_TAG}
container_name: blue-container
environment:
- PORT=3000
ports:
- "3000:80"
networks:
- app-network
green-container:
image: ${DOCKER_USERNAME}/${DOCKER_REPOSITORY}:${DEPLOY_TAG}
container_name: green-container
environment:
- PORT=3001
ports:
- "3001:80"
networks:
- app-network
certbot:
image: certbot/certbot
restart: unless-stopped
volumes:
- /home/ubuntu/data/certbot/conf:/etc/letsencrypt
- /home/ubuntu/data/certbot/www:/var/www/certbot
networks:
- app-network
networks:
app-network:
driver: bridge
driver: bridge: 네트워크의 드라이버를 지정한다. bridge는 Docker의 기본 네트워크 드라이버로, 컨테이너 간 통신을 위한 격리된 네트워크를 제공합니다. 이를 통해 각 컨테이너는 같은 네트워크 내에서 서로 통신할 수 있으며, 외부와는 격리된 상태로 실행된다.
(네트워크를 설정하면 도커 컴포즈를 실행시켰을 때, 자동으로 생성이 되지만 나는 안 되어서...네트워크 생성하고 수동으로 연결해주었다.
docker network create app-network
docker network connect app-network <container_name> )
그런 다음 sudo docker network inspect app-network 를 통해 해당 네트워크에 연결 된 컨테이너들을 확인 할 수 있다.
배포 스크립트 작성
마지막으로 배포 스크립트 까지 작성해주면 끝!
# 환경 변수 파일 로드
if [ -f ./deploy-env.sh ]; then
source ./deploy-env.sh
else
echo "Environment file not found!"
exit 1
fi
# 설정된 환경 변수
DOCKER_IMAGE=${DOCKER_USERNAME}/${DOCKER_REPOSITORY}:${DEPLOY_TAG} # 새 이미지 이름
BLUE_PORT=3000
GREEN_PORT=3001
NGINX_CONFIG=~/data/nginx/default.conf
# 현재 실행 중인 컨테이너 확인
CURRENT_PORT=$(sudo docker ps --format "{{.Ports}}" | grep -oE "3000|3001" | head -n 1)
echo "$CURRENT_PORT"
if [ -z "$CURRENT_PORT" ]; then
echo "No active container found. Starting with Blue container."
CURRENT_CONTAINER=""
NEXT_CONTAINER="blue-container"
NEXT_PORT=$BLUE_PORT
else
# 공백 제거 후 비교
if [ "$CURRENT_PORT" == "$BLUE_PORT" ]; then
echo "Blue container is active. Switching to Green."
CURRENT_CONTAINER="blue-container"
NEXT_CONTAINER="green-container"
NEXT_PORT=$GREEN_PORT
else
echo "Green container is active. Switching to Blue."
CURRENT_CONTAINER="green-container"
NEXT_CONTAINER="blue-container"
NEXT_PORT=$BLUE_PORT
fi
fi
echo "$CURRENT_CONTAINER"
echo "$NEXT_CONTAINER"
# 기존 컨테이너 확인 및 삭제
if sudo docker ps -a --filter "name=$CURRENT_CONTAINER" --format "{{.Names}}" | grep -q "$CURRENT_CONTAINER"; then
echo "Stopping and removing existing container: $CURRENT_CONTAINER"
sudo docker stop $CURRENT_CONTAINER
sudo docker rm $CURRENT_CONTAINER
fi
# 새로운 컨테이너 실행
echo "Started new container: $NEXT_CONTAINER on port $NEXT_PORT for $DOCKER_IMAGE"
sudo DOCKER_USERNAME=$DOCKER_USERNAME DOCKER_REPOSITORY=$DOCKER_REPOSITORY DEPLOY_TAG=$DEPLOY_TAG docker-compose -f /home/ubuntu/data/docker-compose.yml up -d $NEXT_CONTAINER
# 헬스체크: 새로운 컨테이너가 준비되었는지 확인
for i in {1..10}; do
echo "Checking health of $NEXT_CONTAINER on port $NEXT_PORT..."
if curl -s http://$NEXT_CONTAINER:80 > /dev/null; then
echo "$NEXT_CONTAINER is healthy!"
break
fi
echo "Waiting for $NEXT_CONTAINER to be ready..."
sleep 3
done
# Nginx 설정 업데이트
# 다음 활성화 컨테이너 결정
if [ "$NEXT_CONTAINER" == "blue-container" ]; then
echo "Switching to Blue container on port $NEXT_PORT"
sed -i "s/server .*:.*;/server blue-container:80;/" $NGINX_CONFIG
elif [ "$NEXT_CONTAINER" == "green-container" ]; then
echo "Switching to Green container on port $NEXT_PORT"
sed -i "s/server .*:.*;/server green-container:80;/" $NGINX_CONFIG 69,0-1 62%
else
echo "Error: Invalid container name"
exit 1
fi
# Nginx 재시작
sudo DOCKER_USERNAME=$DOCKER_USERNAME DOCKER_REPOSITORY=$DOCKER_REPOSITORY DEPLOY_TAG=$DEPLOY_TAG docker-compose -f /home/ubuntu/data/docker-compose.yml exec nginx nginx -s reload
echo "Nginx configuration updated. Traffic switched to $NEXT_CONTAINER"
echo "Deployment complete. Active container: $NEXT_CONTAINER on port $NEXT_PORT"
blue/green 배포 방식으로 배포 스크립트를 작성했다. 여기서 주의해야할 점이 몇가지 있다.
self hoseted runner 사용하기 때문에 runner가 설정된 서버(즉, self-hosted 서버)의 특정 폴더에서 실행된다.
따라서 배포 스크립트를 작성할 때 그 경로를 고려해서 작성해야 한다. 또 하나 주의할 점은 배포 스크립트에서 docker-compose 로 정의한 컨테이너를 실행 시킬 때, 서비스 이름으로 실행시키기 때문에 컨테이너 이름이랑 서비스 이름이랑 잘 구분해서 스크립트를 작성해야 한다. (난 그냥 컨테이너 이름이랑 서비스 이름을 통일 시키긴 했다..🐒)
⚡️ 미니 트러블 슈팅
컨테이너 모두 잘 실행이 되었지만, 포트 매핑 방식에 대해서 헷갈린 탓에 리액트 애플리케이션으로 접속이 안되는 이슈가 있었다.
도커 컨테이너로 실행 된 리액트 애플리케이션이 3000 -> 80 포트로 매핑된 것때문에 해당 컨테이너를 3000으로 접근해야 한다고 잘 못 생각하고 있던 것이다. nginx 설정에서 컨테이너를 3000포트로 upstream 했더니 계속해서 접속이 실패하였다.
때리액트 애플리케이션을 도커 이미지로 빌드할 때, nginx 가 리스닝할 port 를 80 으로 expose 했기 때문에 ec2 내에 nginx 컨테이너가 리액트 애플리케이션 정적파일을 서빙한 nginx 에 접근하려면 80 포트로 접근 해야했다 ! !
업스트림 설정에서 포트를 80 으로 변경해준 뒤 깃허브 액션을 실행시켰더니 도커 컨테이너도 잘 뜨고, 도메인으로 접속도 잘 된다 ! !
끝으로.. 🧚
하나의 인스턴스에서 여러개의 서비스를 실행할 수 있는 환경이 필요했기 때문에 docker 와 docker-compose 를 이용해서 필요한 컨테이너들을 실행시키고 연결해보면서 배포를 진행 해보았다.
이번 배포를 통해서 도커와 도커 컴포즈의 네트워크 연결 방식, docker-compose.yml 으로 컨테이너를 관리하는 방법 대해서 더 깊게 이해할 수 있었다.
그리고 네임서버와 도메인 관련 지식을 이해할 수 있는 좋은 기회가 되었다. 도메인과 네임서버가 어떻게 연결되고, DNS(Domain Name System)가 인터넷상의 주소 해석에 어떻게 중요한 역할을 하는지에 대해 더 잘 알게 되었다.
추후에는 롤백도 할 수 있게 수정할 예정이다! 그리고 아직 health check API 를 구현하지 못해서 그 부분도 추가할 예정이다.
스프링부트 배포하고 연결은 다음 포스팅으루...🦿
https://olrlobt.tistory.com/82