Devin.KR

버전 고정과 재실행

80분 안팎

학습 목표

태그와 digest 및 설정 변경을 기록합니다.

개념

배포 기억을 파일로 남깁니다

어제 실행한 버전으로 다시 띄워 달라는 요청을 받았을 때 태그 이름 하나만 있으면 당시 내용을 확정하기 어렵습니다. 릴리스 명세는 어떤 산출물과 설정을 사용했는지 연결하는 기록입니다. 이번 레슨은 로컬 이미지 식별값, JAR 체크섬, 플랫폼, 환경 설정 체크섬을 모아 실제 재생성 결과와 연결합니다. 명세를 예쁜 보고서로만 만들지 않고 다음 실행이 검증할 수 있는 입력과 증거로 사용합니다.

태그가 가리키는 대상은 바뀔 수 있습니다

같은 notice-m03:practice 이름을 다른 빌드에 붙일 수 있으므로 태그만 보관하면 과거 내용이 사라질 수 있습니다. 테스트 환경과 시연 환경에서 같은 이름을 썼다는 설명도 같은 내용의 증거가 아닙니다. 검사기는 image inspect에서 읽은 완전한 sha256 이미지 ID로 두 환경을 시작하고 컨테이너 Image 필드와 다시 비교합니다. 태그는 사람이 찾는 보조 정보로 남기고 imageRef는 실측한 고정 식별값으로 둡니다.

서로 다른 digest를 같은 값으로 쓰지 않습니다

로컬 image inspect의 Id는 이미지 config를 식별하는 SHA256 값입니다. 레지스트리의 repository@sha256 값은 manifest 또는 index를 식별합니다. JAR 파일을 해시한 값은 그 JAR 바이트의 지문입니다. 모두 sha256이라는 이름을 사용할 수 있지만 해시 대상이 달라 서로 대신할 수 없습니다. 이번 명세의 imageDigest는 config digest이며 digestKind=local-image-id로 표시하고 registryDigest는 null로 둡니다. 이 계약을 생략하면 다음 사람이 레지스트리에서 잘못 pull할 수 있습니다.

레지스트리가 없는 조건을 정직하게 적습니다

이 실습은 클라우드 계정이나 개인 레지스트리를 요구하지 않습니다. 로컬에서 빌드한 이미지의 RepoDigests가 비어 있을 수 있으며 존재하지 않는 manifest digest를 만들어 넣지 않습니다. 동일 daemon에서는 image ID로 재실행합니다. 다른 daemon에 옮길 때는 docker save와 load로 산출물을 전달한 뒤 실제 ID를 재확인할 수 있습니다. 이후 승인된 레지스트리로 배포할 때는 push 결과의 repository digest를 별도 필드에 추가하는 계약을 검토합니다.

플랫폼을 산출물 조건으로 기록합니다

이미지에는 운영체제와 CPU 아키텍처가 있으며 모든 플랫폼에서 동일한 실행 결과를 기대하지 않습니다. 명세는 inspect의 Os와 Architecture를 읽어 linux/arm64 또는 실제 관측값을 남깁니다. 멀티플랫폼 index digest와 선택된 플랫폼 manifest digest도 구분할 필요가 있습니다. 이번 프로젝트는 현재 daemon의 단일 로컬 이미지 범위입니다. 다른 아키텍처에서도 동작한다고 쓰려면 그 환경의 빌드·실행 검사 증거가 추가로 필요합니다.

설정 파일을 내용으로 식별합니다

같은 이미지에서도 NOTICE_NAME과 데이터 경로가 바뀌면 사용자 결과가 달라질 수 있습니다. 명세는 test.env와 demo.env 파일의 SHA256을 각각 기록하고 configPolicy=external-env를 선언합니다. 환경 파일 원문에는 공개 교육용 이름만 있으며 실제 비밀은 명세에 복사하지 않습니다. 체크섬은 어떤 파일 바이트를 사용했는지 비교하는 단서이지 설정의 의미가 올바른지 증명하지 않습니다. /identity 관측을 함께 두어 의미를 확인합니다.

템플릿과 관측 결과의 역할을 분리합니다

release-template.json은 digestKind, imagePolicy, configPolicy 같은 요구 정책을 담습니다. 실행하지 않고 imageDigest를 미리 채우는 파일이 아닙니다. check.sh가 이미지를 만든 뒤 실제 inspect 결과와 JAR·설정 파일 해시를 모아 release.json을 생성합니다. 실패하면 성공 명세가 만들어졌다고 주장하지 않습니다. 이전 실행의 release.json이 남아 있다면 현재 결과로 착각하지 않도록 검사 시작에서 제거하고 이번 성공에서만 다시 생성합니다.

재생성으로 명세의 주장을 확인합니다

검사는 test의 /notices 파일 내용을 바꾸고 첫 컨테이너를 정상 중지·제거합니다. 이어 기록한 같은 image ID와 같은 test 볼륨을 사용해 새 컨테이너를 만듭니다. 새 Image가 기록값과 같고 /notices가 kept-by-volume이면 산출물 선택과 데이터 보존을 각각 확인한 것입니다. 새 컨테이너 ID는 이전과 달라질 수 있으며 새 호스트 임의 포트도 달라질 수 있습니다. 변해도 되는 실행 상태와 유지할 계약을 나누어 판정합니다.

검사 증거와 배포 입력을 구별합니다

release.json의 evidenceScope=ephemeral-check는 임시 실험이라는 의미입니다. 검사기는 자기 컨테이너와 볼륨을 종료 뒤 정리하므로 resourcesCleaned=true를 남깁니다. 명세의 포트와 볼륨 이름을 다음 배포에 살아 있는 자원으로 사용하면 안 됩니다. 다음 모듈은 산출물 ID·체크섬·정책을 이어받고 환경 자원을 다시 구성합니다. 이 파일을 실제 배포 선언으로 확장할 때는 대상 환경과 보존할 볼륨의 수명 정책을 따로 설계합니다.

