-
1. CI/CD ๊ธฐ๋ณธ ๊ฐ๋ / Github Actions ๊ธฐ๋ณธ ๊ฐ๋
-
1. CI/CD
-
2. Github Actions
-
3. Github Actions ๋ฌธ๋ฒ
-
2. ๋ฐฑ์๋(Spring Boot) ํ๋ก์ ํธ์ CI/CD ์ ์ฉํ๊ธฐ
-
1. Github Actions: ๊ฐ์ธ ํ๋ก์ ํธ
-
์ค์ต
-
2. Github Actions, SCP: ์ผ๋ฐ ํ๋ก์ ํธ
-
์ค์ต
-
3. Code Deploy: ํ์ฅ์ฑ ๊ณ ๋ คํ ํ๋ก์ ํธ
-
CodeDeploy ์ธํ / IAM ์ค์
-
-
์ค์ต
1. CI/CD ๊ธฐ๋ณธ ๊ฐ๋ / Github Actions ๊ธฐ๋ณธ ๊ฐ๋
1. CI/CD
- Continuous Integration, Continuous Deployment
- ๋ฐฐ์ฐ๋ ์ด์
- ์๋น์ค ์ด์ ์ ์๋ก์ด ๊ธฐ๋ฅ ํ์
- ์ด์ ๋ฐ๋ผ, ์ฝ๋ ์์ฑ -> Commit -> Merge -> ๋ฐฐํฌ
- ๋งค์ฐ ๊ท์ฐฎ๋ค -> ์ด๋ฐ ๋ฐ๋ณต์ ์ธ ๊ณผ์ ์ ์๋ํ

2. Github Actions
- ์ ๋ฒ์ ์ ํจ์ค๋ฅผ ํ์ฉํ์๋๋ฐ, ์ด๋ฒ์๋ Github Actions๋ฅผ ๊ณต๋ถํด๋ณด์
- https://koreatstm.tistory.com/140
- ๋ก์ง์ ์คํ์ํฌ ์ ์๋ ์ผ์ข ์ ์ปดํจํฐ
- ์ ํจ์ค์ ๊ฒฝ์ฐ, ๋ณ๋ ์๋ฒ๊ฐ ํ์ํ์ง๋ง, Github Actions๋ ์๋ฒ ๊ตฌ์ถ ์์ด ๋ด์ฅ๋ Github Actions ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
- ๋น์ฉ๋ ์ข๊ณ , ์ ํ ํ๋๋ฐ ์๊ฐ๋ ์ ์ฝ
- CI/CD ํ๋ฆ๋

- ์ฝ๋ ์์ฑ ํ Commit
- Github์ Push
- Push๋ฅผ ๊ฐ์งํ์ฌ Github Actions์ ์์ฑํ ๋ก์ง ์คํ
- ๋น๋
- ํ ์คํธ
- ๋ฐฐํฌ
- ์๋ฒ์์ ๋ฐฐํฌ๋ ์ต์ ์ฝ๋๋ก ์๋ฒ ์ฌ์คํ
3. Github Actions ๋ฌธ๋ฒ
- ์ ํ๋ก์ ํธ ํด๋ ๋ง๋ค๊ธฐ
- .github/workflows/deploy.yml ๋ง๋ค๊ธฐ
# Workflow์ ์ด๋ฆ
# Workflow : ํ๋์ yml ํ์ผ์ ํ๋์ Workflow๋ผ๊ณ ๋ถ๋ฅธ๋ค.
name: Github Actions ์คํ์์ผ๋ณด๊ธฐ
# Event : ์คํ๋๋ ์์ ์ ์ค์
# main์ด๋ผ๋ ๋ธ๋์น์ push ๋ ๋ ์๋ Workflow๋ฅผ ์คํ
# ์ง๊ธ์ 1๊ฐ์ Job์ผ๋ก ์งํํ๊ฒ ๋ค.
on:
push:
branches:
- main
# ํ๋์ Workflow๋ 1๊ฐ ์ด์์ Job์ผ๋ก ๊ตฌ์ฑ๋๋ค.
# ์ฌ๋ฌ Job์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ณ๋ ฌ์ ์ผ๋ก ์ํ๋๋ค.
jobs:
# ์๋๋ Job์ ์๋ณํ๊ธฐ ์ํ id
My-Deploy-Job:
# ๊นํ๋ธ ์ก์
๋ ํ๋์ ์ปดํจํฐ. ์ด๋, Github Actions๋ฅผ ์คํ์ํฌ ์๋ฒ ์ข
๋ฅ ์ ํ
runs-on: ubuntu-latest
# Step : ํน์ ์์
์ ์ํํ๋ ๊ฐ์ฅ ์์ ๋จ์
# Job์ ์ฌ๋ฌ Step๋ค๋ก ๊ตฌ์ฑ๋์ด ์๋ค.
steps:
- name: Hello World ์ฐ๊ธฐ # ํด๋น Step์ ์ด๋ฆ ๋ถ์ด๋ ๊ธฐ๋ฅ
run: echo "Hello World" # ์คํ์ํฌ ๋ช
๋ น์ด ์์ฑ
- name: ์ฌ๋ฌ ๋ช
๋ น์ด ๋ฌธ์ฅ ์์ฑํ๊ธฐ # "|"๋ฅผ ์ถ๊ฐํ๊ณ ์
๋ ฅํ๋ฉด ๋๋ค.
run: |
echo "Good"
echo "Morning"
- name: Github Actions ์์ฒด์ ์ ์ฅ๋์ด ์๋ ๋ณ์ ์ฌ์ฉํด๋ณด๊ธฐ
run: |
echo $GITHUB_SHA #commit์ ID๊ฐ
echo $GITHUB_REPOSITORY #github repository ๊ฐ
- name: Github Actions Secret ๋ณ์ ์ฌ์ฉํด๋ณด๊ธฐ
run: |
echo ${{ secrets.MY_NAME }}
echo ${{ secrets.MY_HOBBY }}
- ์ฃผ์์
- .github/workflows ๋๋ ํฐ๋ฆฌ์ .yml or .yaml ํ์ฅ์๋ก ํ์ผ ์์ฑ
- .github/workflows๋ ํ๋ก์ ํธ ํด๋์ ์ต์๋จ์ ์์ฑ

- Github Repository ๋ง๋ค๊ณ ์ ๋ก๋
$ git init
$ git add .
$ git commit -m "first commit"
$ git branch -M main
$ git remote add origin {Repository ์ฃผ์}
$ git push -u origin main



- Github Actions Secret ๋ณ์ ์ฌ์ฉํด๋ณด๊ธฐ



- Github Actions ์ ์ฒด ๊ตฌ์กฐ
- Event๋ฐ์ -> workflow์คํ -> workflow๋ job์ผ๋ก ์ด๋ฃจ์ด์ง -> job์ step์ผ๋ก ์ด๋ฃจ์ด์ง
์ฐธ๊ณ
https://docs.github.com/ko/actions
2. ๋ฐฑ์๋(Spring Boot) ํ๋ก์ ํธ์ CI/CD ์ ์ฉํ๊ธฐ
- 3๊ฐ์ง ๋ฐฉ๋ฒ ์กด์ฌ
- Github Actions: ๊ฐ์ธ ํ๋ก์ ํธ
- Github Actions, SCP: ์ผ๋ฐ ํ๋ก์ ํธ
- Code Deploy: ํ์ฅ์ฑ ๊ณ ๋ คํ ํ๋ก์ ํธ
1. Github Actions: ๊ฐ์ธ ํ๋ก์ ํธ
- ์ ์ฒด ํ๋ฆ

- ์ฅ์
- git pull ์ฌ์ฉํ์ฌ ๋ณ๊ฒฝ๋ ๋ถ๋ถ์ ๋ํด์๋ง ์ ๋ฐ์ดํธ -> CI/CD ์๋ ๋น ๋ฅด๋ค
- CI/CD ํด๋ก Github Actions๋ง ์ฌ์ฉ -> ์ธํ๋ผ ๊ฐ๋จ
- ๋จ์
- ๋น๋๋ฅผ EC2์์ ์งํ -> ์๋ฒ ์ฑ๋ฅ์ ์ํฅ ๊ฐ๋ฅ
- Github๊ณ์ ์ ๋ณด๊ฐ EC2์ ์ ์ฅ -> ๋ณด์๋ฌธ์
- ์ฌ์ฉ
- ๊ฐ์ธ ํ๋ก์ ํธ์์ ์ฃผ๋ก ์ฌ์ฉ
์ค์ต
- ๊ฐ๋จํ ์คํ๋ง๋ถํธ ํ๋ก์ ํธ ์์ฑ
- Github์ ํ๋ก์ ํธ ์ฌ๋ฆฌ๊ธฐ
- Github์ Repository๋ฅผ ๋ง๋ ๋ค.
- Github Repository์ ํ๋ก์ ํธ ์ฝ๋๋ฅผ ์ฌ๋ฆฐ๋ค.
$ cd instagram-server
$ git init
$ git add .
$ git commit -m "first commit"
$ git branch -M main
$ git remote add origin _______
$ git push -u origin main
- EC2 ๊ตฌ์ฑ
- EC2๋ฅผ ๊ตฌ์ฑํ๋ค
- ๋ณด์๊ทธ๋ฃน 8080 ํฌํธ ์ด๊ธฐ
- JDK ์ค์น
- ํ๋ก์ ํธ ๋ค์ด
- ํด๋ก ๋ฐ์ ์๋ฒ ์๋ ํ์ธ


#JDK ์ค์น
$ sudo apt update && /
sudo apt install openjdk-17-jdk -y
$ java -version # ์ ์ค์น๋๋ ์ง ํ์ธ
# ํ๋ก์ ํธ ๋ค์ด
$ git clone {git repository clone ์ฃผ์}
# ํด๋ก ๋ฐ์ ์๋ฒ ์๋ ํ์ธ
$ cd {ํ๋ก์ ํธ ๊ฒฝ๋ก}
$ ./gradlew clean build
$ cd build/libs
$ nohup java -jar ________.jar &
$ sudo lsof -i:8080 # 8080๋ฒ ํฌํธ์ Spring Boot๊ฐ ์คํ๋๊ณ ์๋ ์ง ํ์ธ
- ์ด๋ ๊นํ๋ธ ํด๋ก ๋ฐ์ ๋ id,pw๊ฐ ํ์ํ๋ฐ pw๋ ์๋ ๋ธ๋ก๊ทธ ์ฐธ๊ณ !!
- https://velog.io/@nara7875/github-ํ ํฐ-๋ฐ๊ธํ๊ธฐ


