반응형

프로젝트를 시작할 때마다, 가장 먼저하는 CI/CD 설정이다.

기존에는 대부분 Jenkins를 통해 CI/CD 설정을 했었지만, 이번 프로젝트는 별도의 서버를 구성할 여유가 없어 Github에서 제공하는 Github action을 통해 설정을 해보려고 한다.

 

우선 Github의 리포지토리에서 actions 탭을 클릭한다.

그러면 이런 식으로 페이지가 나올텐데, 여기에 gradle을 검색한다.

 

그리고 이 action을 configure해준다.

 

이거 클릭하면 코드의 .github 폴더에 yml 파일이 생길텐데, 해당 파일을 수정해주면 된다.

 

크게 build와 deploy로 나뉜다.

build는 Gradle을 바탕으로 spring을 빌드하는 부분이고, deploy는 빌드된 jar파일을 서버로 전송하여 배포하는 부분이다.

 

name: CI/CD for develop branch

on:
  push:
    branches: [ "develop" ]
  pull_request:
    branches: [ "develop" ]
  workflow_dispatch:
    

jobs:
  build:

    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
    - uses: actions/checkout@v4
    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        java-version: '17'
        distribution: 'temurin'
    - name: Setup Gradle
      uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582

    - name: Grant execute permission for gradlew
      run: chmod +x ./gradlew
      working-directory: ./WAS

    - name: Build with Gradle Wrapper
      run: ./gradlew build
      working-directory: ./WAS
      
    - name: Scp to EC2
      uses: appleboy/scp-action@master
      with:
        host: ${{ secrets.SERVER_IP }}
        username: ${{secrets.SSH_USER}}
        key: ${{secrets.SSH_PRIVATE_KEY}}
        source: |
          WAS/build/libs/{빌드된 파일 이름}.war
        target: was/
      
  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Setup SSH
        uses: webfactory/ssh-agent@v0.5.4
        with:
          ssh-private-key: ${{secrets.SSH_PRIVATE_KEY}}
          
      - name: Deploy Docker Container
        run: |
          ssh -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SERVER_IP}} << 'EOF'
          cd was
          docker stop {컨테이너 이름} && docker rm {컨테이너 이름} && docker rmi {이미지 이름}:latest
          docker build -t {이미지 이름} .
          docker-compose up -d
          EOF

 

우선 작성한 파일은 다음과 같다.

 

step에서 하나씩 뜯어보도록 하자.

  • build
    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        java-version: '17'
        distribution: 'temurin'
    - name: Setup Gradle
      uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582

이 부분은 자바와 gradle을 준비하는 부분이다.

큰 이상이 없다면 아마 고정적으로 사용할 것 같다.

 

    - name: Grant execute permission for gradlew
      run: chmod +x ./gradlew
      working-directory: ./WAS

    - name: Build with Gradle Wrapper
      run: ./gradlew build
      working-directory: ./WAS

이 부분은 빌드하는 부분이다.

gradlew에 실행 권한을 부여하고, ./gradlew build를 통해 스프링부트를 빌드한다.

만약 테스트와 관련된 명령어가 있다면, 이곳에 추가하면 된다.

 

아래를 보면 working-directory가 설정되어 있는 것을 볼 수 있는데, 만약 빌드하는 폴더가 루트 폴더가 아니라면 해당 명령어를 통해 폴더를 지정해주어야 한다.

 

    - name: Scp to EC2
      uses: appleboy/scp-action@master
      with:
        host: ${{ secrets.SERVER_IP }}
        username: ${{secrets.SSH_USER}}
        key: ${{secrets.SSH_PRIVATE_KEY}}
        source: |
          WAS/build/libs/{빌드된 파일}.war
        target: was/

이제 빌드된 jar(war) 파일을 서버로 전송하는 부분이다.

당연히 서버의 ip, 사용자 이름, pem 키가 필요하다.

이런 부분은 yml 파일에 작성할 수 없기 때문에, 해당 Repository의 설정에 환경변수로 추가해주도록 하자.

 

pem키를 환경변수로 추가할 때는 위, 아래 boundary까지 그냥 추가해주면 된다.

source는 빌드된 파일(결과물)이고, target은 해당 서버에서 어떤 폴더에 저장할 것인지를 적어주면 된다.

 

이렇게 작성하면 빌드 후, 파일이 서버에 저장되게 된다.

그럼 이제 해당 파일을 통해 배포를 설정해주어야 한다.

 

 

  • deploy

해당 jar 파일을 docker container를 통해 실행해보자.

 

    needs: build

needs에 build를 추가해서, 해당 작업이 build 이후에 이루어질 수 있도록 해준다.

 

 

      - name: Setup SSH
        uses: webfactory/ssh-agent@v0.5.4
        with:
          ssh-private-key: ${{secrets.SSH_PRIVATE_KEY}}

