diff --git a/.env.example b/.env.example index 0b3d396..fbc4a0a 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,12 @@ # Public URL that docker clients use to reach the Nuxt auth endpoint -# Behind NPM/Traefik this should be the HTTPS URL, e.g. https://registry-ui.example.com +# Behind NPM/Traefik this should be the HTTPS URL of the admin UI AUTH_PUBLIC_URL=http://localhost:3080 +# Public registry host shown in UI quick-start / used by docker login·push·pull +# Local: localhost:5050 +# Behind proxy: docker.sejong.dev (or https://docker.sejong.dev — scheme is stripped for CLI) +REGISTRY_PUBLIC_URL=localhost:5050 + # Registry token auth (must match auth.token.service / issuer in registry config) REGISTRY_AUTH_SERVICE=registry REGISTRY_AUTH_ISSUER=registry-aio diff --git a/README.md b/README.md index 67b3300..7724b7f 100644 --- a/README.md +++ b/README.md @@ -34,13 +34,16 @@ docker push localhost:5050/demo/alpine:latest ## 중요한 환경 변수 -- `AUTH_PUBLIC_URL` — **docker 클라이언트가 실제로 호출하는** Nuxt 공개 URL +- `AUTH_PUBLIC_URL` — **docker 클라이언트가 실제로 호출하는** Nuxt(관리 UI) 공개 URL - 로컬: `http://localhost:3080` - - 프록시 뒤: `https://registry-ui.example.com` + - 프록시 뒤: `https://docker-ui.sejong.dev` - Registry `auth.token.realm` = `${AUTH_PUBLIC_URL}/auth/token` +- `REGISTRY_PUBLIC_URL` — **docker login / push / pull에 쓰는** Registry 공개 주소 (UI 빠른 시작에도 표시) + - 로컬: `localhost:5050` + - 프록시 뒤: `docker.sejong.dev` (`https://`를 넣어도 CLI용으로 스킴은 제거됨) - `REGISTRY_PORT` / `APP_PORT` — 호스트 포트 (기본 `5050` / `3080`) - `REGISTRY_AUTH_SERVICE` / `REGISTRY_AUTH_ISSUER` — Registry와 Auth JWT 설정 (기본 `registry` / `registry-aio`) - - 주의: registry 컨테이너에는 `REGISTRY_*` 환경변수를 직접 넣지 않습니다(공식 이미지가 설정 오버라이드로 해석함). + - 주의: registry 컨테이너에는 `REGISTRY_*` 환경변수를 직접 넣지 않습니다(공식 이미지가 설정 오버라이드로 해석함). `REGISTRY_PUBLIC_URL`은 app에만 전달됩니다. - `SESSION_SECRET` — 관리 UI 세션 서명 키 (운영에서 반드시 변경) - `ADMIN_USERNAME` / `ADMIN_PASSWORD` — 최초 admin 시드 @@ -54,12 +57,13 @@ docker compose up -d --force-recreate registry 이 프로젝트는 TLS를 내장하지 않습니다. 이미 운영 중인 프록시에 연결하세요. -1. `registry.example.com` → 호스트 `:5050` -2. `registry-ui.example.com` → 호스트 `:3080` (UI + `/auth/token` + `/api`) +1. `docker.sejong.dev` → 호스트 `:5050` (Registry) +2. `docker-ui.sejong.dev` → 호스트 `:3080` (UI + `/auth/token` + `/api`) 3. `.env`에 다음을 설정 후 Compose 재기동: ```env -AUTH_PUBLIC_URL=https://registry-ui.example.com +AUTH_PUBLIC_URL=https://docker-ui.sejong.dev +REGISTRY_PUBLIC_URL=docker.sejong.dev ``` 프록시에서 Registry로 큰 이미지 업로드 시 body size 제한을 충분히 올리세요 (예: NPM의 client max body size). diff --git a/app/app/pages/guide.vue b/app/app/pages/guide.vue index e7fc648..42fdccb 100644 --- a/app/app/pages/guide.vue +++ b/app/app/pages/guide.vue @@ -28,11 +28,11 @@ docker compose up -d --build
UI / Auth
- localhost:3080 + {{ authPublicHost }}
Registry
- localhost:5050 + {{ registryHost }}
@@ -47,8 +47,8 @@ docker compose up -d --build UI에서 생성한 계정으로 로그인합니다. -
docker login localhost:5050
-docker pull localhost:5050/demo/alpine:latest
+
docker login {{ registryHost }}
+docker pull {{ registryHost }}/demo/alpine:latest

