지속적 통합, 지속적 배포 ‐ (2) EC2 설정 (with.Docker, Nginx) - ttasjwi/board-system GitHub Wiki

EC2 접속

# board-system
Host board-system
  HostName 13.209.85.239
  User ubuntu
  IdentityFile ~/.ssh/board-system.pem
  • config 파일을 별도로 만들고 ~/.ssh 폴더에 두기
    • Host board-system : board-system 이름을 식별명으로 지정
    • HostName: 주소
    • User: 사용자인데 ubuntu 로 해야함
    • IdentifyFile: pem 파일 경로
ssh board-system

EC2 설정

date # 시간대 확인
timedatectl list-timezones | grep Seoul # timedatectl 의 timezone 에 Asia/Seoul 이 있는 지 확인
sudo timedatectl set-timezone Asia/Seoul # 시간대 변경
date # 한국 시간대가 잘 뜨는 지 확인

도커 설치

sudo apt-get update && \
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common && \
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && \
sudo apt-key fingerprint 0EBFCD88 && \
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" && \
sudo apt-get update && \
sudo apt-get install -y docker-ce && \
sudo usermod -aG docker ubuntu && \
newgrp docker && \
sudo curl -L "https://github.com/docker/compose/releases/download/2.37.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \
sudo chmod +x /usr/local/bin/docker-compose && \
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
docker -v # Docker 버전 확인
docker compose version # Docker Compose 버전 확인

Nginx 컨테이너 구성

docker pull nginx

# nginx 이름의 컨테이너를 실행해라 / 백그라운드에서 / 외부 80번 포트 - 내부 80 포트 / nginx 이미지로
docker run --name nginx -d -p 80:80 nginx

# bash 쉘로 nginx 컨테이너 접속
docker exec -it nginx bash

Nginx 설정

# vim 설치
apt update
apt upgrade -y
apt install vim -y
cd etc/nginx/conf.d
vim default.conf

Nginx 설정파일 수정

# 로드밸런싱 그룹 - blue 그룹 (세미콜론 써야함 주의)
upstream blue {
  server (e2-private-ip):8081;
}

# 로드밸런싱 그룹 - green 그룹
upstream green {
  server (e2-private-ip):8082;
}

