deploy: Compose 호스트 포트 42881·42917 및 문서 동기화
Made-with: Cursor
This commit is contained in:
15
.env.example
15
.env.example
@@ -1,2 +1,13 @@
|
|||||||
# PocketBase 공개 URL (끝 슬래시 없이). Docker 배포 시 브라우저에서 접근 가능한 주소로 설정
|
# 사용자에게 노출되는 웹앱 URL(끝 슬래시 없음). PWA manifest 식별 등에 사용
|
||||||
VITE_POCKETBASE_URL=http://127.0.0.1:8090
|
VITE_PUBLIC_APP_URL=https://todo.sori.studio
|
||||||
|
|
||||||
|
# PocketBase 공개 URL(끝 슬래시 없음). 브라우저가 직접 호출한다
|
||||||
|
VITE_POCKETBASE_URL=https://api.todo.sori.studio
|
||||||
|
|
||||||
|
# 로컬에서 PocketBase 컨테이너만 띄울 때 예시(필요 시 위 두 줄 대신 사용)
|
||||||
|
# VITE_PUBLIC_APP_URL=http://127.0.0.1:5173
|
||||||
|
# VITE_POCKETBASE_URL=http://127.0.0.1:8090
|
||||||
|
|
||||||
|
# docker compose 기본 호스트 포트로 NAS LAN에서 접속할 때(포트는 docker-compose.yml과 맞출 것)
|
||||||
|
# VITE_PUBLIC_APP_URL=http://192.168.0.50:42881
|
||||||
|
# VITE_POCKETBASE_URL=http://192.168.0.50:42917
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ COPY . .
|
|||||||
ARG VITE_POCKETBASE_URL
|
ARG VITE_POCKETBASE_URL
|
||||||
ENV VITE_POCKETBASE_URL=${VITE_POCKETBASE_URL}
|
ENV VITE_POCKETBASE_URL=${VITE_POCKETBASE_URL}
|
||||||
|
|
||||||
|
ARG VITE_PUBLIC_APP_URL
|
||||||
|
ENV VITE_PUBLIC_APP_URL=${VITE_PUBLIC_APP_URL}
|
||||||
|
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
FROM nginx:1.27-alpine
|
FROM nginx:1.27-alpine
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# 호스트 포트는 다른 스택과 겹치지 않게 4만 번대로 둔다. 충돌 시 아래 두 줄만 바꾼다.
|
||||||
|
# 웹(nginx 정적): 호스트 42881 -> 컨테이너 80
|
||||||
|
# PocketBase: 호스트 42917 -> 컨테이너 8090
|
||||||
services:
|
services:
|
||||||
pocketbase:
|
pocketbase:
|
||||||
image: ghcr.io/muchobien/pocketbase:latest
|
image: ghcr.io/muchobien/pocketbase:latest
|
||||||
@@ -6,7 +9,7 @@ services:
|
|||||||
PB_HOST: 0.0.0.0
|
PB_HOST: 0.0.0.0
|
||||||
PB_PORT: 8090
|
PB_PORT: 8090
|
||||||
ports:
|
ports:
|
||||||
- "8090:8090"
|
- "42917:8090"
|
||||||
volumes:
|
volumes:
|
||||||
- pocketbase_data:/pb_data
|
- pocketbase_data:/pb_data
|
||||||
|
|
||||||
@@ -14,10 +17,11 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
args:
|
args:
|
||||||
VITE_POCKETBASE_URL: ${VITE_POCKETBASE_URL:-http://127.0.0.1:8090}
|
VITE_POCKETBASE_URL: ${VITE_POCKETBASE_URL:-http://127.0.0.1:42917}
|
||||||
|
VITE_PUBLIC_APP_URL: ${VITE_PUBLIC_APP_URL:-}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "8080:80"
|
- "42881:80"
|
||||||
depends_on:
|
depends_on:
|
||||||
- pocketbase
|
- pocketbase
|
||||||
|
|
||||||
|
|||||||
@@ -2,37 +2,49 @@
|
|||||||
|
|
||||||
## 현재 버전
|
## 현재 버전
|
||||||
|
|
||||||
- `v0.0.2`
|
- `v0.0.4`
|
||||||
|
|
||||||
NAS에 SSH로 올리는 **전체 순서**는 `docs/nas-deploy-guide.md`에 따로 정리했다.
|
NAS에 SSH로 올리는 **전체 순서**는 `docs/nas-deploy-guide.md`에 따로 정리했다.
|
||||||
|
|
||||||
## 로컬 개발
|
## 로컬 개발
|
||||||
|
|
||||||
1. `cp .env.example .env` 후 `VITE_POCKETBASE_URL`을 실제 PocketBase 주소로 맞춘다.
|
1. `cp .env.example .env` 후 아래를 실제 주소로 맞춘다.
|
||||||
|
- `VITE_PUBLIC_APP_URL`: 브라우저에서 웹앱을 여는 URL(로컬이면 `http://127.0.0.1:5173` 등).
|
||||||
|
- `VITE_POCKETBASE_URL`: PocketBase URL(로컬이면 `http://127.0.0.1:8090` 등).
|
||||||
2. `npm install`
|
2. `npm install`
|
||||||
3. `npm run dev`
|
3. `npm run dev`
|
||||||
|
|
||||||
PocketBase는 Docker로 띄우려면 `docker compose up pocketbase`만 실행해도 된다(기본 `8090`).
|
운영 예시는 `.env.example`에 `https://todo.sori.studio` / `https://api.todo.sori.studio` 로 적어 두었다.
|
||||||
|
|
||||||
|
## 운영 도메인(todo.sori.studio) 요약
|
||||||
|
|
||||||
|
- 웹앱: `https://todo.sori.studio` → 리버스 프록시에서 정적 웹 컨테이너(또는 빌드 산출물)로 연결.
|
||||||
|
- API(PocketBase): `https://api.todo.sori.studio` → 같은 프록시 또는 별도 가상 호스트로 PocketBase에 연결.
|
||||||
|
- 빌드 시 `VITE_POCKETBASE_URL=https://api.todo.sori.studio`, `VITE_PUBLIC_APP_URL=https://todo.sori.studio` 를 넣는다. (`docker compose`는 프로젝트 루트의 `.env`를 읽어 `todo-web` 빌드 인자로 전달할 수 있다.)
|
||||||
|
- PocketBase **CORS** 허용 출처에 `https://todo.sori.studio` 를 추가한다.
|
||||||
|
|
||||||
|
PocketBase는 Docker로 띄우려면 `docker compose up pocketbase`만 실행해도 된다. 컨테이너 **내부**에서는 PocketBase가 `8090`을 쓰고, **호스트에 노출되는 포트**는 `docker-compose.yml`의 `ports`를 따른다(기본값: 웹 `42881`→컨테이너 `80`, API `42917`→컨테이너 `8090`).
|
||||||
|
|
||||||
## Docker Compose(웹 + PocketBase)
|
## Docker Compose(웹 + PocketBase)
|
||||||
|
|
||||||
프로젝트 루트에서:
|
프로젝트 루트에서(LAN IP 예시):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export VITE_POCKETBASE_URL="http://<이_기기_IP>:8090"
|
export VITE_PUBLIC_APP_URL="http://<이_기기_IP>:42881"
|
||||||
|
export VITE_POCKETBASE_URL="http://<이_기기_IP>:42917"
|
||||||
docker compose up -d --build
|
docker compose up -d --build
|
||||||
```
|
```
|
||||||
|
|
||||||
- 웹: `http://<이_기기_IP>:8080`
|
- 웹: `http://<이_기기_IP>:42881`
|
||||||
- PocketBase 관리자: `http://<이_기기_IP>:8090/_/`
|
- PocketBase 관리자: `http://<이_기기_IP>:42917/_/`
|
||||||
|
|
||||||
**중요:** `VITE_POCKETBASE_URL`은 **컨테이너가 아니라 브라우저**에서 접근한다. 같은 PC에서만 쓸 때는 `http://127.0.0.1:8090`이 가능하지만, 휴대폰 등 다른 기기에서 접속할 때는 NAS/PC의 LAN IP 또는 공인 도메인을 사용해야 한다.
|
**중요:** `VITE_POCKETBASE_URL`은 **컨테이너가 아니라 브라우저**에서 접근한다. 같은 PC에서만 쓸 때는 `http://127.0.0.1:42917`(compose 기본 호스트 포트)이 가능하지만, 휴대폰 등 다른 기기에서는 NAS LAN IP 또는 공인 도메인을 사용해야 한다. 외부에는 리버스 프록시 **80/443**만 열고 내부 포트는 NAS 안에서만 쓰는 구성도 가능하다.
|
||||||
|
|
||||||
### PocketBase 초기 설정 요약
|
### PocketBase 초기 설정 요약
|
||||||
|
|
||||||
1. 관리자 UI에서 컬렉션 `todos` 생성(`title` text, `done` bool).
|
1. 관리자 UI에서 컬렉션 `todos` 생성(`title` text, `done` bool).
|
||||||
2. API 규칙을 배포 방식에 맞게 설정(인증 사용 시 로그인 사용자만 생성·수정 가능 등).
|
2. API 규칙을 배포 방식에 맞게 설정(인증 사용 시 로그인 사용자만 생성·수정 가능 등).
|
||||||
3. CORS 허용 출처에 웹 앱 출처(예: `http://<IP>:8080`)를 추가한다.
|
3. CORS 허용 출처에 웹 앱 출처를 추가한다. (LAN이면 `http://<IP>:42881`, 도메인이면 `https://todo.sori.studio` 등 **주소창과 동일**하게.)
|
||||||
|
|
||||||
### 선택: 관리자 자동 생성
|
### 선택: 관리자 자동 생성
|
||||||
|
|
||||||
@@ -40,10 +52,13 @@ docker compose up -d --build
|
|||||||
|
|
||||||
## 단일 이미지(웹만)
|
## 단일 이미지(웹만)
|
||||||
|
|
||||||
`Dockerfile`은 정적 빌드 결과를 nginx로 제공한다. 빌드 시점에 `VITE_POCKETBASE_URL`이 번들에 포함된다.
|
`Dockerfile`은 정적 빌드 결과를 nginx로 제공한다. 빌드 시점에 `VITE_POCKETBASE_URL`, `VITE_PUBLIC_APP_URL`이 번들·매니페스트에 반영된다.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build --build-arg VITE_POCKETBASE_URL="https://pb.example.com" -t todo-web .
|
docker build \
|
||||||
|
--build-arg VITE_POCKETBASE_URL="https://api.todo.sori.studio" \
|
||||||
|
--build-arg VITE_PUBLIC_APP_URL="https://todo.sori.studio" \
|
||||||
|
-t todo-web .
|
||||||
```
|
```
|
||||||
|
|
||||||
## PWA·HTTPS
|
## PWA·HTTPS
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
# 의사결정 이력
|
# 의사결정 이력
|
||||||
|
|
||||||
|
## 2026-04-13 · v0.0.4 — Compose 호스트 포트 분리
|
||||||
|
|
||||||
|
NAS에 동시에 띄우는 서비스가 많아 **8080/8090 고정 매핑이 충돌**할 수 있어, `docker-compose.yml`에서 호스트 포트를 **42881(웹)·42917(PocketBase)** 로 바꿨다. 컨테이너 내부 포트(웹 80, PocketBase 8090)는 그대로 두어 이미지·설정 호환을 유지한다. 기본 `VITE_POCKETBASE_URL`은 `http://127.0.0.1:42917`으로 맞춘다.
|
||||||
|
|
||||||
## 2026-04-13 · v0.0.2 — NAS 배포 가이드 문서 분리
|
## 2026-04-13 · v0.0.2 — NAS 배포 가이드 문서 분리
|
||||||
|
|
||||||
실제 NAS 경로(`/volume1/docker/projects/apps/todo` 등)에서 **Git 클론 → 환경 변수 → `docker compose` → PocketBase 초기 설정**까지 한 번에 따라 할 수 있도록 `docs/nas-deploy-guide.md`를 두었다. 요약은 `docs/deploy.md`에 두고, 단계별 설명은 NAS 가이드로 옮겨 유지보수 단위를 나눈다.
|
실제 NAS 경로(`/volume1/docker/projects/apps/todo` 등)에서 **Git 클론 → 환경 변수 → `docker compose` → PocketBase 초기 설정**까지 한 번에 따라 할 수 있도록 `docs/nas-deploy-guide.md`를 두었다. 요약은 `docs/deploy.md`에 두고, 단계별 설명은 NAS 가이드로 옮겨 유지보수 단위를 나눈다.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## 현재 버전
|
## 현재 버전
|
||||||
|
|
||||||
- `v0.0.2`
|
- `v0.0.4`
|
||||||
|
|
||||||
| 경로 | 역할 |
|
| 경로 | 역할 |
|
||||||
| ------------------------- | ----------------------------------------- |
|
| ------------------------- | ----------------------------------------- |
|
||||||
@@ -13,9 +13,9 @@
|
|||||||
| `src/lib/pocketBase.js` | PocketBase 싱글톤 클라이언트 |
|
| `src/lib/pocketBase.js` | PocketBase 싱글톤 클라이언트 |
|
||||||
| `src/lib/todoSchema.js` | 할 일 제목 Zod 스키마 |
|
| `src/lib/todoSchema.js` | 할 일 제목 Zod 스키마 |
|
||||||
| `src/composables/useTodos.js` | 목록 로드·추가·완료 토글 |
|
| `src/composables/useTodos.js` | 목록 로드·추가·완료 토글 |
|
||||||
| `vite.config.js` | Vue 플러그인, PWA 매니페스트 |
|
| `vite.config.js` | Vue 플러그인, PWA 매니페스트(`VITE_PUBLIC_APP_URL` 반영) |
|
||||||
| `tailwind.config.js` | 테마 색·폰트 |
|
| `tailwind.config.js` | 테마 색·폰트 |
|
||||||
| `docker-compose.yml` | PocketBase + 정적 웹(nginx) 구성 |
|
| `docker-compose.yml` | PocketBase + 정적 웹(nginx), 호스트 포트 기본 42881·42917 |
|
||||||
| `Dockerfile` | Vite 빌드 후 nginx 이미지 |
|
| `Dockerfile` | Vite 빌드 후 nginx 이미지 |
|
||||||
| `nginx.conf` | SPA 폴백 라우팅 |
|
| `nginx.conf` | SPA 폴백 라우팅 |
|
||||||
| `docs/nas-deploy-guide.md` | NAS SSH·Git 클론·Compose·PocketBase 설정 순서 |
|
| `docs/nas-deploy-guide.md` | NAS SSH·Git 클론·Compose·PocketBase 설정 순서 |
|
||||||
|
|||||||
@@ -103,8 +103,9 @@ ls
|
|||||||
|
|
||||||
예시:
|
예시:
|
||||||
|
|
||||||
- 같은 NAS 안의 브라우저만: `http://127.0.0.1:8090`도 동작할 수 있으나, **폰이나 다른 PC**에서는 거의 항상 실패한다.
|
- `docker-compose.yml`에 적어 둔 **호스트 포트**(웹 `42881`, PocketBase `42917`)는 다른 스택과 겹치지 않게 잡은 값이다. 겹치면 해당 파일의 `ports`만 바꾼 뒤, 아래 `export`·`.env`의 포트도 같이 맞춘다.
|
||||||
- 집 안에서 여러 기기: `http://192.168.x.x:8090` 형태의 **NAS LAN IP**를 쓴다.
|
- 같은 NAS 안의 브라우저만: `http://127.0.0.1:42917`처럼 **호스트에 열린 포트**로 접근한다. **폰이나 다른 PC**에서는 `127.0.0.1` 대신 **NAS LAN IP**를 써야 한다.
|
||||||
|
- 집 안에서 여러 기기: `http://192.168.x.x:42917`(API), `http://192.168.x.x:42881`(웹) 형태로 쓴다.
|
||||||
|
|
||||||
IP 확인은 NAS 관리 화면의 네트워크 정보를 보거나, SSH에서 NAS OS에 맞는 명령으로 확인한다. (기종별로 명령이 다를 수 있다.)
|
IP 확인은 NAS 관리 화면의 네트워크 정보를 보거나, SSH에서 NAS OS에 맞는 명령으로 확인한다. (기종별로 명령이 다를 수 있다.)
|
||||||
|
|
||||||
@@ -112,20 +113,43 @@ IP 확인은 NAS 관리 화면의 네트워크 정보를 보거나, SSH에서 NA
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. 환경 변수 `VITE_POCKETBASE_URL` 설정 후 Compose 실행
|
## 6. 환경 변수 설정 후 Compose 실행
|
||||||
|
|
||||||
프로젝트 루트(`docker-compose.yml`이 있는 곳)에서:
|
`docker compose`는 프로젝트 루트에 **`.env` 파일이 있으면 자동으로 읽는다.** (Git에 올리지 말 것. `.gitignore`에 포함됨.)
|
||||||
|
|
||||||
|
### 6-0. 운영 도메인을 쓰는 경우(예: todo.sori.studio)
|
||||||
|
|
||||||
|
`/volume1/docker/projects/apps/todo/.env` 예시:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
VITE_PUBLIC_APP_URL=https://todo.sori.studio
|
||||||
|
VITE_POCKETBASE_URL=https://api.todo.sori.studio
|
||||||
|
```
|
||||||
|
|
||||||
|
그다음:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /volume1/docker/projects/apps/todo
|
cd /volume1/docker/projects/apps/todo
|
||||||
export VITE_POCKETBASE_URL="http://192.168.0.50:8090"
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
리버스 프록시에서 **`todo.sori.studio` → 웹**, **`api.todo.sori.studio` → PocketBase** 로 각각 연결해야 한다. (경로·TLS는 사용 중인 NAS/프록시 제품 문서를 따른다.)
|
||||||
|
|
||||||
|
### 6-1. LAN IP만 쓰는 경우
|
||||||
|
|
||||||
|
프로젝트 루트에서 `export`로 한 세션에만 줄 수도 있다.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /volume1/docker/projects/apps/todo
|
||||||
|
export VITE_PUBLIC_APP_URL="http://192.168.0.50:42881"
|
||||||
|
export VITE_POCKETBASE_URL="http://192.168.0.50:42917"
|
||||||
docker compose up -d --build
|
docker compose up -d --build
|
||||||
```
|
```
|
||||||
|
|
||||||
- 첫 실행은 이미지 다운로드·빌드로 **시간이 걸릴 수 있다.**
|
- 첫 실행은 이미지 다운로드·빌드로 **시간이 걸릴 수 있다.**
|
||||||
- 백그라운드 실행은 `-d` 때문이다.
|
- 백그라운드 실행은 `-d` 때문이다.
|
||||||
|
|
||||||
### 6-1. 잘 떴는지 확인
|
### 6-2. 잘 떴는지 확인
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose ps
|
docker compose ps
|
||||||
@@ -133,7 +157,7 @@ docker compose ps
|
|||||||
|
|
||||||
`pocketbase`, `todo-web`(또는 compose에 정의된 웹 서비스 이름)이 `running`에 가깝게 보이면 된다.
|
`pocketbase`, `todo-web`(또는 compose에 정의된 웹 서비스 이름)이 `running`에 가깝게 보이면 된다.
|
||||||
|
|
||||||
### 6-2. 로그가 궁금할 때
|
### 6-3. 로그가 궁금할 때
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose logs -f --tail=100
|
docker compose logs -f --tail=100
|
||||||
@@ -145,19 +169,19 @@ docker compose logs -f --tail=100
|
|||||||
|
|
||||||
예시 IP 기준:
|
예시 IP 기준:
|
||||||
|
|
||||||
- **할 일 웹앱:** `http://192.168.0.50:8080`
|
- **할 일 웹앱:** `http://192.168.0.50:42881`
|
||||||
- **PocketBase 관리자 UI:** `http://192.168.0.50:8090/_/`
|
- **PocketBase 관리자 UI:** `http://192.168.0.50:42917/_/`
|
||||||
|
|
||||||
접속이 안 되면:
|
접속이 안 되면:
|
||||||
|
|
||||||
- NAS 방화벽 또는 보안 앱에서 **8080, 8090** 포트가 막혀 있지 않은지 확인한다.
|
- NAS 방화벽 또는 보안 앱에서 **42881, 42917** 포트가 막혀 있지 않은지 확인한다.
|
||||||
- `docker compose ps`로 컨테이너가 떠 있는지 다시 본다.
|
- `docker compose ps`로 컨테이너가 떠 있는지 다시 본다.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. PocketBase 최초 설정(한 번)
|
## 8. PocketBase 최초 설정(한 번)
|
||||||
|
|
||||||
1. 브라우저에서 `http://<NAS_IP>:8090/_/` 를 연다.
|
1. 브라우저에서 `http://<NAS_IP>:42917/_/` 를 연다. (호스트 포트를 바꿨다면 그 번호로 연다.)
|
||||||
2. 관리자 계정(이메일·비밀번호)을 만들고 마법사를 끝낸다.
|
2. 관리자 계정(이메일·비밀번호)을 만들고 마법사를 끝낸다.
|
||||||
3. **컬렉션 `todos` 생성**
|
3. **컬렉션 `todos` 생성**
|
||||||
- 필드 `title`: 타입 **Text**
|
- 필드 `title`: 타입 **Text**
|
||||||
@@ -165,10 +189,10 @@ docker compose logs -f --tail=100
|
|||||||
4. **API 규칙**
|
4. **API 규칙**
|
||||||
처음에는 테스트로 느슨하게 두었다가, 나중에 로그인 기반으로 조이는 것을 권장한다. (운영 정책에 맞게 조정.)
|
처음에는 테스트로 느슨하게 두었다가, 나중에 로그인 기반으로 조이는 것을 권장한다. (운영 정책에 맞게 조정.)
|
||||||
5. **설정 → CORS**
|
5. **설정 → CORS**
|
||||||
웹앱 출처를 허용 목록에 넣는다. 예: `http://192.168.0.50:8080`
|
웹앱 출처를 허용 목록에 넣는다. 예: `http://192.168.0.50:42881` 또는 `https://todo.sori.studio`
|
||||||
포트·프로토콜·호스트가 **실제로 주소창에 쓰는 것과 한 글자라도 다르면** 브라우저가 차단한다.
|
포트·프로토콜·호스트가 **실제로 주소창에 쓰는 것과 한 글자라도 다르면** 브라우저가 차단한다.
|
||||||
|
|
||||||
이후 `http://<NAS_IP>:8080`에서 목록·추가·완료 토글이 동작하는지 본다.
|
이후 `http://<NAS_IP>:42881`에서 목록·추가·완료 토글이 동작하는지 본다.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -179,7 +203,8 @@ NAS IP나 도메인이 바뀌면, **다시 빌드**해야 한다.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /volume1/docker/projects/apps/todo
|
cd /volume1/docker/projects/apps/todo
|
||||||
export VITE_POCKETBASE_URL="http://새로운_주소:8090"
|
export VITE_PUBLIC_APP_URL="http://새로운_주소:42881"
|
||||||
|
export VITE_POCKETBASE_URL="http://새로운_주소:42917"
|
||||||
docker compose up -d --build
|
docker compose up -d --build
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -190,7 +215,8 @@ docker compose up -d --build
|
|||||||
```bash
|
```bash
|
||||||
cd /volume1/docker/projects/apps/todo
|
cd /volume1/docker/projects/apps/todo
|
||||||
git pull
|
git pull
|
||||||
export VITE_POCKETBASE_URL="http://192.168.0.50:8090"
|
export VITE_PUBLIC_APP_URL="http://192.168.0.50:42881"
|
||||||
|
export VITE_POCKETBASE_URL="http://192.168.0.50:42917"
|
||||||
docker compose up -d --build
|
docker compose up -d --build
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -217,7 +243,7 @@ docker compose up -d --build
|
|||||||
|
|
||||||
| 증상 | 점검 |
|
| 증상 | 점검 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 웹은 뜨는데 데이터가 안 됨 | PocketBase `todos` 컬렉션·필드명, API 규칙, CORS에 `8080` 출처가 들어갔는지 |
|
| 웹은 뜨는데 데이터가 안 됨 | PocketBase `todos` 컬렉션·필드명, API 규칙, CORS에 웹 출처(`http://…:42881` 또는 `https://todo.sori.studio`)가 들어갔는지 |
|
||||||
| 폰에서만 안 됨 | `VITE_POCKETBASE_URL`이 `127.0.0.1`이 아닌지, 폰이 같은 Wi‑Fi인지, NAS IP가 맞는지 |
|
| 폰에서만 안 됨 | `VITE_POCKETBASE_URL`이 `127.0.0.1`이 아닌지, 폰이 같은 Wi‑Fi인지, NAS IP가 맞는지 |
|
||||||
| 빌드 후에도 주소가 이상함 | `docker compose build --no-cache` 후 다시 `up`, 또는 `export`를 잊지 않았는지 |
|
| 빌드 후에도 주소가 이상함 | `docker compose build --no-cache` 후 다시 `up`, 또는 `export`를 잊지 않았는지 |
|
||||||
| ARM NAS에서 이미지 오류 | 사용 중인 이미지가 해당 CPU 아키텍처를 지원하는지 로그로 확인한다. |
|
| ARM NAS에서 이미지 오류 | 사용 중인 이미지가 해당 CPU 아키텍처를 지원하는지 로그로 확인한다. |
|
||||||
@@ -230,9 +256,9 @@ docker compose up -d --build
|
|||||||
2. `cd /volume1/docker/projects/apps`
|
2. `cd /volume1/docker/projects/apps`
|
||||||
3. `git clone … todo` **또는** `cd todo` 후 `git clone … .`
|
3. `git clone … todo` **또는** `cd todo` 후 `git clone … .`
|
||||||
4. NAS LAN IP 확인
|
4. NAS LAN IP 확인
|
||||||
5. `export VITE_POCKETBASE_URL="http://<NAS_IP>:8090"`
|
5. LAN만 쓸 때: `export VITE_PUBLIC_APP_URL="http://<NAS_IP>:42881"` 및 `export VITE_POCKETBASE_URL="http://<NAS_IP>:42917"` (또는 6-0과 같이 `.env`에 기록)
|
||||||
6. `docker compose up -d --build`
|
6. `docker compose up -d --build`
|
||||||
7. 브라우저: `:8080` 앱, `:8090/_/` 관리자
|
7. 브라우저: `:42881` 앱, `:42917/_/` 관리자
|
||||||
8. `todos` 컬렉션·CORS·API 규칙 설정
|
8. `todos` 컬렉션·CORS·API 규칙 설정
|
||||||
|
|
||||||
이후 작업은 `git pull` → `export` → `docker compose up -d --build`를 반복하면 된다.
|
이후 작업은 `git pull` → `export` → `docker compose up -d --build`를 반복하면 된다.
|
||||||
|
|||||||
16
docs/spec.md
16
docs/spec.md
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## 현재 버전
|
## 현재 버전
|
||||||
|
|
||||||
- `v0.0.2`
|
- `v0.0.4`
|
||||||
|
|
||||||
## 스택
|
## 스택
|
||||||
|
|
||||||
@@ -25,8 +25,18 @@
|
|||||||
|
|
||||||
| 이름 | 설명 |
|
| 이름 | 설명 |
|
||||||
| ------------------------ | ------------------------------------------------------------ |
|
| ------------------------ | ------------------------------------------------------------ |
|
||||||
| `VITE_POCKETBASE_URL` | PocketBase 루트 URL(끝 슬래시 없음). **브라우저가 접근 가능한 주소**여야 한다. |
|
| `VITE_POCKETBASE_URL` | PocketBase 루트 URL(끝 슬래시 없음). **브라우저가 접근 가능한 주소**여야 한다. 운영 예: `https://api.todo.sori.studio` |
|
||||||
|
| `VITE_PUBLIC_APP_URL` | 사용자에게 보이는 웹앱 URL(끝 슬래시 없음). PWA Web App Manifest의 `id` 등에 사용. 운영 예: `https://todo.sori.studio` |
|
||||||
|
|
||||||
|
## Docker Compose 기본 호스트 포트
|
||||||
|
|
||||||
|
다른 서비스와의 충돌을 줄이기 위해 **호스트**에 붙는 포트를 4만 번대로 둔다. `docker-compose.yml` 상단 주석과 `ports` 항목을 기준으로 한다.
|
||||||
|
|
||||||
|
- 웹(nginx 정적): 호스트 **42881** → 컨테이너 `80`
|
||||||
|
- PocketBase: 호스트 **42917** → 컨테이너 `8090`
|
||||||
|
|
||||||
|
포트를 바꾼 경우 `VITE_POCKETBASE_URL`·`VITE_PUBLIC_APP_URL`의 포트·도메인도 동일하게 맞춘 뒤 이미지를 다시 빌드한다.
|
||||||
|
|
||||||
## 버전 정책
|
## 버전 정책
|
||||||
|
|
||||||
- 앱 버전은 `package.json`의 `version`과 문서의 `v0.0.1` 형식을 맞춘다.
|
- 앱 버전은 `package.json`의 `version`과 문서의 `v0.0.x` 형식을 맞춘다.
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
# 업데이트 로그
|
# 업데이트 로그
|
||||||
|
|
||||||
|
## v0.0.4
|
||||||
|
|
||||||
|
- ~수정. Docker Compose 호스트 포트: 웹 `42881`, PocketBase `42917`(충돌 시 `docker-compose.yml`만 조정).
|
||||||
|
- ~수정. `docs/deploy.md`, `docs/nas-deploy-guide.md`, `docs/spec.md`, `.env.example` 포트 안내 동기화.
|
||||||
|
|
||||||
|
## v0.0.3
|
||||||
|
|
||||||
|
- ~추가. `VITE_PUBLIC_APP_URL` 및 운영 도메인 예시(`todo.sori.studio`, `api.todo.sori.studio`).
|
||||||
|
- ~수정. `vite.config.js` PWA manifest `id`, Docker 빌드 인자·NAS 가이드 `.env` 절.
|
||||||
|
|
||||||
## v0.0.2
|
## v0.0.2
|
||||||
|
|
||||||
- ~추가. `docs/nas-deploy-guide.md` NAS 배포 SSH·Git·Compose 상세 가이드.
|
- ~추가. `docs/nas-deploy-guide.md` NAS 배포 SSH·Git·Compose 상세 가이드.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "todo",
|
"name": "todo",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.2",
|
"version": "0.0.4",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -1,40 +1,54 @@
|
|||||||
import { fileURLToPath, URL } from 'node:url'
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig, loadEnv } from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
import { VitePWA } from 'vite-plugin-pwa'
|
import { VitePWA } from 'vite-plugin-pwa'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig(({ mode }) => {
|
||||||
plugins: [
|
const env = loadEnv(mode, process.cwd(), '')
|
||||||
vue(),
|
const publicAppUrl = (env.VITE_PUBLIC_APP_URL || '').trim().replace(/\/+$/, '')
|
||||||
VitePWA({
|
|
||||||
registerType: 'autoUpdate',
|
const manifestIdentity =
|
||||||
includeAssets: ['favicon.svg'],
|
publicAppUrl !== ''
|
||||||
manifest: {
|
? {
|
||||||
name: 'Todo',
|
id: `${publicAppUrl}/`,
|
||||||
short_name: 'Todo',
|
scope: '/'
|
||||||
description: 'NAS용 Todo 웹앱',
|
}
|
||||||
theme_color: '#f2f2f7',
|
: {}
|
||||||
background_color: '#f2f2f7',
|
|
||||||
display: 'standalone',
|
return {
|
||||||
start_url: '/',
|
plugins: [
|
||||||
lang: 'ko',
|
vue(),
|
||||||
icons: [
|
VitePWA({
|
||||||
{
|
registerType: 'autoUpdate',
|
||||||
src: '/favicon.svg',
|
includeAssets: ['favicon.svg'],
|
||||||
sizes: 'any',
|
manifest: {
|
||||||
type: 'image/svg+xml',
|
name: 'Todo',
|
||||||
purpose: 'any'
|
short_name: 'Todo',
|
||||||
}
|
description: 'NAS용 Todo 웹앱',
|
||||||
]
|
theme_color: '#f2f2f7',
|
||||||
},
|
background_color: '#f2f2f7',
|
||||||
workbox: {
|
display: 'standalone',
|
||||||
globPatterns: ['**/*.{js,css,html,ico,svg,woff2}']
|
start_url: '/',
|
||||||
|
lang: 'ko',
|
||||||
|
icons: [
|
||||||
|
{
|
||||||
|
src: '/favicon.svg',
|
||||||
|
sizes: 'any',
|
||||||
|
type: 'image/svg+xml',
|
||||||
|
purpose: 'any'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
...manifestIdentity
|
||||||
|
},
|
||||||
|
workbox: {
|
||||||
|
globPatterns: ['**/*.{js,css,html,ico,svg,woff2}']
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
}
|
}
|
||||||
})
|
|
||||||
],
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user