• ABOUT
  • PORTFOLIO
  • POSTS
  • GUESTBOOK

ยฉ 2025 BlueCool12 All rights reserved.

2025.09.17ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

๐Ÿž CI/CD ์˜ค๋ฅ˜: GHCR์„ ์ด์šฉํ•œ GitHub Actions ์ตœ์ ํ™” ๋ฐฐํฌ

1. ๋ฌธ์ œ ์ƒํ™ฉ

๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ GitHub Actions ๊ตฌ์„ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์•˜๋‹ค. 

name: Deploy to Raspberry Pi 

on:
push:
branches: [ main ]

jobs:
deploy:
name: Deploy via SSH
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup SSH
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

- name: SSH and deploy to Raspberry Pi
run: |
ssh -p ${{ secrets.RASPBERRY_PORT }} -o StrictHostKeyChecking=no ${{ secrets.RASPBERRY_USER }}@${{ secrets.RASPBERRY_HOST }} << 'EOF'
set -euo pipefail

cd /home/${{ secrets.RASPBERRY_USER }}/docker-compose/bluecool/blue
git fetch --all --prune
git reset --hard origin/main
git config core.ignorecase false

docker compose build --no-cache blue
docker compose up -d --force-recreate blue

docker image prune -f || true
EOF

ํ”„๋กœ์ ํŠธ ๊ทœ๋ชจ๊ฐ€ ์ž‘์„๋•Œ์—๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ์ง€๋งŒ ์ ์  ๊ทœ๋ชจ๊ฐ€ ์ปค์ง€๋ฉด์„œ ์„œ๋ฒ„ ์ธก์—์„œ docker compose build --no-cache ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ์‹ ๋•Œ๋ฌธ์— ๋นŒ๋“œ ์‹œ๊ฐ„์ด ์ฆ๊ฐ€ํ•˜์—ฌ ํƒ€์ž„์•„์›ƒ์ด ๋ฐœ์ƒํ–ˆ๋‹ค. 


2. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

CI์—์„œ ์ด๋ฏธ์ง€๋ฅผ GHCR์— ๋นŒ๋“œ/ํ‘ธ์‹œํ•˜๊ณ  ์„œ๋ฒ„๋Š” ๋นŒ๋“œ ์—†์ด pull๋งŒ ํ•˜๋„๋ก ๋ณ€๊ฒฝํ–ˆ๋‹ค.

GHCR์€ GitHub์—์„œ ์ œ๊ณตํ•˜๋Š” ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€ ์ €์žฅ์†Œ ์„œ๋น„์Šค์ด๋‹ค. Docker Hub์™€ ์œ ์‚ฌํ•œ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๋ฉฐ ๋ณ„๋„์˜ ์™ธ๋ถ€ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ์„ค์ • ์—†์ด GitHub Actions ๋‚ด์—์„œ ์ด๋ฏธ์ง€ ํ‘ธ์‹œ ๋ฐ ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

๋ณ€๊ฒฝ๋œ ์„ค์ •์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค. 

name: Build & Deploy to Raspberry Pi

on:
push:
branches: [ main ]

concurrency:
group: blue-deploy-${{ github.ref }}
cancel-in-progress: true

env:
IMAGE_NAME: ghcr.io/bluecool12/blue

jobs:
build:
name: Build & Push (GHCR)
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4

- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3

- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build & Push
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/arm64
push: true
tags: |
${{ env.IMAGE_NAME }}:latest
${{ env.IMAGE_NAME }}:${{ github.sha }}
cache-from: type-gha
cache-to: type-gha,mode=max
build-args: |
NEXT_PUBLIC_API_BASE_URL=${{ vars.NEXT_PUBLIC_API_BASE_URL }}
PUBLIC_API_BASE_URL=${{ vars.PUBLIC_API_BASE_URL }}

deploy:
name: Deploy via SSH (pull & up)
runs-on: ubuntu-latest
needs: build
steps:
- name: Setup SSH
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

- name: Add host key (known_hosts)
run: |
mkdir -p ~/.ssh
ssh-keyscan -p "${{ secrets.RASPBERRY_PORT }}" -H "${{ secrets.RASPBERRY_HOST }}" >> ~/.ssh/known_hosts
chmod 700 ~/.ssh
chmod 644 ~/.ssh/known_hosts

- name: SSH and deploy to Raspberry Pi
run: |
ssh -p ${{ secrets.RASPBERRY_PORT }} \
-o ServerAliveInterval=30 -o ServerAliveCountMax=10 \
${{ secrets.RASPBERRY_USER }}@${{ secrets.RASPBERRY_HOST }} << 'EOF'
set -Eeuo pipefail

cd /home/${{ secrets.RASPBERRY_USER }}/docker-compose/bluecool/blue

git fetch --all --prune || true
git reset --hard origin/main || true
git config core.ignorecase false || true

docker compose pull blue
docker compose up -d blue
docker image prune -f || true
EOF

๊ธฐ์กด์˜ Dockerfile์„ ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋กœ ์˜ฎ๊ธฐ๊ณ  GitHub Actions์—์„œ GHCR๋กœ ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œ/ํ‘ธ์‹œํ•˜๋„๋ก ๊ตฌ์„ฑํ•˜์˜€๊ณ  Buildx๋ฅผ ๋„์ž…ํ•˜์˜€๋‹ค.

Buildx๋Š” Docker์˜ ์ฐจ์„ธ๋Œ€ ๋นŒ๋“œ ์—”์ง„์ธ BuildKit์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ํ™•์žฅ ๋„๊ตฌ๋‹ค. ๋ฉ€ํ‹ฐ ํ”Œ๋žซํผ ๋นŒ๋“œ๋ฅผ ์ง€์›ํ•˜๋ฉฐ GitHub Actions ์ „์šฉ ์บ์‹œ(type-gha)๋ฅผ ํ™œ์šฉํ•ด ๋นŒ๋“œ ์‹œ๊ฐ„์„ ํš๊ธฐ์ ์œผ๋กœ ๋‹จ์ถ•ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ™ˆ์„œ๋ฒ„์—์„œ๋Š” docker-compose.yml์ด ํ•ด๋‹น ์ด๋ฏธ์ง€๋ฅผ ์ฐธ์กฐํ•˜๋„๋ก ์ˆ˜์ •ํ•˜๊ณ  ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋˜ํ•œ GitHub Variables๋ฅผ ํ†ตํ•ด ์ฃผ์ž…ํ•˜์˜€๋‹ค. 

๋˜ํ•œ SSH ์ ‘์† ์‹œ ํ˜ธ์ŠคํŠธ ์ธ์ฆ์„ ์ƒ๋žตํ•˜์ง€ ์•Š๊ณ  known_hosts์— ํ‚ค๋ฅผ ๋ฏธ๋ฆฌ ๋“ฑ๋กํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•˜์˜€๋‹ค. 

์ด์ „ ๊ธ€
๐Ÿ” chownยทchmod๋กœ ๋ฐฐ์šฐ๋Š” ๋ฆฌ๋ˆ…์Šค ํŒŒ์ผ ๊ถŒํ•œ ๊ด€๋ฆฌ
๋‹ค์Œ ๊ธ€
๐Ÿ“ก ์ธํ„ฐ๋„ท ํ†ต์‹ ์˜ ํ•ต์‹ฌ - TCP, IP ๊ทธ๋ฆฌ๊ณ  UDP ์ดํ•ดํ•˜๊ธฐ
์žฅ์‹์šฉ ๋กœ๊ณ