fix: allow Nginx to read NAS card assets
This commit is contained in:
@@ -150,6 +150,9 @@ function createGameCardInstances(importedCards) {
|
||||
`/volume1/docker/projects/apps/uniare/config/www/images`를 컨테이너에 읽기
|
||||
전용으로 연결하고 `/card-assets` 경로로 제공한다.
|
||||
- 기존 Uniare의 `config/www/images`에는 쓰기 작업을 수행하지 않는다.
|
||||
- NAS 카드 파일 소유자 UID가 `1000`이므로 Nginx 워커는 `cardreader`
|
||||
사용자(UID 1000)로 실행한다. 이 기준을 바꾸기 전에는 실제 NAS 파일
|
||||
소유자를 다시 확인한다.
|
||||
- 로컬 Socket.IO 서버 기본 포트는 `31873`을 사용한다.
|
||||
- 운영 환경에서는 Socket.IO 포트를 브라우저에 직접 노출하지 않고 같은
|
||||
도메인의 `/socket.io` 경로로 리버스 프록시한다.
|
||||
|
||||
@@ -10,8 +10,12 @@ RUN npm run build
|
||||
|
||||
FROM nginx:1.27-alpine AS runtime
|
||||
|
||||
RUN adduser -D -H -u 1000 -G wheel cardreader \
|
||||
&& sed -i 's/user nginx;/user cardreader wheel;/' /etc/nginx/nginx.conf
|
||||
|
||||
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
RUN chmod -R a+rX /usr/share/nginx/html
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
|
||||
@@ -242,6 +242,10 @@ docker exec playuniare-web ls /srv/uniare-card-images
|
||||
|
||||
이 경로 역시 같은 시리즈 폴더를 보여야 한다.
|
||||
|
||||
Play Uniare의 Nginx 작업 프로세스는 기존 카드 파일 소유자와 같은 UID
|
||||
`1000`의 `cardreader` 사용자로 실행된다. 원본 카드 폴더는 계속 읽기 전용으로
|
||||
마운트되므로 시뮬레이터가 파일을 수정하거나 삭제할 수 없다.
|
||||
|
||||
## 새 버전 업데이트
|
||||
|
||||
### 안전한 권장 순서
|
||||
@@ -375,6 +379,59 @@ docker compose \
|
||||
컨테이너 내부의 80 포트는 다른 컨테이너와 같아도 괜찮다. `.env`에 설정하는
|
||||
NAS 호스트 포트만 겹치지 않으면 된다.
|
||||
|
||||
## 카드 이미지가 `403 Forbidden`인 경우
|
||||
|
||||
로그에 다음 내용이 있으면 Nginx 작업 사용자가 NAS 카드 파일을 읽지 못한
|
||||
것이다.
|
||||
|
||||
```text
|
||||
open() "/srv/uniare-card-images/..." failed (13: Permission denied)
|
||||
```
|
||||
|
||||
현재 Docker 이미지는 기존 카드 파일 소유자 UID `1000`에 맞춘 `cardreader`
|
||||
사용자를 사용한다. 최신 소스를 받은 후 이미지를 반드시 다시 빌드한다.
|
||||
|
||||
```bash
|
||||
cd /volume1/docker/projects/apps/playuniare
|
||||
git pull
|
||||
|
||||
docker compose \
|
||||
-f compose.test.yaml \
|
||||
-f compose.test.nas.yaml \
|
||||
down
|
||||
|
||||
docker compose \
|
||||
-f compose.test.yaml \
|
||||
-f compose.test.nas.yaml \
|
||||
up -d --build
|
||||
```
|
||||
|
||||
Nginx 워커 사용자를 확인하려면:
|
||||
|
||||
```bash
|
||||
docker exec playuniare-test-web ps aux
|
||||
```
|
||||
|
||||
`nginx: worker process`가 `cardreader`로 표시되어야 한다.
|
||||
|
||||
카드 파일 읽기를 직접 확인하려면:
|
||||
|
||||
```bash
|
||||
docker exec playuniare-test-web \
|
||||
su -s /bin/sh cardreader -c \
|
||||
'head -c 10 /srv/uniare-card-images/ua03/EX01BT_HTR-2-001.png >/dev/null && echo READ_OK'
|
||||
```
|
||||
|
||||
`READ_OK`가 나오면 다음 주소에서 카드가 보여야 한다.
|
||||
|
||||
```text
|
||||
http://NAS_IP:41808/card-assets/ua03/EX01BT_HTR-2-001.png
|
||||
```
|
||||
|
||||
NAS에서 카드 파일 소유자의 UID가 `1000`이 아닌 경우에는 임의로 폴더 권한을
|
||||
`777`로 변경하지 말고, 실제 UID를 확인한 뒤 Docker 실행 사용자 정책을
|
||||
조정한다.
|
||||
|
||||
## 배포 체크리스트
|
||||
|
||||
- [ ] 로컬 `npm run build` 성공
|
||||
|
||||
@@ -50,3 +50,11 @@
|
||||
- 기존 테스트 포트 `18080`이 NAS의 다른 서비스와 충돌했다.
|
||||
- 테스트 기본 포트를 `41808`, 운영 기본 포트를 `41809`로 변경했다.
|
||||
- NAS별 포트 충돌에 대응할 수 있도록 `.env`와 Compose 변수로 관리한다.
|
||||
|
||||
## 2026-06-19: NAS 카드 이미지 ACL 대응
|
||||
|
||||
- NAS 카드 파일은 POSIX 권한이 열려 있어도 ACL 때문에 기본 Nginx UID
|
||||
`101`에서 읽기가 거부되었다.
|
||||
- 카드 파일 소유자 UID가 `1000`인 것을 확인했다.
|
||||
- Nginx 워커를 UID `1000`의 `cardreader` 사용자로 실행하도록 변경했다.
|
||||
- Vue 정적 파일에는 빌드 단계에서 명시적인 읽기 권한을 적용했다.
|
||||
|
||||
@@ -116,5 +116,7 @@ Play Uniare 컨테이너 내부:
|
||||
- `config/www`는 기존 `index.html`이 존재하는 실제 웹 루트다.
|
||||
- Docker bind mount는 `images` 폴더만 읽기 전용으로 연결한다.
|
||||
- Play Uniare는 기존 카드 이미지를 읽을 수 있지만 수정하거나 삭제할 수 없다.
|
||||
- Nginx 작업 프로세스는 NAS 카드 파일 소유자와 같은 UID `1000`의
|
||||
`cardreader` 사용자로 실행한다.
|
||||
- 카드 이미지 URL은 `/card-assets/<series>/<fileName>` 형식을 사용한다.
|
||||
- 같은 Play Uniare 도메인으로 제공되므로 별도의 CORS 설정이 필요하지 않다.
|
||||
|
||||
@@ -15,3 +15,5 @@
|
||||
문서화했다.
|
||||
- NAS HTTP 포트 충돌을 해결하기 위해 테스트·운영 포트를 환경변수로
|
||||
변경하고 `port is already allocated` 복구 절차를 추가했다.
|
||||
- NAS ACL로 인한 카드 이미지와 favicon의 403 오류를 해결하기 위해 Nginx
|
||||
워커 UID와 정적 파일 권한을 조정했다.
|
||||
|
||||
Reference in New Issue
Block a user