체크섬이 알려 주는 한계를 읽습니다

JAR와 명세가 모두 공격자에게 바뀌면 체크섬 비교가 통과해도 믿을 수 있는 제작자라는 증거는 없습니다. 이 레슨은 전달 중 변형이나 잘못된 산출물 선택을 찾는 내용 식별을 다룹니다. 출처 검증·서명·접근 권한을 해결했다고 단정하지 않습니다. JAR 해시가 같아도 기반 이미지나 시작 명령이 다르면 이미지 ID는 달라질 수 있습니다. 어떤 대상을 해시했는지 필드 이름과 생성 명령을 함께 적어 해석 오류를 줄입니다.

불일치 때 즉시 명세를 덮어쓰지 않습니다

재실행한 컨테이너의 Image가 기록값과 다르면 기대값을 새 값으로 바꿔 성공 처리하지 않습니다. 실행 명령이 태그를 사용했는지, 원래 이미지를 전달했는지, 선택한 Docker context가 같은지 먼저 확인합니다. No such image이면 원래 산출물이 daemon에 있는지 확인하고 보관한 이미지에서 복원합니다. 설정 해시 불일치도 파일 변경인지 줄바꿈 변화인지 검토합니다. 각 불일치는 재현 조건이 달라졌다는 신호이며 원인을 설명한 뒤 새 릴리스로 기록합니다.

시작 정책을 고치고 미션으로 연결합니다

이 레슨 starter는 imagePolicy가 mutable-tag여서 마지막 고정 정책 assertion이 실패합니다. image-id로 수정하고 실제 ID를 명세에서 확인합니다. 미션에서는 비루트 USER, 환경 이름, 이미지 선택 정책의 세 결함을 함께 고칩니다. 기존 m02 요청 로그와 진단 검사를 유지하며 /health만이 아니라 /identity·/notices까지 통과시킵니다. 제출 자료는 실행 명령, 실제 명세, 보존 전후 응답, 실패 원인과 수정 이유입니다.

동료에게 인계할 때 같은 daemon에서의 재실행 범위, 이미지 전달 방법, 검사 자원 정리 여부를 설명합니다. 태그를 고정했다고 해서 빌드 환경과 데이터까지 모두 고정된 것은 아닙니다. 기록된 이미지, 외부 설정, 보존할 데이터의 세 조건이 갖춰져야 안내판 결과를 재현할 수 있습니다. 파일 체크섬 명령과 검증 목록의 세부 문법은 서재 sha256sum 장에서 더 읽고 이 레슨에서는 명세의 해시 대상과 실제 실행을 연결합니다.

이미지 보관·전달 절차는 공식 image save 문서에서 확인할 수 있습니다. 본문 명세의 값은 문서 예제가 아니라 개인 실습에서 관측한 값으로 채웁니다.

완료 검사에서는 artifacts/notice-image.tar와 그 archiveSha256도 보관합니다. 임시 daemon 자원을 정리한 뒤 이 아카이브를 load하고 기록한 imageDigest와 비교하면 테스트한 산출물을 다음 모듈로 전달할 수 있습니다. 아카이브는 현재 실행 데이터의 백업이 아니며 볼륨 내용은 별도입니다. 새 검사 시작은 이전 명세와 아카이브를 지우므로 유지할 릴리스는 먼저 다른 보관 위치로 복사합니다.

따라하기

명세 요구 수정

imagePolicy를 image-id로 바꿉니다. digestKind는 local-image-id, registryDigest는 null, configPolicy는 external-env로 둡니다.

python3 -m json.tool release-template.json

실제 산출물 기록

검사 성공 뒤 release.json이 생성되는지 확인합니다. 실제 Docker 빌드와 HTTP 검증을 하지 않은 환경에서는 성공 기록을 작성하지 않습니다.

bash check.sh

해시 대상 대조

imageDigest와 imageRef가 같고 jarSha256은 별도 파일 해시인지 확인합니다. platform과 두 configSha256, evidenceScope도 읽습니다.

python3 -m json.tool release.json

보관 이미지 재로딩

성공한 검사에서 남긴 아카이브를 사용합니다. archiveSha256을 실제 파일 해시와 대조한 뒤 load합니다. imageDigest는 release.json에서 읽은 값을 사용하고 < > 표식을 명령에 입력하지 않습니다. image inspect 결과가 원본 imageDigest와 같은지 확인합니다. Docker 실행은 외부 검증 대상입니다.

docker load -i artifacts/notice-image.tar
python3 -m json.tool release.json

확인 문제

실습

release-template.json의 이미지 선택 정책을 고치고 실제 image ID·JAR 해시·설정 해시를 구분한 명세를 생성합니다. 검사 코드와 기대값은 수정하지 않습니다. bash check.sh가 해당 결함을 거부하고 solution은 전체 HTTP·데이터·명세 검사를 통과해야 합니다. 실행 도구가 없는 환경에서는 external 검증 대기로 남깁니다.

시작 코드·테스트 내려받기

실행 명령

bash check.sh

기대 결과

개인 Docker 환경에서 모든 PASS 항목과 RESULT: 0 failure(s). 실제 imageDigest를 기록한 release.json 생성.

모범 답안모범 답안 내려받기

더 읽기

면접 질문

  • 환경마다 달라지는 설정을 주입하는 방법을 설명합니다.
  • 컨테이너 이미지와 실행 중 컨테이너의 차이를 설명합니다.