์ธํ๋ผ ๊ตฌ์ถ์ ์ฐธ ์ฝ์ง ์๋ค. ์ธํ๋ผ ๊ณต๋ถ๋ ๋๋์ฑ ์ด๋ ค์ด ๊ฒ ๊ฐ๋ค.
๋ฌด์๋ณด๋ค ์ค์ต์ ํ๋ ค๋ฉด ๋น์ฉ์ด ์ฐธ ๋ง์ด ๋ ๋ค.
ํ์ง๋ง, ์ํํ ๊ฐ๋ฐ์ ์ํด์๋ ์๋ ๋ฐฐํฌ๋ฅผ ๊ตฌ์ถํด์ผ์ง๋ง, ์๋น์ค ๊ฐ๋ฐ์๋ง ์ง์คํ ์ ์๋ค.
๊ทธ๋์ ๋ฐฑ์๋ ๊ฐ๋ฐ์๋ ์๋ฒ ๊ฐ๋ฐ ๋ฅ๋ ฅ ์ด์ธ์, ์ด๋ ์ ๋ ์ธํ๋ผ ๊ตฌ์ถ ๋ฐ ํ๊ฒฝ์ ๋ํ ๊ฐ๋ ์ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฌํด์ผ ๋๋ค๊ณ ์๊ฐํ๋ค.
์ด๋ฒ์ ์ฌ์ด๋ ํ๋ก์ ํธ ๊ธฐํ ๋ฐ ์ธํ๋ผ ๊ตฌ์ถ์ ํด์ผ๋ ์ผ์ด ์๊ฒผ๋ค.
์ด๋ป๊ฒ ์ต๋ํ ์ฝ๊ณ ๋น ๋ฅด๊ฒ ๊ตฌ์ถํ ์ง ๊ณ ๋ฏผ์ ํด๋ต๋ค.
์ด ์ ์๋ jar ํ์ผ์ ๊ทธ๋๋ก ์คํํ๊ธฐ ์ํด AWS EC2 ์ธ์คํด์ค์ ๊ณ ๋๋ก ๋ก์ปฌ๊ณผ ๋น์ทํ ํ๊ฒฝ์ ๊ตฌ์ฑํด ๋๊ณ , yaml ๋ ๊ทธ๋๋ก ๋ฃ์ด๋๊ณ , ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ์๋ํ๋ค. Ubuntu ์๋ฒ์์ ํ ๊ฒ ์ฐธ ๋ง์๋ค.
๋์ปค๋ฅผ ๊ณต๋ถํ๊ณ , ์ฌ์ฉํด๋ณด๋ฉด์ EC2 ์ ์ง์ ์ ์ธ ํ๊ฒฝ ๊ตฌ์ถ ๋์ ์ด ๋์ปค๋ฅผ ์จ๋ณด๋ฉด ์ด๋จ๊น ํ๋ ์๊ฐ์ด ๋ค์๋ค.
๊ทธ๋์ ๊ณ ๋ฏผ ๊ณผ์ ๋ฐ ๊ฒฐ๊ณผ๋ฅผ ๋์ดํด๋ณด๊ฒ ๋ค.
์๊ฐํ ํ๋ก์ฐ
- Github actions ๋ก CI ์งํ
- Github actions ๋ก Docker image (Spring boot application) ์์ฑ ํ Docker hub ์ ํธ์,
- Docker hub ์ ์ต์ image ๊ฐ ํธ์๋ ๊ฒฝ์ฐ, EC2 ์์ ์ด๋ฅผ ๊ฐ์ง, Docker hub ์์ pull ๋ฐ์์ docker image run
์ด๊ฒ ๋์ด๋ค.
ํ์ง๋ง, ์ต์ ์ด๋ฏธ์ง๊ฐ ํ๋ธ์ ์ฌ๋ผ๊ฐ๋ค๋ ๊ฒ์ EC2 ์์ ์ด๋ป๊ฒ ๊ฐ์งํ์ง?
๋ค Shell Script ๋ก ์ง์ผ ํ๋ (๋์ปค ํ๋ธ์ ์ ์ํด์ ์ต์ ์ด๋ฏธ์ง๊ฐ ์์ผ๋ฉด ์ฐพ๊ณ , pull ๋ฐ์์ run)
์๊ฐ๋ง ํด๋ ๋ง๋งํ๋ค.
๋์์ ์ป๊ณ ์, ๋๋ณด๋ค ๊ฒฝ๋ ฅ ์๋ ์ฃผ๋ณ ์ง์ธ๋ค๊ป ๋ด๊ฐ ์๊ฐํ ์๋ ๋ฐฐํฌ ํ๋ก์ฐ๋ฅผ ์ค๋ช ๋๋ ธ๋ค.
์๋..??
Github actions ๋ก ์ถฉ๋ถํ ๋ค ๊ฐ๋ฅํ๋จ๋ค.
์ญ์๋ ๋๊ตฐ๊ฐ ๋ง๋ค์ด ๋์ Github Actions ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋ค.
์ฐธ ์ธ์ ํธํ๋ค..
https://github.com/appleboy/ssh-action
GitHub - appleboy/ssh-action: GitHub Actions for executing remote ssh commands.
GitHub Actions for executing remote ssh commands. Contribute to appleboy/ssh-action development by creating an account on GitHub.
github.com
์ด apple boy ๋ฅผ ์ด์ฉํ๋ฉด, ์ถฉ๋ถํ ๊ฐ๋ฅํ๋ค.
๊ตณ์ด ์ต์ docker image ์๋ ๊ฐ์ง๋ ๋ญ๋, shell ์ ์งค ํ์๊ฐ ์๋ค.
Github actions ์์ฑํ๊ธฐ
ํ๋ !!
- AWS EC2 ์ธ์คํด์ค๋ ์ด๋ฏธ ๋ง๋ค์ด์ (๋๋ Ubuntu 22.4) ์คํ์ค์ด๋ผ๊ณ ๊ฐ์ ํ๊ณ ์งํํ๊ฒ ๋ค.
- spring boot application ๋ ์ด๋ฏธ ๋ง๋ค์ด์ก๋ค๊ณ ์๊ฐํ๋ฉด ๋๋ค.
- docker hub ์ repository ๋ ์ด๋ฏธ ๋ง๋ค์๋ค๊ณ ์๊ฐํ๋ฉด ๋๋ค.
name: deploy
on:
push:
branches: [ "master" ]
jobs:
deploy:
name: spring boot server ci-cd
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Build
run: ./gradlew build -x test
- name: Test
#run: ./gradlew asciidoctor
run: echo 'empty test'
# ๋์ปค๋ฅผ ํ๋ธ์ ๋ก๊ทธ์ธ ํ๊ธฐ, docker hub username ๊ณผ token ์ด ํ์ํ๋ค.
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# Jib ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ, docker file, docker compose ๋ฅผ ์ง์ ์์ฑํ ํ์๊ฐ ์์ด ์๋์ผ๋ก ๋ง๋ค์ด ์ฃผ๊ณ , docker hub ์ push ๊น์ง ํด์ค๋ค..
- name: Jib
env:
DOCKERHUB_REPOSITORY_PATH: ${{ secrets.DOCKERHUB_REPOSITORY_PATH }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
run: ./gradlew jib -x test
-Djib.to.image=$DOCKERHUB_REPOSITORY_PATH
-Djib.to.tags=latest
-Djib.container.creationTime=USE_CURRENT_TIMESTAMP
-Djib.container.environment=SLACK_WEB_HOOK_URL=$SLACK_WEBHOOK_URL
-Djib.container.jvmFlags=-XX:MaxRAMPercentage=30.0,-XX:MinRAMPercentage=30.0,-Duser.timezone=Asia/Seoul,-Dspring.profiles.active=dev
# ์ง๊ธ ์คํ์ค์ธ github actions ํ๊ฒฝ์ ip ๋ฅผ ๋ฐ์จ๋ค.
- name: Get Github action IP
id: ip
uses: haythem/public-ip@v1.2
# ๋ฐ์จ github actions ip ๋ฅผ ๋ฐฐํฌํ EC2 ์ ๋ณด์ ๊ทธ๋ฃน์ ์ถ๊ฐํ๋ AWS CLI ์คํ.
- name: Add Github Actions IP to Security group
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}
run: |
aws ec2 authorize-security-group-ingress --group-id ${{ secrets.AWS_Security_Group_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32
# apple boy ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ด์ฉ, EC2 ์ ์ง์ ์ ์ํด์, docker hub ์ push ๋ spring boot image ๋ฅผ pull ๋ฐ๊ณ ์์ฑ๋ docker compose ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์คํํ๋ค.
- name: spring boot server deploy
uses: appleboy/ssh-action@master
env:
DOCKERHUB_REPOSITORY_PATH: ${{ secrets.DOCKERHUB_REPOSITORY_PATH }}
with:
host: ${{ secrets.REMOTE_IP }}
username: ${{ secrets.REMOTE_EC2_NAME }}
key: ${{ secrets.REMOTE_SSH_KEY }}
script: |
cd ~/app
sudo docker-compose down --rmi all
sudo docker-compose up -d
# docker ์ปจํ
์ด๋๊ฐ ์ ์ ์คํ๋๋ฉด, ๋ณด์ ๊ทธ๋ฃน์ ์ถ๊ฐํ๋ github actions ip ๋ฅผ ์ญ์ ํ๋ค.
- name: Remove Github Actions IP from security group
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}
run: |
aws ec2 revoke-security-group-ingress --group-id ${{ secrets.AWS_Security_Group_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32 > /dev/null
if: always()
# ์ด๊ฑด ์์ ์ง๋ง, slack ์๋ฆผ๋ ๋ฐฐํฌ ์ฑ๊ณต ์ฌ๋ถ์ ๋ฐ๋ผ ์ค๊ฒ ํ ์ ์๋ค.
- name: Slack notification
uses: 8398a7/action-slack@v3
with:
username: github action
status: ${{ job.status }}
author_name: Github Action
fields: repo,message,commit # repo,message,commit,author,action,eventName,ref,workflow,job,took
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
if: always()
์ด๊ฑธ .github ํด๋ ์์ ๋ฃ์ด์ฃผ์.
์์ ${{secrets.~~~}} ๋ก ๋์ด ์๋ ๊ฑด github secret ํ๊ฒฝ ๋ณ์์ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค.
- AWS_ACCESS_KEY : AWS iam ์ฌ์ฉ์ access key
- AWS_SECRET_ACCESS_KEY : iam ์ฌ์ฉ์ secret key
- REMOTE_IP : EC2 ํผ๋ธ๋ฆญ ip
- REMOTE_EC2_NAME : ๋๋ ubuntu ์ด๋ฏ๋ก, ubuntu ๋ผ ์ ์ผ๋ฉด ๋จ. (ssh ์ ์ ํ ๋, ~~@ํผ๋ธ๋ฆญip ์ด๋ ๊ฒ ์ ์ ๋, ์ด ๋ฌผ๊ฒฐ ์ด๋ฆ์.)
- REMOTE_SSH_KEY : EC2 ์์ฑํ ๋, ๋ณดํต pem ํค ๋ฐ๊ธ ๋ฐ๋ ๊ทธ๊ฑฐ์.
- ๋๋จธ์ง snake ์ผ์ด์ค ์๋ ๋ณ์๋ค์, github actions ์์ ์ ๊ณตํ๋ ๋ณ์๋ค์ด๋ค.
EC2 ์์ ํด์ผํ ๊ฒ.
์ผ๋จ EC2 ์ ์ ์ํด๋ณด์์.
๊ทธ๋ฆฌ๊ณ , app ์ด๋ผ๋ ๋๋ ํฐ๋ฆฌ๋ฅผ ๋ง๋ค์ด๋ผ.
ํ์ํ๋ฉด ์๋๋๋ก, log ๋๋ ํฐ๋ฆฌ๋ ๋ง๋ค์ด๋ผ.
๊ทธ๋ฆฌ๊ณ docker-compose.yml ์ ์์ฑํ์.
### docker-compose.yml
version: "3.7"
services:
attieadconfig:
container_name: springbootapp
image: {์ด๋ฏธ์ง ๊ฒฝ๋ก ์ ๊ธฐ}:latest
ports:
- 80:8080
deploy:
resources:
limits:
cpus: '0.30'
memory: 700m
logging:
driver: "json-file"
options:
max-file: "3"
max-size: "10m"
volumes:
- ~/app/logs:/logs
๊ทธ๋ฆฌ๊ณ ์คํ
github actions ๊ฐ ์คํ๋๊ณ ,
๋ฐฐํฌ๊ฐ ์๊ณตํ๋ค๋ฉด ์๋ ๋ฐฐํฌ๊ฐ ์ข ๋ฃ๋์๋ค.
๋ณดํต ์๋ฌ๋ apple boy ์คํ ์์ ํฐ์ง ๊ฒ์ด๋ค.
๊ทธ๋ ์์ ์ฌ๋ ค๋์๋, apple boy github README ๋ฅผ ์ ์ฝ์ด๋ณด๋ฉด, ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์์ธํ ์ ํ์์ ๊ฒ์ด๋ค.
๋์ ๊ฒฝ์ฐ๋, authorized keys ์์ ๊ถํ์ ์ฃผ์ด ํด๊ฒฐํ๋ ๊ธฐ์ต์ด ์๋ค.
๊ทธ๋ผ ๊ตฌ์ถ๋ ์๋ ๋ฐฐํฌ๊ฐ ๋ ๋ ํ ๋ท๋ฐ์นจ ๋์์ผ๋,
์ฆ๊ฑฐ์ด ๊ฐ๋ฐ์ ์งํํด๋ณด์~~!