이미지 빌드 · 레이어와 캐시 · 실습
캐시가 깨지는 자리 찾기
이 실습은 진짜 VM 에서 돕니다
이 상자는 파드가 아니라 KubeVirt 가 띄운 가상머신입니다. 리눅스 커널이
따로 돌고 systemd 가 실제로 서비스를 관리하며, docker 는 흉내가 아니라
진짜 도커 엔진입니다. docker run 으로 띄운 컨테이너는 실제로 프로세스가
되고 docker exec 도 docker logs 도 그대로 동작합니다.
예전에는 이 실습이 파드 안에서 돌았습니다. 커널 권한을 전부 내려놓은 상자라
컨테이너를 띄우는 단계가 막혀 있었고, 그래서 이미지 아카이브를 직접 풀어
보는 우회로 배웠습니다. 이제 우회가 필요 없습니다.
알아 둘 것이 둘 있습니다.
- 처음 뜨는 데 1분 남짓 걸립니다. VM 이 부팅하고 도커를 설치하기
- 브라우저 미리보기가 없습니다. VM 으로 들어오는 연결은 채점 포트
때문입니다. 파드 실습(보통 40초)보다 느립니다.
하나만 열려 있습니다. 웹 서버를 띄웠다면 VM 안에서 curl 로 확인하세요.
목표
캐시가 어디서 깨지는지 이미지 ID 로 증명하고, 유니온 파일시스템에서
삭제가 크기를 줄이지 못한다는 것을 두 이미지의 크기 차이로 확인합니다.
왜 중요한가
"빌드가 느려요"라는 문제는 캐시 설정을 켜고 끄는 문제가 아니라 **순서
문제**인 경우가 압도적으로 많습니다. 캐시 키가 부모 다이제스트에 연쇄로
묶여 있다는 사실 하나만 이해하면, 고칠 지점은 언제나 "캐시가 처음으로
깨지는 그 한 줄"이라는 것이 자명해집니다. 그 위는 건드릴 필요가 없고
그 아래는 손댈 방법이 없습니다. 크기도 마찬가지입니다. 레이어는 되감기지
않으므로, **최종 이미지에 들어가면 안 되는 것은 애초에 그 레이어에서
만들지 않아야** 합니다.
단계
1. /root/build2 를 만들고, nginx:1.27-alpine 의 레이어 개수를 세어 /root/build2/nginx-layers.txt 에 숫자만 적습니다.
2. alpine:3.20 의 레이어별 히스토리를 잘리지 않게 /root/build2/alpine-history.txt 로 저장합니다.docker history 가 보여 주는 표는 이미지 config 블롭의 history 배열 그 자체입니다. 이 상자에서는 skopeo inspect --config oci-archive:/opt/images/alpine_3.20.tar | jq -r '.history[]' 로 같은 값을 읽습니다.
3. /root/build2 에 deps.txt 와 src/main.txt 를 만들고, 두 파일을 각각 COPY 하는 Dockerfile 을 작성합니다. labhub/cache:v1 로 빌드한 뒤 이미지 ID 를 /root/build2/id1.txt 에 적고, 아무것도 바꾸지 않고 다시 빌드해 ID 를 /root/build2/id2.txt 에 적습니다. 두 값은 같아야 합니다.
4. deps.txt 의 내용을 바꾸고 labhub/cache:v2 로 빌드해 ID 를 /root/build2/id3.txt 에 적습니다. id1.txt 와 달라야 합니다.
5. /root/build2/ordered.Dockerfile 을 만들어 COPY deps.txt 가 COPY src/ 보다 먼저 나오게 하고 labhub/cache:v3 로 빌드합니다.
6. /root/build2/big.log 를 만들고, /root/build2/.dockerignore 에 로그 파일 제외 규칙을 넣습니다. 컨텍스트 전체를 /ctx 로 복사하는 Dockerfile 로 labhub/cache:v4 를 빌드하면 이미지 안에 /ctx/deps.txt 는 있고 /ctx/big.log 는 없어야 합니다.
7. 20MB 파일을 만든 뒤 다음 RUN 에서 지우는 이미지를 labhub/fat:bad 로, 같은 RUN 안에서 지우는 이미지를 labhub/fat:good 으로 빌드합니다.
8. /root/build2/cache.md 에 아래 세 줄을 실제 값으로 적습니다.
bad_mb=<labhub/fat:bad 크기(MB)>good_mb=<labhub/fat:good 크기(MB)>diff_mb=<두 값의 차>참고
docker image inspect <이미지> | jq -r '.[0].Id'로 이미지 ID 를,jq -r '.[0].Size'로 바이트 크기를 얻습니다.- 20MB 파일은
dd if=/dev/zero of=/big bs=1M count=20으로 만들 수 있습니다. - 흔한 실수 1: 3단계에서 빌드 사이에 파일을 건드리면 ID 가 달라집니다.
- 흔한 실수 2: 8단계의 MB 는 1048576 바이트 기준입니다. 소수점을 버린 정수로 적으세요.
단계 8개
- 이미지의 레이어 수 세기
- 레이어별 명령 들여다보기
- 바뀐 게 없으면 같은 이미지
- 앞 레이어를 깨뜨려 보기
- 변경 빈도 순으로 배치하기
- 빌드 컨텍스트에서 빼기
- 삭제해도 줄지 않는다는 증거
- 측정값 정리