단일 솔루션없이 다양한 기술이 사용됩니다. 다음 중 몇 가지를하고 싶을 것입니다.
먼저 재사용을 위해 이미지 레이어를 최적화하십시오. Dockerfile에 자주 변경되는 단계를 나중에 초기 빌드가 이전 빌드에서 캐시 될 가능성을 높이십시오. 재사용 된 계층은에 더 많은 디스크 공간으로 표시 docker image ls
되지만 기본 파일 시스템을 검사하면 각 계층의 사본 하나만 디스크에 저장됩니다. 즉, 마지막 2 계층에서 50MB 만 다른 3 개의 이미지는 각각 2GB의 3 개 이미지를 의미합니다. 목록에서 2GB의 디스크 공간 만 차지합니다. 재사용 된 각 레이어를 두 번 계산합니다.
레이어 재사용으로 인해 빌드 종속성이 자주 바뀌지 않는 이미지가 코드에 복사하기 전에 이미지를 먼저 설치하는 것을 볼 수 있습니다. 다음과 같은 패턴을 가진 파이썬 예제를 참조하십시오.
FROM python
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
# note how the code is copied only after the pip install
# since code changes but requirements.txt doesn't
COPY . .
CMD ["gunicorn", "app:app"]
최소 기본 이미지를 선택하십시오. 당신은 사람들이에서 이동 볼 이유입니다 ubuntu
에 debian:slim
(슬림 변형이 적은 도구를 출시, 작은), 또는 alpine
. 이렇게하면 시작점의 크기가 줄어들고 기본 이미지의 새 버전을 지속적으로 가져 오는 경우 매우 유용합니다. 그러나 기본 이미지가 거의 변경되지 않으면 레이어 재사용으로 최소 기본 이미지의 이점을 상당 부분 제거 할 수 있습니다.
선택할 수있는 가장 작은 기본 이미지는입니다 scratch
. 이것은 쉘이나 라이브러리가 없으며 정적으로 컴파일 된 바이너리에만 유용합니다. 그렇지 않으면 필요하지 않은 많은 도구없이 필요한 도구가 포함 된 기본 이미지를 선택하십시오.
다음으로, 파일을 변경하거나 삭제하는 단계는 해당 파일을 작성하는 이전 단계와 결합되어야합니다. 그렇지 않으면 파일 사용 권한 변경과 같은 경우에도 쓰기시 복사를 사용하는 계층 파일 시스템은 이전 계층의 원본 파일을 가지므로 파일을 제거해도 이미지 크기가 줄어들지 않습니다. 이것이 rm
명령이 결과 디스크 공간에 영향을 미치지 않는 이유 입니다. 대신 다음과 같이 명령을 연결할 수 있습니다.
RUN apt-get update \
&& apt-get install -y \
a-package \
wget \
&& ... \
&& apt-get purge -y wget \
&& rm -r a-build-dir \
&& apt-get purge -y a-package
명령 체인을 과도하게 사용하면 전제 조건이 변경 될 때마다 동일한 도구 세트를 다시 설치해야하므로 빌드 속도가 느려질 수 있습니다 (예 : wget으로 코드 가져 오기). 더 나은 대안은 아래의 다단계를 참조하십시오.
결과 이미지에 필요하지 않은 파일은 생성 단계에서 삭제해야합니다. 여기에는 패키지 캐시, 로그, 매뉴얼 페이지 등이 포함됩니다. 각 계층에서 생성되는 파일을 발견하려면 wagoodman / dive와 같은 도구를 사용할 수 있습니다. 중간 컨테이너를 잘라 내지 않고 도커 이미지를 만들고 다음과 같이 diff를 볼 수 있습니다.
# first create and leave containers from any RUN step using options on build
docker image build --rm=false --no-cache -t image_name .
# review which layers use an unexpectedly large amount of space
docker image history image_name
# list all containers, particularly the exited ones from above
docker container ps -a
# examine any of those containers
docker container diff ${container_id}
# ... repeat the diff for other build steps
# then cleanup exited containers
docker container prune
그 중간 용기의 각각과 상기 DIFF 파일 추가, 변경 또는 삭제하는 단계에있는 것을 보여주는 것이다 (이러한는로 표시되고 A
, C
또는 D
각 파일명 전). 차이점은 컨테이너 별 읽기 / 쓰기 파일 시스템이며, 이는 기록 중 복사를 사용하여 컨테이너가 이미지 상태에서 변경된 파일입니다.
이미지 크기를 줄이는 가장 좋은 방법은 제공된 이미지에서 컴파일러와 같은 불필요한 구성 요소를 제거하는 것입니다. 이를 위해 다단계 빌드를 사용하면 한 단계에서 컴파일 한 다음 결과 아티팩트 만 빌드 단계에서 애플리케이션 실행에 필요한 최소한의 런타임 이미지로 복사 할 수 있습니다. 결과 이미지와 함께 제공되지 않으므로 빌드 단계를 최적화 할 필요가 없습니다.
FROM debian:9 as build
# still chain update with install to prevent stale cache issues
RUN apt-get update \
&& apt-get install -y \
a-package \
wget \
RUN ... # perform any download/compile steps
FROM debian:9-slim as release
COPY --from=build /usr/local/bin/app /usr/local/bin/app
CMD [ "/usr/local/bin/app" ]
다단계는 기본 이미지로 스크래치로 실행하거나 JDK와 같은 컴파일 환경에서 JRE와 같은 런타임으로 전환 할 수있는 정적으로 컴파일 된 바이너리에 이상적입니다. 빠른 빌드를 유지하면서 이미지 크기를 크게 줄이는 가장 쉬운 방법입니다. 이전 단계에서 생성 된 파일을 변경하거나 삭제하는 단계가있는 경우 릴리스 단계에서 단계 체인을 계속 수행 할 수 있지만 대부분의 경우 COPY
다른 단계에서 릴리스 단계를 이전 빌드 단계에서 경험 한 모든 레이어 팽창과 분리합니다.
레이어 재사용을 제거하면서 하나의 이미지의 크기를 줄이므로 이미지 스 쿼싱을 권장하지 않습니다. 즉, 동일한 이미지를 향후 빌드 할 때 업데이트를 보내려면 더 많은 디스크 및 네트워크 트래픽이 필요합니다. 첫 번째 예로 돌아가려면 스쿼시로 인해 이미지가 2GB에서 1GB로 줄어들 수 있지만 2.1GB 대신 3GB의 이미지가 3GB를 차지할 수는 없습니다.
2.37
대1.47 GB