forked from baron/baron-sso
production 푸시 초안
This commit is contained in:
@@ -287,9 +287,10 @@ Upload flow:
|
||||
2. `dump.sh`가 `reports/backup-report.md`를 생성한다. report에는 사용자 수, 테넌트 수, RP 수, Hydra client 수, WORKS 관련 row count, 서비스별 수행 시간이 Markdown 표로 기록된다.
|
||||
3. `upload_cloud.sh`가 백업 디렉터리를 `baron-sso-backup-*.tar.zst`로 압축한다.
|
||||
4. Drive API용 access token을 확인한다.
|
||||
- 우선순위: `WORKS_DRIVE_ACCESS_TOKEN`, `WORKS_DRIVE_ACCESS_TOKEN_FILE`, `WORKS_DRIVE_ACCESS_TOKEN_CMD`
|
||||
- fallback 1: `WORKS_DRIVE_OAUTH_REFRESH_TOKEN`으로 Drive 앱 access token 갱신
|
||||
- fallback 2: `WORKS_DRIVE_OAUTH_*` 서비스 계정 JWT 토큰 발급
|
||||
- `WORKS_DRIVE_ACCESS_TOKEN`, `WORKS_DRIVE_ACCESS_TOKEN_FILE`, `WORKS_DRIVE_ACCESS_TOKEN_CMD`는 항상 최우선이다.
|
||||
- `WORKS_DRIVE_AUTH_MODE=auto` 기본값은 service account credentials가 완비되어 있으면 `WORKS_DRIVE_OAUTH_*` 서비스 계정 JWT 토큰 발급을 먼저 사용하고, 없으면 `WORKS_DRIVE_OAUTH_REFRESH_TOKEN` 갱신으로 fallback한다.
|
||||
- `WORKS_DRIVE_AUTH_MODE=service-account`는 service account JWT 토큰 발급을 강제한다.
|
||||
- `WORKS_DRIVE_AUTH_MODE=refresh-token`은 service account 설정이 있어도 refresh token 갱신을 강제한다.
|
||||
5. WORKS Drive upload URL 생성 API를 호출한다.
|
||||
6. 발급받은 upload URL에 multipart `Filedata`로 `.tar.zst` archive를 업로드한다.
|
||||
7. `WORKS_DRIVE_UPLOAD_REPORTS=true`이면 대상 폴더 아래 `WORKS_DRIVE_REPORT_FOLDER_NAME` 하위 폴더를 찾거나 생성한 뒤 `reports/*.md`만 업로드한다.
|
||||
@@ -312,8 +313,13 @@ Upload flow:
|
||||
- Drive API는 `file` scope가 필요하다.
|
||||
- `WORKS_DRIVE_PARENT_FILE_ID`는 폴더 이름이나 경로가 아니라 WORKS Drive API가 반환하는 폴더 `fileId`여야 한다.
|
||||
- 계정 동기화용 `WORKS_ADMIN_OAUTH_*`와 백업 업로드용 `WORKS_DRIVE_OAUTH_*`는 용도가 다른 앱/키로 분리한다.
|
||||
- 운영 기본 경로는 Drive용 access token을 명시 주입하거나 `WORKS_DRIVE_OAUTH_REFRESH_TOKEN`으로 갱신하는 방식이다.
|
||||
- 서비스 계정 JWT fallback은 Drive 업로드 앱 정책에서 Drive scope 위임이 허용된 경우에만 성공한다.
|
||||
- 운영 기본 경로는 Drive용 access token을 명시 주입하거나 service account JWT를 사용하는 방식이다.
|
||||
- refresh token을 재발급해 사용하는 경우 `make works-drive-refresh-token`을 사용한다. WORKS OAuth refresh token은 Authorization Code Flow에서 발급되며, WORKS Token 설정의 Refresh Token Rotation 상태에 따라 갱신 응답에 새 refresh token이 포함될 수 있다.
|
||||
- 기존 refresh token이 아직 유효하면 `make works-drive-refresh-token WORKS_DRIVE_TOKEN_GRANT=refresh-token`로 `.env`의 `WORKS_DRIVE_OAUTH_REFRESH_TOKEN`을 자동 갱신한다.
|
||||
- 기존 refresh token이 폐기되어 401이 발생하면 `WORKS_DRIVE_TOKEN_GRANT=print-authorize-url scripts/backup/refresh_works_drive_token.sh`로 출력된 URL을 브라우저에서 승인한 뒤, callback의 `code`를 `make works-drive-refresh-token WORKS_DRIVE_TOKEN_GRANT=authorization-code WORKS_DRIVE_AUTH_CODE=<code>`에 전달한다.
|
||||
- callback URL 전체를 복사할 수 있으면 `WORKS_DRIVE_AUTH_CALLBACK_URL=<callback-url>`을 사용해도 된다.
|
||||
- 토큰 갱신 도구는 짧게 만료되는 access token을 `.env`에 저장하지 않고 refresh token과 `WORKS_DRIVE_AUTH_MODE=refresh-token`만 갱신한다.
|
||||
- 서비스 계정 JWT는 Drive 업로드 앱 정책에서 Drive scope 위임이 허용되고 Client ID, Service Account, Private Key가 같은 앱에서 발급된 조합일 때만 성공한다.
|
||||
- 파일 크기가 WORKS Drive 단일 파일 제한에 걸릴 수 있으면 `WORKS_DRIVE_MAX_SINGLE_FILE_BYTES` 또는 `WORKS_DRIVE_FORCE_SPLIT=true`로 split part 업로드를 사용한다.
|
||||
- Markdown report 업로드 기본 폴더명은 `reports`이며 `WORKS_DRIVE_REPORT_FOLDER_NAME`으로 바꿀 수 있다.
|
||||
- 외부 업로드 성공은 복구 가능성을 보장하지 않는다. 업로드 후에도 `make dump-verify BACKUP=...`와 restore rehearsal을 별도로 수행해야 한다.
|
||||
|
||||
190
docs/traefik-production-rp-bootstrap-design.md
Normal file
190
docs/traefik-production-rp-bootstrap-design.md
Normal file
@@ -0,0 +1,190 @@
|
||||
# Traefik Production RP Bootstrap Design
|
||||
|
||||
## Context
|
||||
|
||||
프로덕션 배포환경에서는 Baron SSO 앞단에 Traefik이 reverse proxy로 먼저 떠 있고, Traefik dashboard와 보호 대상 라우트도 Baron SSO 인증을 사용해야 한다.
|
||||
|
||||
현재 `config/traefik-compose.yml`은 Traefik과 `traefik-forward-auth`를 사전 구동하는 형태지만 다음 보완이 필요하다.
|
||||
|
||||
- `CLIENT_ID`, `CLIENT_SECRET`, `SECRET`가 파일에 하드코딩되어 있다.
|
||||
- OIDC endpoint가 Baron/Ory Hydra가 아니라 Keycloak style path를 가리킨다.
|
||||
- `traefik-public` external network가 선언만 되어 있고 서비스에 연결되어 있지 않다.
|
||||
- production boot flow에서 Traefik forward-auth RP가 Hydra에 자동 등록되지 않는다.
|
||||
|
||||
관련 이슈: #1221
|
||||
|
||||
## Policy Alignment
|
||||
|
||||
- OAuth2/OIDC client SoT는 Ory Hydra다.
|
||||
- client secret 원문은 Git에 커밋하지 않고 `.env`, 배포 host의 secret file, Gitea Actions secret, 또는 운영 secret store에서 주입한다.
|
||||
- Kratos는 identity SoT, Keto는 authorization relation SoT로 유지한다.
|
||||
- Traefik과 forward-auth가 신뢰할 수 있는 last-hop proxy가 되며, 애플리케이션은 임의 외부 요청의 identity header를 신뢰하지 않는다.
|
||||
- Wiki가 사용 중이므로 실제 Wiki 업데이트 전 검토본은 `docs/` 문서로 둔다.
|
||||
|
||||
## Target Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
User[Browser] --> Traefik[Traefik edge proxy]
|
||||
Traefik -->|ForwardAuth| TFA[traefik-forward-auth]
|
||||
TFA -->|OIDC authorize/token/userinfo| Hydra[Ory Hydra public endpoint]
|
||||
Hydra --> UserFront[Baron UserFront login/consent]
|
||||
UserFront --> Backend[Baron Backend]
|
||||
Backend --> Kratos[Ory Kratos]
|
||||
Backend --> Keto[Ory Keto]
|
||||
Traefik --> Dashboard[api@internal dashboard]
|
||||
Traefik --> BaronRoute[Baron app routes]
|
||||
```
|
||||
|
||||
`traefik-forward-auth`는 Hydra confidential client로 등록한다. SPA용 `adminfront`, `devfront`, `orgfront`와 달리 server-side middleware이므로 `client_secret` 기반 client로 다룬다.
|
||||
|
||||
## Configuration Contract
|
||||
|
||||
운영 환경 변수는 다음 이름을 기준으로 둔다.
|
||||
|
||||
| Key | Required | Example | Note |
|
||||
|---|---:|---|---|
|
||||
| `TRAEFIK_DASHBOARD_HOST` | yes | `traefik.brsw.kr` | Traefik dashboard host |
|
||||
| `TRAEFIK_FORWARD_AUTH_HOST` | yes | `auth.brsw.kr` | forward-auth callback host |
|
||||
| `TRAEFIK_FORWARD_AUTH_CLIENT_ID` | yes | `traefik-forward-auth` | Hydra client id |
|
||||
| `TRAEFIK_FORWARD_AUTH_CLIENT_SECRET` | yes in production | secret value | Git에 저장하지 않는다 |
|
||||
| `TRAEFIK_FORWARD_AUTH_COOKIE_SECRET` | yes in production | 32+ byte random | forward-auth cookie signing secret |
|
||||
| `TRAEFIK_FORWARD_AUTH_CALLBACK_URLS` | yes | `https://auth.brsw.kr/_oauth` | comma-separated |
|
||||
| `HYDRA_PUBLIC_URL` | yes | `https://app.brsw.kr/oidc` | Baron/Ory public issuer base |
|
||||
|
||||
`config/traefik-compose.yml`은 위 값을 직접 박지 않고 `${...}` placeholder만 사용한다. 여기서 금지하는 것은 "운영 secret 원문을 코드/문서/compose 파일에 커밋하는 것"이다. 배포 이후에는 발급된 client id/secret/cookie secret을 운영 설정 또는 저장소 secret에 고정해 재사용해야 한다.
|
||||
|
||||
## Compose Design
|
||||
|
||||
`config/traefik-compose.yml`의 방향은 다음과 같다.
|
||||
|
||||
- `traefik`와 `forward-auth` 모두 `traefik-public` external network에 붙인다.
|
||||
- `forward-auth` service에는 `traefik.http.services.forward-auth.loadbalancer.server.port=4181` label을 명시한다.
|
||||
- dashboard router에는 `auth-forward@docker` middleware를 적용한다.
|
||||
- forward-auth provider endpoint는 `HYDRA_PUBLIC_URL` 기반 `generic-oauth` 설정으로 산출한다. Traefik이 Baron/Ory보다 먼저 떠야 하는 bootstrap 순서에서는 OIDC discovery가 시작 시점에 실패할 수 있으므로 명시 endpoint 방식을 사용한다.
|
||||
- auth: `${HYDRA_PUBLIC_URL}/oauth2/auth`
|
||||
- token: `${HYDRA_PUBLIC_URL}/oauth2/token`
|
||||
- userinfo: `${HYDRA_PUBLIC_URL}/userinfo`
|
||||
- `INSECURE_COOKIE=false`를 production 기본값으로 둔다.
|
||||
- `CLIENT_SECRET`과 cookie `SECRET`는 운영 secret 주입만 허용한다.
|
||||
|
||||
Baron app compose 쪽에서도 production-facing 진입 서비스는 `traefik-public`에 붙어야 한다. 기존 정책상 외부 진입은 gateway/Oathkeeper 계층으로 수렴하는 것이 맞으므로, Traefik이 직접 backend admin endpoint로 붙는 구조는 피한다.
|
||||
|
||||
## Hydra Client Bootstrap Design
|
||||
|
||||
현재 `compose.ory.yaml`의 `init-rp`는 Hydra 준비 후 기본 RP를 등록한다. Traefik forward-auth RP도 같은 부팅 경로에 넣되, production mode에서만 활성화한다.
|
||||
|
||||
권장 조건:
|
||||
|
||||
```sh
|
||||
APP_ENV in production|prod
|
||||
TRAEFIK_FORWARD_AUTH_ENABLED=true
|
||||
```
|
||||
|
||||
등록 payload:
|
||||
|
||||
```json
|
||||
{
|
||||
"client_id": "traefik-forward-auth",
|
||||
"client_name": "Traefik Forward Auth",
|
||||
"client_secret": "<from env>",
|
||||
"grant_types": ["authorization_code", "refresh_token"],
|
||||
"response_types": ["code"],
|
||||
"scope": "openid offline_access profile email",
|
||||
"redirect_uris": ["https://auth.brsw.kr/_oauth"],
|
||||
"token_endpoint_auth_method": "client_secret_basic",
|
||||
"metadata": {
|
||||
"managed_by": "baron-sso-boot",
|
||||
"system_client": true,
|
||||
"purpose": "traefik-forward-auth",
|
||||
"status": "active"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
구현은 delete/create보다 idempotent upsert가 안전하다. 최초 부팅 시에는 값이 없으면 생성값을 발급할 수 있지만, RP가 한번 등록된 뒤에는 같은 `client_id`, `client_secret`, callback URI를 운영 설정으로 고정해야 한다. 재배포마다 secret이 바뀌면 forward-auth cookie/session과 Hydra client 인증이 깨질 수 있으므로 rotation은 별도 운영 작업으로만 수행한다.
|
||||
|
||||
1. `hydra get oauth2-client <client_id>`로 존재 여부 확인
|
||||
2. 없으면 env/secret store 값을 사용해 `hydra create oauth2-client`
|
||||
3. 없고 초기 생성 모드가 명시되어 있으면 random secret을 생성해 운영자가 저장할 수 있게 출력 또는 secret file에 기록
|
||||
4. 있으면 `hydra update oauth2-client`로 redirect URI, scope, metadata 같은 비밀값이 아닌 설정을 동기화
|
||||
5. client secret은 기본적으로 덮어쓰지 않고, rotation flag가 있을 때만 갱신
|
||||
6. secret mismatch나 필수 redirect URI 누락 시 실패
|
||||
|
||||
기본 RP 등록 shell block이 길어지고 있으므로, 구현 단계에서는 `scripts/register_hydra_clients.sh` 같은 별도 boot script로 분리하는 편이 유지보수에 유리하다.
|
||||
|
||||
## Generated Auth Config
|
||||
|
||||
`scripts/auth_config.sh`는 다음을 확장한다.
|
||||
|
||||
- `TRAEFIK_FORWARD_AUTH_CALLBACK_URLS` parsing
|
||||
- production mode에서 Traefik client id/secret/cookie secret 필수 검증
|
||||
- generated `config/.generated/auth-config.env`에 Traefik callback CSV 포함
|
||||
- `KRATOS_ALLOWED_RETURN_URLS_JSON`에 forward-auth callback URL 포함
|
||||
- `verify` mode에서 runtime Hydra client에 Traefik callback이 들어 있는지 확인
|
||||
|
||||
운영 secret 보관 위치는 두 가지를 허용한다.
|
||||
|
||||
- 배포 host 기준: `.env` 또는 Docker secret/secret file로 주입
|
||||
- 저장소 기준: Gitea Actions secret에 저장하고 배포 workflow에서 `.env` 또는 secret file로 렌더링
|
||||
|
||||
두 경우 모두 Git tracked 파일에는 실제 secret 값을 남기지 않는다.
|
||||
|
||||
이렇게 하면 Ory 렌더링과 Hydra RP 등록이 같은 auth config contract를 공유한다.
|
||||
|
||||
## Test Plan
|
||||
|
||||
구현 전에 RED test를 먼저 추가한다.
|
||||
|
||||
1. `test/traefik_forward_auth_config_policy_test.sh`
|
||||
- `config/traefik-compose.yml`에 literal `CLIENT_SECRET=` 또는 `SECRET=` 값이 있으면 실패
|
||||
- `traefik`와 `forward-auth`가 `traefik-public` network에 붙지 않으면 실패
|
||||
- `PROVIDER_GENERIC_*_URL`이 Keycloak path를 사용하면 실패
|
||||
- dashboard router에 `auth-forward` middleware가 없으면 실패
|
||||
|
||||
2. `test/auth_config_traefik_rp_policy_test.sh`
|
||||
- `APP_ENV=production`에서 Traefik client secret이 없으면 `scripts/auth_config.sh validate` 실패
|
||||
- callback URL이 `/_oauth` 형태가 아니거나 http URL이면 실패
|
||||
- generated env에 `TRAEFIK_FORWARD_AUTH_CALLBACK_URLS`가 없으면 실패
|
||||
|
||||
3. `test/compose_ory_traefik_rp_bootstrap_policy_test.sh`
|
||||
- `init-rp` 또는 분리된 boot script가 Traefik RP를 등록하지 않으면 실패
|
||||
- boot flow가 delete/create only 방식이면 실패하고 upsert 방식을 요구
|
||||
|
||||
4. live verification
|
||||
- `hydra get oauth2-client --endpoint "$HYDRA_ADMIN_URL" "$TRAEFIK_FORWARD_AUTH_CLIENT_ID"`
|
||||
- dashboard 접근 시 Hydra authorize redirect 발생
|
||||
- callback URL이 registered redirect URI와 정확히 일치
|
||||
- `docker network inspect traefik-public`에서 `traefik`, `forward-auth`, production entry service 연결 확인
|
||||
|
||||
## Rollout Sequence
|
||||
|
||||
1. `.env.sample`에 Traefik forward-auth 변수를 placeholder로 추가한다.
|
||||
2. RED policy tests를 추가하고 실패를 확인한다.
|
||||
3. `config/traefik-compose.yml`을 env-driven Baron/Ory 설정으로 교체한다.
|
||||
4. `scripts/auth_config.sh`와 Hydra RP bootstrap script를 확장한다.
|
||||
5. `compose.ory.yaml`의 `init-rp`가 production에서 Traefik RP upsert를 실행하도록 연결한다.
|
||||
6. Baron SSO production deployment template의 public-facing services에 Traefik labels와 `traefik-public` external network를 연결한다.
|
||||
7. `make validate-auth-config`, 관련 shell policy tests, compose config 검증을 통과시킨다.
|
||||
8. 운영 환경에서 live verification을 수행한다.
|
||||
|
||||
## Baron SSO Deployment Labels
|
||||
|
||||
`deploy/templates/docker-compose.yaml`에서 외부 진입 서비스는 다음 Traefik router를 갖는다.
|
||||
|
||||
| Service | Host variable | Internal port | Purpose |
|
||||
|---|---|---:|---|
|
||||
| `gateway` | `PUBLIC_HOST` | 80 | SSO main app, `/api`, `/auth`, `/oidc` |
|
||||
| `adminfront` | `ADMINFRONT_HOST` | 5173 | Admin console |
|
||||
| `devfront` | `DEVFRONT_HOST` | 5173 | Developer/RP console |
|
||||
| `orgfront` | `ORGFRONT_HOST` | 5175 | Organization console |
|
||||
|
||||
각 public-facing service는 내부 `app_net`과 external `traefik_public`에 동시에 연결한다. `traefik_public`의 실제 Docker network name은 `.env`의 `TRAEFIK_PUBLIC_NETWORK`로 관리하며 기본값은 `traefik-public`이다.
|
||||
|
||||
`deploy/create-instance.sh`는 `TARGET_DIR=/home/user/prod.baron-sso`처럼 레포 밖 고정 경로에 생성할 수 있고, 이 경우에도 compose build context가 깨지지 않도록 `.env`의 `SOURCE_ROOT`를 실행 중인 레포 루트 절대 경로로 채운다.
|
||||
|
||||
## Open Decisions
|
||||
|
||||
- `TRAEFIK_FORWARD_AUTH_HOST`를 `auth.brsw.kr`로 분리할지, `app.brsw.kr/_oauth` 같은 동일 host callback으로 둘지 결정이 필요하다.
|
||||
- `External RP Ory IAM Foundation` 마일스톤은 현재 Due Date가 비어 있다. 구현 착수 전에 목표 Due Date를 정하는 것이 좋다.
|
||||
- `traefik-forward-auth`를 계속 사용할지, Baron Backend/Oathkeeper에 first-party forward-auth endpoint를 만들지는 별도 장기 개선안으로 남긴다. 단기 목표는 현재 compose 구조를 안전하게 Baron/Ory에 맞추는 것이다.
|
||||
121
docs/works-drive-docker-image-archive.md
Normal file
121
docs/works-drive-docker-image-archive.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# WORKS Drive Docker Image Archive
|
||||
|
||||
## 목적
|
||||
|
||||
WORKS Drive는 Docker Registry HTTP API v2 backend로 직접 사용하지 않는다. 대신 프로덕션 배포용 Docker 이미지를 `docker save` 결과물로 내보내고, zstd 압축 archive와 검증 파일을 WORKS Shared Drive에 보관하는 CLI 기반 보조 저장소로 사용한다.
|
||||
|
||||
이 방식은 다음 상황을 목표로 한다.
|
||||
|
||||
- Harbor 또는 공용 Registry 장애 시 수동 복구용 이미지 보관
|
||||
- 작은 규모의 프로덕션 배포 이미지 이관
|
||||
- `docker load` 기반 오프라인 배포
|
||||
|
||||
## 저장 구조
|
||||
|
||||
기본 최상위 디렉터리는 다음 환경 변수로 지정한다.
|
||||
|
||||
```dotenv
|
||||
WORKS_SHAREDRIVE_DOCKER_IMAGE_DIR=docker-build-image
|
||||
```
|
||||
|
||||
이미지는 WORKS Shared Drive에서 다음 구조로 저장한다.
|
||||
|
||||
```text
|
||||
docker-build-image/<repository-path>/<tag>/
|
||||
image.tar.zst
|
||||
image.tar.zst.sha256
|
||||
manifest.json
|
||||
```
|
||||
|
||||
예시:
|
||||
|
||||
```text
|
||||
docker-build-image/baron_sso/backend/v1.2606.ab12/
|
||||
image.tar.zst
|
||||
image.tar.zst.sha256
|
||||
manifest.json
|
||||
```
|
||||
|
||||
Registry hostname은 저장 경로에서 제외한다. 예를 들어 `registry.example/baron_sso/backend:v1.2606.ab12`는 `baron_sso/backend/v1.2606.ab12` 아래에 저장한다.
|
||||
|
||||
## Manifest
|
||||
|
||||
`manifest.json`에는 다음 정보를 기록한다.
|
||||
|
||||
- archive format: `docker-save-zstd`
|
||||
- 원본 `image_ref`
|
||||
- repository path
|
||||
- tag
|
||||
- Docker image id
|
||||
- Git commit
|
||||
- archive 파일명, 크기, sha256
|
||||
- WORKS Drive remote path
|
||||
- 복원 명령 예시
|
||||
|
||||
복원은 다음 흐름으로 처리한다.
|
||||
|
||||
```bash
|
||||
sha256sum -c image.tar.zst.sha256
|
||||
zstd -d -c image.tar.zst | docker load
|
||||
```
|
||||
|
||||
## 업로드 CLI
|
||||
|
||||
로컬 컨테이너를 먼저 이미지로 commit한 뒤 업로드하려면 다음처럼 실행한다.
|
||||
|
||||
```bash
|
||||
WORKS_SHAREDRIVE_DOCKER_IMAGE_DIR=docker-build-image \
|
||||
WORKS_DOCKER_COMMIT_CONTAINER=baron_backend \
|
||||
DOCKER_IMAGE_REF=registry.example/baron_sso/backend:v1.2606.ab12 \
|
||||
scripts/docker-image/upload_works_drive.sh
|
||||
```
|
||||
|
||||
이미지가 이미 로컬에 있으면 `WORKS_DOCKER_COMMIT_CONTAINER`를 생략한다.
|
||||
|
||||
```bash
|
||||
DOCKER_IMAGE_REF=registry.example/baron_sso/backend:v1.2606.ab12 \
|
||||
scripts/docker-image/upload_works_drive.sh
|
||||
```
|
||||
|
||||
실제 업로드에는 기존 백업 업로드와 같은 WORKS Drive 인증 변수를 사용한다.
|
||||
|
||||
- `WORKS_DRIVE_TARGET=sharedrive`
|
||||
- `WORKS_DRIVE_SHARED_DRIVE_ID` 또는 `WORKS_SHAREDRIVE_ID`
|
||||
- 선택: `WORKS_DRIVE_PARENT_FILE_ID`
|
||||
- `WORKS_DRIVE_ACCESS_TOKEN`, `WORKS_DRIVE_ACCESS_TOKEN_FILE`, `WORKS_DRIVE_ACCESS_TOKEN_CMD`, `WORKS_DRIVE_OAUTH_REFRESH_TOKEN`, 또는 서비스 계정 OAuth 변수
|
||||
|
||||
업로드 전 packaging만 확인하려면 다음을 사용한다.
|
||||
|
||||
```bash
|
||||
WORKS_DRIVE_DRY_RUN=true \
|
||||
DOCKER_IMAGE_REF=registry.example/baron_sso/backend:v1.2606.ab12 \
|
||||
scripts/docker-image/upload_works_drive.sh
|
||||
```
|
||||
|
||||
smoke 검증에는 Alpine 계열보다 운영 환경과 libc/패키지 계열 차이가 적은 Debian slim 계열을 사용한다.
|
||||
|
||||
```bash
|
||||
docker create --name baron-works-image-smoke debian:trixie-slim \
|
||||
sh -c 'printf works-drive-docker-image-smoke >/works-smoke.txt'
|
||||
docker start -a baron-works-image-smoke
|
||||
WORKS_DOCKER_COMMIT_CONTAINER=baron-works-image-smoke \
|
||||
DOCKER_IMAGE_REF=registry.example/baron_sso/works-smoke:works-test-ab12 \
|
||||
scripts/docker-image/upload_works_drive.sh
|
||||
```
|
||||
|
||||
## Staging/Production 계약
|
||||
|
||||
Action에서 `dev` 브랜치를 checkout한 뒤 한 번만 이미지를 빌드하고 immutable `image_tag`를 계산한다. staging과 production은 같은 image_tag를 입력받아 같은 registry image를 pull한다.
|
||||
|
||||
```text
|
||||
dev branch -> publish image tag vX.YYMM.<commit4> -> staging deploy -> production deploy
|
||||
```
|
||||
|
||||
WORKS Drive archive도 Action에서 push된 이미지를 다시 pull한 뒤 `docker save`로 만든다. 따라서 WORKS archive, staging, production은 모두 같은 registry image tag를 기준으로 한다.
|
||||
|
||||
## 제한
|
||||
|
||||
- 이 구조는 `docker push`/`docker pull`과 호환되는 Registry backend가 아니다.
|
||||
- layer deduplication이 없으므로 같은 기반 이미지가 반복 저장된다.
|
||||
- 배포 전에는 반드시 `image.tar.zst.sha256` 검증 후 `docker load`를 수행해야 한다.
|
||||
- tag 없는 image ref와 digest-only image ref는 지원하지 않는다.
|
||||
Reference in New Issue
Block a user