server {
  include /etc/nginx/conf.d/service-env.inc;

  location / {
    proxy_pass http://$service_url;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    }
}
  • upstream 설정 부분
    • 로드밸런싱 그룹을 설정하는 부분이다.
    • 우리는 blue, greene 그룹을 설정했고 각 그룹에 한대의 서버들만 뒀다.
    • nginx 서버 입장에서는 blue, green 서버의 주소를 모르므로 이를 ec2의 private ip 기준으로 하여 잡아줬다.
  • server 설정
    • include : 외부 설정파일을 설정에 포함
      • 여기에 $service_url 변수값 설정을 두고 향후 동적으로 blue, green 값을 변경해가면서 블루그린 배포를 가능하게 할 예정
    • location / : / (루트) 로 들어온 요청을 어떻게 처리할 지 설정하는 부분
      • proxy_pass 설정 : 요청을 대상 서버로 포워딩 시킨다.
      • proxy_set_header : 대상 서버에 보낼 때 헤더 추가 설정
        • X-Real-IP : 클라이언트의 실제 IP 주소
        • X-Forwarded-For : 클라이언트 ip 주소 및 경유한 프록시 ip 주소들…
        • Host: 대상 서버 url
vim service-env.inc
set $service_url green;
  • 여기까지 하면 80번 포트로 들어온 요청은 향후 외부에서 설정값을 바꿀 때마다 blue, green 으로 대상서버를 바꿔가면서 요청을 포워딩시킬 수 있게 된다.

docker-compose 파일 두기(EC2에)

# nginx 컨테이너에서 빠져나오기
exit
vim docker-compose-blue.yml
version: "3.8"
services:
  blue:
    image: ttasjwi/board-be:latest
    container_name: blue
    ports:
      - "8081:8080"
    volumes:
      - "./keys:/app/keys"
    environment:
      - SERVER_PROFILE=blue
      - DATABASE_URL=${DATABASE_URL}
      - DATABASE_USERNAME=${DATABASE_USERNAME}
      - DATABASE_PASSWORD=${DATABASE_PASSWORD}
      - REDIS_HOST=${REDIS_HOST}
      - REDIS_PORT=${REDIS_PORT}
      - MAIL_HOST=${MAIL_HOST}
      - MAIL_PORT=${MAIL_PORT}
      - MAIL_USERNAME=${MAIL_USERNAME}
      - MAIL_PASSWORD=${MAIL_PASSWORD}
      - GOOGLE_OAUTH2_CLIENT_ID=${GOOGLE_OAUTH2_CLIENT_ID}
      - GOOGLE_OAUTH2_CLIENT_SECRET=${GOOGLE_OAUTH2_CLIENT_SECRET}
      - GOOGLE_OAUTH2_REDIRECT_URI=${GOOGLE_OAUTH2_REDIRECT_URI}
      - GOOGLE_OAUTH2_SCOPE=${GOOGLE_OAUTH2_SCOPE}
      - NAVER_OAUTH2_CLIENT_ID=${NAVER_OAUTH2_CLIENT_ID}
      - NAVER_OAUTH2_CLIENT_SECRET=${NAVER_OAUTH2_CLIENT_SECRET}
      - NAVER_OAUTH2_AUTHORIZATION_GRANT_TYPE=${NAVER_OAUTH2_AUTHORIZATION_GRANT_TYPE}
      - NAVER_OAUTH2_REDIRECT_URI=${NAVER_OAUTH2_REDIRECT_URI}
      - NAVER_OAUTH2_SCOPE=${NAVER_OAUTH2_SCOPE}
      - KAKAO_OAUTH2_CLIENT_ID=${KAKAO_OAUTH2_CLIENT_ID}
      - KAKAO_OAUTH2_CLIENT_SECRET=${KAKAO_OAUTH2_CLIENT_SECRET}
      - KAKAO_OAUTH2_REDIRECT_URI=${KAKAO_OAUTH2_REDIRECT_URI}
      - KAKAO_OAUTH2_SCOPE=${KAKAO_OAUTH2_SCOPE}
      - RSA_ACCESS_TOKEN_PUBLIC_KEY_PATH=file:/app/keys/access-token_public-key.pem
      - RSA_ACCESS_TOKEN_PRIVATE_KEY_PATH=file:/app/keys/access-token_private-key.pem
      - RSA_REFRESH_TOKEN_PUBLIC_KEY_PATH=file:/app/keys/refresh-token_public-key.pem
      - RSA_REFRESH_TOKEN_PRIVATE_KEY_PATH=file:/app/keys/refresh-token_private-key.pem
vim docker-compose-green.yml
version: "3.8"
services:
  blue:
    image: ttasjwi/board-be:latest
    container_name: green
    ports:
      - "8082:8080"
    volumes:
      - "./keys:/app/keys"
    environment:
      - SERVER_PROFILE=green
      - DATABASE_URL=${DATABASE_URL}
      - DATABASE_USERNAME=${DATABASE_USERNAME}
      - DATABASE_PASSWORD=${DATABASE_PASSWORD}
      - REDIS_HOST=${REDIS_HOST}
      - REDIS_PORT=${REDIS_PORT}
      - MAIL_HOST=${MAIL_HOST}
      - MAIL_PORT=${MAIL_PORT}
      - MAIL_USERNAME=${MAIL_USERNAME}
      - MAIL_PASSWORD=${MAIL_PASSWORD}
      - GOOGLE_OAUTH2_CLIENT_ID=${GOOGLE_OAUTH2_CLIENT_ID}
      - GOOGLE_OAUTH2_CLIENT_SECRET=${GOOGLE_OAUTH2_CLIENT_SECRET}
      - GOOGLE_OAUTH2_REDIRECT_URI=${GOOGLE_OAUTH2_REDIRECT_URI}
      - GOOGLE_OAUTH2_SCOPE=${GOOGLE_OAUTH2_SCOPE}
      - NAVER_OAUTH2_CLIENT_ID=${NAVER_OAUTH2_CLIENT_ID}
      - NAVER_OAUTH2_CLIENT_SECRET=${NAVER_OAUTH2_CLIENT_SECRET}
      - NAVER_OAUTH2_AUTHORIZATION_GRANT_TYPE=${NAVER_OAUTH2_AUTHORIZATION_GRANT_TYPE}
      - NAVER_OAUTH2_REDIRECT_URI=${NAVER_OAUTH2_REDIRECT_URI}
      - NAVER_OAUTH2_SCOPE=${NAVER_OAUTH2_SCOPE}
      - KAKAO_OAUTH2_CLIENT_ID=${KAKAO_OAUTH2_CLIENT_ID}
      - KAKAO_OAUTH2_CLIENT_SECRET=${KAKAO_OAUTH2_CLIENT_SECRET}
      - KAKAO_OAUTH2_REDIRECT_URI=${KAKAO_OAUTH2_REDIRECT_URI}
      - KAKAO_OAUTH2_SCOPE=${KAKAO_OAUTH2_SCOPE}
      - RSA_ACCESS_TOKEN_PUBLIC_KEY_PATH=file:/app/keys/access-token_public-key.pem
      - RSA_ACCESS_TOKEN_PRIVATE_KEY_PATH=file:/app/keys/access-token_private-key.pem
      - RSA_REFRESH_TOKEN_PUBLIC_KEY_PATH=file:/app/keys/refresh-token_public-key.pem
      - RSA_REFRESH_TOKEN_PRIVATE_KEY_PATH=file:/app/keys/refresh-token_private-key.pem