
๐ก ๋ชฉํ
CI/CD ์๋ํ๋ฅผ ํตํด main ๋ธ๋์น๋ก Pull Request ๊ฐ ์ด๋ฃจ์ด์ง๋ฉด ์๋์ผ๋ก ๋ฐฐํฌ๊น์ง ๋๋๋ก ์ค์ ํ๊ณ ์ ํ๋ค.
DockerFile
FROM amazoncorretto:17-alpine-jdk
EXPOSE 8080
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
Github Actions ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ Docker File ์ ๋ง๋ค์ด์ค๋ค.
CICD.yml
name: CI/CD
on:
pull_request:
branches: ["main"]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Build with Gradle
run: |
chmod +x ./gradlew
./gradlew clean build -x test
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build Docker Image
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1 .
- name: Push Docker Image
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy to Server
uses: appleboy/ssh-action@master
with:
username: ubuntu
host: ${{ secrets.SSAKTIUM_SERVER_IP }}
key: ${{ secrets.EC2_SSH_KEY }}
script_stop: true
script: |
# Pull the latest image from DockerHub
sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1
# Stop and remove the existing container if it exists
if [ "$(sudo docker ps -q -f name=daegyuhan-ssak)" ]; then
sudo docker stop daegyuhan-ssak
fi
if [ "$(sudo docker ps -aq -f status=exited -f name=daegyuhan-ssak)" ]; then
sudo docker rm daegyuhan-ssak
fi
# Run the new container with the .env file for environment variables
sudo docker run -d --name daegyuhan-ssak --env-file /home/ubuntu/.env -p 8080:8080 ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1
์ด๋ฒคํธ๊ฐ ์ผ์ด๋ฌ์ ๋ ์๋์ผ๋ก ์คํ๋๋ ๊ฒ์ด ํธ๋ฆฌ๊ฑฐ.
main ๋ธ๋์น์ pull request ๊ฐ ์ผ์ด๋๋ฉด ์ด ํ์ผ์ ์คํํ๊ฒ ๋ค๋ ๋ป์ด๋ค.
๐ก Work Flow ๋ถ์: Build
jobs:
build:
runs-on: ubuntu-latest
runs on : ubuntu ์ต์ ๋ฒ์
๊ฐ์์ pc ๊ฐ ์คํ๋ ํ ๋ฐ ์ค์ ํด์ฃผ๋ ๊ฒ
ubuntu ๊ฐ ๊ฐ์ฅ ๊ฐ๋ณ๊ณ ๋ณดํธ์ ๊ณ ์๋ฒ๋ก ๋ง์ด ์ฌ์ฉ๋จ
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Build with Gradle
run: |
chmod +x ./gradlew
./gradlew clean build -x test
steps:
๋จ์๋ name ์ผ๋ก ๋์ด์ ์คํํ๋ค.
uses:
github action ์ ํ ํ๋ฆฟ์ด ๋ช ๊ฐ์ง ์๋ค.
์ด ๋ ํฌ์งํ ๋ฆฌ์ pull request ๊ฐ ์ผ์ด๋๋ฉด checkout, ์๋์ผ๋ก ํจ์นํ๊ณ ํ ํ๊ฒ ๋ค๋ ๋ป์ด๋ค.
ubuntu ์๋ค๊ฐ ์๋์ผ๋ก git ์ค์นํ๊ณ repository ๋ฅผ pull ํ๋ ๊ณผ์ ์ ๋ค ์๋ตํด์ฃผ๋ ํธํ ๊ธฐ๋ฅ์ด๋ค.
install JDK 17
clean ํ๊ณ build ๋๋ฅด๋ฉด jar ํ์ผ ๋ง๋ค์ด์ง๋๋ฐ jar ํ์ผ์ด ์์ด์ผ์ง ๋ค๋ฅธ ํ๊ฒฝ์์ ์คํ์ ํ ์ ์๋ค.
์ด jar ํ์ผ์ ๊ฐ์ง๊ณ docker ๋ฅผ ์คํ์ํฌ ๊ฒ์ธ๋ฐ ๊ทธ๋ ๊ฒ ํ๊ธฐ ์ํด์
- name: Build with Gradle
run: |
chmod +x ./gradlew
./gradlew clean build -x test
clean, build ์์ ์ ์งํํ๋ค.
์ด๋ฌ๋ฉด jar ํ์ผ์ด ๋ง๋ค์ด์ง๋ค.
์ง๊ธ ๋จ๊ณ์์ ํ ์คํธ์ฝ๋๊ฐ ์์ฑ์ด ์๋์ด์๊ธฐ ๋๋ฌธ์ -x test ๋ฅผ ํตํด test ์ฝ๋ ์คํ์ ์คํตํด์ฃผ์๋ค.
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build Docker Image
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1 .
- name: Push Docker Image
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1
build ๋ฅผ ํตํด ๋ง๋ jar ํ์ผ์ Docker ์ด๋ฏธ์ง๋ก ๋ง๋ค๊ณ Docker Hub ์ ์ฌ๋ฆฌ๊ธฐ ์ํด์ Docker Hub ์ ๋ก๊ทธ์ธ์ ํด์ผํ๋ค.
์ดํ์ Docker Hub ์ ์ฌ๋ ค์ง ์ด ์ด๋ฏธ์ง ํ์ผ์ EC2 ์ ์ ์ํด ๋ค์ด๋ฐ๊ฒ ํ๊ธฐ ์ํจ์ด๋ค.
github ํํ์ด์ง์์ ์ค์ ํ ํ๊ฒฝ๋ณ์๋ฅผ ํ์ฉํด์ ํด๋น ์ด๋ฆ์ผ๋ก ์ด๋ฏธ์ง๋ฅผ ๋ง๋ค๊ณ ,
๊ทธ ์ด๋ฏธ์ง๋ฅผ Docker Hub ์ push ๋ฅผ ํ๋ค.
Repository Secrets ์ค์ ํ๊ธฐ