- ์ด๋ฒ์ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ๊ณ ์ ๋๋ ํ์ธํด๋ณด์
- ์ค์ ์ฝ๋ ์
๋ฐ์ดํธ ํ์ธ
- ์ ์ฝ๋ ์์ฑ
- Github์ Git Push
- EC2์์ Git Pull
- ๋น๋ ํ ์ฌ๋ฐฐํฌ
- ์๋์ ๊ฐ์ด Hello -> Hi๋ก ๋ฐ๊พธ๊ณ ๋ค์ ๊นํ๋ธ ์ฌ๋ฆฌ๊ณ ์งํ
package com.example.instgram_server;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AppController {
@GetMapping
public String hello() {
return "Hi World!";
}
}
# EC2์์ Git Pull
$ cd {ํ๋ก์ ํธ ๊ฒฝ๋ก}
$ git pull origin main
# ๋น๋ ํ ์ฌ๋ฐฐํฌ
$ sudo lsof -i:8080 # 8080๋ฒ ํฌํธ์ Spring Boot๊ฐ ์คํ๋๊ณ ์๋ ์ง ํ์ธ
$ sudo fuser -k -n tcp 8080 # 8080๋ฒ ํฌํธ์ ์คํ๋๊ณ ์๋ ํ๋ก์ธ์ค ์ข
๋ฃ
$ ./gradlew clean build #~/instagram-serverํด๋์์ ์คํํด์ผํ๋ค.
$ cd build/libs
$ nohup java -jar ________.jar &

- Github ๊ณ์ ์ ๋ณด ๋ฐ๋ณต ์
๋ ฅ ๊ณผ์ ์ญ์
- ์ต์ด ํ๋ฒ๋ง ์์ฑํ๊ณ ๊ทธ ์ดํ๋ ์ ๋ ฅ์๋๊ฒ ํ์
- ~/.git-credentials์ ๋ก๊ทธ์ธ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ ๋ฐฉ์์ผ๋ก ์ด๋ EC2 ์ ๊ทผํ๋ ๋ชจ๋ ์ฌ์ฉ์๊ฐ ๊นํ๋ธ ์ ๋ณด๋ฅผ ๋ณผ ์ ์๋ค.
$ git config --global credential.helper store
$ git pull origin main
# Github ๊ณ์ ๋ฐ ๋น๋ฐ๋ฒํธ ์
๋ ฅ
$ git pull origin main # ๋ ์ด์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ฌป๋ ๊ฑธ ํ์ธํ ์ ์๋ค.