서버에서 사용할 pem키를 등록해준다.

 

      - name: Deploy Docker Container
        run: |
          ssh -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SERVER_IP}} << 'EOF'
          cd was
          docker stop {컨테이너 이름} && docker rm {컨테이너 이름} && docker rmi {이미지 이름}:latest
          docker build -t {이미지 이름} .
          docker-compose up -d
          EOF

 

그리고는 이제 원격 서버에 접속해 해당 파일을 바탕으로 도커를 빌드한다.

원격 서버에서 추가적으로 실행하고 싶은 부분이 있다면, 저 안에 추가해주면 된다.

 

이제 작성이 모두 완료되었으니, 실행해보도록 하자.

위의 on에 workflow_dispatch:를 지정해주면 직접 실행 할 수도 있다.

 

 

이렇게 초록색으로 체크표시가 된다면 성공한 것이다.

서버에서도 배포가 완료된 것을 확인 할 수 있었다.

'틔움랩' 카테고리의 다른 글

Spring에서 DeepL API를 사용해 문서를 번역하기  (0) 2025.02.27
MockBean deprecated와 대체  (0) 2025.01.28
반응형

저번에는 Docker를 사용하지 않고, 그냥 ubuntu 서버에서 빌드하고 실행해서 Swagger를 proxy 했었다.

 

이번에는 Docker를 사용해보려고 한다.

우선 Docker가 설치되어 있어야 하고, Docker-compose도 설치가 되어 있어야 한다.

 

  • Nginx

우선 nginx의 config 파일이다.

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

    location /auth/ {
    		proxy_pass http://auth-server:8080/;
    		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;

    		proxy_set_header X-Forwarded-Prefix /auth;
    	}

    location /chat/ {
    		proxy_pass http://chat-server:12041/;
    		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;

    		proxy_set_header X-Forwarded-Prefix /chat;
    }

    location /writing/ {
        		proxy_pass http://writing-server:12042/;
        		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;

        		proxy_set_header X-Forwarded-Prefix /writing;
        }


    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

 

당연히 저번과 다른 것은 없다.

 

이거를 Docker 컨테이너에 있는 Nginx에도 넣어줘야 하기 때문에, 일단 파일로 작성하여 nginx/config 폴더에 default.con라는 이름으로 저장해둔다.

 

  • SpringBoot

이제 스프링부트의 Dockerfile을 만들어보자.

 

build 한 빌드 파일을 도커의 볼륨에 넣고, 실행하여 배포하면 된다.

 

FROM openjdk:17-jdk

CMD ["./gradlew", "clean", "build", "-x", "test"]

VOLUME /auth

ARG JAR_FILE=build/libs/auth-0.0.1-SNAPSHOT.war

COPY ${JAR_FILE} auth.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "/auth.jar"]

 

openjdk:17을 가져와서

기본 실행 폴더를 /auth로 지정하고 빌드 폴더에 있는 war 파일을 가져가서 실행하면 된다.

 

이 부분은 어렵지 않기 때문에 바로 넘어가겠다.

 

  • docker-compose

가장 루트 폴더에 docker-compose.yml이다.

이곳에 의존성과 각 이미지를 빌드하는 설정들을 명시하면 된다.

 

version: '3'

services:
  auth-server:
    container_name: auth-server
    build: ./auth
    ports:
      - "8080:8080"
    networks:
      - cobo
  chat-server:
    container_name: chat-server
    build: ./chat
    ports:
      - "12041:12041"
    networks:
      - cobo
  writing-server:
    container_name: writing-server
    build: ./writing
    ports:
      - "12042:12042"
    networks:
      - cobo

  nginx:
    build: ./nginx
    image: nginx:stable-perl
    ports:
      - "80:80"
    volumes:
      - ./nginx/config/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - auth-server
      - chat-server
      - writing-server
    networks:
      - cobo

networks:
  cobo:

 

services에서 각 폴더에 있는 Dockerfile을 이용해 이미지를 생성하며 네트워크는 cobo라는 동일한 네트워크를 사용해, 각 컨테이너끼리 통신할 수 있도록 한다.

 

그리고 Nginx의 구성파일을 Nginx 컨테이너의 /etc/nginx/conf.d에 넣어줘야 하는데

가지고 있는 default.conf 파일을 volumes로 해서 마운트해줘, 해당 파일을 우리가 작성한 파일로 변경해주면 된다.

 

'크무톡톡 프로젝트' 카테고리의 다른 글

SpringBoot 시간 설정  (0) 2024.08.09
JPA Soft Delete  (0) 2024.08.06
JDBC ON DUPLICATE KEY UPDATE  (0) 2024.07.29
JUnit을 Kotlin으로 테스트 할 때 beforeAll, AfterAll  (0) 2024.07.26
카카오 Oauth 로그인, SpringBoot  (0) 2024.07.25

+ Recent posts