DB 이름 vexplor → invyone 전환
Build & Deploy to K8s / build-and-deploy (push) Successful in 4m30s

- application.yml, k8s configmap, docker-compose 4종: SPRING_DATASOURCE_URL path
- provisioning 코드: {prefix}_vexplor → {prefix}_invyone 테넌트 DB 네이밍 규칙
- 프론트 마법사: Step1Basic, Step4Run 미리보기 라벨
- CompanyAccordionRow: 기본 DB 이름 포맷
- 마이그레이션/멀티테넌시 문서 동기화
- Traefik 와일드카드 설정 산출물 보관 (notes/)

비밀번호(vexplor0909!!) 및 역사 기록 문서(INVYONE_CONCEPT,
DDD1542, test-output, dashboard-runtime-fixes) 는 의도적으로 미변경.
This commit is contained in:
2026-04-24 19:15:06 +09:00
parent 8c861144dc
commit 76f43cea9b
20 changed files with 116 additions and 37 deletions
@@ -24,7 +24,7 @@ import java.util.UUID;
* *
* 6 단계: * 6 단계:
* 1. REGISTER_META — COMPANY_MNG 에 db_status='provisioning' 으로 row 선반영 (initiate) * 1. REGISTER_META — COMPANY_MNG 에 db_status='provisioning' 으로 row 선반영 (initiate)
* 2. CREATE_DATABASE — CREATE DATABASE "{prefix}_vexplor" * 2. CREATE_DATABASE — CREATE DATABASE "{prefix}_invyone"
* 3. COPY_SCHEMA — pg_dump --schema-only | psql * 3. COPY_SCHEMA — pg_dump --schema-only | psql
* 4. COPY_DATA — 선택 + 필수 그룹의 테이블들 JDBC 복사 * 4. COPY_DATA — 선택 + 필수 그룹의 테이블들 JDBC 복사
* 5. CREATE_ADMIN — user_info 에 {prefix}_admin INSERT (BCrypt) * 5. CREATE_ADMIN — user_info 에 {prefix}_admin INSERT (BCrypt)
@@ -53,7 +53,7 @@ public class CompanyProvisioningService {
private String metaDbName() { private String metaDbName() {
int slash = metaJdbcUrl.lastIndexOf('/'); int slash = metaJdbcUrl.lastIndexOf('/');
if (slash < 0) return "vexplor"; if (slash < 0) return "invyone";
String tail = metaJdbcUrl.substring(slash + 1); String tail = metaJdbcUrl.substring(slash + 1);
int q = tail.indexOf('?'); int q = tail.indexOf('?');
return q < 0 ? tail : tail.substring(0, q); return q < 0 ? tail : tail.substring(0, q);
@@ -63,7 +63,7 @@ public class CompanyProvisioningService {
public ProvisioningStatus initiate(Map<String, Object> req) { public ProvisioningStatus initiate(Map<String, Object> req) {
String companyCode = (String) req.get("company_code"); String companyCode = (String) req.get("company_code");
String dbPrefix = (String) req.get("db_prefix"); String dbPrefix = (String) req.get("db_prefix");
String dbName = dbPrefix + "_vexplor"; String dbName = dbPrefix + "_invyone";
String subdomain = (String) req.get("subdomain"); String subdomain = (String) req.get("subdomain");
// 템플릿 그룹 수 집계: 필수(3) + 선택된 optional // 템플릿 그룹 수 집계: 필수(3) + 선택된 optional
@@ -99,7 +99,7 @@ public class ProvisioningController {
if (dbPrefix != null) { if (dbPrefix != null) {
boolean formatOk = isValidDbPrefix(dbPrefix); boolean formatOk = isValidDbPrefix(dbPrefix);
String dbName = dbPrefix + "_vexplor"; String dbName = dbPrefix + "_invyone";
boolean exists = false; boolean exists = false;
if (formatOk) { if (formatOk) {
Map<String, Object> p = new HashMap<>(); Map<String, Object> p = new HashMap<>();
@@ -161,7 +161,7 @@ public class ProvisioningController {
"error", "invalid_format", "field", "db_prefix")); "error", "invalid_format", "field", "db_prefix"));
} }
// 중복 // 중복
String dbName = dbPrefix + "_vexplor"; String dbName = dbPrefix + "_invyone";
if (sqlSession.selectOne("provisioning.existsCompanyCode", Map.of("company_code", companyCode)) != null) { if (sqlSession.selectOne("provisioning.existsCompanyCode", Map.of("company_code", companyCode)) != null) {
return ResponseEntity.status(409).body(Map.of("error", "duplicate", "field", "company_code")); return ResponseEntity.status(409).body(Map.of("error", "duplicate", "field", "company_code"));
} }
@@ -17,7 +17,7 @@ public class ProvisioningStatus {
private String id; private String id;
/** 생성 요청한 회사 코드 */ /** 생성 요청한 회사 코드 */
private String companyCode; private String companyCode;
/** 생성 대상 DB 이름 (예: qnc_vexplor) */ /** 생성 대상 DB 이름 (예: qnc_invyone) */
private String dbName; private String dbName;
/** 서브도메인 */ /** 서브도메인 */
private String subdomain; private String subdomain;
@@ -14,7 +14,7 @@ spring:
jackson: jackson:
default-property-inclusion: always default-property-inclusion: always
datasource: datasource:
url: jdbc:postgresql://183.99.177.40:5432/vexplor url: jdbc:postgresql://183.99.177.40:5432/invyone
username: postgres username: postgres
password: "vexplor0909!!" password: "vexplor0909!!"
driver-class-name: org.postgresql.Driver driver-class-name: org.postgresql.Driver
+1 -1
View File
@@ -11,7 +11,7 @@
SOURCE_HOST="localhost" SOURCE_HOST="localhost"
SOURCE_PORT="5432" SOURCE_PORT="5432"
SOURCE_DB="vexplor" SOURCE_DB="invyone"
SOURCE_USER="postgres" SOURCE_USER="postgres"
TARGET_HOST="대상_호스트" TARGET_HOST="대상_호스트"
+4 -4
View File
@@ -14,7 +14,7 @@ Phase 1 은 **라우팅 no-op** 단계 — 컬럼만 추가, 실제 라우팅은
| 컬럼 | 타입 | 설명 | | 컬럼 | 타입 | 설명 |
|---|---|---| |---|---|---|
| `DB_NAME` | VARCHAR(64) | 실제 DB 이름 (예: `qnc_vexplor`). Phase 3 이전엔 NULL 허용 | | `DB_NAME` | VARCHAR(64) | 실제 DB 이름 (예: `qnc_invyone`). Phase 3 이전엔 NULL 허용 |
| `SUBDOMAIN` | VARCHAR(64) | 접속 서브도메인 (예: `qnc`). UNIQUE | | `SUBDOMAIN` | VARCHAR(64) | 접속 서브도메인 (예: `qnc`). UNIQUE |
| `DB_HOST` | VARCHAR(128) | DB 서버 호스트 (향후 분산 대비). 기본 NULL | | `DB_HOST` | VARCHAR(128) | DB 서버 호스트 (향후 분산 대비). 기본 NULL |
| `DB_STATUS` | VARCHAR(20) | `provisioning` / `schema_copied` / `admin_created` / `active` / `failed` / `suspended`. 기본 `active` | | `DB_STATUS` | VARCHAR(20) | `provisioning` / `schema_copied` / `admin_created` / `active` / `failed` / `suspended`. 기본 `active` |
@@ -44,13 +44,13 @@ CREATE UNIQUE INDEX IF NOT EXISTS UX_COMPANY_MNG_SUBDOMAIN
## 실행 방법 ## 실행 방법
### 방법 1: DBeaver / pgAdmin ### 방법 1: DBeaver / pgAdmin
1. `vexplor` DB 연결 1. `invyone` DB 연결
2. 위 SQL 블록 복사 & 실행 2. 위 SQL 블록 복사 & 실행
3. 확인 쿼리 돌려서 컬럼 생성 여부 확인 3. 확인 쿼리 돌려서 컬럼 생성 여부 확인
### 방법 2: psql ### 방법 2: psql
```bash ```bash
psql -h 183.99.177.40 -U postgres -d vexplor <<'SQL' psql -h 183.99.177.40 -U postgres -d invyone <<'SQL'
ALTER TABLE COMPANY_MNG ALTER TABLE COMPANY_MNG
ADD COLUMN IF NOT EXISTS DB_NAME VARCHAR(64), ADD COLUMN IF NOT EXISTS DB_NAME VARCHAR(64),
ADD COLUMN IF NOT EXISTS SUBDOMAIN VARCHAR(64), ADD COLUMN IF NOT EXISTS SUBDOMAIN VARCHAR(64),
@@ -99,6 +99,6 @@ ALTER TABLE COMPANY_MNG
## 체크리스트 ## 체크리스트
- [ ] `vexplor` DB 에 위 SQL 실행 - [ ] `invyone` DB 에 위 SQL 실행
- [ ] 확인 쿼리 1, 2, 3 모두 통과 - [ ] 확인 쿼리 1, 2, 3 모두 통과
- [ ] `SELECT * FROM COMPANY_MNG LIMIT 1;` 로 기존 데이터 정상 조회 확인 - [ ] `SELECT * FROM COMPANY_MNG LIMIT 1;` 로 기존 데이터 정상 조회 확인
+2 -2
View File
@@ -26,11 +26,11 @@ CREATE UNIQUE INDEX IF NOT EXISTS UX_COMPANY_MNG_DB_NAME
## 실행 방법 ## 실행 방법
### DBeaver / pgAdmin ### DBeaver / pgAdmin
위 SQL 블록을 `vexplor` DB 에 실행. 위 SQL 블록을 `invyone` DB 에 실행.
### psql ### psql
```bash ```bash
psql -h 183.99.177.40 -U postgres -d vexplor <<'SQL' psql -h 183.99.177.40 -U postgres -d invyone <<'SQL'
CREATE UNIQUE INDEX IF NOT EXISTS UX_COMPANY_MNG_DB_NAME CREATE UNIQUE INDEX IF NOT EXISTS UX_COMPANY_MNG_DB_NAME
ON COMPANY_MNG (DB_NAME) ON COMPANY_MNG (DB_NAME)
WHERE DB_NAME IS NOT NULL; WHERE DB_NAME IS NOT NULL;
+1 -1
View File
@@ -39,7 +39,7 @@ ALTER TABLE COMPANY_MNG
## 실행 ## 실행
```bash ```bash
psql -h 183.99.177.40 -U postgres -d vexplor <<'SQL' psql -h 183.99.177.40 -U postgres -d invyone <<'SQL'
ALTER TABLE COMPANY_MNG ALTER TABLE COMPANY_MNG
ADD COLUMN IF NOT EXISTS PLAN VARCHAR(20) DEFAULT 'Starter', ADD COLUMN IF NOT EXISTS PLAN VARCHAR(20) DEFAULT 'Starter',
ADD COLUMN IF NOT EXISTS INDUSTRY VARCHAR(50), ADD COLUMN IF NOT EXISTS INDUSTRY VARCHAR(50),
+1 -1
View File
@@ -12,7 +12,7 @@ services:
environment: environment:
- SPRING_PROFILES_ACTIVE=dev - SPRING_PROFILES_ACTIVE=dev
- SERVER_PORT=8081 - SERVER_PORT=8081
- SPRING_DATASOURCE_URL=jdbc:postgresql://183.99.177.40:5432/vexplor - SPRING_DATASOURCE_URL=jdbc:postgresql://183.99.177.40:5432/invyone
- SPRING_DATASOURCE_USERNAME=postgres - SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=vexplor0909!! - SPRING_DATASOURCE_PASSWORD=vexplor0909!!
- JWT_SECRET=ilshin-plm-super-secret-jwt-key-2024 - JWT_SECRET=ilshin-plm-super-secret-jwt-key-2024
+1 -1
View File
@@ -11,7 +11,7 @@ services:
environment: environment:
SPRING_PROFILES_ACTIVE: prod SPRING_PROFILES_ACTIVE: prod
SERVER_PORT: "8081" SERVER_PORT: "8081"
SPRING_DATASOURCE_URL: jdbc:postgresql://183.99.177.40:5432/vexplor SPRING_DATASOURCE_URL: jdbc:postgresql://183.99.177.40:5432/invyone
SPRING_DATASOURCE_USERNAME: postgres SPRING_DATASOURCE_USERNAME: postgres
SPRING_DATASOURCE_PASSWORD: "vexplor0909!!" SPRING_DATASOURCE_PASSWORD: "vexplor0909!!"
JWT_SECRET: ilshin-plm-super-secret-jwt-key-2024 JWT_SECRET: ilshin-plm-super-secret-jwt-key-2024
+1 -1
View File
@@ -12,7 +12,7 @@ services:
environment: environment:
- SPRING_PROFILES_ACTIVE=dev - SPRING_PROFILES_ACTIVE=dev
- SERVER_PORT=8082 - SERVER_PORT=8082
- SPRING_DATASOURCE_URL=jdbc:postgresql://183.99.177.40:5432/vexplor - SPRING_DATASOURCE_URL=jdbc:postgresql://183.99.177.40:5432/invyone
- SPRING_DATASOURCE_USERNAME=postgres - SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=vexplor0909!! - SPRING_DATASOURCE_PASSWORD=vexplor0909!!
- JWT_SECRET=ilshin-plm-super-secret-jwt-key-2024 - JWT_SECRET=ilshin-plm-super-secret-jwt-key-2024
+1 -1
View File
@@ -12,7 +12,7 @@ services:
environment: environment:
- SPRING_PROFILES_ACTIVE=prod - SPRING_PROFILES_ACTIVE=prod
- SERVER_PORT=8081 - SERVER_PORT=8081
- SPRING_DATASOURCE_URL=jdbc:postgresql://183.99.177.40:5432/vexplor - SPRING_DATASOURCE_URL=jdbc:postgresql://183.99.177.40:5432/invyone
- SPRING_DATASOURCE_USERNAME=postgres - SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=vexplor0909!! - SPRING_DATASOURCE_PASSWORD=vexplor0909!!
- JWT_SECRET=ilshin-plm-super-secret-jwt-key-2024 - JWT_SECRET=ilshin-plm-super-secret-jwt-key-2024
+9 -9
View File
@@ -11,9 +11,9 @@
INVYONE 은 **회사(=tenant)별로 독립된 PostgreSQL 데이터베이스**를 가진다. 접속한 서브도메인에 따라 요청이 자동으로 해당 회사 DB 로 라우팅된다. INVYONE 은 **회사(=tenant)별로 독립된 PostgreSQL 데이터베이스**를 가진다. 접속한 서브도메인에 따라 요청이 자동으로 해당 회사 DB 로 라우팅된다.
``` ```
qnc.invyone.com → qnc_vexplor DB qnc.invyone.com → qnc_invyone DB
kookje.invyone.com → kookje_vexplor DB kookje.invyone.com → kookje_invyone DB
vexplor (메타 DB) → 회사 정보·라우팅 테이블·SUPER_ADMIN 데이터 invyone (메타 DB) → 회사 정보·라우팅 테이블·SUPER_ADMIN 데이터
``` ```
### 설계 원칙 ### 설계 원칙
@@ -46,25 +46,25 @@ vexplor (메타 DB) → 회사 정보·라우팅 테이블·SUPER_ADMIN 데이
↓ (HTTP Host 헤더) ↓ (HTTP Host 헤더)
[SubdomainResolverFilter] [SubdomainResolverFilter]
↓ subdomain=qnc → CompanyResolver.resolveDbName("qnc") ↓ subdomain=qnc → CompanyResolver.resolveDbName("qnc")
↓ DbContextHolder.set("qnc_vexplor") ↓ DbContextHolder.set("qnc_invyone")
[JwtAuthenticationFilter] [JwtAuthenticationFilter]
[Controller → Service → sqlSession.selectList(...)] [Controller → Service → sqlSession.selectList(...)]
[TenantRoutingDataSource.determineTargetDataSource()] [TenantRoutingDataSource.determineTargetDataSource()]
↓ DbContextHolder.get() = "qnc_vexplor" ↓ DbContextHolder.get() = "qnc_invyone"
[HikariDataSource for qnc_vexplor] → 실제 SQL 실행 [HikariDataSource for qnc_invyone] → 실제 SQL 실행
``` ```
### 2.3 메타 DB 의 역할 ### 2.3 메타 DB 의 역할
`vexplor` DB (COMPANY_MNG 테이블) 는 **라우팅 룩업 테이블**만 담당: `invyone` DB (COMPANY_MNG 테이블) 는 **라우팅 룩업 테이블**만 담당:
| 컬럼 | 용도 | | 컬럼 | 용도 |
|---|---| |---|---|
| `COMPANY_CODE` | 회사 식별자 (PK) | | `COMPANY_CODE` | 회사 식별자 (PK) |
| `SUBDOMAIN` | 서브도메인 prefix (UNIQUE) | | `SUBDOMAIN` | 서브도메인 prefix (UNIQUE) |
| `DB_NAME` | 실제 tenant DB 이름 (예: `qnc_vexplor`) (UNIQUE) | | `DB_NAME` | 실제 tenant DB 이름 (예: `qnc_invyone`) (UNIQUE) |
| `DB_HOST` | tenant DB 호스트 (분산 대비, 현재 단일) | | `DB_HOST` | tenant DB 호스트 (분산 대비, 현재 단일) |
| `DB_STATUS` | `provisioning` / `active` / `failed` / `suspended` | | `DB_STATUS` | `provisioning` / `active` / `failed` / `suspended` |
| `PLAN`, `INDUSTRY`, `TEMPLATES_COUNT`, `DB_QUOTA_GB` | UI 메타 | | `PLAN`, `INDUSTRY`, `TEMPLATES_COUNT`, `DB_QUOTA_GB` | UI 메타 |
@@ -87,7 +87,7 @@ vexplor (메타 DB) → 회사 정보·라우팅 테이블·SUPER_ADMIN 데이
``` ```
1. REGISTER_META COMPANY_MNG 에 status='provisioning' 선반영 1. REGISTER_META COMPANY_MNG 에 status='provisioning' 선반영
2. CREATE_DATABASE CREATE DATABASE "{prefix}_vexplor" (postgres 기본 DB 경유) 2. CREATE_DATABASE CREATE DATABASE "{prefix}_invyone" (postgres 기본 DB 경유)
3. COPY_SCHEMA pg_dump --schema-only | psql (ProcessBuilder 배열 인자) 3. COPY_SCHEMA pg_dump --schema-only | psql (ProcessBuilder 배열 인자)
4. COPY_DATA 선택된 그룹 테이블 JDBC 복사 (company_code 필터) 4. COPY_DATA 선택된 그룹 테이블 JDBC 복사 (company_code 필터)
5. CREATE_ADMIN {prefix}_admin BCrypt 계정 생성 5. CREATE_ADMIN {prefix}_admin BCrypt 계정 생성
@@ -58,7 +58,7 @@ export default function CompanyAccordionRow({
const sub = r.subdomain || ""; const sub = r.subdomain || "";
const name = r.company_name || r.name || r.company_code; const name = r.company_name || r.name || r.company_code;
const plan = (r.plan || "Starter").toString(); const plan = (r.plan || "Starter").toString();
const dbName = r.db_name || `${sub}_vexplor`; const dbName = r.db_name || `${sub}_invyone`;
const dbPct = Number(r.db_pct) || 0; const dbPct = Number(r.db_pct) || 0;
const users = Number(r.users) || 0; const users = Number(r.users) || 0;
const active30 = Number(r.active30) || 0; const active30 = Number(r.active30) || 0;
@@ -167,7 +167,7 @@ export default function Step1Basic({
value={state.db_prefix || ""} value={state.db_prefix || ""}
onChange={onDbPrefixChange} onChange={onDbPrefixChange}
placeholder="영문 소문자 · 숫자 · 밑줄" placeholder="영문 소문자 · 숫자 · 밑줄"
suffix="_vexplor" suffix="_invyone"
mono mono
status={availToInputStatus(prefStatus)} status={availToInputStatus(prefStatus)}
/> />
@@ -289,7 +289,7 @@ export default function Step1Basic({
<span style={{ color: "var(--v5-primary)", fontWeight: 700 }}> <span style={{ color: "var(--v5-primary)", fontWeight: 700 }}>
{state.db_prefix || "___"} {state.db_prefix || "___"}
</span> </span>
<span style={{ color: "var(--v5-text-sec)" }}>_vexplor</span> <span style={{ color: "var(--v5-text-sec)" }}>_invyone</span>
</PreviewField> </PreviewField>
<PreviewField label="회사 코드"> <PreviewField label="회사 코드">
@@ -527,7 +527,7 @@ export default function Step4Run({
idx={i} idx={i}
status={rowStatus(s.key)} status={rowStatus(s.key)}
isLast={i === DISPLAY_STEPS.length - 1} isLast={i === DISPLAY_STEPS.length - 1}
dbName={`${state.db_prefix || "___"}_vexplor`} dbName={`${state.db_prefix || "___"}_invyone`}
/> />
))} ))}
</div> </div>
+2 -2
View File
@@ -6,13 +6,13 @@ metadata:
data: data:
SPRING_PROFILES_ACTIVE: "prod" SPRING_PROFILES_ACTIVE: "prod"
SERVER_PORT: "8081" SERVER_PORT: "8081"
SPRING_DATASOURCE_URL: "jdbc:postgresql://183.99.177.40:5432/vexplor" SPRING_DATASOURCE_URL: "jdbc:postgresql://183.99.177.40:5432/invyone"
SPRING_DATASOURCE_USERNAME: "postgres" SPRING_DATASOURCE_USERNAME: "postgres"
JWT_EXPIRATION: "86400000" JWT_EXPIRATION: "86400000"
FILE_UPLOAD_DIR: "./uploads" FILE_UPLOAD_DIR: "./uploads"
NODE_ENV: "production" NODE_ENV: "production"
NODE_PORT: "8080" NODE_PORT: "8080"
DATABASE_URL: "postgresql://postgres:vexplor0909!!@183.99.177.40:5432/vexplor" DATABASE_URL: "postgresql://postgres:vexplor0909!!@183.99.177.40:5432/invyone"
CORS_ORIGIN: "https://solution.invyone.com" CORS_ORIGIN: "https://solution.invyone.com"
NEXT_PUBLIC_API_URL: "https://solution.invyone.com/api" NEXT_PUBLIC_API_URL: "https://solution.invyone.com/api"
NEXT_TELEMETRY_DISABLED: "1" NEXT_TELEMETRY_DISABLED: "1"
@@ -41,7 +41,7 @@
| 목업에 없지만 UI 에서 파생 | 소스 | | 목업에 없지만 UI 에서 파생 | 소스 |
|---|---| |---|---|
| `{prefix}.invyone.com` 프리뷰 | `SUBDOMAIN` + 하드코딩 도메인 | | `{prefix}.invyone.com` 프리뷰 | `SUBDOMAIN` + 하드코딩 도메인 |
| `{prefix}_vexplor` DB 명 | `DB_NAME` | | `{prefix}_invyone` DB 명 | `DB_NAME` |
| 상태 dot | `DB_STATUS` | | 상태 dot | `DB_STATUS` |
### 1.2 런타임 집계 (CompanyStatsService) ### 1.2 런타임 집계 (CompanyStatsService)
@@ -67,7 +67,7 @@
| 목업 필드 | 계산 | | 목업 필드 | 계산 |
|---|---| |---|---|
| `url_preview` (`qnc.invyone.com`) | `${subdomain}.invyone.com` | | `url_preview` (`qnc.invyone.com`) | `${subdomain}.invyone.com` |
| `db_name_display` (`qnc_vexplor`) | `db_name` (이미 있음) | | `db_name_display` (`qnc_invyone`) | `db_name` (이미 있음) |
--- ---
@@ -86,7 +86,7 @@
"company_code": "COMPANY_10", "company_code": "COMPANY_10",
"company_name": "큐엔씨", "company_name": "큐엔씨",
"subdomain": "qnc", "subdomain": "qnc",
"db_name": "qnc_vexplor", "db_name": "qnc_invyone",
"db_host": "183.99.177.40", "db_host": "183.99.177.40",
"db_status": "active", "db_status": "active",
"status": "active", "status": "active",
@@ -0,0 +1,44 @@
services:
traefik:
image: traefik:v2.11
container_name: traefik
restart: always
ports:
- "80:80"
- "443:443"
command:
- --api.insecure=false
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --providers.docker.network=traefik-net
- --providers.file.directory=/dynamic
- --providers.file.watch=true
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.web.http.redirections.entryPoint.to=websecure
- --entrypoints.web.http.redirections.entryPoint.scheme=https
- --entrypoints.web.http.redirections.entryPoint.permanent=true
- --certificatesresolvers.le.acme.httpchallenge=true
- --certificatesresolvers.le.acme.httpchallenge.entrypoint=web
- --certificatesresolvers.le.acme.email=admin@junggomoa.com
- --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
- --certificatesresolvers.ledns.acme.dnschallenge=true
- --certificatesresolvers.ledns.acme.dnschallenge.provider=porkbun
- --certificatesresolvers.ledns.acme.email=admin@junggomoa.com
- --certificatesresolvers.ledns.acme.storage=/letsencrypt/acme-dns.json
- --log.level=INFO
environment:
- PORKBUN_API_KEY=${PORKBUN_API_KEY}
- PORKBUN_SECRET_API_KEY=${PORKBUN_SECRET_API_KEY}
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /opt/docker/traefik/letsencrypt:/letsencrypt
- /opt/docker/traefik/dynamic:/dynamic:ro
networks:
- traefik-net
networks:
traefik-net:
external: true
@@ -0,0 +1,35 @@
http:
routers:
invyone-tenant-frontend:
rule: "HostRegexp(`{sub:[a-z0-9-]+}.invyone.com`)"
entryPoints:
- web
- websecure
service: invyone-tenant-frontend
tls:
certResolver: ledns
domains:
- main: invyone.com
sans:
- "*.invyone.com"
invyone-tenant-api:
rule: "HostRegexp(`{sub:[a-z0-9-]+}.invyone.com`) && PathPrefix(`/api`)"
entryPoints:
- web
- websecure
service: invyone-tenant-api
tls:
certResolver: ledns
priority: 100
services:
invyone-tenant-frontend:
loadBalancer:
servers:
- url: "http://host.docker.internal:30000"
invyone-tenant-api:
loadBalancer:
servers:
- url: "http://host.docker.internal:30081"