-
Notifications
You must be signed in to change notification settings - Fork 0
173 lines (150 loc) · 6.55 KB
/
Copy pathdeploy-to-dev-ec2-docker.yml
File metadata and controls
173 lines (150 loc) · 6.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
name: Deploy Admin to Dev (ARM64 EC2 + Docker Compose)
on:
push:
branches: [ develop ]
workflow_dispatch: {}
concurrency:
group: deploy-admin-dev
cancel-in-progress: false
jobs:
deploy:
# 서버 전환이 끝나기 전에는 develop 머지가 새 서버를 자동으로 변경하지 않게 한다.
# 검증이 끝난 뒤 저장소 변수 DEV_ARM64_AUTODEPLOY를 true로 설정한다.
if: ${{ github.event_name == 'workflow_dispatch' || vars.DEV_ARM64_AUTODEPLOY == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
environment: dev
steps:
- name: 🧾 Checkout
uses: actions/checkout@v4
- name: 🔡 Normalize image repo (lowercase)
id: normalize
run: echo "image_repo=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT"
- name: 🏗️ Setup QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64
- name: 🧱 Setup Buildx
uses: docker/setup-buildx-action@v3
- name: 🔐 Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ secrets.GHCR_USERNAME }}
password: ${{ secrets.GHCR_TOKEN }}
- name: 🏷️ Meta (tags/labels)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ steps.normalize.outputs.image_repo }}
tags: |
type=raw,value=dev-latest
type=sha,format=long,prefix=dev-
- name: 🏗️ Build & Push ARM64 Image
id: build
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
platforms: linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ steps.normalize.outputs.image_repo }}:buildcache-arm64
cache-to: type=registry,ref=${{ steps.normalize.outputs.image_repo }}:buildcache-arm64,mode=max
- name: 📁 Prepare deployment directory
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.EC2_HOST }}
username: ubuntu
key: ${{ secrets.EC2_SSH_PRIVATE_KEY }}
script: |
set -euo pipefail
# 최초 배포 시에도 사용자가 디렉터리를 직접 만들 필요가 없게 한다.
install -d -m 0750 "${HOME}/saerok-admin"
- name: 📤 Copy compose files to EC2
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ubuntu
key: ${{ secrets.EC2_SSH_PRIVATE_KEY }}
source: "deploy/docker-compose.yml,deploy/docker-compose.dev.yml"
# 기존 서버와 동일하게 ubuntu 사용자의 홈 아래에 배포한다.
target: ~/saerok-admin/
strip_components: 1
- name: 🚀 Deploy on EC2
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.EC2_HOST }}
username: ubuntu
key: ${{ secrets.EC2_SSH_PRIVATE_KEY }}
script: |
set -euo pipefail
DEPLOY_DIR="${HOME}/saerok-admin"
IMAGE_REF="${{ steps.normalize.outputs.image_repo }}@${{ steps.build.outputs.digest }}"
cd "$DEPLOY_DIR"
# 0) Docker와 Compose가 설치되어 있는지 확인한다.
docker --version
docker compose version
# 1) 관리자 이미지 pull을 위해 GHCR에 로그인한다.
echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u "${{ secrets.GHCR_USERNAME }}" --password-stdin
# 2) 인증정보는 디스크의 배포 폴더가 아닌 /run의 임시 파일로 전달한다.
sudo install -d -m 0700 -o "$(id -un)" -g "$(id -gn)" /run/saerok-admin
ENV_FILE="/run/saerok-admin/env.dev"
umask 177
: > "$ENV_FILE"
cleanup() { shred -u "$ENV_FILE" || rm -f "$ENV_FILE"; }
trap cleanup EXIT
add_kv() { printf '%s\n' "$1=$2" >> "$ENV_FILE"; }
add_kv SPRING_PROFILES_ACTIVE "dev"
add_kv SAEROK_API_BASE_URL "${{ secrets.SAEROK_API_BASE_URL }}"
add_kv SAEROK_API_PREFIX "${{ secrets.SAEROK_API_PREFIX }}"
add_kv KAKAO_CLIENT_ID "${{ secrets.KAKAO_CLIENT_ID }}"
add_kv KAKAO_REDIRECT_URI "${{ secrets.KAKAO_REDIRECT_URI }}"
add_kv APPLE_CLIENT_ID "${{ secrets.APPLE_CLIENT_ID }}"
add_kv APPLE_REDIRECT_URI "${{ secrets.APPLE_REDIRECT_URI }}"
add_kv UNSPLASH_ACCESS_KEY "${{ secrets.UNSPLASH_ACCESS_KEY }}"
add_kv UNSPLASH_APP_NAME "${{ secrets.UNSPLASH_APP_NAME }}"
add_kv IMAGE_REF "$IMAGE_REF"
add_kv ENV_FILE "$ENV_FILE"
# 3) 이번 실행에서 만든 digest 이미지로 관리자 컨테이너를 교체한다.
docker pull "$IMAGE_REF"
docker compose \
--env-file "$ENV_FILE" \
-p saerok-admin \
-f docker-compose.yml \
-f docker-compose.dev.yml \
up -d --force-recreate --quiet-pull app
docker compose \
--env-file "$ENV_FILE" \
-p saerok-admin \
-f docker-compose.yml \
-f docker-compose.dev.yml \
ps
# 4) Nginx를 거치기 전 localhost에서 로그인 화면을 확인한다.
echo "Waiting for admin login page..."
for i in {1..45}; do
if curl -fsS -I http://127.0.0.1:8081/login > /dev/null; then
echo "Admin healthcheck passed"
docker image prune -af --filter "until=24h" || true
docker builder prune -af --filter "until=24h" || true
exit 0
fi
echo "Waiting ($i/45)..."
sleep 3
done
echo "Admin healthcheck failed after retries"
# 세션이나 인증정보가 포함될 수 있는 원문 로그는 공개 Actions에 출력하지 않는다.
docker inspect --format 'admin status={{.State.Status}} health={{.State.Health.Status}} restart={{.RestartCount}}' saerok-admin-dev || true
exit 1
- name: Summarize deployment
if: ${{ success() }}
run: |
{
echo "## Dev admin arm64 deploy"
echo "- Platform: linux/arm64"
echo "- Image: ${{ steps.normalize.outputs.image_repo }}@${{ steps.build.outputs.digest }}"
echo "- Commit: ${{ github.sha }}"
} >> "$GITHUB_STEP_SUMMARY"