fix(web): keep Firebase build-args out of Docker RUN logs
Move SW render + flutter build into a stage script so secret values are not expanded into Dockerfile RUN instructions. Document that APP_ID must be a Web (:web:) app id and that secrets belong on the deploy host .env. Co-authored-by: okuma <o0kuma@users.noreply.github.com>
This commit is contained in:
parent
4aa21a6099
commit
fed6739a56
|
|
@ -37,7 +37,7 @@ Phase 1 **A~C** 이후 실행 트랙. 작업 단위를 하나씩 처리한다.
|
||||||
|
|
||||||
- 앱 코드는 클로즈드 베타 직전 수준
|
- 앱 코드는 클로즈드 베타 직전 수준
|
||||||
- **`https://msn.iykyka.com` 라이브 + N3 완료 + Gemini 실초안 OK + Track A/B 완료**
|
- **`https://msn.iykyka.com` 라이브 + N3 완료 + Gemini 실초안 OK + Track A/B 완료**
|
||||||
- **웹 고도화:** [`web-upgrade.md`](./web-upgrade.md) — W0~W3·W5~W7 **done** · **W4 code shipped** (live: Master `.env`에 FIREBASE_*/VAPID 후 `web` 재빌드)
|
- **웹 고도화:** [`web-upgrade.md`](./web-upgrade.md) — W0~W3·W5~W7 **done** · **W4 live injected** (SW populated · accept: Web `:web:` APP_ID + push-test)
|
||||||
- 후순위: **N4 Android FCM/UI** — Master 시크릿·실기기
|
- 후순위: **N4 Android FCM/UI** — Master 시크릿·실기기
|
||||||
- UI: **iMessage-inspired light default** + soft charcoal dark 프로덕션 반영
|
- UI: **iMessage-inspired light default** + soft charcoal dark 프로덕션 반영
|
||||||
- **Track C 콘텐츠 갭 A~F**: 프로덕션 반영 완료 (`95422bb`대)
|
- **Track C 콘텐츠 갭 A~F**: 프로덕션 반영 완료 (`95422bb`대)
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,10 @@ Android N4(실기기)와 **병행 가능**. 서버 서비스 계정(HTTP v1)은
|
||||||
### Master 준비물 (live accept)
|
### Master 준비물 (live accept)
|
||||||
|
|
||||||
1. Firebase Console → **Web** 앱 추가 (authorized domain: `msn.iykyka.com`) — SA 프로젝트와 동일
|
1. Firebase Console → **Web** 앱 추가 (authorized domain: `msn.iykyka.com`) — SA 프로젝트와 동일
|
||||||
|
- `FIREBASE_APP_ID`는 **`1:…:web:…` 형태**여야 함. Android(`:android:`) / `google-services.json`의 mobilesdk_app_id를 넣으면 웹 토큰 발급이 실패할 수 있음.
|
||||||
2. Cloud Messaging → Web Push certificates / **VAPID public key**
|
2. Cloud Messaging → Web Push certificates / **VAPID public key**
|
||||||
3. 배포 호스트 `~/project/ykavu/.env`에 기입 (`.env.example` 키 이름 — **값 git 금지**):
|
3. 배포 호스트 **`~/project/ykavu/.env`**(클라우드 에이전트 `/workspace/.env`가 아님)에 기입
|
||||||
|
(`.env.example` 키 이름 — **값 git 금지**):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
FIREBASE_API_KEY=
|
FIREBASE_API_KEY=
|
||||||
|
|
@ -95,7 +97,7 @@ FIREBASE_AUTH_DOMAIN= # 비우면 {projectId}.firebaseapp.com
|
||||||
FIREBASE_PROJECT_ID=
|
FIREBASE_PROJECT_ID=
|
||||||
FIREBASE_STORAGE_BUCKET= # 비우면 {projectId}.appspot.com
|
FIREBASE_STORAGE_BUCKET= # 비우면 {projectId}.appspot.com
|
||||||
FIREBASE_MESSAGING_SENDER_ID=
|
FIREBASE_MESSAGING_SENDER_ID=
|
||||||
FIREBASE_APP_ID=
|
FIREBASE_APP_ID= # must be :web: app id
|
||||||
FIREBASE_VAPID_KEY=
|
FIREBASE_VAPID_KEY=
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -255,7 +255,7 @@ flowchart LR
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|--|--|
|
|--|--|
|
||||||
| **Status** | **code shipped** (2026-08-04) — **live accept**는 Master Firebase Web config + VAPID를 서버 `.env`에 넣고 `web` 재빌드 후 |
|
| **Status** | **live injected** (2026-08-04) — 서버 `.env`+SW populated · **accept 대기:** `FIREBASE_APP_ID`가 `:android:`로 보여 Web 앱(`:web:`) 교체 후 브라우저 토큰·push-test 확인 |
|
||||||
| **목표** | 웹 탭이 백그라운드여도 에스컬레이션 등 서버 `notifyUser`가 **실 FCM 웹 토큰**으로 전달 |
|
| **목표** | 웹 탭이 백그라운드여도 에스컬레이션 등 서버 `notifyUser`가 **실 FCM 웹 토큰**으로 전달 |
|
||||||
| **비범위** | 레거시 `FCM_SERVER_KEY` 신규 의존, 커스텀 푸시 프로토콜 |
|
| **비범위** | 레거시 `FCM_SERVER_KEY` 신규 의존, 커스텀 푸시 프로토콜 |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
# docker build -f mobile/Dockerfile --build-arg CORE_API_BASE=https://msn.iykyka.com .
|
# docker build -f mobile/Dockerfile --build-arg CORE_API_BASE=https://msn.iykyka.com .
|
||||||
# Optional Web Push (N4-W4) — pass FIREBASE_* / FIREBASE_VAPID_KEY as build-args
|
# Optional Web Push (N4-W4) — pass FIREBASE_* / FIREBASE_VAPID_KEY as build-args
|
||||||
# (never commit real values; see .env.example and docs/fcm-setup.md).
|
# (never commit real values; see .env.example and docs/fcm-setup.md).
|
||||||
|
#
|
||||||
|
# Secrets are copied into ENV for the build stage only (not the final nginx image).
|
||||||
|
# The RUN line calls a script so values are not expanded into Docker build logs.
|
||||||
ARG FLUTTER_IMAGE=ghcr.io/cirruslabs/flutter:3.32.7
|
ARG FLUTTER_IMAGE=ghcr.io/cirruslabs/flutter:3.32.7
|
||||||
FROM ${FLUTTER_IMAGE} AS build
|
FROM ${FLUTTER_IMAGE} AS build
|
||||||
|
|
||||||
|
|
@ -15,39 +18,20 @@ ARG FIREBASE_MESSAGING_SENDER_ID=
|
||||||
ARG FIREBASE_APP_ID=
|
ARG FIREBASE_APP_ID=
|
||||||
ARG FIREBASE_VAPID_KEY=
|
ARG FIREBASE_VAPID_KEY=
|
||||||
|
|
||||||
|
ENV CORE_API_BASE=${CORE_API_BASE} \
|
||||||
|
FIREBASE_API_KEY=${FIREBASE_API_KEY} \
|
||||||
|
FIREBASE_AUTH_DOMAIN=${FIREBASE_AUTH_DOMAIN} \
|
||||||
|
FIREBASE_PROJECT_ID=${FIREBASE_PROJECT_ID} \
|
||||||
|
FIREBASE_STORAGE_BUCKET=${FIREBASE_STORAGE_BUCKET} \
|
||||||
|
FIREBASE_MESSAGING_SENDER_ID=${FIREBASE_MESSAGING_SENDER_ID} \
|
||||||
|
FIREBASE_APP_ID=${FIREBASE_APP_ID} \
|
||||||
|
FIREBASE_VAPID_KEY=${FIREBASE_VAPID_KEY}
|
||||||
|
|
||||||
COPY mobile/pubspec.yaml mobile/pubspec.lock ./
|
COPY mobile/pubspec.yaml mobile/pubspec.lock ./
|
||||||
RUN flutter pub get
|
RUN flutter pub get
|
||||||
|
|
||||||
COPY mobile/ .
|
COPY mobile/ .
|
||||||
|
RUN chmod +x scripts/docker_build_web.sh && ./scripts/docker_build_web.sh
|
||||||
# Populate firebase-messaging-sw.js when Web config is present; keep stub otherwise.
|
|
||||||
RUN set -eu; \
|
|
||||||
if [ -n "${FIREBASE_API_KEY}" ] && [ -n "${FIREBASE_APP_ID}" ] && \
|
|
||||||
[ -n "${FIREBASE_MESSAGING_SENDER_ID}" ] && [ -n "${FIREBASE_PROJECT_ID}" ]; then \
|
|
||||||
AUTH_DOMAIN="${FIREBASE_AUTH_DOMAIN:-${FIREBASE_PROJECT_ID}.firebaseapp.com}"; \
|
|
||||||
STORAGE_BUCKET="${FIREBASE_STORAGE_BUCKET:-${FIREBASE_PROJECT_ID}.appspot.com}"; \
|
|
||||||
sed \
|
|
||||||
-e "s|__FIREBASE_API_KEY__|${FIREBASE_API_KEY}|g" \
|
|
||||||
-e "s|__FIREBASE_AUTH_DOMAIN__|${AUTH_DOMAIN}|g" \
|
|
||||||
-e "s|__FIREBASE_PROJECT_ID__|${FIREBASE_PROJECT_ID}|g" \
|
|
||||||
-e "s|__FIREBASE_STORAGE_BUCKET__|${STORAGE_BUCKET}|g" \
|
|
||||||
-e "s|__FIREBASE_MESSAGING_SENDER_ID__|${FIREBASE_MESSAGING_SENDER_ID}|g" \
|
|
||||||
-e "s|__FIREBASE_APP_ID__|${FIREBASE_APP_ID}|g" \
|
|
||||||
web/firebase-messaging-sw.js.template > web/firebase-messaging-sw.js; \
|
|
||||||
echo "firebase-messaging-sw.js: populated for project ${FIREBASE_PROJECT_ID}"; \
|
|
||||||
else \
|
|
||||||
echo "firebase-messaging-sw.js: stub (FIREBASE_* build-args empty)"; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
RUN flutter build web --release \
|
|
||||||
--dart-define=CORE_API_BASE=${CORE_API_BASE} \
|
|
||||||
--dart-define=FIREBASE_API_KEY=${FIREBASE_API_KEY} \
|
|
||||||
--dart-define=FIREBASE_AUTH_DOMAIN=${FIREBASE_AUTH_DOMAIN} \
|
|
||||||
--dart-define=FIREBASE_PROJECT_ID=${FIREBASE_PROJECT_ID} \
|
|
||||||
--dart-define=FIREBASE_STORAGE_BUCKET=${FIREBASE_STORAGE_BUCKET} \
|
|
||||||
--dart-define=FIREBASE_MESSAGING_SENDER_ID=${FIREBASE_MESSAGING_SENDER_ID} \
|
|
||||||
--dart-define=FIREBASE_APP_ID=${FIREBASE_APP_ID} \
|
|
||||||
--dart-define=FIREBASE_VAPID_KEY=${FIREBASE_VAPID_KEY}
|
|
||||||
|
|
||||||
FROM nginx:1.27-alpine
|
FROM nginx:1.27-alpine
|
||||||
COPY --from=build /app/build/web /usr/share/nginx/html
|
COPY --from=build /app/build/web /usr/share/nginx/html
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Runs inside the Flutter build stage. Reads FIREBASE_* from the environment
|
||||||
|
# (set via Dockerfile ENV from build-args) so secret values are not expanded
|
||||||
|
# into the Dockerfile RUN instruction / build logs.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
CORE_API_BASE="${CORE_API_BASE:-https://msn.iykyka.com}"
|
||||||
|
FIREBASE_API_KEY="${FIREBASE_API_KEY:-}"
|
||||||
|
FIREBASE_AUTH_DOMAIN="${FIREBASE_AUTH_DOMAIN:-}"
|
||||||
|
FIREBASE_PROJECT_ID="${FIREBASE_PROJECT_ID:-}"
|
||||||
|
FIREBASE_STORAGE_BUCKET="${FIREBASE_STORAGE_BUCKET:-}"
|
||||||
|
FIREBASE_MESSAGING_SENDER_ID="${FIREBASE_MESSAGING_SENDER_ID:-}"
|
||||||
|
FIREBASE_APP_ID="${FIREBASE_APP_ID:-}"
|
||||||
|
FIREBASE_VAPID_KEY="${FIREBASE_VAPID_KEY:-}"
|
||||||
|
|
||||||
|
if [[ -n "${FIREBASE_API_KEY}" && -n "${FIREBASE_APP_ID}" && \
|
||||||
|
-n "${FIREBASE_MESSAGING_SENDER_ID}" && -n "${FIREBASE_PROJECT_ID}" ]]; then
|
||||||
|
AUTH_DOMAIN="${FIREBASE_AUTH_DOMAIN:-${FIREBASE_PROJECT_ID}.firebaseapp.com}"
|
||||||
|
STORAGE_BUCKET="${FIREBASE_STORAGE_BUCKET:-${FIREBASE_PROJECT_ID}.appspot.com}"
|
||||||
|
# Detect common misconfiguration: Android app id used for web build.
|
||||||
|
if [[ "${FIREBASE_APP_ID}" == *":android:"* ]]; then
|
||||||
|
echo "WARN: FIREBASE_APP_ID looks like an Android app id (:android:)."
|
||||||
|
echo "WARN: Web Push needs a Firebase Web app id (:web:). Token registration may fail."
|
||||||
|
fi
|
||||||
|
sed \
|
||||||
|
-e "s|__FIREBASE_API_KEY__|${FIREBASE_API_KEY}|g" \
|
||||||
|
-e "s|__FIREBASE_AUTH_DOMAIN__|${AUTH_DOMAIN}|g" \
|
||||||
|
-e "s|__FIREBASE_PROJECT_ID__|${FIREBASE_PROJECT_ID}|g" \
|
||||||
|
-e "s|__FIREBASE_STORAGE_BUCKET__|${STORAGE_BUCKET}|g" \
|
||||||
|
-e "s|__FIREBASE_MESSAGING_SENDER_ID__|${FIREBASE_MESSAGING_SENDER_ID}|g" \
|
||||||
|
-e "s|__FIREBASE_APP_ID__|${FIREBASE_APP_ID}|g" \
|
||||||
|
web/firebase-messaging-sw.js.template > web/firebase-messaging-sw.js
|
||||||
|
echo "firebase-messaging-sw.js: populated for project ${FIREBASE_PROJECT_ID}"
|
||||||
|
else
|
||||||
|
echo "firebase-messaging-sw.js: stub (FIREBASE_* build-args empty)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
flutter build web --release \
|
||||||
|
--dart-define="CORE_API_BASE=${CORE_API_BASE}" \
|
||||||
|
--dart-define="FIREBASE_API_KEY=${FIREBASE_API_KEY}" \
|
||||||
|
--dart-define="FIREBASE_AUTH_DOMAIN=${FIREBASE_AUTH_DOMAIN}" \
|
||||||
|
--dart-define="FIREBASE_PROJECT_ID=${FIREBASE_PROJECT_ID}" \
|
||||||
|
--dart-define="FIREBASE_STORAGE_BUCKET=${FIREBASE_STORAGE_BUCKET}" \
|
||||||
|
--dart-define="FIREBASE_MESSAGING_SENDER_ID=${FIREBASE_MESSAGING_SENDER_ID}" \
|
||||||
|
--dart-define="FIREBASE_APP_ID=${FIREBASE_APP_ID}" \
|
||||||
|
--dart-define="FIREBASE_VAPID_KEY=${FIREBASE_VAPID_KEY}"
|
||||||
Loading…
Reference in New Issue