이번 시간에는 GitHub Action과 Docker를 사용한 CD를 구축하겠습니다.
Deploy는 EC2 Linux 서버에 진행됩니다.
하나의 서버에 각 Micro Service Container를 띄우는 형식의 MSA를 구축할 것이므로 앞단에 SSL(TLS)을 적용하고 각 컨테이너에 요청을 분배하는 무언가를 붙여야되지만, 우선 사용자 애그리거트를 개발할 예정이므로 다른 것은 신경쓰지 않고 User Micro Server를 띄우는 것을 목표로 합니다!
Secret에는 Docker Hub 계정 정보, EC2 정보가 필요합니다.
따라서 Secret에 해당 정보들을 추가합니다.
Docker를 이용한 CD를 구축할 것이므로 Docker Hub의 계정 정보를 입력하고, EC2 서버의 Host와 pem key를 저장합니다.
EC2 서버에선 Docker Hub를 통해 Pull 받아 이미지를 저장하고 docker-compose up 하기위해 Docker와 docker-compose를 설치합니다.
# Docker 설치
sudo yum install docker -y
# Docker 권한 추가
sudo chmod 666 /var/run/docker.sock
# docker-compose 설치
sudo curl \
-L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/bin/docker-compose
# docker-compose 권한 추가
sudo chmod +x /usr/local/bin/docker-compose
그리고 docker-compose.yml을 작성해줍니다.
우선 Reach Rich의 사용자 MS, MySQL, Redis를 설정해줍니다.
version: '3.7'
volumes:
reach-rich-user-mysql-volume:
external: true
reach-rich-redis-volume:
external: true
networks:
redis-network:
driver: bridge
external: true
services:
mysql:
container_name: reach-rich-user-mysql
image: mysql:latest
ports:
- 3306:3306
volumes:
- reach-rich-user-mysql-volume:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: [비밀번호]
redis:
container_name: reach-rich-redis
hostname: reach-rich-redis
image: redis:latest
command: redis-server --port 6379
ports:
- 6379:6379
volumes:
- reach-rich-redis-volume:/data
networks:
- redis-network
spring:
container_name: reach-rich-user
image: [CD 과정에서 Push할 Docker Hub Repository]
expose:
- 8080
위 과정에서 Volume과 Network가 이미 존재한 상태라면 에러가 발생하여 생성되지 않은채로 컨테이너가 띄워질 수 있으므로, 이미 있는 경우 external 옵션을 추가합니다.
Spring Application을 이미지로 빌드하기 위한 dockerfile을 작성합니다.
FROM openjdk:11
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
간단한 설명을 덧붙이자면,
과 같습니다.
이제 CD 스크립트를 작성할 차례입니다.
CI 스크립트를 작성했던 것처럼 Yaml 파일을 추가합니다.
name: CD
on:
push:
branches: [ "develop" ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
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: Config File Write
run: |
# main 설정 파일 디렉토리로 이동
cd ./src/main/resources
# application-mysql.yml
touch ./application-mysql.yml
echo "${{secrets.CI_APPLICATION_MYSQL}}" >> ./application-mysql.yml
# application-redis.yml
touch ./application-redis.yml
echo "${{ secrets.CI_APPLICATION_REDIS }}" >> ./application-redis.yml
shell: bash
- name: Gradle Build
run: ./gradlew bootJar
- name: Build Docker Image
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -t ${{ secrets.DOCKER_USERNAME }}/reach-rich-user .
docker push ${{ secrets.DOCKER_USERNAME }}/reach-rich-user
- name: Docker Pull & Compose Up
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ec2-user
key: ${{ secrets.KEY }}
script: |
docker rm -f $(docker ps -qa)
docker rmi ${{ secrets.DOCKER_USERNAME }}/reach-rich-user
docker pull ${{ secrets.DOCKER_USERNAME }}/reach-rich-user
docker-compose up -d
CD 과정은 CI 과정에서 추가적으로 jar로 빌드하여 Docker Image로 Push하고 EC2에서 해당 Image를 Pull 받아 docker-compose up을 백그라운드로 수행하는 과정이 추가됩니다.
길었던 과정을 마치고 develop에 Push or Merge하여 동작 테스트를 해봅시다!
GitHub Action이 성공적으로 수행된 것을 확인할 수 있습니다.
EC2에 들어가 확인해보면...
우선 모든 컨테이너가 잘 실행된 것을 확인할 수 있습니다.
마지막으로 Spring Application 컨테이너의 로그를 확인하면
성공적인 Run을 확인할 수 있습니다.
이제 어느정도 개발 환경 구축이 끝났으니, 본격적인 Spring Security와 Redis Session을 사용한 로그인/회원가입(인증/인가)를 개발할 예정입니다.
혼자서 서버 구축에 대한 모든 것을 해내려니 힘이 들지만... 그만큼 재밌기도 하네요ㅎㅎ (퇴근하고 플젝하면 언제 쉬지...? 😂)