Registry가 Nuxt의 /auth/token에서 JWT를 발급받아 요청 권한을 검증합니다.

@@ -65,16 +65,17 @@ docker pull localhost:5050/demo/alpine:latest
-
- registry.example.com - :5050 +
+ {{ registryHost }} + :{{ registryPort }}
-
- registry-ui.example.com - :3080 +
+ {{ authPublicHost }} + :{{ appPort }}
-
AUTH_PUBLIC_URL=https://registry-ui.example.com
+
AUTH_PUBLIC_URL={{ authPublicUrl }}
+REGISTRY_PUBLIC_URL={{ registryHost }}
@@ -106,6 +107,26 @@ import { Info } from '@lucide/vue' useHead({ title: '가이드' }) +const config = useRuntimeConfig() + +function stripUrl(value: string) { + return value.replace(/^https?:\/\//i, '').replace(/\/+$/, '') +} + +const authPublicUrl = computed(() => String(config.public.authPublicUrl || 'http://localhost:3080')) +const authPublicHost = computed(() => stripUrl(authPublicUrl.value) || 'localhost:3080') +const registryHost = computed(() => { + const raw = String(config.public.registryPublicUrl || '').trim() + if (raw) return stripUrl(raw) + return `localhost:${config.public.registryPort || '5050'}` +}) +const registryPort = computed(() => String(config.public.registryPort || '5050')) +const appPort = computed(() => { + const host = authPublicHost.value + const match = host.match(/:(\d+)$/) + return match?.[1] || '3080' +}) + const aclPatterns = [ { pattern: 'demo/app', description: '정확한 저장소' }, { pattern: 'demo/*', description: 'demo 아래 한 단계' }, diff --git a/app/app/pages/index.vue b/app/app/pages/index.vue index c191fb1..cd49ce3 100644 --- a/app/app/pages/index.vue +++ b/app/app/pages/index.vue @@ -63,9 +63,11 @@ const { data: stats } = await useFetch<{ repositories: number }>('/api/stats') +/** docker login / push에 쓰는 호스트 (스킴·끝 슬래시 제거) */ const registryHost = computed(() => { - if (import.meta.client) { - return `${window.location.hostname}:${config.public.registryPort || '5050'}` + const raw = String(config.public.registryPublicUrl || '').trim() + if (raw) { + return raw.replace(/^https?:\/\//i, '').replace(/\/+$/, '') } return `localhost:${config.public.registryPort || '5050'}` }) diff --git a/app/nuxt.config.ts b/app/nuxt.config.ts index 02e56a1..916612f 100644 --- a/app/nuxt.config.ts +++ b/app/nuxt.config.ts @@ -17,7 +17,8 @@ export default defineNuxtConfig({ tokenKeyPath: process.env.TOKEN_KEY_PATH || '', tokenCertPath: process.env.TOKEN_CERT_PATH || '', public: { - authPublicUrl: process.env.AUTH_PUBLIC_URL || 'http://localhost:3000', + authPublicUrl: process.env.AUTH_PUBLIC_URL || 'http://localhost:3080', + registryPublicUrl: process.env.REGISTRY_PUBLIC_URL || 'localhost:5050', registryPort: process.env.REGISTRY_PORT || '5050', }, }, diff --git a/docker-compose.yml b/docker-compose.yml index 123cad0..a0842d1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -75,6 +75,7 @@ services: PORT: 3000 DATABASE_URL: file:/data/registry-aio.db AUTH_PUBLIC_URL: ${AUTH_PUBLIC_URL:-http://localhost:3080} + REGISTRY_PUBLIC_URL: ${REGISTRY_PUBLIC_URL:-localhost:5050} REGISTRY_AUTH_SERVICE: ${REGISTRY_AUTH_SERVICE:-registry} REGISTRY_AUTH_ISSUER: ${REGISTRY_AUTH_ISSUER:-registry-aio} REGISTRY_INTERNAL_URL: ${REGISTRY_INTERNAL_URL:-http://registry:5000}