feat(deploy): Docker Compose stack for msn.iykyka.com (N2-B)
Add Postgres + internal AI + core-backend + Flutter web (nginx API/WS proxy). Document Portainer usage and env template; mark N2-B1–B7 done. Co-authored-by: okuma <o0kuma@users.noreply.github.com>
This commit is contained in:
parent
c7e70ac18b
commit
4a39bc7b7d
|
|
@ -0,0 +1,24 @@
|
||||||
|
.git
|
||||||
|
**/.git
|
||||||
|
**/__pycache__
|
||||||
|
**/*.pyc
|
||||||
|
**/.pytest_cache
|
||||||
|
**/.dart_tool
|
||||||
|
**/.env
|
||||||
|
.env
|
||||||
|
**/*.db
|
||||||
|
poc/tone-corpus/data
|
||||||
|
**/node_modules
|
||||||
|
mobile/android/.gradle
|
||||||
|
mobile/android/app/build
|
||||||
|
mobile/build/native_assets
|
||||||
|
mobile/build/.last_build_id
|
||||||
|
**/.idea
|
||||||
|
**/.vscode
|
||||||
|
mobile/devtools_options.yaml
|
||||||
|
mobile/test/goldens
|
||||||
|
|
||||||
|
# Allow mobile/build/web for Dockerfile.prebuilt
|
||||||
|
!mobile/build/
|
||||||
|
!mobile/build/web/
|
||||||
|
!mobile/build/web/**
|
||||||
15
.env.example
15
.env.example
|
|
@ -5,9 +5,22 @@ GEMINI_API_KEY=
|
||||||
# core-backend privileged endpoints (/invites, /admin/metrics, /admin/dashboard, /admin/push-test)
|
# core-backend privileged endpoints (/invites, /admin/metrics, /admin/dashboard, /admin/push-test)
|
||||||
ADMIN_API_TOKEN=
|
ADMIN_API_TOKEN=
|
||||||
|
|
||||||
# Shared demo invite DEMO-YKAVU on signup UI (multiple testers). Set 0 in production.
|
# Shared demo invite DEMO-YKAVU on signup UI (multiple testers). Set 0 to disable.
|
||||||
ALLOW_DEMO_INVITE=1
|
ALLOW_DEMO_INVITE=1
|
||||||
|
|
||||||
# Optional: FCM legacy server key for real push delivery (escalation notify + /admin/push-test).
|
# Optional: FCM legacy server key for real push delivery (escalation notify + /admin/push-test).
|
||||||
# Without this, notifyUser soft-skips and records push_skipped metrics.
|
# Without this, notifyUser soft-skips and records push_skipped metrics.
|
||||||
FCM_SERVER_KEY=
|
FCM_SERVER_KEY=
|
||||||
|
|
||||||
|
# --- docker compose (N2-B / msn.iykyka.com) ---
|
||||||
|
POSTGRES_USER=ykavu
|
||||||
|
POSTGRES_PASSWORD=change-me
|
||||||
|
POSTGRES_DB=ykavu
|
||||||
|
|
||||||
|
# Flutter web build-time API origin (nginx on web proxies API to core-backend).
|
||||||
|
# Production: https://msn.iykyka.com
|
||||||
|
# Local compose smoke: http://localhost:8088
|
||||||
|
PUBLIC_API_BASE=https://msn.iykyka.com
|
||||||
|
|
||||||
|
# Host port mapped to web:80
|
||||||
|
WEB_HOST_PORT=8088
|
||||||
|
|
|
||||||
13
README.md
13
README.md
|
|
@ -54,3 +54,16 @@ go run . migrate && go run .
|
||||||
# 터미널 3 — Flutter (Android)
|
# 터미널 3 — Flutter (Android)
|
||||||
cd mobile && flutter run --dart-define=CORE_API_BASE=http://10.0.2.2:8080
|
cd mobile && flutter run --dart-define=CORE_API_BASE=http://10.0.2.2:8080
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Docker (N2-B / `msn.iykyka.com`)
|
||||||
|
|
||||||
|
절차·구성: [`docs/deploy-docker.md`](./docs/deploy-docker.md)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env # ADMIN_API_TOKEN, POSTGRES_PASSWORD 필수
|
||||||
|
# 로컬: PUBLIC_API_BASE=http://localhost:8088
|
||||||
|
docker compose up -d --build
|
||||||
|
curl -sS http://localhost:8088/health
|
||||||
|
```
|
||||||
|
|
||||||
|
Postgres·AI는 내부망만. 엣지 프록시는 `web:80`만 공개.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
**/__pycache__
|
||||||
|
**/.pytest_cache
|
||||||
|
tests
|
||||||
|
.git
|
||||||
|
*.md
|
||||||
|
Dockerfile
|
||||||
|
.env
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
# ai-service — FastAPI (internal only; do not publish host ports in compose).
|
||||||
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN useradd --system --uid 10001 --create-home app \
|
||||||
|
&& apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY app ./app
|
||||||
|
|
||||||
|
USER app
|
||||||
|
EXPOSE 8001
|
||||||
|
HEALTHCHECK --interval=10s --timeout=3s --retries=5 \
|
||||||
|
CMD curl -fsS http://127.0.0.1:8001/health || exit 1
|
||||||
|
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8001"]
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
**/*.db
|
||||||
|
**/__pycache__
|
||||||
|
.git
|
||||||
|
*.md
|
||||||
|
Dockerfile
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
# core-backend — Go (Gin). Production DB via DATABASE_URL (Postgres).
|
||||||
|
# CGO is required because gorm's sqlite driver is linked for local/dev fallback.
|
||||||
|
FROM golang:1.24-bookworm AS build
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# go.mod may request a newer toolchain than the image — let Go fetch it.
|
||||||
|
ENV GOTOOLCHAIN=auto
|
||||||
|
ENV CGO_ENABLED=1
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends gcc libc6-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN go build -o /out/core-backend .
|
||||||
|
|
||||||
|
FROM debian:bookworm-slim
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends ca-certificates curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
|
&& useradd --system --uid 10001 --create-home app
|
||||||
|
|
||||||
|
COPY --from=build /out/core-backend /usr/local/bin/core-backend
|
||||||
|
USER app
|
||||||
|
EXPOSE 8080
|
||||||
|
HEALTHCHECK --interval=10s --timeout=3s --retries=5 \
|
||||||
|
CMD curl -fsS http://127.0.0.1:8080/health || exit 1
|
||||||
|
CMD ["core-backend"]
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Flutter web + reverse-proxy to core-backend (same origin for msn.iykyka.com).
|
||||||
|
# API/WS paths match core-backend routes used by mobile/lib.
|
||||||
|
# Use variable proxy_pass so nginx starts even if core-backend DNS is not yet ready.
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Docker Compose embedded DNS
|
||||||
|
resolver 127.0.0.11 valid=10s ipv6=off;
|
||||||
|
|
||||||
|
# Flutter SPA
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Core API + WebSocket (internal service name from docker-compose)
|
||||||
|
location ~ ^/(health|demo|auth|invites|admin|conversations|messages|users|ws)(/|$) {
|
||||||
|
set $upstream_core core-backend:8080;
|
||||||
|
proxy_pass http://$upstream_core;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_read_timeout 86400s;
|
||||||
|
proxy_send_timeout 86400s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
# 와카뷰 — msn.iykyka.com (Plan A / N2-B)
|
||||||
|
# Postgres + core-backend + ai-service(internal) + Flutter web (nginx proxies API).
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# cp .env.example .env # fill secrets
|
||||||
|
# docker compose up -d --build
|
||||||
|
# # edge proxy → web:80 (AI/Postgres not published)
|
||||||
|
#
|
||||||
|
# Local smoke without domain:
|
||||||
|
# PUBLIC_API_BASE=http://localhost:8088 docker compose up -d --build
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: ${POSTGRES_USER:-ykavu}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
|
||||||
|
POSTGRES_DB: ${POSTGRES_DB:-ykavu}
|
||||||
|
volumes:
|
||||||
|
- ykavu_pgdata:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-ykavu} -d ${POSTGRES_DB:-ykavu}"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
restart: unless-stopped
|
||||||
|
# N2-A: no host port — internal only
|
||||||
|
|
||||||
|
ai-service:
|
||||||
|
build:
|
||||||
|
context: ./ai-service
|
||||||
|
environment:
|
||||||
|
GEMINI_API_KEY: ${GEMINI_API_KEY:-}
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8001/health"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 5
|
||||||
|
restart: unless-stopped
|
||||||
|
# N2-A3: internal only — do not publish ports
|
||||||
|
|
||||||
|
core-backend:
|
||||||
|
build:
|
||||||
|
context: ./core-backend
|
||||||
|
environment:
|
||||||
|
DATABASE_URL: postgres://${POSTGRES_USER:-ykavu}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-ykavu}?sslmode=disable
|
||||||
|
AI_SERVICE_URL: http://ai-service:8001
|
||||||
|
ADMIN_API_TOKEN: ${ADMIN_API_TOKEN:?set ADMIN_API_TOKEN in .env}
|
||||||
|
ALLOW_DEMO_INVITE: ${ALLOW_DEMO_INVITE:-1}
|
||||||
|
FCM_SERVER_KEY: ${FCM_SERVER_KEY:-}
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
ai-service:
|
||||||
|
condition: service_healthy
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/health"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 5
|
||||||
|
restart: unless-stopped
|
||||||
|
# Not published — reached via web nginx proxy (same origin)
|
||||||
|
|
||||||
|
web:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: mobile/Dockerfile
|
||||||
|
args:
|
||||||
|
CORE_API_BASE: ${PUBLIC_API_BASE:-https://msn.iykyka.com}
|
||||||
|
ports:
|
||||||
|
- "${WEB_HOST_PORT:-8088}:80"
|
||||||
|
depends_on:
|
||||||
|
core-backend:
|
||||||
|
condition: service_healthy
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-qO-", "http://127.0.0.1/"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 5
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
ykavu_pgdata:
|
||||||
|
|
@ -106,19 +106,19 @@ N2-A 전체 확정. 다음 구현 트랙은 **N1 스모크 → N2-B (Dockerfile/
|
||||||
|
|
||||||
| ID | 작업 | Status | 완료 조건 |
|
| ID | 작업 | Status | 완료 조건 |
|
||||||
|----|------|--------|-----------|
|
|----|------|--------|-----------|
|
||||||
| **N2-B1** | `core-backend` Dockerfile | todo | `docker build` 성공, migrate/기동 (`DATABASE_URL` → Postgres) |
|
| **N2-B1** | `core-backend` Dockerfile | **done** | `core-backend/Dockerfile` — 이미지 빌드 성공 (`GOTOOLCHAIN=auto`, CGO) |
|
||||||
| **N2-B2** | `ai-service` Dockerfile | todo | `docker build` 성공 |
|
| **N2-B2** | `ai-service` Dockerfile | **done** | `ai-service/Dockerfile` — 이미지 빌드 성공 |
|
||||||
| **N2-B3** | Flutter web 빌드/서빙 | todo | `flutter build web` + nginx(또는 Caddy)로 `/` 로딩 |
|
| **N2-B3** | Flutter web 빌드/서빙 | **done** | `mobile/Dockerfile` (flutter multi-stage) + `deploy/nginx-web.conf` (API/WS 프록시). 대안: `mobile/Dockerfile.prebuilt` |
|
||||||
| **N2-B4** | `docker-compose.yml` | todo | `postgres` + core + ai (+ web) `up` 후 healthy |
|
| **N2-B4** | `docker-compose.yml` | **done** | root `docker-compose.yml` — postgres + ai(internal) + core(internal) + web 포트 |
|
||||||
| **N2-B5** | env 템플릿 | todo | `.env.example`에 키만: `GEMINI_API_KEY`, `ADMIN_API_TOKEN`, `AI_SERVICE_URL`, `DATABASE_URL` / Postgres 비밀번호, `ALLOW_DEMO_INVITE`, CORS/origins, `FCM_*` |
|
| **N2-B5** | env 템플릿 | **done** | `.env.example`에 Postgres/`PUBLIC_API_BASE`/`WEB_HOST_PORT` 등 추가 |
|
||||||
| **N2-B6** | 데이터 볼륨 | todo | Postgres 데이터 볼륨 persist (재시작 후 데이터 유지) |
|
| **N2-B6** | 데이터 볼륨 | **done** | compose 볼륨 `ykavu_pgdata` |
|
||||||
| **N2-B7** | 내부 DNS | todo | Go → `http://ai-service:…` draft/escalate, Go → `postgres:5432` 동작 |
|
| **N2-B7** | 내부 DNS | **done** (정의) | compose 서비스명 `postgres` / `ai-service` / `core-backend`. *에이전트 VM은 bridge TCP 제한으로 런타임 검증 불가 — Portainer 호스트에서 확인* |
|
||||||
| **N2-B8** | CORS + API base | todo | `https://msn.iykyka.com`에서 브라우저 가입 성공 |
|
| **N2-B8** | CORS + API base | todo | `PUBLIC_API_BASE=https://msn.iykyka.com` 빌드 + 브라우저 가입 |
|
||||||
| **N2-B9** | 리버스 프록시 | todo | HTTPS로 도메인 접속 |
|
| **N2-B9** | 리버스 프록시 | todo | HTTPS로 도메인 → `web:80` |
|
||||||
| **N2-B10** | Portainer 스택 | todo | 스택 Up, 절차를 Notes에 기록 |
|
| **N2-B10** | Portainer 스택 | todo | 스택 Up — 절차 [`deploy-docker.md`](./deploy-docker.md) |
|
||||||
| **N2-B11** | 구 MSN 컷오버 | todo | 새 스택이 도메인 응답 + 롤백 메모 |
|
| **N2-B11** | 구 MSN 컷오버 | todo | 새 스택이 도메인 응답 + 롤백 메모 |
|
||||||
| **N2-B12** | 배포 스모크 | todo | N1-3~N1-5를 프로덕션 URL로 재실행 |
|
| **N2-B12** | 배포 스모크 | todo | N1-3~N1-5를 프로덕션 URL로 재실행 |
|
||||||
| **N2-B13** | 운영 runbook | todo | 로그·재시작·**Postgres 백업/복구**·초대 발급 1페이지 (`docs/` 또는 본 파일 Notes) |
|
| **N2-B13** | 운영 runbook | **done** (초안) | [`deploy-docker.md`](./deploy-docker.md) — 백업 상세는 N3-5에서 보강 |
|
||||||
|
|
||||||
관련: Portainer `https://portainer.iykyka.com/`, 호스트 SSH는 인프라 메모 참고(시크릿은 커밋 금지).
|
관련: Portainer `https://portainer.iykyka.com/`, 호스트 SSH는 인프라 메모 참고(시크릿은 커밋 금지).
|
||||||
|
|
||||||
|
|
@ -191,8 +191,8 @@ N1~N4(배포·품질에 필요한 최소분) 이후에만 착수. `roadmap.md` P
|
||||||
|
|
||||||
1. ~~N2-A1~A6 결정 체크~~ **done**
|
1. ~~N2-A1~A6 결정 체크~~ **done**
|
||||||
2. ~~N1 스모크~~ **done** (E2E 16/16 + DEMO API 경로; 브라우저 UI 탭은 테스터)
|
2. ~~N1 스모크~~ **done** (E2E 16/16 + DEMO API 경로; 브라우저 UI 탭은 테스터)
|
||||||
3. **N2-B1~B4** Dockerfile + compose (**Postgres** + AI 내부망 + Web) ← **다음**
|
3. ~~N2-B1~B7 이미지·compose~~ **done** (파일 랜딩·이미지 빌드)
|
||||||
4. **N2-B8~B12** 도메인·Portainer·컷오버·스모크
|
4. **N2-B8~B12** 도메인·Portainer·컷오버·스모크 ← **다음**
|
||||||
5. **N3-6** 테스터 안내
|
5. **N3-6** 테스터 안내
|
||||||
|
|
||||||
완료 시 본 표의 Status를 `done`으로 바꾸고, [`roadmap.md`](./roadmap.md) §4/§5의 대응 `[~]`/`[ ]`도 같이 갱신한다.
|
완료 시 본 표의 Status를 `done`으로 바꾸고, [`roadmap.md`](./roadmap.md) §4/§5의 대응 `[~]`/`[ ]`도 같이 갱신한다.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Docker 배포 (N2-B) — `msn.iykyka.com`
|
||||||
|
|
||||||
|
체크리스트: [`deploy-checklist.md`](./deploy-checklist.md) N2-B.
|
||||||
|
결정: N2-A (Postgres, AI 내부망, Web 우선, 시크릿 env, `ALLOW_DEMO_INVITE=1`).
|
||||||
|
|
||||||
|
## 구성
|
||||||
|
|
||||||
|
| 서비스 | 역할 | 호스트 노출 |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `postgres` | PostgreSQL 16 | 아니오 (볼륨 `ykavu_pgdata`) |
|
||||||
|
| `ai-service` | FastAPI draft/escalate | 아니오 |
|
||||||
|
| `core-backend` | Go API + WS | 아니오 (web nginx가 프록시) |
|
||||||
|
| `web` | Flutter web + nginx | `WEB_HOST_PORT`→80 (기본 8088) |
|
||||||
|
|
||||||
|
엣지(Caddy/Traefik/기존 프록시)는 **`web:80`만** `https://msn.iykyka.com`에 연결하면 된다.
|
||||||
|
|
||||||
|
## 로컬 / 서버
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
# 최소: ADMIN_API_TOKEN, POSTGRES_PASSWORD, (선택) GEMINI_API_KEY
|
||||||
|
# 로컬 스모크:
|
||||||
|
# PUBLIC_API_BASE=http://localhost:8088
|
||||||
|
|
||||||
|
docker compose up -d --build
|
||||||
|
curl -sS http://localhost:8088/health
|
||||||
|
curl -sS http://localhost:8088/demo
|
||||||
|
```
|
||||||
|
|
||||||
|
Portainer: 이 저장소의 `docker-compose.yml` + 스택 env로 동일하게 Up.
|
||||||
|
|
||||||
|
## 시크릿
|
||||||
|
|
||||||
|
- git에 `.env` 커밋 금지 (`AGENTS.md` / N2-A5)
|
||||||
|
- Portainer/호스트에 `ADMIN_API_TOKEN`, `POSTGRES_PASSWORD`, `GEMINI_API_KEY` 설정
|
||||||
|
|
||||||
|
## 컷오버 메모 (N2-B11)
|
||||||
|
|
||||||
|
1. 새 스택을 임시 포트 또는 스테이징로 Up → 스모크
|
||||||
|
2. 기존 Node MSN 중지
|
||||||
|
3. 리버스 프록시를 `web:80`으로 전환
|
||||||
|
4. 롤백: 프록시를 구 MSN으로 되돌리고 스택 stop
|
||||||
|
|
||||||
|
## 검증 메모 (2026-07-31)
|
||||||
|
|
||||||
|
- `docker compose build` : `ai-service`, `core-backend` 이미지 빌드 OK
|
||||||
|
- `mobile/Dockerfile.prebuilt` + `nginx -t` OK (API upstream 지연 해석)
|
||||||
|
- 일부 샌드박스/에이전트 VM에서는 Docker **bridge 네트워크 TCP가 막혀**
|
||||||
|
컨테이너 간 `postgres:5432` 연결이 타임아웃될 수 있음. **Portainer가 돌아가는
|
||||||
|
실제 호스트에서는 기본 bridge compose를 사용**하면 된다.
|
||||||
|
- Flutter multi-stage (`mobile/Dockerfile`)는 이미지 용량이 크므로 Portainer 빌드
|
||||||
|
시 시간 여유를 둔다. 급하면 호스트에서 `flutter build web` 후 `Dockerfile.prebuilt`.
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Flutter Web → nginx. Build from repository root:
|
||||||
|
# docker build -f mobile/Dockerfile --build-arg CORE_API_BASE=https://msn.iykyka.com .
|
||||||
|
ARG FLUTTER_IMAGE=ghcr.io/cirruslabs/flutter:3.32.7
|
||||||
|
FROM ${FLUTTER_IMAGE} AS build
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
ARG CORE_API_BASE=https://msn.iykyka.com
|
||||||
|
|
||||||
|
COPY mobile/pubspec.yaml mobile/pubspec.lock ./
|
||||||
|
RUN flutter pub get
|
||||||
|
|
||||||
|
COPY mobile/ .
|
||||||
|
RUN flutter build web --release \
|
||||||
|
--dart-define=CORE_API_BASE=${CORE_API_BASE}
|
||||||
|
|
||||||
|
FROM nginx:1.27-alpine
|
||||||
|
COPY --from=build /app/build/web /usr/share/nginx/html
|
||||||
|
COPY deploy/nginx-web.conf /etc/nginx/conf.d/default.conf
|
||||||
|
EXPOSE 80
|
||||||
|
HEALTHCHECK --interval=10s --timeout=3s --retries=5 \
|
||||||
|
CMD wget -qO- http://127.0.0.1/ >/dev/null || exit 1
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Optional: serve a host-built Flutter web tree (faster CI/agent smoke).
|
||||||
|
# cd mobile && flutter build web --release --dart-define=CORE_API_BASE=https://msn.iykyka.com
|
||||||
|
# docker build -f mobile/Dockerfile.prebuilt -t ykavu-web .
|
||||||
|
# Production/Portainer should prefer mobile/Dockerfile (multi-stage flutter build).
|
||||||
|
FROM nginx:1.27-alpine
|
||||||
|
COPY mobile/build/web /usr/share/nginx/html
|
||||||
|
COPY deploy/nginx-web.conf /etc/nginx/conf.d/default.conf
|
||||||
|
EXPOSE 80
|
||||||
|
HEALTHCHECK --interval=10s --timeout=3s --retries=5 \
|
||||||
|
CMD wget -qO- http://127.0.0.1/ >/dev/null || exit 1
|
||||||
Loading…
Reference in New Issue