현재 진행 중인 프로젝트는 Github Actions를 활용해 배포 과정을 자동화하였다.
on:
workflow_dispatch:
branches:
- develop
jobs:
docker-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: DockerHub Login
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Gradle Caching
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build Gradle
run: ./gradlew clean bootJar -PSERVER_URL=${{ secrets.SERVER_URL }}
- name: Docker Build
run: docker build --build-arg PROFILE=dev -t 도커허브ID/이미지:latest .
- name: Docker Push
run: docker push 도커허브ID/이미지:latest
보통 PR이 Merge될 때 마다 동작하게 할 수 있으나 사실 코드의 변경이 드물어서 그냥 직접 실행시킬 수 있는 workflow_dispatch 기능을 사용했다.
프로젝트 저장소의 Actions 메뉴에서 직접 실행할 수 있다. 완전 자동화 한 것은 아닐수도..
도커허브 로그인 → jar 빌드 → 도커 이미지 빌드 → 이미지 push 순으로 진행된다.
deploy:
runs-on: self-hosted
needs: docker-build
steps:
- name: Docker Pull & Run
run: |
docker pull 도커허브ID/이미지:latest
docker stop server || true
docker container prune -f
docker run -d --name server -p 8080:8080 --network redis-network \
-e DB_PATH=${{secrets.DB_PATH}} \
-e DB_PASSWORD=${{secrets.DB_PASSWORD}} \
-e JWT_SECRET=${{secrets.JWT_SECRET}} \
-e ALLOWED_ORIGINS=${{secrets.ALLOWED_ORIGINS}} \
...
도커허브ID/이미지:latest
그 다음 self-hosted runner를 통해 서버가 실행되는 환경에 접속한다.
원래는 서버에서 run.sh를 실행해야 연결이 되는데, run.sh를 nohup 명령어로 백그라운드에서 돌려놔서 Action이 작동할 때 마다 바로바로 실행이 된다.
프로젝트 저장소 → Settings → Secrets and variables → Actions
Repository secrets에 필요한 만큼 환경변수를 저장해놓고 ${{secrets.환경변수명}}
이런식으로 사용할 수 있다.
- name: DockerHub Login
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
이렇게 빌드 과정에 필요한 환경변수는 바로 가져와 사용하였다.
도커 컨테이너 실행 시 필요한 환경변수를 어떻게 전달할 지 고민이 많았다.
- -e 옵션으로 환경변수 직접 전달
- --env-file 옵션으로 파일 사용
- ?
1번 방법과 Github Actions의 secrets를 활용해 환경변수를 전달하는 방법을 선택했었다.
하지만 기능이 추가되면서 환경변수가 점점 많아지자 일일이 전달하는 방법이 비효율적이라고 느껴졌고, 코드가 지저분해졌다..
환경변수가 담긴 파일을 사용하기 위해 모든 -e 옵션을 삭제하고 --env-file ./.env
을 추가했다.
조금 번거로운 점은 서버에 직접 원격 접속해 env파일을 생성해야 한다는 것이다. 이 작업도 자동화를 할 수 있을 것 같기도 하다.
.env파일에 모든 환경변수 정보를 저장한 다음 workflow를 실행시킨 결과
예상했던 대로 경로가 잘못 설정되었는지 .env파일을 찾을 수 없었다.
self-hosted runner가 명령어를 실행하는 위치를 확인하기 위해 pwd
명령어를 임시로 스크립트 파일에 추가한 결과
경로를 확인할 수 있었다.
이후 mv .env 확인한 경로
mv 명령어로 .env파일을 명령어가 실행되는 위치로 옮겼다.
그 결과 컨테이너가 정상적으로 실행된 것을 확인할 수 있었다.