TeamGuu / teamguu-backend

University Teamguu project API server
0 stars 0 forks source link

Procedure for deploy #54

Open Minuooooo opened 1 year ago

Minuooooo commented 1 year ago

지금까지 삽질하면서 얻은 배포 과정을 정리해보려고 합니다 앞으로 이 문서를 많이 참고하셨으면 좋겠네요 수정할 사항이 있으면 마음대로 수정하셔도 됩니다 이제 마감 기간도 얼마 남지 않았습니다 조금만 같이 화이팅 해봅시다!!

Minuooooo commented 1 year ago

제가 지금까지 경험한 배포 과정을 정리해서 설명하자면,

**1. EC2 배포 전 초기 세팅

  1. Local: 이미지 build & push
  2. EC2: 이미지 pull & 배포
  3. HTTPS 적용**

이와 같이 순차적으로 설명하겠습니다

Minuooooo commented 1 year ago

1. EC2 배포 전 초기 세팅

  1. 시스템 패키지 최신화 및 필요 패키지 설치

    sudo apt-get update, upgrade
    sudo apt install zip, git, docker, docker-compose  // zip 설치했는데 Sdkman 실행 시 unzip 필요하다면 설치
  2. Sdkman 접속 및 JDK 설치

    curl -s "https://get.sdkman.io/" | bash → Enter the sdkman (To download JDK)`
    source "$HOME/.sdkman/bin/sdkman-init.sh”
    sdk version  // check sdk version
    sdk list java  // JDK List
    sdk install java “version”  // install JDK
  3. 도커 컴포즈 관련 파일 직접 추가 sudo vi docker-compose.yml, .env

Minuooooo commented 1 year ago

2. Local: 이미지 build & push

  1. Jar 파일 생성 ./gradlew clean build

  2. mysql, redis 이미지 생성 후 이미지 이름 변경 (app은 처음부터 원하는 이름으로 생성) docker tag <기존의 이미지 이름> <도커 허브 사용자명>/<리포지토리 이름>:<태그> // 태그 생략 시 latest

  3. 이미지 build & push

    docker login
    docker push <도커 허브 사용자명>/<리포지토리 이름>:<태그>  // 이미지 하나만 push
    docker-compose push  // 도커 컴포즈에 정의된 이미지 모두 push
    docker-compose -f docker-compose-prod.yml push
Minuooooo commented 1 year ago

3. EC2: 이미지 pull & 배포

  1. docker-compose.yml, .env 파일 등이 수정되었을 경우 vi docker-compose.yml, .env

  2. 컨테이너 & 이미지 삭제

    sudo docker ps -a  // 도커 컨테이너 정보 조회
    sudo docker stop <컨테이너 이름 또는 ID>
    sudo docker rm <컨테이너 이름 또는 ID>  // app 컨테이너만 삭제 권장
    sudo docker images  // 도커 이미지 정보 조회
    sudo docker rmi <이미지 이름>  // app 이미지만 삭제 권장
  3. 이미지 pull

    sudo docker pull <도커 허브 사용자명>/<리포지토리 이름>:<태그>
    sudo docker-compsoe pull  // 도커 컴포즈에 정의된 이미지 모두 pull
    sudo docker-compose -f docker-compose-prod.yml pull
  4. 컨테이너 실행

    sudo docker-compose up
    sudo docker-compose -f docker-compose-prod.yml up
    sudo docker-compose -f docker-compose-prod.yml up -d  // 백그라운드 환경에서 실행

2~4 과정은 자동화를 필요로 합니다 Github Actions CI/CD 활용을 우선적으로 하죠

Minuooooo commented 1 year ago

4. HTTPS 적용

  1. 도메인 DNS 레코드에 EC2 탄력적 IP와 연결하여 2개 추가

    도메인
  2. Certbot 위한 repository (저장소) 추가 sudo add-apt-repository ppa:certbot/certbot

  3. Certbot의 Nginx 패키지 설치

    sudo apt install python-certbot-nginx
    sudo apt install -y certbot python3-certbot-nginx  // 위의 명령어가 안될 경우
  4. Nginx Configuration 설정 sudo vim /etc/nginx/sites-available/default // Nginx 설정 파일

    Untitled (6) Untitled (7)
  5. 변경 후 테스트 sudo nginx -t

  6. 설정 파일 적용 sudo systemctl reload nginx

  7. 방화벽 HTTPS 허용 sudo ufw status // Status: inactive

  8. SSL 인증서 받기 sudo certbot --nginx -d 도메인 -d www.도메인

  9. 해당 링크에서 도메인 서버 테스트 => 오류가 난다면 EC2 인바운드 규칙 재설정 https://www.ssllabs.com/ssltest/

  10. Certbot 자동 갱신 확인 ※ Let's Encrypt 인증서는 90일 동안만 유효, 90일 마다 갱신 필요 ※ /etc/cron.d 경로에 자동으로 갱신 시켜주는 커맨드 존재 ※ 갱신 프로세스가 잘 동작하는지 테스트 sudo certbot renew --dry-run

  11. Nginx & Spring Boot 연결을 위한 location 설정

    server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name [teamguu.o-r.kr](http://teamguu.o-r.kr/) [www.teamguu.o-r.kr](http://www.teamguu.o-r.kr/);
    
    location / {
        proxy_pass <http://localhost:8080>; # 스프링 애플리케이션으로 프록시
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    
    location /api {  # Swagger
        proxy_pass <http://localhost:8080/api>; # 스프링 애플리케이션의 /api로 프록시
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    # 나머지 설정 내용...
    }
Minuooooo commented 1 year ago

일단 지금까지 경험한 배포 과정을 직접 정리해보았습니다 앞으로 더 알게 된 사실이 있다면 코멘트 달고 이 문서에 적용하겠습니다😁

Minuooooo commented 1 year ago

EC2에 배포할 때 저희는 원래 git clone 하여 프로젝트를 가져왔습니다 하지만 제가 테스트 해본 결과, 도커 이미지에는 application.yml, secure.properties를 비롯한 스프링 앱을 구성하는 요소를 모두 포함하고 있었습니다 그렇다면 저희는 이제 배포할 때, 도커 이미지만 있다면 docker-compose.yml, .env 만 추가해도 깔끔하게 실행할 수 있다는 결론입니다!!!

weejinyoung commented 1 year ago

오우 미친 정리 감사합니다 다른것도 마찬가지지만 제가 인프라 쪽은 특히 쥐약인데 덕분에 많은 정보 얻어갑니다 민우씨 이정도면 데브옵스 노려봄직 하다고 봅니다 파멸적인 성장곡선 부럽습니다 민우씨가 피땀흘려 정리한 것들 보면서 민우씨 쫙 따라가보도록 하겠습니다

weejinyoung commented 1 year ago
name: deploy

on:
  push:
    branches:
      - master

permissions:
  contents: read

jobs:
  build:

    runs-on: ubuntu-latest

    - name: Grant execute permission for gradlew
      run: chmod +x gradlew

    - name: Build with Gradle
      run: ./gradlew clean build 

    - name: image build
      run: |
        docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
        docker-compose -f docker-compose-prod.yml build 
        docker push ${{ secrets.DOCKER_USERNAME }}/teamguu_app:latest

    - name: Deploy
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.HOST }} # EC2 인스턴스 퍼블릭 DNS
        username: ubuntu
        key: ${{ secrets.PRIVATE_KEY }} # pem 키
        # 도커 작업
        script: | 
            sudo docker stop ubuntu_app_1 ubuntu_redis_1
            sudo docker rm ubuntu_app_1
            sudo docker rmi minuooooo/teamguu_app
            sudo docker pull minuooooo/teamguu_app
            sudo docker-compose -f docker-compose-prod.yml up -d