Skip to content

Commit 5621c04

Browse files
authored
fix: repair deploy image build (#32)
1 parent 55a56de commit 5621c04

6 files changed

Lines changed: 51 additions & 34 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -82,34 +82,44 @@ jobs:
8282
cache-to: type=gha,mode=max
8383

8484
# ---------------------------------------------------------------------------
85-
# 2) SSH 로 N100 접속 → docker compose pull && up -d
85+
# 2) N100 SSH secrets 준비 여부 확인. 미등록이면 이미지 build/push 까지만 하고 deploy 는 skip.
86+
# ---------------------------------------------------------------------------
87+
deploy-preflight:
88+
name: Check deploy secrets
89+
runs-on: ubuntu-latest
90+
timeout-minutes: 3
91+
outputs:
92+
deploy_ready: ${{ steps.secrets.outputs.deploy_ready }}
93+
steps:
94+
- name: Check N100 secrets
95+
id: secrets
96+
run: |
97+
if [ -n "$N100_HOST" ] && [ -n "$N100_USER" ] && [ -n "$N100_SSH_KEY" ]; then
98+
echo "deploy_ready=true" >> "$GITHUB_OUTPUT"
99+
else
100+
echo "deploy_ready=false" >> "$GITHUB_OUTPUT"
101+
echo "::notice::N100 deploy secrets are not configured yet. Image build/push completed; SSH deploy is skipped."
102+
fi
103+
env:
104+
N100_HOST: ${{ secrets.N100_HOST }}
105+
N100_USER: ${{ secrets.N100_USER }}
106+
N100_SSH_KEY: ${{ secrets.N100_SSH_KEY }}
107+
108+
109+
# ---------------------------------------------------------------------------
110+
# 3) SSH 로 N100 접속 → docker compose pull && up -d
86111
# ---------------------------------------------------------------------------
87112
deploy:
88113
name: Deploy to ${{ needs.build.outputs.target }}
89-
needs: build
114+
needs: [build, deploy-preflight]
115+
if: needs.deploy-preflight.outputs.deploy_ready == 'true'
90116
runs-on: ubuntu-latest
91117
timeout-minutes: 10
92118
# prod 는 환경(environment) 보호로 수동 승인 가능
93119
environment:
94120
name: ${{ needs.build.outputs.target }}
95121

96122
steps:
97-
- name: Sanity check secrets
98-
run: |
99-
missing=""
100-
for v in N100_HOST N100_USER N100_SSH_KEY; do
101-
eval val="\$$v"
102-
if [ -z "$val" ]; then missing="$missing $v"; fi
103-
done
104-
if [ -n "$missing" ]; then
105-
echo "::error::Missing required secrets:$missing"
106-
echo "GitHub repo Settings → Secrets and variables → Actions 에서 등록하세요."
107-
exit 1
108-
fi
109-
env:
110-
N100_HOST: ${{ secrets.N100_HOST }}
111-
N100_USER: ${{ secrets.N100_USER }}
112-
N100_SSH_KEY: ${{ secrets.N100_SSH_KEY }}
113123

114124
- name: Pull & restart on N100
115125
uses: appleboy/ssh-action@v1.0.3
@@ -118,11 +128,12 @@ jobs:
118128
username: ${{ secrets.N100_USER }}
119129
key: ${{ secrets.N100_SSH_KEY }}
120130
# 호스트의 deploy/ 디렉터리에서 pull → up.
121-
# IMAGE_TAG 가 .env 의 placeholder 를 덮어쓰며 docker compose 가 사용.
131+
# IMAGE_TAG selects the pushed GHCR image; MURUN_ENV_FILE selects .env.staging/.env.prod.
122132
script: |
123133
set -e
124134
cd ${MURUN_DEPLOY_DIR:-~/murun-peterabcd/deploy}
125135
export IMAGE_TAG="${{ needs.build.outputs.image_tag }}"
126-
docker compose -p murun-${{ needs.build.outputs.target }} pull
127-
docker compose -p murun-${{ needs.build.outputs.target }} up -d --remove-orphans
136+
export MURUN_ENV_FILE=".env.${{ needs.build.outputs.target }}"
137+
docker compose -p murun-${{ needs.build.outputs.target }} --env-file "$MURUN_ENV_FILE" pull
138+
docker compose -p murun-${{ needs.build.outputs.target }} --env-file "$MURUN_ENV_FILE" up -d --remove-orphans
128139
docker image prune -f

deploy/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ RUN apk add --no-cache openssl libc6-compat
2020
RUN corepack enable
2121
COPY --from=deps /app/node_modules ./node_modules
2222
COPY . .
23+
RUN mkdir -p public
2324
ENV NEXT_TELEMETRY_DISABLED=1
2425
ENV NEXT_OUTPUT_STANDALONE=true
2526

deploy/README.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ cp .env.example .env.prod
2323
echo "<PAT_with_read:packages>" | docker login ghcr.io -u <github_user> --password-stdin
2424

2525
# 4) 첫 가동 (이미지 빌드는 GH Actions 가 대신, 여기선 pull 만)
26+
export MURUN_ENV_FILE=.env.staging
27+
export IMAGE_TAG=staging
28+
2629
docker compose -p murun-staging --env-file .env.staging pull
2730
docker compose -p murun-staging --env-file .env.staging up -d
2831
```
@@ -45,6 +48,8 @@ gh secret set N100_HOST --body "<ip-or-domain>"
4548
gh secret set N100_USER --body "<user>"
4649
```
4750

51+
Secrets 가 아직 없으면 GitHub Actions 는 GHCR 이미지 build/push 까지만 성공 처리하고, SSH deploy job 은 skip 된다. N100 준비 후 위 3개 secret 을 넣으면 다음 dev push 부터 staging deploy 까지 진행된다.
52+
4853
### (옵션) prod environment 보호
4954

5055
main 으로의 자동 배포 전에 수동 승인이 필요하면 Settings → Environments → "prod" 생성 후 "Required reviewers" 본인 추가.
@@ -60,9 +65,9 @@ cd murun-peterabcd/deploy
6065
cp .env.example .env
6166
# (도메인 붙기 전엔 DOMAIN=:80 그대로 두기)
6267

63-
# app 환경변수 (지금은 비어 있어도 OK, 후속 PR에서 채워짐)
64-
touch .env # app 서비스 env_file 이 ./.env 라서 같은 파일이 두 용도 겸함
65-
# — 추후 app.env 로 분리 예정
68+
# compose 변수와 app 환경변수를 같은 파일에서 읽음
69+
# 기본 수동 실행은 .env, staging/prod 분리는 MURUN_ENV_FILE 로 지정
70+
6671

6772
# 빌드 + 기동
6873
docker compose up -d --build
@@ -77,7 +82,7 @@ curl -fsS http://localhost/ && echo OK
7782
cd murun-peterabcd
7883
git pull
7984
cd deploy
80-
docker compose up -d --build
85+
MURUN_ENV_FILE=.env docker compose --env-file .env up -d --build
8186
docker image prune -f
8287
```
8388

@@ -86,11 +91,11 @@ docker image prune -f
8691
같은 디렉터리에 `.env.staging`, `.env.prod` 를 별도로 두고 project name 으로 분리.
8792

8893
```bash
89-
# staging (포트 8080)
90-
CADDY_HTTP_PORT=8080 docker compose -p murun-staging --env-file .env.staging up -d --build
94+
# staging (포트 8080; .env.staging 안에 CADDY_HTTP_PORT=8080 권장)
95+
MURUN_ENV_FILE=.env.staging docker compose -p murun-staging --env-file .env.staging up -d --build
9196

9297
# prod (포트 80)
93-
docker compose -p murun-prod --env-file .env.prod up -d --build
98+
MURUN_ENV_FILE=.env.prod docker compose -p murun-prod --env-file .env.prod up -d --build
9499
```
95100

96101
볼륨은 project name prefix 가 자동으로 붙어 분리됨 (`murun-staging_data` vs `murun-prod_data`).
@@ -109,10 +114,10 @@ docker compose -p murun-prod --env-file .env.prod up -d --build
109114

110115
```bash
111116
# 직전 이미지 태그 확인
112-
docker images ghcr.io/boostcampwm-snu-2026-1/murun --format '{{.Tag}}\t{{.CreatedAt}}'
117+
docker images ghcr.io/boostcampwm-snu-2026-1/murun-peterabcd --format '{{.Tag}}\t{{.CreatedAt}}'
113118

114119
# 특정 태그로 되돌리기
115-
IMAGE_TAG=<sha> docker compose up -d
120+
IMAGE_TAG=<tag> MURUN_ENV_FILE=.env.staging docker compose --env-file .env.staging up -d
116121
```
117122

118123
## 6. 트러블슈팅

deploy/docker-compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ services:
1717
build:
1818
context: ..
1919
dockerfile: deploy/Dockerfile
20-
image: ghcr.io/boostcampwm-snu-2026-1/murun:${IMAGE_TAG:-local}
20+
image: ghcr.io/boostcampwm-snu-2026-1/murun-peterabcd:${IMAGE_TAG:-local}
2121
restart: unless-stopped
2222
env_file:
23-
- ./.env
23+
- ${MURUN_ENV_FILE:-.env}
2424
volumes:
2525
- data:/app/data
2626
- uploads:/app/uploads

docs/wiki/02-Tech-Stack.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ murun-peterabcd/
154154
```
155155

156156
- staging/prod 분리: 같은 이미지를 `-p murun-staging` / `-p murun-prod` 다른 project name으로 동시에. 볼륨·포트·서브도메인 전부 분리.
157-
- 빌드는 GitHub Actions에서 → `ghcr.io/boostcampwm-snu-2026-1/murun:<sha>` 로 push. N100은 pull만.
157+
- 빌드는 GitHub Actions에서 → `ghcr.io/boostcampwm-snu-2026-1/murun-peterabcd:<target-sha>` 로 push. N100은 pull만.
158158

159159
## 6. 채택하지 않은 것
160160

docs/wiki/Retrospective-Week2.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ AI 가 실제 브라우저를 못 클릭하는 건 사실이다. 그렇다고
7474

7575
- 이번 PR 의 CI 워크플로우 — PR 마다 typecheck/lint/build 자동. 솔로 프로젝트지만, "내가 매번 로컬에서 돌리는 단계" 를 GH 가 대신 해주는 게 안전망.
7676
- 이번 PR 의 Deploy 워크플로우 — dev push → ghcr.io build → SSH → N100 staging 자동. main 은 environment 보호 후 수동 승인.
77-
- SSH key + N100_HOST 등 secrets 등록은 호스트(나) 의 책임. README 에 절차가 있고, 등록 안 된 채 workflow 실행 시 sanity check 가 명확히 막아준다.
77+
- SSH key + N100_HOST 등 secrets 등록은 호스트(나) 의 책임. README 에 절차가 있고, 등록 전에는 이미지 build/push 까지만 성공시키고 SSH deploy 는 skip 하도록 했다.
7878

7979
남은 호스트 작업:
8080
- N100 에서 첫 `docker compose up -d` 직접 — 코드의 진짜 검증

0 commit comments

Comments
 (0)