Windows 바인드 마운트(./frontend:/app) 너머의 소스를 vite 가 모듈마다 읽는 데다
폴링 감시까지 항상 켜져 있어 첫 서빙에 수 분이 걸렸다. 호스트에서 띄우면 2초다.
- dev 오버라이드의 frontend 를 compose profile `frontend` 뒤로 숨긴다 (운영은 그대로)
- 폴링 감시는 CHOKIDAR_USEPOLLING 으로 컨테이너에서만 켠다
- dev 서버 포트·프록시 대상을 루트 .env.{mode} 에서 읽는다 (포트 SSOT 유지)
포트 충돌 시 조용히 옮기지 않도록 strictPort — CORS_ORIGIN·포트 매핑이 묶여 있다
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI 워크플로는 저장소에 있지만 실행 주체(러너)가 없어 동작하지 않는 상태였다.
러너가 없으면 워크플로는 "Waiting for a runner" 로 대기만 한다.
- ci/docker-compose.runner.yml — act_runner 를 별도 스택으로 분리.
앱 스택은 개발할 때만 띄우지만 러너는 항상 켜져 있어야 하므로 생명주기가 다르다.
- ci/.env.example — 등록 토큰은 ci/.env 에만 두며 커밋되지 않는다.
- ci/README.md — 설치 절차, 증상별 문제 해결, 잡별 리소스 특성.
- 라벨 기본값이 워크플로의 runs-on(ubuntu-latest)과 일치하는지 교차 확인했다.
불일치는 잡이 영원히 대기하는 가장 흔한 원인이다.
러너가 도커 소켓에 접근해 사실상 호스트 관리자 권한을 갖는다는 점도 문서에 명시했다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Redis 컨테이너가 항상 떠 있었지만 애플리케이션은 사용하지 않았다.
쓰지 않는 컨테이너는 메모리를 차지하고 "이게 왜 떠 있지" 하는 혼란을 준다.
- redis 서비스를 profiles: ["redis"] 로 숨겨 기본 기동에서 제외
- backend 의 redis 의존성을 required: false 로 두어 없어도 정상 기동
- 루트 .env 의 COMPOSE_PROFILES 한 줄로 켤 수 있게 함
(데이터 볼륨과 REDIS_* 는 유지되어 켜면 이전 상태가 그대로 이어진다)
profile 미지정 시 서비스 목록에서 제외되는 것, redis 없이 앱이 정상 동작하는 것,
COMPOSE_PROFILES=redis 로 다시 기동되는 것을 모두 확인했다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
security.md 가 금지한다고 적어둔 것을 실제 설정이 어기고 있었다.
- 프론트엔드 운영 컨테이너가 root 로 nginx 를 실행하고 있었다.
nginx-unprivileged 로 전환하고 포트를 8080 으로 맞춤(비-root 는 1024 미만 바인드 불가).
- dev 오버라이드가 사용하는 빌드 스테이지에도 USER node 적용.
익명 볼륨이 node 소유로 생성되도록 chown 을 USER 전환 앞에 둔다
(그렇지 않으면 vite 가 node_modules/.vite 캐시를 쓰지 못한다).
- dev 의 DB/Redis 포트가 0.0.0.0 에 바인딩되어 같은 LAN 에 노출돼 있었다 → 127.0.0.1 로 한정.
- CSP 헤더 추가. 대신 현대 브라우저에서 권장되지 않는 X-XSS-Protection 은 제거.
- CORS 차단 시 Error 를 던져 500(SYS_001)이 되던 것을 헤더 미부여 방식으로 변경.
- 헬스체크가 localhost 를 ::1 로 해석해 항상 실패하던 문제 수정(127.0.0.1 명시).
- graceful shutdown 을 위해 init(tini)과 stop_grace_period 적용.
- *.example 의 실제같은 비밀번호를 placeholder 로 교체하고,
비어 있던 서비스 env 예시에 안내를 채움.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 슬래시 커맨드(nestjs/vue3/flutter)를 정식 스킬(.claude/skills)로 전환하고
docker 스킬을 신설(루트 command.md 이관)
- 공통 규칙을 .claude/rules 로 모듈화(coding-common·response-format·error-codes·
git-convention·security·env-structure·testing·checklist)하고 CLAUDE.md 에서 @import
- 파일·식별자 네이밍 규약, 테스트 규칙 추가
- .claude/settings.json(권한·환경) 추가
- CLAUDE.md·README.md 참조 갱신, 단독 실행(non-Docker) 안내 정리
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>