์ด๋ ๊ฒ ์ ๋ณด๋ค์ ๋ค ๋ฃ์ด์ค๋ค.

๊ทธ๋ผ ํด๋น secrets ์ ๊ฐ์ ๋ฃ์ ์ ์๋ค.
๐ก Work Flow ๋ถ์: Deploy
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy to Server
uses: appleboy/ssh-action@master
with:
username: ubuntu
host: ${{ secrets.SSAKTIUM_SERVER_IP }}
key: ${{ secrets.EC2_SSH_KEY }}
script_stop: true
script: |
# Pull the latest image from DockerHub
sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1
# Stop and remove the existing container if it exists
if [ "$(sudo docker ps -q -f name=daegyuhan-ssak)" ]; then
sudo docker stop daegyuhan-ssak
fi
if [ "$(sudo docker ps -aq -f status=exited -f name=daegyuhan-ssak)" ]; then
sudo docker rm daegyuhan-ssak
fi
# Run the new container with the .env file for environment variables
sudo docker run -d --name daegyuhan-ssak --env-file /home/ubuntu/.env -p 8080:8080 ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1
deploy ํ๊ฒฝ์์๋ build ์ ๋ง์ฐฌ๊ฐ์ง๋ก ubuntu ํ๊ฒฝ์์ ์์ ํ๋ค.
EC2 ์ ์ ์ํ๊ธฐ ์ํด์ ํด๋น IP ์ SSH_KEY ๋ฅผ ์ ๋ ฅํ๋ค.
Build ๋จ๊ณ์์ Push ํ๋ Docker ์ด๋ฏธ์ง๋ฅผ Pull ๋ก ๋น๊ฒจ์๋ค.
์ด์ ์ ์คํ๋๊ณ ์๋ ๋์ผํ ์ด๋ฆ์ ์ปจํ ์ด๋๊ฐ ์์ผ๋ฉด ์ถฉ๋์ด ์ผ์ด๋๊ธฐ ๋๋ฌธ์
์กฐ๊ฑด๋ฌธ์ ์ฌ์ฉํด์ ๋ฉ์ถ ํ ์ญ์ ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
# Run the new container with the .env file for environment variables
sudo docker run -d --name daegyuhan-ssak --env-file /home/ubuntu/.env -p 8080:8080 ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1
ํ์๋ EC2 ์ .env ํ์ผ์ ๋ง๋ค์ด์ ํ๋ก์ ํธ yml ํ์ผ์์ ์ฌ์ฉ๋ ํ๊ฒฝ๋ณ์๋ค์ ์ฒ๋ฆฌํ๋ค.
๋๋ฌธ์ ์ปจํ ์ด๋๋ฅผ ์คํ์ํฌ ๋ EC2 ๋ด๋ถ์ .env ๋ฅผ ์ฐธ๊ณ ํด์ ์คํํ ์ ์๋๋ก ์์ ๊ฐ์ด ์ฝ๋๋ฅผ ์ง์คฌ๋ค.
์ด์ ์ ๋ฐํํ๋ CI, CD ์ ๋ํ ๋ด์ฉ๊ณผ ํ์ดํ๋ผ์ธ ๊ตฌ์ถ์ ๋ํด ๊ณต๋ถ๋ฅผ ํ๋ ๋ด์ฉ๋ค์ ์ฐธ๊ณ ํ๋ค.
https://hanstory33.tistory.com/241
[CS] CI ์ CD ๋?
PPT : CI/CD - ํ๋ ์ ํ ์ด์ YOUTUBE : [CS๋ฐํ] CI / CD - YouTube
hanstory33.tistory.com
https://hanstory33.tistory.com/243
[CS] CI/CD ํ์ดํ๋ผ์ธ ๊ตฌ์ถ์ ์ํ ์ดํด
1. CI/CD ๋ ์ธ ๋จ๊ณ๋ฅผ ๊ฐ์ง๋ค. ๊ฐ๋ฐ, ๋น๋, ๋ฐฐํฌ๊ฐ ๋จ๊ณ๋ ํ๋์ ์๋ฒ ๊ฐ๋ ์ด๋ค.2. Jar ํ์ผ ๋น๋ ์์ ์ ๋ํ ๊ณ ๋ฏผ .jar ํ์ผ์ ๋น๋ํด์ผํ๊ธฐ ๋๋ฌธ์ ์ด ๊ณผ์ ์ ๊ฐ๋ฐ ๋จ๊ณ์์ ํฌํจํด์ ๊ฐ์ ธ๊ฐ๋,
hanstory33.tistory.com