8.4 KiB
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기반 오프라인 배포
Harbor는 이 흐름의 1차 이미지 저장소다. Gitea Actions의 publish workflow가 reg.hmac.kr/baron_sso/<service>:<image_tag> 형태로 이미지를 push하고, staging/production deploy workflow는 같은 image tag를 Harbor에서 pull한다. WORKS Drive는 같은 이미지를 별도로 보관하는 복구용 archive이며, staging/prod가 평상시에 직접 pull하는 대상이 아니다.
현재 Gitea Actions 설정 상태
2026-06-19 기준 repo Actions 설정에서 Harbor 변수/시크릿은 등록되어 있다.
HARBOR_ENDPOINT=https://reg.hmac.krHARBOR_HOSTNAME=reg.hmac.krHARBOR_ROBOT_ACCOUNT=robot$namecard_sso- secret
HARBOR_ROBOT_KEY
Docker image archive 업로드 단계는 .gitea/workflows/production_image_publish.yml의 Upload pushed images to WORKS Drive archive step에서 실행된다. 단, 이 step은 다음 조건을 만족할 때만 실행된다.
if: ${{ vars.WORKS_DRIVE_DOCKER_IMAGE_ARCHIVE_ENABLED == 'true' }}
현재 repo Actions 설정에는 Docker image archive용 WORKS Drive 변수/시크릿이 등록되어 있지 않다. 업로드를 켜려면 최소한 다음 값을 등록해야 한다.
- variable
WORKS_DRIVE_DOCKER_IMAGE_ARCHIVE_ENABLED=true - variable
WORKS_SHAREDRIVE_DOCKER_IMAGE_DIR=docker-build-image - variable
WORKS_DRIVE_SHARED_DRIVE_ID - 선택 variable
WORKS_DRIVE_PARENT_FILE_ID - secret
WORKS_DRIVE_OAUTH_CLIENT_ID - secret
WORKS_DRIVE_OAUTH_CLIENT_SECRET - secret
WORKS_DRIVE_OAUTH_CLIENT_SERVICE_ACCOUNT - secret
WORKS_DRIVE_OAUTH_CLIENT_PRIVATE_KEY - refresh token 방식을 쓸 경우 secret
WORKS_DRIVE_OAUTH_REFRESH_TOKEN
저장 구조
기본 최상위 디렉터리는 다음 환경 변수로 지정한다.
WORKS_SHAREDRIVE_DOCKER_IMAGE_DIR=docker-build-image
이미지는 WORKS Shared Drive에서 다음 구조로 저장한다.
docker-build-image/<repository-path>/<tag>/
image.tar.zst
image.tar.zst.sha256
manifest.json
예시:
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
- 복원 명령 예시
복원은 다음 흐름으로 처리한다.
sha256sum -c image.tar.zst.sha256
zstd -d -c image.tar.zst | docker load
업로드 CLI
로컬 컨테이너를 먼저 이미지로 commit한 뒤 업로드하려면 다음처럼 실행한다.
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를 생략한다.
DOCKER_IMAGE_REF=registry.example/baron_sso/backend:v1.2606.ab12 \
scripts/docker-image/upload_works_drive.sh
실제 업로드에는 기존 백업 업로드와 같은 WORKS Drive 인증 변수를 사용한다.
WORKS_DRIVE_TARGET=sharedriveWORKS_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만 확인하려면 다음을 사용한다.
WORKS_DRIVE_DRY_RUN=true \
DOCKER_IMAGE_REF=registry.example/baron_sso/backend:v1.2606.ab12 \
scripts/docker-image/upload_works_drive.sh
dry-run도 실제 docker save, zstd, checksum, manifest 생성을 수행한다. WORKS Drive API 호출만 생략하므로 업로드 전 산출물 검증에 사용할 수 있다.
다운로드 및 복원 검증 CLI
WORKS Drive에서 다음 세 파일을 같은 로컬 디렉터리로 내려받은 뒤 검증한다.
image.tar.zst
image.tar.zst.sha256
manifest.json
checksum, manifest, zstd stream 무결성만 확인하려면 다음을 실행한다.
scripts/docker-image/verify_archive.sh /path/to/downloaded/archive
make 타깃을 사용할 수도 있다.
make docker-image-verify-works \
WORKS_DOCKER_IMAGE_ARCHIVE_DIR=/path/to/downloaded/archive
실제 Docker image load까지 검증하려면 다음을 실행한다.
WORKS_DOCKER_VERIFY_LOAD=true \
scripts/docker-image/verify_archive.sh /path/to/downloaded/archive
검증은 다음 조건을 모두 확인한다.
image.tar.zst.sha256checksum 성공manifest.json의schema_version=1,format=docker-save-zstd- manifest의 archive 파일명, sha256, size와 실제 파일 일치
zstd -t무결성 성공- 선택적으로
docker load성공
현재 repo에는 WORKS Drive API에서 파일을 자동 다운로드하는 CLI는 없다. 따라서 자동 다운로드 스크립트를 만들기 전까지는 WORKS Drive UI 또는 운영자가 승인한 API 도구로 세 파일을 내려받고, 위 검증 CLI로 복원 가능성을 확인한다.
API로 다운로드할 때는 대상 archive 폴더의 children을 조회해 각 파일의 fileId를 얻은 뒤 다음 endpoint를 호출한다.
GET /v1.0/sharedrives/<sharedDriveId>/files/<fileId>/download
검증 결과 이 endpoint는 302 Location을 반환한다. curl -L만 사용하면 리다이렉트 대상 요청에 인증 헤더가 유지되지 않아 UNAUTHORIZED JSON이 파일로 저장될 수 있다. 자동화할 때는 리다이렉트 대상에도 인증 헤더를 유지하도록 처리해야 한다. curl 기준으로는 다음 형태를 사용한다.
curl -sS -L --location-trusted \
-H "Authorization: Bearer <access-token>" \
-o image.tar.zst \
"https://www.worksapis.com/v1.0/sharedrives/<sharedDriveId>/files/<fileId>/download"
smoke 검증에는 Alpine 계열보다 운영 환경과 libc/패키지 계열 차이가 적은 Debian slim 계열을 사용한다.
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
로컬 smoke 검증 예시는 다음과 같다.
WORKS_DRIVE_DRY_RUN=true \
WORKS_DOCKER_IMAGE_ARCHIVE_DIR=/tmp/baron-sso-works-verify-smoke \
DOCKER_IMAGE_REF=alpine:latest \
scripts/docker-image/upload_works_drive.sh
scripts/docker-image/verify_archive.sh \
/tmp/baron-sso-works-verify-smoke/alpine/latest
WORKS_DOCKER_VERIFY_LOAD=true \
scripts/docker-image/verify_archive.sh \
/tmp/baron-sso-works-verify-smoke/alpine/latest
Staging/Production 계약
Action에서 dev 브랜치를 checkout한 뒤 한 번만 이미지를 빌드하고 immutable image_tag를 계산한다. staging과 production은 같은 image_tag를 입력받아 같은 registry image를 pull한다.
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는 지원하지 않는다.