다운로드 캐시 전체가 런타임에 필요한 것은 아니다
Workload Studio는 입력의 토큰 수를 계산하고 템플릿을 렌더하기 위해 고정 revision의 tokenizer를 사용한다. 다운로드 캐시에는 현재 snapshot뿐 아니라 이전 revision과 refs·잠금·Xet 상태도 남을 수 있다. 그 전체를 이미지에 넣으면 실행에 필요하지 않은 상태까지 배포하고, blob을 가리키는 symlink가 어느 경로에 의존하는지도 함께 다뤄야 한다.
변경은 Python 빌드와 런타임을 같은 python-base의 별도 단계로 나눴다. 런타임에는 설치된 가상환경·소스·빌드한 UI·내보낸 tokenizer 파일을 복사하고, uv와 가상환경 lock 파일은 남기지 않는다. 다운로드용 캐시와 실행에 필요한 파일 묶음을 분리한 것이다.
코드가 고정한 revision의 실제 파일을 복사한다
BuildKit의 rws-tokenizers 캐시는 같은 builder의 소스 변경 사이에서 다운로드를 보존한다. 먼저 오프라인 로드를 시도하고 파일이 없으면 다운로드한다. tokenizer ID와 revision은 Dockerfile에 중복해서 적지 않고 실제 코드의 고정 목록에서 읽는다. 새 builder나 정리된 캐시에서는 다시 다운로드해야 한다.
- 로컬 snapshot 경로 확인고정 repo·revision을 local_files_only로 조회한다.
- 새 목적지에 파일 내보내기symlinks=False로 blob 링크의 실제 내용을 복사한다.
- 내보낸 묶음에서 다시 로드오프라인으로 토큰화와 템플릿 렌더를 확인한다.
이미 있는 목적지는 거절한다. 현재 snapshot 바깥의 과거 revision·refs·잠금·Xet 캐시는 복사하지 않는다. 모든 애플리케이션 파일을 복사한 뒤에는 읽기·디렉터리 탐색 권한과 group/other 쓰기 권한을 검사한다. 권한 검사를 마지막에 두어 뒤늦게 복사한 파일이 검사에서 빠지지 않게 했다.
네트워크가 없는 실행과 빌드 캐시 재사용을 따로 확인한다
당시 저장소의 검증 기록은 UID12345의 non-root 컨테이너를 read-only·network-none으로 실행해 세 tokenizer를 로드했다고 남긴다. 소스만 바꾼 Python 빌드 대상도 네트워크 없이 캐시와 내보낸 snapshot을 확인했다. 전체 오프라인 재빌드는 npm 설치 레이어까지 무효화되어 중단됐으므로, 깨끗한 환경의 모든 의존성을 오프라인으로 설치했다는 결과는 아니다.
| 검증 대상 | 확인한 범위 |
|---|---|
| export 단위 테스트 | 고정 snapshot만 포함 · symlink 실체화 · 기존 목적지 거절 · 로컬 조회 |
| 기록된 실제 컨테이너 실행 | 당시 세 tokenizer의 오프라인 로드 · 모델 추론은 실행하지 않음 |
| 기록된 로컬 이미지 크기 | 512,712,191 → 454,991,422 bytes |
현재 고정 목록은 이후 모델 추가로 다섯 개다. 이를 당시 세 개의 실행 기록에 소급해 넣을 수는 없다. 로컬 이미지 크기도 registry 전송량이나 시작 시간의 측정은 아니다. revision과 lockfile이 선택한 파일을 제한하더라도 base image tag가 digest 고정은 아니므로 비트 단위로 같은 빌드를 보장하지 않는다.
Workload Studio에서 이 변경이 만든 배포 경계는 tokenizer를 가져오는 환경과 사용하는 환경 사이에 있다. 런타임은 현재 코드가 요구하는 snapshot을 독립된 파일로 받고, 네트워크나 다운로드 캐시에 의존하지 않는지 확인한다. 모델 weight·추론·GPU 준비 상태는 별도 검증 대상이다.