diff --git a/backend/infra/backend-deploy.sh b/backend/infra/backend-deploy.sh deleted file mode 100644 index 603bd081..00000000 --- a/backend/infra/backend-deploy.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh - -IS_GREEN=$(docker ps | grep backend-green) # 현재 실행중인 App이 blue인지 확인 - -DEFAULT_CONF="./nginx/default.conf" - -docker-compose up -d nginx -docker-compose up -d redis - -if [ -z $IS_GREEN ];then # blue라면 - echo "### BLUE => GREEN ###" - echo "1. get green image" - docker-compose pull backend-green # 이미지 받아서 - echo "2. green container up" - docker-compose up -d backend-green # 컨테이너 실행 - while [ 1 = 1 ]; do - echo "3. green health check..." - sleep 3 - REQUEST=$(docker exec nginx curl http://backend-green:3001) # green으로 request - if [ -n "$REQUEST" ]; then # 서비스 가능하면 break - echo "health check success" - break ; - fi - done; - sed -i 's/backend-blue/backend-green/g' $DEFAULT_CONF # nginxrk green을 가리키도록 변경 - echo "4. reload nginx" - docker exec nginx service nginx reload - echo "5. blue container down" - docker-compose stop backend-blue -else - echo "### GREEN => BLUE ###" - echo "1. get blue image" - docker-compose pull backend-blue - echo "2. blue container up" - docker-compose up -d backend-blue - while [ 1 = 1 ]; do - sleep 3 - echo "3. blue health check..." - REQUEST=$(docker exec nginx curl http://backend-blue:3001) - if [ -n "$REQUEST" ]; then - echo "health check success" - break ; - fi - done; - sed -i 's/backend-green/backend-blue/g' $DEFAULT_CONF - echo "4. reload nginx" - docker exec nginx service nginx reload - echo "5. green container down" - docker-compose stop backend-green -fi diff --git a/backend/infra/docker-compose.yml b/backend/infra/docker-compose.yml deleted file mode 100644 index 64477753..00000000 --- a/backend/infra/docker-compose.yml +++ /dev/null @@ -1,55 +0,0 @@ -version: '3.7' - -services: - nginx: - image: nginx - container_name: nginx - restart: always - ports: - - '80:80' - volumes: - - ./nginx/:/etc/nginx/conf.d/ - - ./logs/nginx/:/var/log/nginx/ - backend-blue: - image: devrank/backend-api:latest - container_name: backend-blue - restart: always - env_file: - - ./.env - volumes: - - ./logs/nest/:/logs/ - expose: - - 3001 - depends_on: - - redis - backend-green: - image: devrank/backend-api:latest - container_name: backend-green - restart: always - env_file: - - ./.env - volumes: - - ./logs/nest/:/logs/ - expose: - - 3001 - depends_on: - - redis - redis: - image: redis:6.2.5 - command: redis-server - volumes: - - /usr/local/redis/data:/data - ports: - - 6379:6379 - frontend-blue: - image: devrank/frontend:latest - container_name: frontend-blue - restart: always - expose: - - 8080 - frontend-green: - image: devrank/frontend:latest - container_name: frontend-green - restart: always - expose: - - 8080 \ No newline at end of file diff --git a/backend/infra/frontend-deploy.sh b/backend/infra/frontend-deploy.sh deleted file mode 100644 index 75bb6bd3..00000000 --- a/backend/infra/frontend-deploy.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh - -IS_GREEN=$(docker ps | grep frontend-green) # 현재 실행중인 App이 blue인지 확인 - -DEFAULT_CONF="./nginx/default.conf" - -docker-compose up -d nginx - -if [ -z $IS_GREEN ];then # blue라면 - echo "### BLUE => GREEN ###" - echo "1. get green image" - docker-compose pull frontend-green # 이미지 받아서 - echo "2. green container up" - docker-compose up -d frontend-green # 컨테이너 실행 - while [ 1 = 1 ]; do - echo "3. green health check..." - sleep 3 - REQUEST=$(docker exec nginx curl http://frontend-green:8080) # green으로 request - if [ -n "$REQUEST" ]; then # 서비스 가능하면 break - echo "health check success" - break ; - fi - done; - sed -i 's/frontend-blue/frontend-green/g' $DEFAULT_CONF # nginxrk green을 가리키도록 변경 - echo "4. reload nginx" - docker exec nginx service nginx reload - echo "5. blue container down" - docker-compose stop frontend-blue -else - echo "### GREEN => BLUE ###" - echo "1. get blue image" - docker-compose pull frontend-blue - echo "2. blue container up" - docker-compose up -d frontend-blue - while [ 1 = 1 ]; do - sleep 3 - echo "3. blue health check..." - REQUEST=$(docker exec nginx curl http://frontend-blue:8080) - if [ -n "$REQUEST" ]; then - echo "health check success" - break ; - fi - done; - sed -i 's/frontend-green/frontend-blue/g' $DEFAULT_CONF - echo "4. reload nginx" - docker exec nginx service nginx reload - echo "5. green container down" - docker-compose stop frontend-green -fi - \ No newline at end of file diff --git a/backend/yarn.lock b/backend/yarn.lock index 6ee1c280..b7dbeab7 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -3111,9 +3111,9 @@ cookie@^0.4.1: integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== cookiejar@^2.1.3: - version "2.1.3" - resolved "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz" - integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== + version "2.1.4" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" + integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== core-util-is@~1.0.0: version "1.0.3" @@ -4681,9 +4681,9 @@ json-stable-stringify-without-jsonify@^1.0.1: integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json5@^2.1.2, json5@^2.2.1: - version "2.2.1" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonc-parser@3.1.0: version "3.1.0" @@ -4891,9 +4891,9 @@ lru_map@^0.3.3: integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== luxon@^1.23.x: - version "1.28.0" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.0.tgz#e7f96daad3938c06a62de0fb027115d251251fbf" - integrity sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ== + version "1.28.1" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.1.tgz#528cdf3624a54506d710290a2341aa8e6e6c61b0" + integrity sha512-gYHAa180mKrNIUJCbwpmD0aTu9kV0dREDrwNnuyFAsO1Wt0EVYSZelPnJlbj9HplzXX/YWXHFTL45kvZ53M0pw== macos-release@^2.5.0: version "2.5.0" diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 5cf2b89b..8b476d1c 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -8473,9 +8473,9 @@ json-stable-stringify-without-jsonify@^1.0.1: integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json5@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" @@ -12245,9 +12245,9 @@ typescript@4.8.4: integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== ua-parser-js@^0.7.30: - version "0.7.32" - resolved "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.32.tgz" - integrity sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw== + version "0.7.33" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532" + integrity sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw== uglify-js@^3.1.4: version "3.17.4" diff --git a/infra/README.md b/infra/README.md index 76bc863b..d9ed8abb 100644 --- a/infra/README.md +++ b/infra/README.md @@ -1,7 +1,39 @@ ## 실행 방법 -1. infra 디렉토리 내에 서버측 .env파일을 생성 -2. nginx/default.conf에 SSL 인증서 경로 설정 -3. hooks.json의 경로를 수정 -4. hooks.service를 등록 -5. initial-deploy.sh 실행 -6. 이후에는 github Repository의 Main 브랜치에 Merge가 발생하면 자동으로 배포가 됩니다 \ No newline at end of file + +### 기본적으로 docker가 설치되어 있어야합니다. + +1. infra 디렉토리 내에 서버측 .env파일을 생성합니다. +2. 아래와 같이 docker를 이용해서 SSL 인증서 생성합니다.(서드도메인까지 모두 만들어줘야합니다) [참고](https://lynlab.co.kr/blog/72) + +```bash +sudo docker run -it --rm --name certbot \ + -v '/etc/letsencrypt:/etc/letsencrypt' \ + -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \ + certbot/certbot certonly -d '도메인이름' --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory +``` + +3. nginx/default.conf를 아래와 같이 수정합니다. + + - server_name을 도메인에 맞게 수정 + - SSL 인증서 경로 설정 + + > 현재는 dreamdev.me, api.dreamdev.me로 설정되어 있습니다. + +4. hooks.json 파일을 아래와 같이 수정합니다. + - `command-working-directory`를 infra폴더 경로로 수정 + - `execute-command`를 해당 폴더의 backend-deploy.sh, frontend-deploy.sh로 수정 +5. hooks.service를 등록합니다. [참고](https://118k.tistory.com/1055) +6. initial-deploy.sh 실행하면 배포가 완료됩니다. +7. 이후에는 github Repository의 Main 브랜치에 Merge가 발생하면 자동으로 배포가 됩니다! + +- 추가적으로 서버 인스턴스가 변경되었다면 dockerHub에서 웹훅설정을 변경해야합니다! + +8. 추가적으로 ssl 인증서를 자동 갱신하도록 cron을 등록하시면 편리합니다! +``` +#!/bin/bash + +docker run -it --rm --name certbot \ + -v '/etc/letsencrypt:/etc/letsencrypt' \ + -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \ + certbot/certbot renew --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory +``` diff --git a/infra/nginx/default.conf b/infra/nginx/default.conf index 5aacb927..b7f18780 100644 --- a/infra/nginx/default.conf +++ b/infra/nginx/default.conf @@ -1,3 +1,11 @@ +upstream frontend{ + server frontend-blue:8080; +} + +upstream backend{ + server backend-blue:3001; +} + server { listen 80; @@ -10,8 +18,8 @@ server { listen 443 ssl; server_name api.dreamdev.me; - ssl_certificate /etc/letsencrypt/live/dreamdev.me/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/dreamdev.me/privkey.pem; + ssl_certificate /etc/letsencrypt/live/api.dreamdev.me/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/api.dreamdev.me/privkey.pem; location / { proxy_pass http://backend; @@ -38,4 +46,4 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } -} \ No newline at end of file +} diff --git a/infra/renew.sh b/infra/renew.sh new file mode 100644 index 00000000..f08c6b04 --- /dev/null +++ b/infra/renew.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +docker run -it --rm --name certbot \ + -v '/etc/letsencrypt:/etc/letsencrypt' \ + -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \ + certbot/certbot renew --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory