
오랫동안 저는 중간 컨테이너가 있는 Docker를 사용하여 앱을 빌드해왔습니다. 예를 들어 myapp:base
모든 핵심 파일이 복사된 앱을 빌드하겠습니다.
FROM ubuntu:17.10
ADD app /app
이제 다음과 같이 간단하게 기본 컨테이너를 myapp:release
만들 수 있습니다.
FROM myapp:base
ADD app /app
소수의 파일이 디렉토리에서 수정될 수 app
있으며 작은 추가 레이어가 생길 수 있습니다.
하지만 최근 이 최종 ADD
결과로 훨씬 더 큰 레이어가 생성되었으며 Docker 업데이트와 관련이 있는 것으로 의심됩니다(Docker 버전 18.02.0-ce를 사용하고 있으며 fc4de44 빌드).
Docker가 차이점을 파악하는 방식에 변화가 있었나요? 레이어에 업데이트된 파일 수가 적은 효율적인 빌드로 어떻게 돌아갈 수 있나요?
재현 단계:
# make a dummy dir with a 64kb file in it
mkdir -p files
truncate -s 64k files/64k.file
# base container has a copy of the files
cat << EOF > Dockerfile.base
FROM ubuntu:16.04
COPY files/ /root/
EOF
# derived container should just have any updates
cat << EOF > Dockerfile.derived
FROM q899941:base
COPY files/ /root/
EOF
# build them....
docker build --file Dockerfile.base -t q899941:base .
docker build --file Dockerfile.derived -t q899941:derived .
# now let's review the layers
docker history q899941:derived
나는이 결과를 얻습니다
IMAGE CREATED CREATED BY SIZE
4e1eb5168d55 Less than a second ago /bin/sh -c #(nop) COPY dir:8e20ede288278c71e… 65.5kB
022626ac5cf0 Less than a second ago /bin/sh -c #(nop) COPY dir:8e20ede288278c71e… 65.5kB
0458a4468cbc 5 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 5 weeks ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B
<missing> 5 weeks ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$… 2.76kB
<missing> 5 weeks ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0B
<missing> 5 weeks ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 745B
<missing> 5 weeks ago /bin/sh -c #(nop) ADD file:a3344b835ea6fdc56… 112MB
파일이 변경되지 않았음에도 최상위 레이어는 64kb입니다.
답변1
이것은 것 같습니다알려진 문제, 하지만 충분한 사람들이 관심을 갖는 것은 아닙니다!
- Docker 커밋을 사용하지 않고 변경된 파일만 Docker 이미지에 새 레이어로 추가할 수 있는 방법이 있습니까?동일한 근거를 다루는 StackOverflow 질문입니다.
- 예상한 동작이 오버레이 스토리지 드라이버에서 작동하는 것 같지만 일부 시스템 업데이트 후에는 변경된 파일뿐만 아니라 모든 파일을 레이어에 복사하는 overlay2를 사용하기 시작했습니다.
- 한 가지 솔루션은 오버레이로 되돌아가지만 현재로서는 더 이상 사용되지 않는 것 같습니다.'diff' 레이어를 구축하는 대체 방법은 여기에 자세히 설명되어 있습니다.
나는 결국 다음 중 하나에서 언급된 간단한 일을 하게 되었습니다.코멘트버그 보고서에서:
#clean up any previous attempt...
docker rm -f uniquename 2> /dev/null
# now take your base container, mount the updated dir as /src
# then rsync from /src to the target dir - only updated files will
# actually be written, and we use --delete to ensure removed files are
# taken out...
docker run --name uniquename \
-v ~/repo/mycode:/src \
${REPO}/${IMAGE}:${BASE} \
rsync -ar --no-owner --no-group \
--exclude-from '/src/.dockerignore' --delete \
/src/ /app/
# we can commit that updated container with a tag
docker commit uniquename ${REPO}/${IMAGE}:${NEW_TAG}
CMD
한 가지 더 - 이 솔루션은 내 컨테이너에 기본 시작 명령을 제공했던 기존 명령을 없애는 것처럼 보였습니다 . 따라서 이 diff 레이어를 추가한 후 다시 추가된 위의 'diff' 빌드에서 컨테이너를 생성하기 위한 또 다른 Dockerfile이 생겼습니다 CMD
.