๐ง ๋ค์ด๊ฐ๊ธฐ์
์ต๊ทผ์ ์์ ์ ์งํํ๋ ํ๋ก์ ํธ๋ฅผ ์ฝํ๋ง(Kotlin + Spring) ๊ธฐ๋ฐ์ผ๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๋ ์์ ์ ์์ํ๊ฒ ๋์๋ค.
๋น์์๋ ์ฝ๋๊ฐ ์์ ๋ ๋๋ง๋ค ๋ก์ปฌ์์ ๋น๋ํ ํ์ผ์ ์๋ฒ์ ์๋์ผ๋ก ์ ๋ก๋ํ๊ณ ์คํํ๋ ๋ฐฉ์์ผ๋ก ๋ฐฐํฌ๋ฅผ ์งํํ์๋ค.
ํ์ง๋ง ์ด๋ฐ ๋ฐฉ์์ ์ฝ๋๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ๋งค๋ฒ ์์์ ์ผ๋ก ๋น๋ ํ์ผ์ ์ฎ๊ฒจ์ผ ํ๋ ๋ฒ๊ฑฐ๋ก์์ด ์์๊ณ , DB๋ ๊ธฐํ ํ๊ฒฝ ์ค์ ๋ค๋ ์๋ฒ์ ์ง์ ์ค์นํ๊ณ ๊ตฌ์ฑํด์ผ ํด์ ๋ถํธํจ์ด ๋ง์๋ค.
๊ทธ๋์ ์ด๋ฒ์๋ ์ด๋ฐ ๋ถํธ์ ์ค์ด๊ธฐ ์ํด, Docker์ GitHub Actions๋ฅผ ํ์ฉํด ์ฝ๋ ๋ณ๊ฒฝ ์ ์๋์ผ๋ก ํ ์คํธ → ๋น๋ → ๋ฐฐํฌ๊ฐ ์ด๋ฃจ์ด์ง๋ CI/CD ํ์ดํ๋ผ์ธ์ ๊ตฌ์ถํด๋ณด๊ณ ์ ํ๋ค.
์ถ๊ฐ๋ก, ๋ฌด์ค๋จ ๋ฐฐํฌ๊น์ง ๋์ ํด๋ณด๋ฉฐ ์ค๋ฌด์ ๊ฐ๊น์ด ๋ฐฐํฌ ํ๊ฒฝ์ ๊ฒฝํํด๋ณผ ๊ณํ์ด๋ค.
๐ธDocker + Github Actions CI/CD ํ์ดํ๋ผ์ธ ์ดํดํ๊ธฐ
Docker์ Github Actions๋ฅผ ํตํ CI/CD์ ๊ณผ์ ์ด ์ด๋ป๊ฒ ์งํํ๋์ง ๋์ ์๋ฆฌ๋ฅผ ์ดํดํด๋ณด์.
1๏ธโฃ on trigger
์ฐ์ ์ workflow์์ trigger๋ฅผ ๊ฑธ์ด์ git์์ ํด๋น ๋์์ด ์ผ์ด๋ฌ์ ๋ github actions๊ฐ ์คํ๋๋ ์๋ฆฌ์ด๋ค.
# event trigger
# main์ด๋ develop ๋ธ๋์น์ push๊ฐ ๋์์ ๋ ์คํ / main์ pr๋๋ฉด ์คํ
on:
pull_request:
branches:
- main
push:
branches:
- develop
- main
workflow_dispatch:
GitHub Actions์์ workflow๋ฅผ ์ด๋ค ์ด๋ฒคํธ์ ๋ฐ์ํด์ ์คํํ ์ง ์ ํ๋ ๋ถ๋ถ์ด ๋ฐ๋ก on: ํธ๋ฆฌ๊ฑฐ์ด๋ค.
์ฃผ์ ํธ๋ฆฌ๊ฑฐ์ ์ข ๋ฅ๋ก๋ ๋ค์๊ณผ ๊ฐ์ด ์๋ค.
- pull_request : ์กฐ๊ฑด์ ๊ฑธ์ด๋ ๋ธ๋์น์ pr์ด ์ผ์ด๋ฌ์ ๋ ์คํ
- push : ์กฐ๊ฑด์ ๊ฑธ์ด๋ ๋ธ๋์น์ push๊ฐ ์ผ์ด๋ฌ์ ๋ ์คํ
- workflow_dispatch: ์๋ ์คํ ๋ฒํผ์ผ๋ก ์ํฌํ๋ก์ฐ๋ฅผ ์คํํ ์ ์๊ฒ ํจ
- schedule: ์ ํด์ง ์๊ฐ๋ง๋ค workflow ์คํ
- release: ๋ฆด๋ฆฌ์ค๋ฅผ ์์ฑ/์์ /์ญ์ ํ ๋ ์คํ
2๏ธโฃ CI์ flow
CI: Continuous Integration(์ง์์ ํตํฉ)์ ์ฝ์๋ก, ๊ฐ๋ฐ์๊ฐ ์์ฑํ ์ฝ๋๋ฅผ ์ง์์ ์ผ๋ก ํตํฉํ๋ฉด์ ๋ฌธ์ ๊ฐ ์๋์ง ์๋์ผ๋ก ๊ฒ์ฌํ๋ ํ๋ก์ธ์ค๋ฅผ ๋งํ๋ค.
CI์ ๊ณผ์ ์ ํฌ๊ฒ "์๋ํ ํ ์คํธ ์คํ" -> "๋น๋"์ ๊ณผ์ ์ ๋ฐ๋ฅธ๋ค.
๐น1. ์๋ํ ํ ์คํธ ์คํ
# ํ
์คํธ
- name: Run tests
run: ./gradlew test --no-daemon
gradle demon์ด๋?:
Gradle์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋น๋ ์๋๋ฅผ ๋น ๋ฅด๊ฒ ํ๊ธฐ ์ํด ๋ฐฑ๊ทธ๋ผ์ด๋์์ "๋ฐ๋ชฌ(daemon)" ํ๋ก์ธ์ค๋ฅผ ๋์๋๊ณ ์ด๋ฅผ ์ฌ์ฌ์ฉํ๋ค. ์ฆ, ํ ๋ฒ ๋น๋๋ฅผ ์คํํ๋ฉด ๋ค์ ๋น๋๋ถํฐ๋ ๋ฉ๋ชจ๋ฆฌ์ ์์ฃผํ Gradle ๋ฐ๋ชฌ์ด ์์ ์ ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌํ ์ ์๋ค.
ํ์ง๋ง CI์ ํ๊ฒฝ์์๋ demon์ ๊บผ์ฃผ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด๋ค.
- ํ๊ฒฝ์ด ์ผํ์ฑ์ด๊ณ ํ๋ฐ์ฑ์ด๊ธฐ ๋๋ฌธ
→ CI ํ๊ฒฝ์ ์คํ ํ ์ข ๋ฃ๋๊ธฐ ๋๋ฌธ์, ๋ฐ๋ชฌ์ ๋์๋ดค์ ๋ค์ ์ฌ์ฌ์ฉํ์ง ๋ชปํ๋ค. - ๋ฉ๋ชจ๋ฆฌ ์ ์ฝ ๋ฐ ์์ ์ฑ
→ ๋ฐ๋ชฌ์ ์ฌ์ฉํ๋ฉด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ ์ก์๋จน๊ณ , ๊ฐํน ์๊ธฐ์น ์์ ์๋ฌ๋ ์บ์ฑ ์ด์๊ฐ ์๊ธด๋ค.
๐น2. ๋น๋
# gradle build, demon ์ฌ์ฉ x
- name: build
run: ./gradlew build --no-daemon
๋น๋๊น์ง ์๋ฃํ๋ฉด CI์ ๊ณผ์ ์ด ์๋ฃ๋๋ค.
3๏ธโฃ Docker ์ด๋ฏธ์ง build & push
์ฝ๋์ ๋ฐ๋ ๋ด์ฉ์ ์ด๋ป๊ฒ ๋ณด๋ผ ๊ฒ์ธ๊ฐ?
์ฝ๋๊ฐ ๋ฐ๋ ๋๋ง๋ค ์ด๋ฅผ ์๋ฒ์ ๋ฐ์ํ๋ ๊ฐ์ฅ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์, ์ฝ๋๋ฅผ Docker ์ด๋ฏธ์ง๋ก ๋น๋ํ ๋ค Docker Hub์ ์ ๋ก๋ํ๋ ๊ฒ์ด๋ค. ์ด๋ ๊ฒ ์ด๋ฏธ์ง๋ฅผ ์ ๋ก๋ํด๋๋ฉด, ์๋ฒ์์๋ Docker Hub์ ๋ก๊ทธ์ธํ ํ ํด๋น ์ด๋ฏธ์ง๋ฅผ pullํด์์ ๊ณง๋ฐ๋ก ์ปจํ ์ด๋๋ก ์คํ์ํฌ ์ ์๋ค.
# JDK 17 slim ์ด๋ฏธ์ง ์ฌ์ฉ
FROM openjdk:17-jdk-slim
# ์์
๋๋ ํ ๋ฆฌ ์ค์
WORKDIR /app
# ๋น๋๋ JAR ๋ณต์ฌ
COPY build/libs/*.jar app.jar
# ์คํ ๋ช
๋ น์ด
ENTRYPOINT ["java", "-jar", "app.jar"]
๊ทธ๋ ๋ค๋ฉด Docker ์ด๋ฏธ์ง๋ฅผ buildํ๊ธฐ ์ํด์๋ ์์ ๊ฐ์ Dockerfile์ ํ๋ก์ ํธ ๋ฃจํธ ๋๋ ํ ๋ฆฌ์ ์ ์ํด์ผํ๋ค.
์ด๋ ๊ฒ ๋๋ฉด ๋ด ํ๋ก์ ํธ์ ์ฝ๋๊ฐ JDK 17 ์ด๋ฏธ์ง๋ก ๊ฐ์ธ์ ธ์ Docker hub์ ๋ณด๋ผ ์ ์๋ ์ฌ์ ์์ ์ ๋ง์น ๊ฒ์ด๋ค.
# Dockerfile app ์ด๋ฏธ์ง build & push
- name: Docker Log in
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: build Docker Image
run: docker build -t ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGENAME }}:latest .
- name: push Docker Hub
run: docker push ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGENAME }}:latest
Docker hub์ ํ์๊ฐ์ ์ ํ๊ณ USERNAME๊ณผ PASSWORD๋ฅผ github secrets variable์ ์ ์ํด์ผํ๋ค.
CD job์์ ์์ ๊ฐ์ด DOCKER_USERNAME๊ณผ DOCKER_PASSWORD๋ฅผ ํตํด docker hub์ ์ฐ๊ฒฐ์ ํ๊ณ Dockerfile๋ก ๋น๋๋ Image๋ฅผ Docker hub์ pushํ๋ค.
4๏ธโฃ ssh to server & pull docker image
๋ค์์ผ๋ก๋ docker์ image๋ฅผ pushํ์ผ๋ฏ๋ก ์๋ฒ์ ์ ์์ ํด์ pushํ๋ image๋ฅผ ๊ฐ์ ธ์ฌ ๊ฒ์ด๋ค.
# ssh๋ก ์๋ฒ ์ ์ํด์ ์ปจํ
์ด๋ ๋์ฐ๊ธฐ
- name: ssh to ec2 and deploy
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
docker rmi -f ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGENAME }}:latest
docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGENAME }}:latest
github actions์์ ์๋ฒ์ ์ ์ํด์ผํ๋ฏ๋ก, ssh๋ฅผ ํตํด ์๋ฒ์ ์ ์ ํ ํ ๊ธฐ์กด์ ์๋ image๋ฅผ ์ญ์ ํ๊ณ push ํ๋ ์ด๋ฏธ์ง๋ฅผ pullํด์ค๋ ๊ณผ์ ์ด๋ค.
5๏ธโฃ DB ๊ด๋ จ ์ปจํ ์ด๋ ๋ฏธ๋ฆฌ ์๋ฒ์ ๋์๋๊ธฐ
ํ์ฌ app๊ณผ ๊ด๋ จ๋ image๋ฅผ pullํด์จ ์ํ์ด๋ค.
๋ฌผ๋ก CD job์ ๊ณผ์ ์์ db์ ๊ด๋ จ๋ ๋ถ๋ถ๋ค๋ ํจ๊ป docker compose๋ก ๋ด๋ ธ๋ค๊ฐ ๋์ธ ์ ์๊ฒ ์ง๋ง, ๊ทธ๋ ๊ฒ ๋๋ ๊ฒฝ์ฐ์๋ ๋ฐ์ดํฐ๊ฐ ์์ค์ ์ํ์ด ์๋ค.
docker compose down ๋ช ๋ น์ด๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ปจํ ์ด๋์ ํจ๊ป ์ฐ๊ฒฐ๋ ๋คํธ์ํฌ์ ๋ณผ๋ฅจ๊น์ง ์ ๊ฑฐํ๋ค.
๋ฐ๋ผ์ DB ์ปจํ ์ด๋์ ๋ณ๋๋ก ๋ณผ๋ฅจ์ ์ค์ ํด๋์ง ์์๋ค๋ฉด, ์ปจํ ์ด๋๊ฐ ๋ด๋ ค๊ฐ๋ ์๊ฐ DB ๋ฐ์ดํฐ๋ ํจ๊ป ์ญ์ ๋๋ค.
์ด๋ฌํ ์ด์ ๋ก, ๋ฐฐํฌ ์์๋ ์ฑ ์ปจํ
์ด๋๋ง ๋ด๋ ธ๋ค๊ฐ ๋ค์ ์ฌ๋ฆฌ๋ ๋ฐฉ์์ด ๋ ์์ ํ๊ณ ํจ์จ์ ์ด๋ค.
์ฑ ์ปจํ ์ด๋๋ง ๋ด๋ ธ๋ค๊ฐ ๋ค์ ์ฌ๋ฆฌ๋ ๋ฐฉ์์ผ๋ก ์งํํ๋ ค๋ฉด CI/CD๋ฅผ ์งํํ๊ธฐ ์ ์ ์๋ฒ์ docker-compose๋ก db๊ด๋ จ image๋ค์ ๋์์ผ ํ๋ค. db ์๋ฒ๊ฐ ๋์์ ธ ์์ด์ผ app ์ปจํ ์ด๋๊ฐ ์ ๋๋ก ๋์ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
6๏ธโฃ app ์ปจํ ์ด๋ ๋์ฐ๊ธฐ -> ์๋ฒ ์คํ
์ต์ข ์ ์ผ๋ก ์๋ฒ๋ฅผ ์คํํ๋ ๊ณผ์ ์ด๋ค.
services:
app:
image: your-docker-username/daboa-app:latest
container_name: springboot-app
ports:
- "8080:8080"
environment:
<<ํ์ํ ํ๊ฒฝ๋ณ์ ์ ์ํด์ฃผ๊ธฐ>>
์์ docker-compose.yml์ ์๋ฒ์ ๋ฏธ๋ฆฌ ์ ์ํด๋๋ค.
# ssh๋ก ์๋ฒ ์ ์ํด์ ์ปจํ
์ด๋ ๋์ฐ๊ธฐ
- name: ssh to ec2 and deploy
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
docker rmi -f ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGENAME }}:latest
docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGENAME }}:latest
cd /home/ubuntu/daboa/docker/app
docker compose up -d
docker image prune -f
๊ทธ๋ ๊ฒ ๋๋ฉด CD job ๊ณผ์ ์ค์ docker compose up -d ๋ช ๋ น์ด๊ฐ ๋ค์ด์์ ๋ ์ด๋ฏธ์ง๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ปจํ ์ด๋๋ฅผ ๋์ธ ์ ์๋ค.
๐ก ํด๋น ๊ณผ์ ์ด ๋ฌด์ค๋จ ๋ฐฐํฌ๊ฐ ์๋ ์ด์ ?
docker rmi -f ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGENAME }}:latest
docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGENAME }}:latest
cd /home/ubuntu/daboa/docker/app
docker compose up -d
docker image prune -f
ํด๋น ๊ณผ์ ์ค ๊ธฐ์กด์ ์ด๋ฏธ์ง๋ฅผ ์ญ์ ํ๊ณ ๋ค์ pullํด์์ docker compose๋ก ์ปจํ ์ด๋๋ฅผ ๋์ฐ๋ ๊ณผ์ ์ด ์๋ค.
์ฆ, ์ด ํ๋ฆ์ ๊ธฐ์กด ์ฑ ์ปจํ ์ด๋๋ฅผ ์ค๋จํ๊ณ , ๊ทธ ๋ค์์ ์๋ก์ด ์ปจํ ์ด๋๋ฅผ ์คํํ๋ ๋ฐฉ์์ด๊ธฐ ๋๋ฌธ์ ์ค๋จ ๋ฐฐํฌ ๋๋ ์ค์ง ํ ์ฌ๋ฐฐํฌ ๋ฐฉ์์ด๋ผ๊ณ ๋ถ๋ฆฐ๋ค.
๋ฐ๋ผ์ ์๋น์ค๊ฐ ๋ฐฐํฌ ์ค ์ผ์์ ์ผ๋ก๋ผ๋ ๋ด๋ ค๊ฐ ์๋ ์ํ๊ฐ ๋ฐ์ํ ์ ์๋ ๋ฐฉ์์ด๋ค.
๐ธWorkflow ์คํฌ๋ฆฝํธ
name: CI/CD with Docker
# event trigger
# main์ด๋ develop ๋ธ๋์น์ push๊ฐ ๋์์ ๋ ์คํ / main์ pr๋๋ฉด ์คํ
on:
pull_request:
branches:
- main
push:
branches:
- develop
- main
workflow_dispatch:
jobs:
ci:
name: Run CI
runs-on: ubuntu-latest
steps:
# ํ์ฌ ์ํฌํ๋ก์ฐ๋ฅผ ์คํํ๋ ์ ์ฅ์์ ์์ค ์ฝ๋๋ฅผ ๊ฐ์ ธ์ค๋ ์์
- name: checkout
uses: actions/checkout@v4
# JDK setting - github actions์์ ์ฌ์ฉํ JDK ์ค์
- name: setting JDK
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
# gradlew ์คํ๊ถํ ๋ถ์ฌ
- name: Grant execute permission to gradlew
run: chmod +x ./gradlew
# gradle caching - ๋น๋ ์๊ฐ ํฅ์
- name: Gradle cashing
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
gradle-${{ runner.os }}-
# ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ค์ด๋ก๋
- name: dependency
run: ./gradlew dependencies
# ํ
์คํธ
- name: Run tests
run: ./gradlew test --no-daemon
# gradle build, demon ์ฌ์ฉ x
- name: build
run: ./gradlew build --no-daemon
# build๋ jar ํ์ผ ์ ์ฅ
- name: upload artifact
uses: actions/upload-artifact@v4
with:
name: jar
path: build/libs/*.jar
cd:
name: Build & Deploy
runs-on: ubuntu-latest
needs: ci
steps:
- name: code checkout
uses: actions/checkout@v4
# jar ํ์ผ ๊ฐ์ ธ์ค๊ธฐ
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: jar
path: build/libs
# Dockerfile app ์ด๋ฏธ์ง build & push
- name: Docker Log in
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: build Docker Image
run: docker build -t ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGENAME }}:latest .
- name: push Docker Hub
run: docker push ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGENAME }}:latest
# ssh๋ก ์๋ฒ ์ ์ํด์ ์ปจํ
์ด๋ ๋์ฐ๊ธฐ
- name: ssh to ec2 and deploy
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
docker rmi -f ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGENAME }}:latest
docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGENAME }}:latest
cd /home/ubuntu/daboa/docker/app
docker compose up -d
docker image prune -f
๐จํธ๋ฌ๋ธ ์ํ
1๏ธโฃ docker ๊ทธ๋ฃน ๊ถํ ๋ถ์ฌํ๊ธฐ
docker compose up -d
CI/CD๋ฅผ ๋ฐฐํฌํ๊ธฐ ์ docker compose๋ก db๊ด๋ จ๋ ๊ฒ๋ค์ ๋์ธ๋ผ ํ๋๋ฐ,
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock
ํ์ฌ ์ฌ์ฉ์๊ฐ docker ๊ทธ๋ฃน์ ์ํด์์ง ์์ docker compose๋ฅผ ์คํํ ๊ถํ์ด ์๋ค๊ณ ์๋ฌ๊ฐ ๋ด๋ค.
๐ง ํด๊ฒฐํ๊ธฐ
sudo usermod -aG docker $USER
ํ์ฌ ์ ์ ์๊ฒ docker ๊ทธ๋ฃน์ ์ถ๊ฐํด์ฃผ๋ ๋ช ๋ น์ด๋ฅผ ์คํํ๋ค.
๊ทธ๋ฆฌ๊ณ ์๋ฒ๋ฅผ ์ฌ์คํํ ์ดํ์ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํ๋ฉด ์์ ๊ฐ์ด docker ์ปจํ ์ด๋๊ฐ ์ ๋๋ก ๋จ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
2๏ธโฃ gradlew ์คํ๊ถํ ๋ถ์ฌ
# ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ค์ด๋ก๋
- name: dependency
run: ./gradlew dependencies
CI๋ฅผ ์คํํ๋ ๊ณผ์ ์ค ์์ ํ๋ก์ฐ๋ฅผ ์งํํ๋ ๋์ค gradlew์ ๋ํ ์คํ๊ถํ์ด ์์ด์ ๋จ๋ ์๋ฌ์ด๋ค.
๐งํด๊ฒฐํ๊ธฐ
# gradlew ์คํ๊ถํ ๋ถ์ฌ
- name: Grant execute permission to gradlew
run: chmod +x ./gradlew
ํ๋ก์ฐ ์ค์ ์์ ๊ฐ์ด ๊ถํ์ ๋ถ์ฌํด์ฃผ์๋ค.
์ฑ๊ณต์ ์ผ๋ก CI๋ฅผ ์๋ฃํ์๋ค.
3๏ธโฃ CD ๊ณผ์ ์ค jar ํ์ผ์ ์ฐพ์ง ๋ชปํจ
#9 ERROR: lstat /var/lib/docker/tmp/buildkit-mount.../build/libs: no such file or directory
# ๋น๋๋ JAR ๋ณต์ฌ
COPY build/libs/*.jar app.jar
Dockerfile์ ์คํํ๋ ๊ณผ์ ์์, ํด๋น ๋ช ๋ น์ด๋ฅผ ์คํํ๋ ๊ณผ์ ์ค์ *.jar๋ฅผ ์ฐพ์ง ๋ชปํด ๋ฐ์ํ๋ ์๋ฌ์ด๋ค.
์ด์ ๋ CI๋จ๊ณ์์ jar๋ฅผ ๋น๋ํ๋๋ฐ CD๋ฅผ ๋ค์ ์์ํ๋ฉด์ jarํ์ผ์ ๋ถ๋ฌ์ค์ง ๋ชปํด์ ๊ทธ๋ฐ๊ฒ์ด๋ค.
๐งํด๊ฒฐํ๊ธฐ
github actions์๋ artifact๋ผ๋ ์ค๊ฐ ๊ฒฐ๊ณผ๋ฌผ์ ์ ์ฅํ ์ ์๋ ๊ณต๊ฐ์ด ์๋ค.
๋ฐ๋ผ์ artifact๋ฅผ ์ด์ฉํ๋ฉด ์ฝ๊ฒ ํด๊ฒฐํ ์ ์๋ค.
# CI ๋ง์ง๋ง์
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: jar
path: build/libs/*.jar
# CD ์์ ์
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: jar
path: build/libs/
- ๋ฌธ์ ์ : CI Job์์ .jar ํ์ผ์ ๋น๋ํจ → ํ์ง๋ง CD Job์์๋ ํ์ผ์ด ์ฌ๋ผ์ง
- ํด๊ฒฐ๋ฒ: CI Job์์ artifact๋ก ์ ๋ก๋ํ๊ณ → CD Job์์ ๋ค์ด๋ก๋ํด์ ์ด์ด์ ์ฌ์ฉ
์ฑ๊ณต์ ์ผ๋ก CI/CD ํ์ดํ๋ผ์ธ์ ๊ตฌ์ถํ์๋ค.