์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก CI/CD ๊ณผ์ ์ ์๋ํ ํด๋ณด์
- ๊ณผ์ ์๋ํ
- .github/workflows/deploy.yml ์์ฑ
- Github์ Secret๊ฐ ๋ฃ๊ธฐ
- Github์์ ๊ฐ์ธ์ ๋ณด์ Settings/Secrets and variables/Actions/Repository secrets์ ๋ฃ๊ธฐ
- Git Push ํ ํ์ธ
name: Deploy To EC2
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: SSH๋ก EC2์ ์ ์ํ๊ธฐ #๊นํ๋ธ์ก์
๋ ํ๋์ ์ปดํจํฐ, ์ด ์ปดํจํฐ์์ EC2๋ผ๋ ์ปดํจํฐ๋ก ์๊ฒฉ ์ ์
uses: appleboy/ssh-action@v1.0.3 #๋ผ์ด๋ธ๋ฌ๋ฆฌ
with: #์๋๋ ์๊ฒฉ ์ ์์ ์ํ ๋ฌธ๋ฒ์ด๋ผ๊ณ ์๊ฐํ์
host: ${{ secrets.EC2_HOST }} # EC2์ ์ฃผ์
username: ${{ secrets.EC2_USERNAME }} # EC2 ์ ์ username
key: ${{ secrets.EC2_PRIVATE_KEY }} # EC2์ Keyํ์ด
script_stop: true # ์๋ script ์ค ์คํจํ๋ ๋ช
๋ น์ด ํ๋๋ผ๋ ์์ผ๋ฉด ์คํจ๋ก ์ฒ๋ฆฌ
script: |
cd /home/ubuntu/instagram-server # ์ฌ๊ธฐ ๊ฒฝ๋ก๋ ์์ ์ EC2์ ๋ง๋ ๊ฒฝ๋ก๋ก ์ฌ์์ฑํ๊ธฐ
git pull origin main
./gradlew clean build
sudo fuser -k -n tcp 8080 || true # || true๋ฅผ ๋ถ์ธ ์ด์ ๋ 8080์ ์ข
๋ฃ์ํฌ ํ๋ก์ธ์ค๊ฐ ์๋๋ผ๋ ์คํจ๋ก ์ฒ๋ฆฌํ์ง ์๊ธฐ ์ํด์์ด๋ค.
# ํ์ค์ถ๋ ฅ -> ์๊น๋ ./output.log 2>&1 ์ด ๋ถ๋ถ ์์ผ๋๋ฐ, ๋ฒ๊ทธ๊ฐ ์์ด์ ๋ณ๊ฒฝํจ
nohup java -jar build/libs/*SNAPSHOT.jar > ./output.log 2>&1 & # jar ํ์ผ์ ์คํ์ํค๋ ๋ช
๋ น์ด์ด๋ค. ๊ทธ๋ฆฌ๊ณ ํ์ผ์ ์ํด ๋ฐ์ํ๋ ๋ก๊ทธ๋ค์ ./output.log ํ์ผ์ ๋จ๊ธฐ๋ ๋ช
๋ น์ด
- ๋งจ์์์ ํ๋ ๊ฐ์ธ์ ๋ณด๋ฅผ ๊นํ๋ธ(Settings/Secrets and variables/Actions/Repository secrets)์ ๋ฃ์ด์ฃผ์




- ๋์ผ๋ก ํ์ธํ๊ธฐ ์ํด์ print๋ฌธ์ yes~ World!๋ก ๋ณ๊ฒฝํ๊ณ ํด๋ณด์


- ๋ฌธ์

- application.yml ํ์ผ ๋ฃ๋ ๊ณผ์ ์๋ํ
- .gitignore์ application.yml ์ถ๊ฐ
- application.yml ํ์ผ ์์ฑ
- Github์ resources ํด๋๊ฐ push ๋๋๋ก ์์์ ํ์ผ ์์ฑ
- Github Actions ์ฝ๋ ์์
- Github์ Secret ๊ฐ ๋ฃ๊ธฐ
- ํ์ธ

# .gitignore
application.yml
# src/main/resources/application.yml
aws:
access-key: ABCDEFG
secret-key: HIJKLMN
#src/main/resources/empty.txt #ํ
์คํธ์ํ ์์์ ํ์คํธ ํ์ผ
~ ๋ด์ฉ ์์ฑ
# .github/workflows/deploy.yml
name: Deploy To EC2
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: SSH๋ก EC2์ ์ ์ํ๊ธฐ #๊นํ๋ธ์ก์
๋ ํ๋์ ์ปดํจํฐ, ์ด ์ปดํจํฐ์์ EC2๋ผ๋ ์ปดํจํฐ๋ก ์๊ฒฉ ์ ์
uses: appleboy/ssh-action@v1.0.3 #๋ผ์ด๋ธ๋ฌ๋ฆฌ
env:
APPLICATION_PROPERTIES: ${{ secrets.APPLICATION_PROPERTIES }}
with: #์๋๋ ์๊ฒฉ ์ ์์ ์ํ ๋ฌธ๋ฒ์ด๋ผ๊ณ ์๊ฐํ์
host: ${{ secrets.EC2_HOST }} # EC2์ ์ฃผ์
username: ${{ secrets.EC2_USERNAME }} # EC2 ์ ์ username
key: ${{ secrets.EC2_PRIVATE_KEY }} # EC2์ Keyํ์ด
envs: APPLICATION_PROPERTIES
script_stop: true # ์๋ script ์ค ์คํจํ๋ ๋ช
๋ น์ด ํ๋๋ผ๋ ์์ผ๋ฉด ์คํจ๋ก ์ฒ๋ฆฌ
script: |
cd /home/ubuntu/instagram-server # ์ฌ๊ธฐ ๊ฒฝ๋ก๋ ์์ ์ EC2์ ๋ง๋ ๊ฒฝ๋ก๋ก ์ฌ์์ฑํ๊ธฐ
rm -rf src/main/resources/application.yml
git pull origin main
echo "$APPLICATION_PROPERTIES" > src/main/resources/application.yml
./gradlew clean build
sudo fuser -k -n tcp 8080 || true # || true๋ฅผ ๋ถ์ธ ์ด์ ๋ 8080์ ์ข
๋ฃ์ํฌ ํ๋ก์ธ์ค๊ฐ ์๋๋ผ๋ ์คํจ๋ก ์ฒ๋ฆฌํ์ง ์๊ธฐ ์ํด์์ด๋ค.
# ํ์ค์ถ๋ ฅ -> ์๊น๋ ./output.log 2>&1 ์ด ๋ถ๋ถ ์์ผ๋๋ฐ, ๋ฒ๊ทธ๊ฐ ์์ด์ ๋ณ๊ฒฝํจ
nohup java -jar build/libs/*SNAPSHOT.jar > ./output.log 2>&1 & # jar ํ์ผ์ ์คํ์ํค๋ ๋ช
๋ น์ด์ด๋ค. ๊ทธ๋ฆฌ๊ณ ํ์ผ์ ์ํด ๋ฐ์ํ๋ ๋ก๊ทธ๋ค์ ./output.log ํ์ผ์ ๋จ๊ธฐ๋ ๋ช
๋ น์ด


- ํ
์คํธ ์ฝ๋ ์คํจ -> CI/CD ๋ฐฐํฌ๋๋ฉด ์๋๋ค. ์ด๋ฅผ ํ์ธ
- Next.js ํ๋ก์ ํธ์ ๋ด์ฅ๋ ํ ์คํธ ์ฝ๋ ์๋ ํ์ธ
- ํ ์คํธ ์คํจํ๋๋ก ์์
- ๋ฐฐํฌ ์๋๋ ๊ฒ์ ํ์ธ
$ ./gradlew test
# test/โฆ/___ApplicationTests.java
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
@Test
void contextLoads() {
throw new RuntimeException("Fail!");
}
}


2. Github Actions, SCP: ์ผ๋ฐ ํ๋ก์ ํธ
- ์ ์ฒด ํ๋ฆ

- ์ฅ์
- ๋น๋ ์์ ์ Github Actions์์ ํจ -> ์ด์ ์๋ฒ์ ์ํฅ x
- CI/CD ํด๋ก Github Actions๋ง ์ฌ์ฉ -> ์ธํ๋ผ ๊ฐ๋จ
- ๋จ์
- ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ๊ตฌํํ๊ฑฐ๋ ์ฌ๋ฌ EC2์ ๋ฐฐํฌํด์ผ ํ๋ค๋ฉด, ์ง์ Github Actions์ ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑํ์ฌ ๊ตฌํํด์ผ ํ๋ค. -> ๋ณต์ก
- ์ฌ์ฉ
- ํ์
์ด๊ธฐ ์๋น์ค ๊ตฌ์ถ ์ ์ฌ์ฉ
- ์ด๊ธฐ ์๋น์ค ๊ตฌ์ถ ์ ๋๊ท๋ชจ๋ก ๊ตฌํํ์ง ์๊ณ , ํ์ฅ์ ํ์์ฑ์ ๋๋ ๋ ์ธํ๋ผ๋ฅผ ํ์ฅํ๋ค.
- ๋ณต์กํ ์ธํ๋ผ ๊ตฌํ ์
- ๊ตฌ์กฐ ๋ณ๊ฒฝ์ ์๊ฐ ์์
- ์๋ฌ ๋ฐ์์ ๋ฐ๋ฅธ ํธ๋ฌ๋ธ ์ํ ์ ์ด๋ ค์
- ์ธํ๋ผ ๊ตฌ์กฐ ์ดํด ์ด๋ ค์
- ๊ธฐ๋ฅ ์ถ๊ฐ ์ ์๊ฐ&๋น์ฉ ์ถ๊ฐ
- ํ์
์ด๊ธฐ ์๋น์ค ๊ตฌ์ถ ์ ์ฌ์ฉ
์ค์ต
- ๊ธฐ์กด EC2 8080ํฌํธ์์ ์คํ๋๋ ํ๋ก์ธ์ค๋ ์ข ๋ฃํ๋ค.
ubuntu@ip-10-0-1-7:~$ ls
instagram-server
ubuntu@ip-10-0-1-7:~$ lsof -i:8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 5869 ubuntu 9u IPv6 25441 0t0 TCP *:http-alt (LISTEN)
ubuntu@ip-10-0-1-7:~$ sudo fuser -k -n tcp 8080
8080/tcp: 5869
ubuntu@ip-10-0-1-7:~$ lsof -i:8080
ubuntu@ip-10-0-1-7:~$ ls
instagram-server
ubuntu@ip-10-0-1-7:~$ rm -rf instagram-server/
ubuntu@ip-10-0-1-7:~$ ls
- Github Actions๋ง ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์์ ์ฝ๋๋ฅผ ์์ ํ๋ค.
name: Deploy To EC2
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Github Repository ํ์ผ ๋ถ๋ฌ์ค๊ธฐ
uses: actions/checkout@v4
- name: JDK 17๋ฒ์ ์ค์น
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- name: application.yml ํ์ผ ๋ง๋ค๊ธฐ
run: echo "${{ secrets.APPLICATION_PROPERTIES }}" > ./src/main/resources/application.yml
- name: ํ
์คํธ ๋ฐ ๋น๋ํ๊ธฐ
run: ./gradlew clean build
- name: ๋น๋๋ ํ์ผ ์ด๋ฆ ๋ณ๊ฒฝํ๊ธฐ
run: mv ./build/libs/*SNAPSHOT.jar ./project.jar
- name: SCP๋ก EC2์ ๋น๋๋ ํ์ผ ์ ์กํ๊ธฐ
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
source: project.jar
target: /home/ubuntu/instagram-server/tobe
- name: SSH๋ก EC2์ ์ ์ํ๊ธฐ
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
script_stop: true
script: |
rm -rf /home/ubuntu/instagram-server/current
mkdir /home/ubuntu/instagram-server/current
mv /home/ubuntu/instagram-server/tobe/project.jar /home/ubuntu/instagram-server/current/project.jar
cd /home/ubuntu/instagram-server/current
sudo fuser -k -n tcp 8080 || true
nohup java -jar project.jar > ./output.log 2>&1 &
rm -rf /home/ubuntu/instagram-server/tobe
deploy job์ 7๊ฐ์ง steps
- Github Repsitory ํ์ผ ๋ถ๋ฌ์ค๊ธฐ
- ํ์ฌ ๋ฆฌํฌ์งํ ๋ฆฌ์ ์ฝ๋๋ฅผ ๋ถ๋ฌ์จ๋ค.
- GitHub Actions๋ ํธ์๋ ์ฝ๋๋ฅผ ๊ฐ์ ธ์ ๋ก์ปฌ ์์ ๋๋ ํ ๋ฆฌ์ ๋ณต์
- JDK 17 ์ค์น
- actions/setup-java@v4
- Java 17 (Temurin ๋ฐฐํฌํ)์ ์ค์น
- application.yml ํ์ผ ๋ง๋ค๊ธฐ
- run: echo "${{ secrets.APPLICATION_PROPERTIES }}" > ./src/main/resources/application.yml
- secrets.APPLICATION_PROPERTIES์ ์ ์ฅ๋ ํ๊ฒฝ ๋ณ์ ๊ฐ์ ์ฝ์ด application.yml ํ์ผ์ ์์ฑ
- ์ด ํ์ผ์ Java ์ ํ๋ฆฌ์ผ์ด์ ์ ์ค์ ํ์ผ๋ก ์ฌ์ฉ
- ํ
์คํธ ๋ฐ ๋น๋
- run: ./gradlew clean build
- Gradle์ ์ฌ์ฉํ์ฌ ํ๋ก์ ํธ๋ฅผ ๋น๋ํ๊ณ ํ ์คํธ
- clean์ ์ด์ ๋น๋์ ๊ฒฐ๊ณผ๋ฅผ ์ง์ฐ๊ณ , build๋ ํ๋ก์ ํธ๋ฅผ ์ปดํ์ผํ๊ณ ํจํค์งํ๋ค.
- ๋น๋๋ ํ์ผ ์ด๋ฆ ๋ณ๊ฒฝ
- run: mv ./build/libs/*SNAPSHOT.jar ./project.jar
- ๋น๋๋ .jar ํ์ผ์ ์ด๋ฆ์ project.jar๋ก ๋ณ๊ฒฝํ์ฌ EC2์ ๋ฐฐํฌํ ํ์ผ์ ์ด๋ฆ์ ๊ณ ์ ์ํจ๋ค.
- SCP๋ก EC2์ ๋น๋๋ ํ์ผ ์ ์ก
- uses: appleboy/scp-action@v0.1.7
- secrets๋ฅผ ์ฌ์ฉํ์ฌ EC2์ ํธ์คํธ ์ฃผ์, ์ฌ์ฉ์ ์ด๋ฆ, SSH ํค๋ฅผ ๊ฐ์ ธ์ค๊ณ ,
- SCP๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๋ project.jar ํ์ผ์ EC2 ์ธ์คํด์ค (๋๋ ํ ๋ฆฌ: ํ์ผ์ /home/ubuntu/instagram-server/tobe)๋ก ์ ์ก
- SSH๋ก EC2์ ์ ์
- uses: appleboy/ssh-action@v1.0.3
- SSH๋ฅผ ์ฌ์ฉํ์ฌ EC2์ ์ ์ํ๊ณ , ๋ฐฐํฌ๋ project.jar ํ์ผ์ ์คํ
- ๊ธฐ์กด์ current ๋๋ ํ ๋ฆฌ๋ฅผ ์ ๊ฑฐ (rm -rf)
- ์๋ก์ด current ๋๋ ํ ๋ฆฌ๋ฅผ ์์ฑ (mkdir)
- tobe ๋๋ ํ ๋ฆฌ์์ current ๋๋ ํ ๋ฆฌ๋ก project.jar ํ์ผ์ ์ด๋ (mv)
- current ๋๋ ํ ๋ฆฌ๋ก ์ด๋ (cd)
- ํ์ฌ ์คํ ์ค์ธ ํ๋ก์ธ์ค๋ฅผ ์ข ๋ฃ (fuser -k -n tcp 8080)
- project.jar ํ์ผ์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์คํํ๊ณ , ๋ก๊ทธ๋ฅผ output.log ํ์ผ์ ๊ธฐ๋ก (nohup java -jar project.jar > ./output.log 2>&1 &)
- tobe ๋๋ ํ ๋ฆฌ๋ฅผ ์ ๊ฑฐํ์ฌ ์์ ํ์ผ์ ์ ๋ฆฌ (rm -rf)
- ํ ์คํธ๋ฅผ ์ํด steps์ ํ๋ ์ถ๊ฐํด๋ณด์
name: Deploy To EC2
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Github Repository ํ์ผ ๋ถ๋ฌ์ค๊ธฐ #github repository ์ฝ๋๋ค์ github actions ์ปดํจํฐ๋ก ๋ถ๋ฌ์ค๋ ๊ฒ
uses: actions/checkout@v4
- name: Test #github actions๋ ํ๋์ ์ปดํจํฐ์ด๊ธฐ์ ์๋ ๋ด์ฉ๋ค์ด ๋์์ผํ๋ค.
run: |
ls
pwd
- name: JDK 17๋ฒ์ ์ค์น
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- name: application.yml ํ์ผ ๋ง๋ค๊ธฐ
run: echo "${{ secrets.APPLICATION_PROPERTIES }}" > ./src/main/resources/application.yml
- name: ํ
์คํธ ๋ฐ ๋น๋ํ๊ธฐ
run: ./gradlew clean build
- name: ๋น๋๋ ํ์ผ ์ด๋ฆ ๋ณ๊ฒฝํ๊ธฐ
run: mv ./build/libs/*SNAPSHOT.jar ./project.jar
- name: SCP๋ก EC2์ ๋น๋๋ ํ์ผ ์ ์กํ๊ธฐ
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
source: project.jar
target: /home/ubuntu/instagram-server/tobe
- name: SSH๋ก EC2์ ์ ์ํ๊ธฐ
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
script_stop: true
script: |
rm -rf /home/ubuntu/instagram-server/current
mkdir /home/ubuntu/instagram-server/current
mv /home/ubuntu/instagram-server/tobe/project.jar /home/ubuntu/instagram-server/current/project.jar
cd /home/ubuntu/instagram-server/current
sudo fuser -k -n tcp 8080 || true
nohup java -jar project.jar > ./output.log 2>&1 &
rm -rf /home/ubuntu/instagram-server/tobe

3. Code Deploy: ํ์ฅ์ฑ ๊ณ ๋ คํ ํ๋ก์ ํธ
- ์ ์ฒด ํ๋ฆ

- ์ฅ์
- ์๋ง์ EC2์ ๋ฐฐํฌ ์ฝ๊ฒ ๊ฐ๋ฅ -> ์๋ฒ ์ฌ๋ฌ ๋์ฌ๋ ์ฝ๊ฒ ์๋ ๋ฐฐํฌ
- ๋ฌด์ค๋จ ๋ฐฐํฌ๊ฐ ๋ด์ฅ ๋์ด ์ฝ๊ฒ ๋ฌด์ค๋จ ๋ฐฐํฌ ๊ฐ๋ฅ
- ๋จ์
- ์ธํ๋ผ ๊ตฌ์กฐ๊ฐ ๋ณต์ก -> ๊ด๋ฆฌ ๋น์ฉ, ์ ์ง๋ณด์ ๋น์ฉ, ๋ณต์กํจ, ํธ๋ฌ๋ธ ์ํ ์ ์ด๋ น๋ฌด
- ์ฌ์ฉ
- ์๋ฒ ์ฌ๋ฌ๋ ๊ตฌ๋ ํ์ ์
- ๋ฌด์ค๋จ ๋ฐฐํฌ ํ์ ์
CodeDeploy ์ธํ / IAM ์ค์
- CodeDeploy Role ์์ฑ
- CodeDeploy ์์ฑ
- EC2 Role ์์ฑ
- Code Deploy Agent ์ค์น
- Github Actions๊ฐ Code Deploy, S3์ ๊ทผ ์ํ IAM ๋ฐ๊ธ
- Github Actions์ Secret Key์ ์ ์ฅ
- ํ๋ก์ ํธ ํ์ผ ์ ์ฅํ S3 ์์ฑ
1. CodeDeploy Role ์์ฑ
- IAM -> ์ญํ -> ์ญํ ์์ฑ -> ์๋น์ค ๋๋ ์ฌ์ฉ ์ฌ๋ก: CodeDeploy, ์ฌ์ฉ ์ฌ๋ก: CodeDeploy -> ๊ถํ์ถ๊ฐ: AwsCodeDeployRole -> ์ญํ ์ด๋ฆ: code-deploy-role -> ์ญํ ์์ฑ

2. CodeDeploy ์์ฑํ๊ธฐ
- codedeploy -> ์ ํ๋ฆฌ์ผ์ด์ -> ์ ํ๋ฆฌ์ผ์ด์ ์์ฑ -> ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ฆ: instagram-server, ์ปดํจํ ํ๋ซํผ:EC2/์จํ๋ ๋ฏธ์ค -> ์์ฑ
- ๋ฐฐํฌ ๊ทธ๋ฃน: ํ๋ก๋์
ํ๊ฒฝ, ์คํ
์ด์ง ํ๊ฒฝ ๋ฑ์ ๊ตฌ๋ถํ๊ธฐ ์ํ ๋จ์
- ๋ง๋ ์๋น์ค ์ญํ ์ ์ ํํ๊ณ
- ๋ฐฐํฌ ์ ํ: ํ์ฌ ์์น
- ํ๊ฒฝ ๊ตฌ์ฑ: EC2 ์ธ์คํด์ค
- ๋ฐฐํฌ ์ ํ: ํ์ฌ ์์น
- ํ๊ฒฝ ๊ตฌ์ฑ - ํค: Name, ๊ฐ: instagram-server
- ๋ฐฐํฌ ์ค์ : CodeDeployDefault.AllAtOnce
- ๋ก๋๋ฐธ๋ฐ์: ๋ก๋๋ฐธ๋ฐ์ฑ ํ์ฑํ ํด์

3. EC2 Role ์์ฑ
- EC2๋ S3์ ์ ๊ทผํด์ ๋น๋ํ์ผ ๋ค์ด๋ฐ์์ผํ๋ฏ๋ก S3์ ์ ๊ทผ๊ฐ๋ฅํ ์ญํ ํ์
- S3์ ์ ๊ทผํ๊ณ , ์กฐํํ๋ ๊ธฐ๋ฅ์ ๊ถํ์ ํ์ฉ
- ์ ์ฑ
์์ฑ
- ์ ์ฑ -> ์ ์ฑ ์์ฑ -> ๊ถํ ์ง์ ํ๊ธฐ -> JSON -> ์๋์ฝ๋ ์ ๋ ฅ -> ์์ฑ -> ์ ์ฑ ์ด๋ฆ code-deploy-ec2-policy -> ์ ์ฑ ์์ฑ
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:Get*",
"S3:List*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
- S3์ ์ ๊ทผํ๊ณ , ์กฐํํ๋ ๊ธฐ๋ฅ์ ๋ชจ๋ ๊ถํ์ ํ์ฉ
- ์ญํ
- ์ญํ ์์ฑ -> EC2 -> code-deploy-ec2-policy๋ผ๋ ๋ฐฉ๊ธ ๋ง๋ ์ ์ฑ ์ ํ -> ์ญํ ์ด๋ฆ code-deploy-ec2-role -> ์ญํ ์์ฑ
- ์ญํ ์ ์ฌ๋ฌ ์ ์ฑ ์ ๊ฐ์ง ์ ์๋ค.
- EC2์ ์์ฑํ IAM ์ฐ๊ฒฐ
- ์ฌ์ฉํ EC2์ ์ -> ์์ -> ๋ณด์ -> IAM ์ญํ ์์ -> code-deploy-ec2-role ์ ํ
4. Code Deploy Agent ์ค์น
- code deploy๊ฐ EC2์๊ฒ ๋ช ๋ น์ ๋ด๋ ค์ผ ํ๋๋ฐ, ์ด ๋ช ๋ น์ code deploy์ธ์ด๋ผ EC2๊ฐ ์ดํด๋ชปํจ -> ๋ฒ์ญ๊ธฐ์ธ agent๊ฐ ํ์
$ sudo apt update && \
sudo apt install -y ruby-full wget && \
cd /home/ubuntu && \
wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install && \
chmod +x ./install && \
sudo ./install auto
- Code Deploy Agent๊ฐ ์ ์์ ์ผ๋ก ์คํ๋๊ณ ์๋ ์ง ํ์ธ
$ systemctl status codedeploy-agent

5. Github Actions๊ฐ CodeDeploy, S3์ ์ ๊ทผํ ์ ์๊ฒ IAM ๋ฐ๊ธ

- aws IAM ์ฌ์ฉ์ -> ์ฌ์ฉ์ ์์ฑ -> ์ฌ์ฉ์ ์ด๋ฆ: instagram-server-github-actions
- ์ง์ ์ ์ฑ ์ฐ๊ฒฐ(AWSCodeDeployFullAccess, AmazonS3FullAccess)
- IAM -> ์ฌ์ฉ์ -> ์์์ ๋ง๋ ์ฌ์ฉ์์ ๋ณด์ ์๊ฒฉ ์ฆ๋ช -> ์ก์ธ์ค ํค ๋ง๋ค๊ธฐ -> AWS ์ธ๋ถ์์ ์คํ๋๋ ์ ํ๋ฆฌ์ผ์ด์ (github actions๋ aws๊ฐ ์๋๋ผ ์ธ๋ถ์์ ์คํ๋๋ฏ๋ก)
6. Github Actions์ Secret Key์ ์ ์ฅํด๋๊ธฐ
- ์ด๋ ๊ฒ ๋ง๋ ์ก์ธ์คํค๋ ๋ฐ๋ก ์ ๋ณด๊ดํด์ผํ๋ค. -> github settings/Secrets and variables/Actions์ ๋ฃ์ผ๋ฉด ๋๋ค.
7. ๋ฐฐํฌ ์ ์ ํ๋ก์ ํธ ํ์ผ ์ ์ฅํ S3 ๋ง๋ค๊ธฐ
- S3 -> ๋ฒํท๋ง๋ค๊ธฐ -> instagram-server๋ผ๋ ๋ฒํท ๋ง๋ค๋ฉด ๋๋ค.
์ถ๊ฐ: CodeDeploy ๋ก๊ทธ ํ์ธ ๋ฐฉ๋ฒ
https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/deployments-view-logs.html
์ค์ต
- ๊ธฐ์กด EC2 8080ํฌํธ์์ ์คํ๋๋ ํ๋ก์ธ์ค๋ ์ข ๋ฃํ๋ค.
ubuntu@ip-10-0-1-7:~$ ls
instagram-server
ubuntu@ip-10-0-1-7:~$ lsof -i:8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 5869 ubuntu 9u IPv6 25441 0t0 TCP *:http-alt (LISTEN)
ubuntu@ip-10-0-1-7:~$ sudo fuser -k -n tcp 8080
8080/tcp: 5869
ubuntu@ip-10-0-1-7:~$ lsof -i:8080
ubuntu@ip-10-0-1-7:~$ ls
instagram-server
ubuntu@ip-10-0-1-7:~$ rm -rf instagram-server/
ubuntu@ip-10-0-1-7:~$ ls
- Github Actions๋ง ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์์ ์ฝ๋๋ฅผ ์์ ํ๋ค.
name: Deploy To EC2
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Github Repository ํ์ผ ๋ถ๋ฌ์ค๊ธฐ
uses: actions/checkout@v4
- name: JDK 17๋ฒ์ ์ค์น
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- name: application.yml ํ์ผ ๋ง๋ค๊ธฐ
run: echo "${{ secrets.APPLICATION_PROPERTIES }}" > ./src/main/resources/application.yml
- name: ํ
์คํธ ๋ฐ ๋น๋ํ๊ธฐ
run: ./gradlew clean build
- name: ๋น๋๋ ํ์ผ ์ด๋ฆ ๋ณ๊ฒฝํ๊ธฐ
run: mv ./build/libs/*SNAPSHOT.jar ./project.jar
- name: SCP๋ก EC2์ ๋น๋๋ ํ์ผ ์ ์กํ๊ธฐ
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
source: project.jar
target: /home/ubuntu/instagram-server/tobe
- name: SSH๋ก EC2์ ์ ์ํ๊ธฐ
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
script_stop: true
script: |
rm -rf /home/ubuntu/instagram-server/current
mkdir /home/ubuntu/instagram-server/current
mv /home/ubuntu/instagram-server/tobe/project.jar /home/ubuntu/instagram-server/current/project.jar
cd /home/ubuntu/instagram-server/current
sudo fuser -k -n tcp 8080 || true
nohup java -jar project.jar > ./output.log 2>&1 &
rm -rf /home/ubuntu/instagram-server/tobe
์ถ์ฒ
๋น์ ๊ณต์๋ ์ดํดํ ์ ์๋ CI/CD ์ ๋ฌธยท์ค์ ๊ฐ์ | JSCODE ๋ฐ์ฌ์ฑ - ์ธํ๋ฐ
JSCODE ๋ฐ์ฌ์ฑ | ๋น์ ๊ณต์ ์ ์ฅ์์๋ ์ฝ๊ฒ ์ดํดํ ์ ์๊ณ , ์ค์ ์์ ๋ฐ๋ก ์ ์ฉ ๊ฐ๋ฅํ CI/CD ์ ๋ฌธ ๊ฐ์๋ฅผ ๋ง๋ค์ด๋ดค์ต๋๋ค!, ๐คฌ ์๋ผ์ด, ๋ชป ํด๋จน๊ฒ ๋ค!๋น์ ๊ณต์๋ก ๊ฐ๋ฐ์ ์์ํด ์ฌ๋ฌ ํ์ฌ์์ CTO๋ก
www.inflearn.com
'๐ณ ์ธํ๋ผ > Cloud & CI-CD' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
EC2, ECR, Docker Compose, Github Actions ์ฌ์ฉํ์ฌ SpringBoot, MongoDB ๋ฐฐํฌํ๊ธฐ (1) | 2024.10.01 |
---|---|
๋น์ ๊ณต์๋ ์ดํดํ ์ ์๋ CI/CD ์ ๋ฌธ/์ค์ (2) (0) | 2024.09.24 |
1. CI/CD ๊ธฐ๋ณธ ๊ฐ๋ / Github Actions ๊ธฐ๋ณธ ๊ฐ๋
1. CI/CD
- Continuous Integration, Continuous Deployment
- ๋ฐฐ์ฐ๋ ์ด์
- ์๋น์ค ์ด์ ์ ์๋ก์ด ๊ธฐ๋ฅ ํ์
- ์ด์ ๋ฐ๋ผ, ์ฝ๋ ์์ฑ -> Commit -> Merge -> ๋ฐฐํฌ
- ๋งค์ฐ ๊ท์ฐฎ๋ค -> ์ด๋ฐ ๋ฐ๋ณต์ ์ธ ๊ณผ์ ์ ์๋ํ

2. Github Actions
- ์ ๋ฒ์ ์ ํจ์ค๋ฅผ ํ์ฉํ์๋๋ฐ, ์ด๋ฒ์๋ Github Actions๋ฅผ ๊ณต๋ถํด๋ณด์
- https://koreatstm.tistory.com/140
- ๋ก์ง์ ์คํ์ํฌ ์ ์๋ ์ผ์ข ์ ์ปดํจํฐ
- ์ ํจ์ค์ ๊ฒฝ์ฐ, ๋ณ๋ ์๋ฒ๊ฐ ํ์ํ์ง๋ง, Github Actions๋ ์๋ฒ ๊ตฌ์ถ ์์ด ๋ด์ฅ๋ Github Actions ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
- ๋น์ฉ๋ ์ข๊ณ , ์ ํ ํ๋๋ฐ ์๊ฐ๋ ์ ์ฝ
- CI/CD ํ๋ฆ๋

- ์ฝ๋ ์์ฑ ํ Commit
- Github์ Push
- Push๋ฅผ ๊ฐ์งํ์ฌ Github Actions์ ์์ฑํ ๋ก์ง ์คํ
- ๋น๋
- ํ ์คํธ
- ๋ฐฐํฌ
- ์๋ฒ์์ ๋ฐฐํฌ๋ ์ต์ ์ฝ๋๋ก ์๋ฒ ์ฌ์คํ
3. Github Actions ๋ฌธ๋ฒ
- ์ ํ๋ก์ ํธ ํด๋ ๋ง๋ค๊ธฐ
- .github/workflows/deploy.yml ๋ง๋ค๊ธฐ
# Workflow์ ์ด๋ฆ
# Workflow : ํ๋์ yml ํ์ผ์ ํ๋์ Workflow๋ผ๊ณ ๋ถ๋ฅธ๋ค.
name: Github Actions ์คํ์์ผ๋ณด๊ธฐ
# Event : ์คํ๋๋ ์์ ์ ์ค์
# main์ด๋ผ๋ ๋ธ๋์น์ push ๋ ๋ ์๋ Workflow๋ฅผ ์คํ
# ์ง๊ธ์ 1๊ฐ์ Job์ผ๋ก ์งํํ๊ฒ ๋ค.
on:
push:
branches:
- main
# ํ๋์ Workflow๋ 1๊ฐ ์ด์์ Job์ผ๋ก ๊ตฌ์ฑ๋๋ค.
# ์ฌ๋ฌ Job์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ณ๋ ฌ์ ์ผ๋ก ์ํ๋๋ค.
jobs:
# ์๋๋ Job์ ์๋ณํ๊ธฐ ์ํ id
My-Deploy-Job:
# ๊นํ๋ธ ์ก์
๋ ํ๋์ ์ปดํจํฐ. ์ด๋, Github Actions๋ฅผ ์คํ์ํฌ ์๋ฒ ์ข
๋ฅ ์ ํ
runs-on: ubuntu-latest
# Step : ํน์ ์์
์ ์ํํ๋ ๊ฐ์ฅ ์์ ๋จ์
# Job์ ์ฌ๋ฌ Step๋ค๋ก ๊ตฌ์ฑ๋์ด ์๋ค.
steps:
- name: Hello World ์ฐ๊ธฐ # ํด๋น Step์ ์ด๋ฆ ๋ถ์ด๋ ๊ธฐ๋ฅ
run: echo "Hello World" # ์คํ์ํฌ ๋ช
๋ น์ด ์์ฑ
- name: ์ฌ๋ฌ ๋ช
๋ น์ด ๋ฌธ์ฅ ์์ฑํ๊ธฐ # "|"๋ฅผ ์ถ๊ฐํ๊ณ ์
๋ ฅํ๋ฉด ๋๋ค.
run: |
echo "Good"
echo "Morning"
- name: Github Actions ์์ฒด์ ์ ์ฅ๋์ด ์๋ ๋ณ์ ์ฌ์ฉํด๋ณด๊ธฐ
run: |
echo $GITHUB_SHA #commit์ ID๊ฐ
echo $GITHUB_REPOSITORY #github repository ๊ฐ
- name: Github Actions Secret ๋ณ์ ์ฌ์ฉํด๋ณด๊ธฐ
run: |
echo ${{ secrets.MY_NAME }}
echo ${{ secrets.MY_HOBBY }}
- ์ฃผ์์
- .github/workflows ๋๋ ํฐ๋ฆฌ์ .yml or .yaml ํ์ฅ์๋ก ํ์ผ ์์ฑ
- .github/workflows๋ ํ๋ก์ ํธ ํด๋์ ์ต์๋จ์ ์์ฑ

- Github Repository ๋ง๋ค๊ณ ์ ๋ก๋
$ git init
$ git add .
$ git commit -m "first commit"
$ git branch -M main
$ git remote add origin {Repository ์ฃผ์}
$ git push -u origin main



- Github Actions Secret ๋ณ์ ์ฌ์ฉํด๋ณด๊ธฐ



- Github Actions ์ ์ฒด ๊ตฌ์กฐ
- Event๋ฐ์ -> workflow์คํ -> workflow๋ job์ผ๋ก ์ด๋ฃจ์ด์ง -> job์ step์ผ๋ก ์ด๋ฃจ์ด์ง
์ฐธ๊ณ
https://docs.github.com/ko/actions
2. ๋ฐฑ์๋(Spring Boot) ํ๋ก์ ํธ์ CI/CD ์ ์ฉํ๊ธฐ
- 3๊ฐ์ง ๋ฐฉ๋ฒ ์กด์ฌ
- Github Actions: ๊ฐ์ธ ํ๋ก์ ํธ
- Github Actions, SCP: ์ผ๋ฐ ํ๋ก์ ํธ
- Code Deploy: ํ์ฅ์ฑ ๊ณ ๋ คํ ํ๋ก์ ํธ
1. Github Actions: ๊ฐ์ธ ํ๋ก์ ํธ
- ์ ์ฒด ํ๋ฆ

- ์ฅ์
- git pull ์ฌ์ฉํ์ฌ ๋ณ๊ฒฝ๋ ๋ถ๋ถ์ ๋ํด์๋ง ์ ๋ฐ์ดํธ -> CI/CD ์๋ ๋น ๋ฅด๋ค
- CI/CD ํด๋ก Github Actions๋ง ์ฌ์ฉ -> ์ธํ๋ผ ๊ฐ๋จ
- ๋จ์
- ๋น๋๋ฅผ EC2์์ ์งํ -> ์๋ฒ ์ฑ๋ฅ์ ์ํฅ ๊ฐ๋ฅ
- Github๊ณ์ ์ ๋ณด๊ฐ EC2์ ์ ์ฅ -> ๋ณด์๋ฌธ์
- ์ฌ์ฉ
- ๊ฐ์ธ ํ๋ก์ ํธ์์ ์ฃผ๋ก ์ฌ์ฉ
์ค์ต
- ๊ฐ๋จํ ์คํ๋ง๋ถํธ ํ๋ก์ ํธ ์์ฑ
- Github์ ํ๋ก์ ํธ ์ฌ๋ฆฌ๊ธฐ
- Github์ Repository๋ฅผ ๋ง๋ ๋ค.
- Github Repository์ ํ๋ก์ ํธ ์ฝ๋๋ฅผ ์ฌ๋ฆฐ๋ค.
$ cd instagram-server
$ git init
$ git add .
$ git commit -m "first commit"
$ git branch -M main
$ git remote add origin _______
$ git push -u origin main
- EC2 ๊ตฌ์ฑ
- EC2๋ฅผ ๊ตฌ์ฑํ๋ค
- ๋ณด์๊ทธ๋ฃน 8080 ํฌํธ ์ด๊ธฐ
- JDK ์ค์น
- ํ๋ก์ ํธ ๋ค์ด
- ํด๋ก ๋ฐ์ ์๋ฒ ์๋ ํ์ธ


#JDK ์ค์น
$ sudo apt update && /
sudo apt install openjdk-17-jdk -y
$ java -version # ์ ์ค์น๋๋ ์ง ํ์ธ
# ํ๋ก์ ํธ ๋ค์ด
$ git clone {git repository clone ์ฃผ์}
# ํด๋ก ๋ฐ์ ์๋ฒ ์๋ ํ์ธ
$ cd {ํ๋ก์ ํธ ๊ฒฝ๋ก}
$ ./gradlew clean build
$ cd build/libs
$ nohup java -jar ________.jar &
$ sudo lsof -i:8080 # 8080๋ฒ ํฌํธ์ Spring Boot๊ฐ ์คํ๋๊ณ ์๋ ์ง ํ์ธ
- ์ด๋ ๊นํ๋ธ ํด๋ก ๋ฐ์ ๋ id,pw๊ฐ ํ์ํ๋ฐ pw๋ ์๋ ๋ธ๋ก๊ทธ ์ฐธ๊ณ !!
- https://velog.io/@nara7875/github-ํ ํฐ-๋ฐ๊ธํ๊ธฐ


- ์ด๋ฒ์ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ๊ณ ์ ๋๋ ํ์ธํด๋ณด์
- ์ค์ ์ฝ๋ ์
๋ฐ์ดํธ ํ์ธ
- ์ ์ฝ๋ ์์ฑ
- Github์ Git Push
- EC2์์ Git Pull
- ๋น๋ ํ ์ฌ๋ฐฐํฌ
- ์๋์ ๊ฐ์ด Hello -> Hi๋ก ๋ฐ๊พธ๊ณ ๋ค์ ๊นํ๋ธ ์ฌ๋ฆฌ๊ณ ์งํ
package com.example.instgram_server;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AppController {
@GetMapping
public String hello() {
return "Hi World!";
}
}
# EC2์์ Git Pull
$ cd {ํ๋ก์ ํธ ๊ฒฝ๋ก}
$ git pull origin main
# ๋น๋ ํ ์ฌ๋ฐฐํฌ
$ sudo lsof -i:8080 # 8080๋ฒ ํฌํธ์ Spring Boot๊ฐ ์คํ๋๊ณ ์๋ ์ง ํ์ธ
$ sudo fuser -k -n tcp 8080 # 8080๋ฒ ํฌํธ์ ์คํ๋๊ณ ์๋ ํ๋ก์ธ์ค ์ข
๋ฃ
$ ./gradlew clean build #~/instagram-serverํด๋์์ ์คํํด์ผํ๋ค.
$ cd build/libs
$ nohup java -jar ________.jar &

- Github ๊ณ์ ์ ๋ณด ๋ฐ๋ณต ์
๋ ฅ ๊ณผ์ ์ญ์
- ์ต์ด ํ๋ฒ๋ง ์์ฑํ๊ณ ๊ทธ ์ดํ๋ ์ ๋ ฅ์๋๊ฒ ํ์
- ~/.git-credentials์ ๋ก๊ทธ์ธ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ ๋ฐฉ์์ผ๋ก ์ด๋ EC2 ์ ๊ทผํ๋ ๋ชจ๋ ์ฌ์ฉ์๊ฐ ๊นํ๋ธ ์ ๋ณด๋ฅผ ๋ณผ ์ ์๋ค.
$ git config --global credential.helper store
$ git pull origin main
# Github ๊ณ์ ๋ฐ ๋น๋ฐ๋ฒํธ ์
๋ ฅ
$ git pull origin main # ๋ ์ด์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ฌป๋ ๊ฑธ ํ์ธํ ์ ์๋ค.

์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก CI/CD ๊ณผ์ ์ ์๋ํ ํด๋ณด์
- ๊ณผ์ ์๋ํ
- .github/workflows/deploy.yml ์์ฑ
- Github์ Secret๊ฐ ๋ฃ๊ธฐ
- Github์์ ๊ฐ์ธ์ ๋ณด์ Settings/Secrets and variables/Actions/Repository secrets์ ๋ฃ๊ธฐ
- Git Push ํ ํ์ธ
name: Deploy To EC2
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: SSH๋ก EC2์ ์ ์ํ๊ธฐ #๊นํ๋ธ์ก์
๋ ํ๋์ ์ปดํจํฐ, ์ด ์ปดํจํฐ์์ EC2๋ผ๋ ์ปดํจํฐ๋ก ์๊ฒฉ ์ ์
uses: appleboy/ssh-action@v1.0.3 #๋ผ์ด๋ธ๋ฌ๋ฆฌ
with: #์๋๋ ์๊ฒฉ ์ ์์ ์ํ ๋ฌธ๋ฒ์ด๋ผ๊ณ ์๊ฐํ์
host: ${{ secrets.EC2_HOST }} # EC2์ ์ฃผ์
username: ${{ secrets.EC2_USERNAME }} # EC2 ์ ์ username
key: ${{ secrets.EC2_PRIVATE_KEY }} # EC2์ Keyํ์ด
script_stop: true # ์๋ script ์ค ์คํจํ๋ ๋ช
๋ น์ด ํ๋๋ผ๋ ์์ผ๋ฉด ์คํจ๋ก ์ฒ๋ฆฌ
script: |
cd /home/ubuntu/instagram-server # ์ฌ๊ธฐ ๊ฒฝ๋ก๋ ์์ ์ EC2์ ๋ง๋ ๊ฒฝ๋ก๋ก ์ฌ์์ฑํ๊ธฐ
git pull origin main
./gradlew clean build
sudo fuser -k -n tcp 8080 || true # || true๋ฅผ ๋ถ์ธ ์ด์ ๋ 8080์ ์ข
๋ฃ์ํฌ ํ๋ก์ธ์ค๊ฐ ์๋๋ผ๋ ์คํจ๋ก ์ฒ๋ฆฌํ์ง ์๊ธฐ ์ํด์์ด๋ค.
# ํ์ค์ถ๋ ฅ -> ์๊น๋ ./output.log 2>&1 ์ด ๋ถ๋ถ ์์ผ๋๋ฐ, ๋ฒ๊ทธ๊ฐ ์์ด์ ๋ณ๊ฒฝํจ
nohup java -jar build/libs/*SNAPSHOT.jar > ./output.log 2>&1 & # jar ํ์ผ์ ์คํ์ํค๋ ๋ช
๋ น์ด์ด๋ค. ๊ทธ๋ฆฌ๊ณ ํ์ผ์ ์ํด ๋ฐ์ํ๋ ๋ก๊ทธ๋ค์ ./output.log ํ์ผ์ ๋จ๊ธฐ๋ ๋ช
๋ น์ด
- ๋งจ์์์ ํ๋ ๊ฐ์ธ์ ๋ณด๋ฅผ ๊นํ๋ธ(Settings/Secrets and variables/Actions/Repository secrets)์ ๋ฃ์ด์ฃผ์




- ๋์ผ๋ก ํ์ธํ๊ธฐ ์ํด์ print๋ฌธ์ yes~ World!๋ก ๋ณ๊ฒฝํ๊ณ ํด๋ณด์


- ๋ฌธ์

- application.yml ํ์ผ ๋ฃ๋ ๊ณผ์ ์๋ํ
- .gitignore์ application.yml ์ถ๊ฐ
- application.yml ํ์ผ ์์ฑ
- Github์ resources ํด๋๊ฐ push ๋๋๋ก ์์์ ํ์ผ ์์ฑ
- Github Actions ์ฝ๋ ์์
- Github์ Secret ๊ฐ ๋ฃ๊ธฐ
- ํ์ธ

# .gitignore
application.yml
# src/main/resources/application.yml
aws:
access-key: ABCDEFG
secret-key: HIJKLMN
#src/main/resources/empty.txt #ํ
์คํธ์ํ ์์์ ํ์คํธ ํ์ผ
~ ๋ด์ฉ ์์ฑ
# .github/workflows/deploy.yml
name: Deploy To EC2
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: SSH๋ก EC2์ ์ ์ํ๊ธฐ #๊นํ๋ธ์ก์
๋ ํ๋์ ์ปดํจํฐ, ์ด ์ปดํจํฐ์์ EC2๋ผ๋ ์ปดํจํฐ๋ก ์๊ฒฉ ์ ์
uses: appleboy/ssh-action@v1.0.3 #๋ผ์ด๋ธ๋ฌ๋ฆฌ
env:
APPLICATION_PROPERTIES: ${{ secrets.APPLICATION_PROPERTIES }}
with: #์๋๋ ์๊ฒฉ ์ ์์ ์ํ ๋ฌธ๋ฒ์ด๋ผ๊ณ ์๊ฐํ์
host: ${{ secrets.EC2_HOST }} # EC2์ ์ฃผ์
username: ${{ secrets.EC2_USERNAME }} # EC2 ์ ์ username
key: ${{ secrets.EC2_PRIVATE_KEY }} # EC2์ Keyํ์ด
envs: APPLICATION_PROPERTIES
script_stop: true # ์๋ script ์ค ์คํจํ๋ ๋ช
๋ น์ด ํ๋๋ผ๋ ์์ผ๋ฉด ์คํจ๋ก ์ฒ๋ฆฌ
script: |
cd /home/ubuntu/instagram-server # ์ฌ๊ธฐ ๊ฒฝ๋ก๋ ์์ ์ EC2์ ๋ง๋ ๊ฒฝ๋ก๋ก ์ฌ์์ฑํ๊ธฐ
rm -rf src/main/resources/application.yml
git pull origin main
echo "$APPLICATION_PROPERTIES" > src/main/resources/application.yml
./gradlew clean build
sudo fuser -k -n tcp 8080 || true # || true๋ฅผ ๋ถ์ธ ์ด์ ๋ 8080์ ์ข
๋ฃ์ํฌ ํ๋ก์ธ์ค๊ฐ ์๋๋ผ๋ ์คํจ๋ก ์ฒ๋ฆฌํ์ง ์๊ธฐ ์ํด์์ด๋ค.
# ํ์ค์ถ๋ ฅ -> ์๊น๋ ./output.log 2>&1 ์ด ๋ถ๋ถ ์์ผ๋๋ฐ, ๋ฒ๊ทธ๊ฐ ์์ด์ ๋ณ๊ฒฝํจ
nohup java -jar build/libs/*SNAPSHOT.jar > ./output.log 2>&1 & # jar ํ์ผ์ ์คํ์ํค๋ ๋ช
๋ น์ด์ด๋ค. ๊ทธ๋ฆฌ๊ณ ํ์ผ์ ์ํด ๋ฐ์ํ๋ ๋ก๊ทธ๋ค์ ./output.log ํ์ผ์ ๋จ๊ธฐ๋ ๋ช
๋ น์ด


- ํ
์คํธ ์ฝ๋ ์คํจ -> CI/CD ๋ฐฐํฌ๋๋ฉด ์๋๋ค. ์ด๋ฅผ ํ์ธ
- Next.js ํ๋ก์ ํธ์ ๋ด์ฅ๋ ํ ์คํธ ์ฝ๋ ์๋ ํ์ธ
- ํ ์คํธ ์คํจํ๋๋ก ์์
- ๋ฐฐํฌ ์๋๋ ๊ฒ์ ํ์ธ
$ ./gradlew test
# test/โฆ/___ApplicationTests.java
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
@Test
void contextLoads() {
throw new RuntimeException("Fail!");
}
}


2. Github Actions, SCP: ์ผ๋ฐ ํ๋ก์ ํธ
- ์ ์ฒด ํ๋ฆ

- ์ฅ์
- ๋น๋ ์์ ์ Github Actions์์ ํจ -> ์ด์ ์๋ฒ์ ์ํฅ x
- CI/CD ํด๋ก Github Actions๋ง ์ฌ์ฉ -> ์ธํ๋ผ ๊ฐ๋จ
- ๋จ์
- ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ๊ตฌํํ๊ฑฐ๋ ์ฌ๋ฌ EC2์ ๋ฐฐํฌํด์ผ ํ๋ค๋ฉด, ์ง์ Github Actions์ ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑํ์ฌ ๊ตฌํํด์ผ ํ๋ค. -> ๋ณต์ก
- ์ฌ์ฉ
- ํ์
์ด๊ธฐ ์๋น์ค ๊ตฌ์ถ ์ ์ฌ์ฉ
- ์ด๊ธฐ ์๋น์ค ๊ตฌ์ถ ์ ๋๊ท๋ชจ๋ก ๊ตฌํํ์ง ์๊ณ , ํ์ฅ์ ํ์์ฑ์ ๋๋ ๋ ์ธํ๋ผ๋ฅผ ํ์ฅํ๋ค.
- ๋ณต์กํ ์ธํ๋ผ ๊ตฌํ ์
- ๊ตฌ์กฐ ๋ณ๊ฒฝ์ ์๊ฐ ์์
- ์๋ฌ ๋ฐ์์ ๋ฐ๋ฅธ ํธ๋ฌ๋ธ ์ํ ์ ์ด๋ ค์
- ์ธํ๋ผ ๊ตฌ์กฐ ์ดํด ์ด๋ ค์
- ๊ธฐ๋ฅ ์ถ๊ฐ ์ ์๊ฐ&๋น์ฉ ์ถ๊ฐ
- ํ์
์ด๊ธฐ ์๋น์ค ๊ตฌ์ถ ์ ์ฌ์ฉ
์ค์ต
- ๊ธฐ์กด EC2 8080ํฌํธ์์ ์คํ๋๋ ํ๋ก์ธ์ค๋ ์ข ๋ฃํ๋ค.
ubuntu@ip-10-0-1-7:~$ ls
instagram-server
ubuntu@ip-10-0-1-7:~$ lsof -i:8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 5869 ubuntu 9u IPv6 25441 0t0 TCP *:http-alt (LISTEN)
ubuntu@ip-10-0-1-7:~$ sudo fuser -k -n tcp 8080
8080/tcp: 5869
ubuntu@ip-10-0-1-7:~$ lsof -i:8080
ubuntu@ip-10-0-1-7:~$ ls
instagram-server
ubuntu@ip-10-0-1-7:~$ rm -rf instagram-server/
ubuntu@ip-10-0-1-7:~$ ls
- Github Actions๋ง ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์์ ์ฝ๋๋ฅผ ์์ ํ๋ค.
name: Deploy To EC2
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Github Repository ํ์ผ ๋ถ๋ฌ์ค๊ธฐ
uses: actions/checkout@v4
- name: JDK 17๋ฒ์ ์ค์น
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- name: application.yml ํ์ผ ๋ง๋ค๊ธฐ
run: echo "${{ secrets.APPLICATION_PROPERTIES }}" > ./src/main/resources/application.yml
- name: ํ
์คํธ ๋ฐ ๋น๋ํ๊ธฐ
run: ./gradlew clean build
- name: ๋น๋๋ ํ์ผ ์ด๋ฆ ๋ณ๊ฒฝํ๊ธฐ
run: mv ./build/libs/*SNAPSHOT.jar ./project.jar
- name: SCP๋ก EC2์ ๋น๋๋ ํ์ผ ์ ์กํ๊ธฐ
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
source: project.jar
target: /home/ubuntu/instagram-server/tobe
- name: SSH๋ก EC2์ ์ ์ํ๊ธฐ
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
script_stop: true
script: |
rm -rf /home/ubuntu/instagram-server/current
mkdir /home/ubuntu/instagram-server/current
mv /home/ubuntu/instagram-server/tobe/project.jar /home/ubuntu/instagram-server/current/project.jar
cd /home/ubuntu/instagram-server/current
sudo fuser -k -n tcp 8080 || true
nohup java -jar project.jar > ./output.log 2>&1 &
rm -rf /home/ubuntu/instagram-server/tobe
deploy job์ 7๊ฐ์ง steps
- Github Repsitory ํ์ผ ๋ถ๋ฌ์ค๊ธฐ
- ํ์ฌ ๋ฆฌํฌ์งํ ๋ฆฌ์ ์ฝ๋๋ฅผ ๋ถ๋ฌ์จ๋ค.
- GitHub Actions๋ ํธ์๋ ์ฝ๋๋ฅผ ๊ฐ์ ธ์ ๋ก์ปฌ ์์ ๋๋ ํ ๋ฆฌ์ ๋ณต์
- JDK 17 ์ค์น
- actions/setup-java@v4
- Java 17 (Temurin ๋ฐฐํฌํ)์ ์ค์น
- application.yml ํ์ผ ๋ง๋ค๊ธฐ
- run: echo "${{ secrets.APPLICATION_PROPERTIES }}" > ./src/main/resources/application.yml
- secrets.APPLICATION_PROPERTIES์ ์ ์ฅ๋ ํ๊ฒฝ ๋ณ์ ๊ฐ์ ์ฝ์ด application.yml ํ์ผ์ ์์ฑ
- ์ด ํ์ผ์ Java ์ ํ๋ฆฌ์ผ์ด์ ์ ์ค์ ํ์ผ๋ก ์ฌ์ฉ
- ํ
์คํธ ๋ฐ ๋น๋
- run: ./gradlew clean build
- Gradle์ ์ฌ์ฉํ์ฌ ํ๋ก์ ํธ๋ฅผ ๋น๋ํ๊ณ ํ ์คํธ
- clean์ ์ด์ ๋น๋์ ๊ฒฐ๊ณผ๋ฅผ ์ง์ฐ๊ณ , build๋ ํ๋ก์ ํธ๋ฅผ ์ปดํ์ผํ๊ณ ํจํค์งํ๋ค.
- ๋น๋๋ ํ์ผ ์ด๋ฆ ๋ณ๊ฒฝ
- run: mv ./build/libs/*SNAPSHOT.jar ./project.jar
- ๋น๋๋ .jar ํ์ผ์ ์ด๋ฆ์ project.jar๋ก ๋ณ๊ฒฝํ์ฌ EC2์ ๋ฐฐํฌํ ํ์ผ์ ์ด๋ฆ์ ๊ณ ์ ์ํจ๋ค.
- SCP๋ก EC2์ ๋น๋๋ ํ์ผ ์ ์ก
- uses: appleboy/scp-action@v0.1.7
- secrets๋ฅผ ์ฌ์ฉํ์ฌ EC2์ ํธ์คํธ ์ฃผ์, ์ฌ์ฉ์ ์ด๋ฆ, SSH ํค๋ฅผ ๊ฐ์ ธ์ค๊ณ ,
- SCP๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๋ project.jar ํ์ผ์ EC2 ์ธ์คํด์ค (๋๋ ํ ๋ฆฌ: ํ์ผ์ /home/ubuntu/instagram-server/tobe)๋ก ์ ์ก
- SSH๋ก EC2์ ์ ์
- uses: appleboy/ssh-action@v1.0.3
- SSH๋ฅผ ์ฌ์ฉํ์ฌ EC2์ ์ ์ํ๊ณ , ๋ฐฐํฌ๋ project.jar ํ์ผ์ ์คํ
- ๊ธฐ์กด์ current ๋๋ ํ ๋ฆฌ๋ฅผ ์ ๊ฑฐ (rm -rf)
- ์๋ก์ด current ๋๋ ํ ๋ฆฌ๋ฅผ ์์ฑ (mkdir)
- tobe ๋๋ ํ ๋ฆฌ์์ current ๋๋ ํ ๋ฆฌ๋ก project.jar ํ์ผ์ ์ด๋ (mv)
- current ๋๋ ํ ๋ฆฌ๋ก ์ด๋ (cd)
- ํ์ฌ ์คํ ์ค์ธ ํ๋ก์ธ์ค๋ฅผ ์ข ๋ฃ (fuser -k -n tcp 8080)
- project.jar ํ์ผ์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์คํํ๊ณ , ๋ก๊ทธ๋ฅผ output.log ํ์ผ์ ๊ธฐ๋ก (nohup java -jar project.jar > ./output.log 2>&1 &)
- tobe ๋๋ ํ ๋ฆฌ๋ฅผ ์ ๊ฑฐํ์ฌ ์์ ํ์ผ์ ์ ๋ฆฌ (rm -rf)
- ํ ์คํธ๋ฅผ ์ํด steps์ ํ๋ ์ถ๊ฐํด๋ณด์
name: Deploy To EC2
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Github Repository ํ์ผ ๋ถ๋ฌ์ค๊ธฐ #github repository ์ฝ๋๋ค์ github actions ์ปดํจํฐ๋ก ๋ถ๋ฌ์ค๋ ๊ฒ
uses: actions/checkout@v4
- name: Test #github actions๋ ํ๋์ ์ปดํจํฐ์ด๊ธฐ์ ์๋ ๋ด์ฉ๋ค์ด ๋์์ผํ๋ค.
run: |
ls
pwd
- name: JDK 17๋ฒ์ ์ค์น
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- name: application.yml ํ์ผ ๋ง๋ค๊ธฐ
run: echo "${{ secrets.APPLICATION_PROPERTIES }}" > ./src/main/resources/application.yml
- name: ํ
์คํธ ๋ฐ ๋น๋ํ๊ธฐ
run: ./gradlew clean build
- name: ๋น๋๋ ํ์ผ ์ด๋ฆ ๋ณ๊ฒฝํ๊ธฐ
run: mv ./build/libs/*SNAPSHOT.jar ./project.jar
- name: SCP๋ก EC2์ ๋น๋๋ ํ์ผ ์ ์กํ๊ธฐ
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
source: project.jar
target: /home/ubuntu/instagram-server/tobe
- name: SSH๋ก EC2์ ์ ์ํ๊ธฐ
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
script_stop: true
script: |
rm -rf /home/ubuntu/instagram-server/current
mkdir /home/ubuntu/instagram-server/current
mv /home/ubuntu/instagram-server/tobe/project.jar /home/ubuntu/instagram-server/current/project.jar
cd /home/ubuntu/instagram-server/current
sudo fuser -k -n tcp 8080 || true
nohup java -jar project.jar > ./output.log 2>&1 &
rm -rf /home/ubuntu/instagram-server/tobe

3. Code Deploy: ํ์ฅ์ฑ ๊ณ ๋ คํ ํ๋ก์ ํธ
- ์ ์ฒด ํ๋ฆ

- ์ฅ์
- ์๋ง์ EC2์ ๋ฐฐํฌ ์ฝ๊ฒ ๊ฐ๋ฅ -> ์๋ฒ ์ฌ๋ฌ ๋์ฌ๋ ์ฝ๊ฒ ์๋ ๋ฐฐํฌ
- ๋ฌด์ค๋จ ๋ฐฐํฌ๊ฐ ๋ด์ฅ ๋์ด ์ฝ๊ฒ ๋ฌด์ค๋จ ๋ฐฐํฌ ๊ฐ๋ฅ
- ๋จ์
- ์ธํ๋ผ ๊ตฌ์กฐ๊ฐ ๋ณต์ก -> ๊ด๋ฆฌ ๋น์ฉ, ์ ์ง๋ณด์ ๋น์ฉ, ๋ณต์กํจ, ํธ๋ฌ๋ธ ์ํ ์ ์ด๋ น๋ฌด
- ์ฌ์ฉ
- ์๋ฒ ์ฌ๋ฌ๋ ๊ตฌ๋ ํ์ ์
- ๋ฌด์ค๋จ ๋ฐฐํฌ ํ์ ์
CodeDeploy ์ธํ / IAM ์ค์
- CodeDeploy Role ์์ฑ
- CodeDeploy ์์ฑ
- EC2 Role ์์ฑ
- Code Deploy Agent ์ค์น
- Github Actions๊ฐ Code Deploy, S3์ ๊ทผ ์ํ IAM ๋ฐ๊ธ
- Github Actions์ Secret Key์ ์ ์ฅ
- ํ๋ก์ ํธ ํ์ผ ์ ์ฅํ S3 ์์ฑ
1. CodeDeploy Role ์์ฑ
- IAM -> ์ญํ -> ์ญํ ์์ฑ -> ์๋น์ค ๋๋ ์ฌ์ฉ ์ฌ๋ก: CodeDeploy, ์ฌ์ฉ ์ฌ๋ก: CodeDeploy -> ๊ถํ์ถ๊ฐ: AwsCodeDeployRole -> ์ญํ ์ด๋ฆ: code-deploy-role -> ์ญํ ์์ฑ

2. CodeDeploy ์์ฑํ๊ธฐ
- codedeploy -> ์ ํ๋ฆฌ์ผ์ด์ -> ์ ํ๋ฆฌ์ผ์ด์ ์์ฑ -> ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ฆ: instagram-server, ์ปดํจํ ํ๋ซํผ:EC2/์จํ๋ ๋ฏธ์ค -> ์์ฑ
- ๋ฐฐํฌ ๊ทธ๋ฃน: ํ๋ก๋์
ํ๊ฒฝ, ์คํ
์ด์ง ํ๊ฒฝ ๋ฑ์ ๊ตฌ๋ถํ๊ธฐ ์ํ ๋จ์
- ๋ง๋ ์๋น์ค ์ญํ ์ ์ ํํ๊ณ
- ๋ฐฐํฌ ์ ํ: ํ์ฌ ์์น
- ํ๊ฒฝ ๊ตฌ์ฑ: EC2 ์ธ์คํด์ค
- ๋ฐฐํฌ ์ ํ: ํ์ฌ ์์น
- ํ๊ฒฝ ๊ตฌ์ฑ - ํค: Name, ๊ฐ: instagram-server
- ๋ฐฐํฌ ์ค์ : CodeDeployDefault.AllAtOnce
- ๋ก๋๋ฐธ๋ฐ์: ๋ก๋๋ฐธ๋ฐ์ฑ ํ์ฑํ ํด์

3. EC2 Role ์์ฑ
- EC2๋ S3์ ์ ๊ทผํด์ ๋น๋ํ์ผ ๋ค์ด๋ฐ์์ผํ๋ฏ๋ก S3์ ์ ๊ทผ๊ฐ๋ฅํ ์ญํ ํ์
- S3์ ์ ๊ทผํ๊ณ , ์กฐํํ๋ ๊ธฐ๋ฅ์ ๊ถํ์ ํ์ฉ
- ์ ์ฑ
์์ฑ
- ์ ์ฑ -> ์ ์ฑ ์์ฑ -> ๊ถํ ์ง์ ํ๊ธฐ -> JSON -> ์๋์ฝ๋ ์ ๋ ฅ -> ์์ฑ -> ์ ์ฑ ์ด๋ฆ code-deploy-ec2-policy -> ์ ์ฑ ์์ฑ
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:Get*",
"S3:List*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
- S3์ ์ ๊ทผํ๊ณ , ์กฐํํ๋ ๊ธฐ๋ฅ์ ๋ชจ๋ ๊ถํ์ ํ์ฉ
- ์ญํ
- ์ญํ ์์ฑ -> EC2 -> code-deploy-ec2-policy๋ผ๋ ๋ฐฉ๊ธ ๋ง๋ ์ ์ฑ ์ ํ -> ์ญํ ์ด๋ฆ code-deploy-ec2-role -> ์ญํ ์์ฑ
- ์ญํ ์ ์ฌ๋ฌ ์ ์ฑ ์ ๊ฐ์ง ์ ์๋ค.
- EC2์ ์์ฑํ IAM ์ฐ๊ฒฐ
- ์ฌ์ฉํ EC2์ ์ -> ์์ -> ๋ณด์ -> IAM ์ญํ ์์ -> code-deploy-ec2-role ์ ํ
4. Code Deploy Agent ์ค์น
- code deploy๊ฐ EC2์๊ฒ ๋ช ๋ น์ ๋ด๋ ค์ผ ํ๋๋ฐ, ์ด ๋ช ๋ น์ code deploy์ธ์ด๋ผ EC2๊ฐ ์ดํด๋ชปํจ -> ๋ฒ์ญ๊ธฐ์ธ agent๊ฐ ํ์
$ sudo apt update && \
sudo apt install -y ruby-full wget && \
cd /home/ubuntu && \
wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install && \
chmod +x ./install && \
sudo ./install auto
- Code Deploy Agent๊ฐ ์ ์์ ์ผ๋ก ์คํ๋๊ณ ์๋ ์ง ํ์ธ
$ systemctl status codedeploy-agent

5. Github Actions๊ฐ CodeDeploy, S3์ ์ ๊ทผํ ์ ์๊ฒ IAM ๋ฐ๊ธ

- aws IAM ์ฌ์ฉ์ -> ์ฌ์ฉ์ ์์ฑ -> ์ฌ์ฉ์ ์ด๋ฆ: instagram-server-github-actions
- ์ง์ ์ ์ฑ ์ฐ๊ฒฐ(AWSCodeDeployFullAccess, AmazonS3FullAccess)
- IAM -> ์ฌ์ฉ์ -> ์์์ ๋ง๋ ์ฌ์ฉ์์ ๋ณด์ ์๊ฒฉ ์ฆ๋ช -> ์ก์ธ์ค ํค ๋ง๋ค๊ธฐ -> AWS ์ธ๋ถ์์ ์คํ๋๋ ์ ํ๋ฆฌ์ผ์ด์ (github actions๋ aws๊ฐ ์๋๋ผ ์ธ๋ถ์์ ์คํ๋๋ฏ๋ก)
6. Github Actions์ Secret Key์ ์ ์ฅํด๋๊ธฐ
- ์ด๋ ๊ฒ ๋ง๋ ์ก์ธ์คํค๋ ๋ฐ๋ก ์ ๋ณด๊ดํด์ผํ๋ค. -> github settings/Secrets and variables/Actions์ ๋ฃ์ผ๋ฉด ๋๋ค.
7. ๋ฐฐํฌ ์ ์ ํ๋ก์ ํธ ํ์ผ ์ ์ฅํ S3 ๋ง๋ค๊ธฐ
- S3 -> ๋ฒํท๋ง๋ค๊ธฐ -> instagram-server๋ผ๋ ๋ฒํท ๋ง๋ค๋ฉด ๋๋ค.
์ถ๊ฐ: CodeDeploy ๋ก๊ทธ ํ์ธ ๋ฐฉ๋ฒ
https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/deployments-view-logs.html
์ค์ต
- ๊ธฐ์กด EC2 8080ํฌํธ์์ ์คํ๋๋ ํ๋ก์ธ์ค๋ ์ข ๋ฃํ๋ค.
ubuntu@ip-10-0-1-7:~$ ls
instagram-server
ubuntu@ip-10-0-1-7:~$ lsof -i:8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 5869 ubuntu 9u IPv6 25441 0t0 TCP *:http-alt (LISTEN)
ubuntu@ip-10-0-1-7:~$ sudo fuser -k -n tcp 8080
8080/tcp: 5869
ubuntu@ip-10-0-1-7:~$ lsof -i:8080
ubuntu@ip-10-0-1-7:~$ ls
instagram-server
ubuntu@ip-10-0-1-7:~$ rm -rf instagram-server/
ubuntu@ip-10-0-1-7:~$ ls
- Github Actions๋ง ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์์ ์ฝ๋๋ฅผ ์์ ํ๋ค.
name: Deploy To EC2
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Github Repository ํ์ผ ๋ถ๋ฌ์ค๊ธฐ
uses: actions/checkout@v4
- name: JDK 17๋ฒ์ ์ค์น
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- name: application.yml ํ์ผ ๋ง๋ค๊ธฐ
run: echo "${{ secrets.APPLICATION_PROPERTIES }}" > ./src/main/resources/application.yml
- name: ํ
์คํธ ๋ฐ ๋น๋ํ๊ธฐ
run: ./gradlew clean build
- name: ๋น๋๋ ํ์ผ ์ด๋ฆ ๋ณ๊ฒฝํ๊ธฐ
run: mv ./build/libs/*SNAPSHOT.jar ./project.jar
- name: SCP๋ก EC2์ ๋น๋๋ ํ์ผ ์ ์กํ๊ธฐ
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
source: project.jar
target: /home/ubuntu/instagram-server/tobe
- name: SSH๋ก EC2์ ์ ์ํ๊ธฐ
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
script_stop: true
script: |
rm -rf /home/ubuntu/instagram-server/current
mkdir /home/ubuntu/instagram-server/current
mv /home/ubuntu/instagram-server/tobe/project.jar /home/ubuntu/instagram-server/current/project.jar
cd /home/ubuntu/instagram-server/current
sudo fuser -k -n tcp 8080 || true
nohup java -jar project.jar > ./output.log 2>&1 &
rm -rf /home/ubuntu/instagram-server/tobe
์ถ์ฒ
๋น์ ๊ณต์๋ ์ดํดํ ์ ์๋ CI/CD ์ ๋ฌธยท์ค์ ๊ฐ์ | JSCODE ๋ฐ์ฌ์ฑ - ์ธํ๋ฐ
JSCODE ๋ฐ์ฌ์ฑ | ๋น์ ๊ณต์ ์ ์ฅ์์๋ ์ฝ๊ฒ ์ดํดํ ์ ์๊ณ , ์ค์ ์์ ๋ฐ๋ก ์ ์ฉ ๊ฐ๋ฅํ CI/CD ์ ๋ฌธ ๊ฐ์๋ฅผ ๋ง๋ค์ด๋ดค์ต๋๋ค!, ๐คฌ ์๋ผ์ด, ๋ชป ํด๋จน๊ฒ ๋ค!๋น์ ๊ณต์๋ก ๊ฐ๋ฐ์ ์์ํด ์ฌ๋ฌ ํ์ฌ์์ CTO๋ก
www.inflearn.com
'๐ณ ์ธํ๋ผ > Cloud & CI-CD' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
EC2, ECR, Docker Compose, Github Actions ์ฌ์ฉํ์ฌ SpringBoot, MongoDB ๋ฐฐํฌํ๊ธฐ (1) | 2024.10.01 |
---|---|
๋น์ ๊ณต์๋ ์ดํดํ ์ ์๋ CI/CD ์ ๋ฌธ/์ค์ (2) (0) | 2024.09.24 |