17.1.도커 이미지를 최적화하는 방법

  • 내려받은 이미지는 명시적으로 삭제하지 않는 한 자동으로 삭제되지 않는다.
  • 예약 작업을 만들어 사용하지 않는 이미지 레이어를 삭제하는 방법도 좋지만, 이미지를 잘 최적화하면 이 문제가 크게 줄어든다.
  • 꼭 필요한 파일만 이미지에 포함시켜야 한다.
  • 실제 Dockerfile 스크립트를 작성해 보면 사용되지 않을 이미지 파일이나 문서 파일까지 한꺼번에 디렉터리 채로 이미지에 포함시키는 경우가 많다.

예제 17.1 불필요한 파일을 제거해 최적화를 시도한 Dockerfile 스크립트

# Dockerfile v1 - 전체 디렉터리 구조를 이미지에 복사함
FROM diamol/base
CMD echo app- && ls app && echo docs- && ls docs
COPY . . 

# Dockerfile v2 - 불필요한 파일을 별도로 삭제함
FROM diamol/base
CMD echo app- && ls app && echo docs- && ls docs
COPY . . 
RUN rm -rf docs
  • 이미지는 이미지 레이어가 쌓여 만들어진다.
  • docs 디렉터리는 COPY 인스트럭션으로 만든 레이어에 그대로 남아 있다.
  • 삭제 레이어에 가려 보이지 않을 뿐 전체 이미지 크기는 전혀 줄어들지 않는다.

실습 앞에 나온 두 Dockerfile 스크립트로 이미지를 빌드해 크기를 비교해 보자.

001)  cd ch17/exercises/build-context
002) 
003)  docker image build -t diamol/ch17-build-context:v1 .
004) [+] Building 3.1s (8/8) FINISHED                                                                                                                     
005)  => exporting to image                                                                                                                          0.0s
006)  => => naming to docker.io/diamol/ch17-build-context:v1                                                                                         0.0s
007) 
008)  docker image build -t diamol/ch17-build-context:v2 -f ./Dockerfile.v2 .
009) [+] Building 1.2s (8/8) FINISHED                                                                                                                     
010)  => exporting to image                                                                                                                          0.0s
011)  => => naming to docker.io/diamol/ch17-build-context:v2                                                                                         0.0s
012) 
013)  docker image ls
014) REPOSITORY                  TAG       IMAGE ID       CREATED              SIZE
015) diamol/ch17-build-context   v2        206c5fa79f99   43 seconds ago       8.99MB
016) diamol/ch17-build-context   v1        2e1ca97fac74   About a minute ago   8.99MB
  1. 015~016: 파일을 삭제한 v2 이미지의 크기가 v1 이미지와 같다. 이미지는 이미지 레이어가 합쳐져 만들어지는데, 파일이 삭제된 것이 아니라 그다음 레이어가 해당 파일을 가린 것이다.

  2. 다음 레이어에서 불필요한 파일을 제거해 봐야 소용이 없으며, 각 레이어마다 따로 최적화해야 한다.

실습 캐시에 저장된 레이어로 컨테이너를 실행할 수 있다. 전체 이미지로 실행한 컨테이너와 비교해 보자.

001)  docker container run diamol/ch17-build-context:v2
002) app-
003) init.txt
004) docs-
005) ls: docs: No such file or directory
006) 
007)  docker history diamol/ch17-build-context:v2
008) IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
009) 206c5fa79f99   8 minutes ago   RUN /bin/sh -c rm -rf docs # buildkit           0B        buildkit.dockerfile.v0
010) <missing>      8 minutes ago   COPY . . # buildkit                             2.1MB     buildkit.dockerfile.v0
011) <missing>      8 minutes ago   CMD ["/bin/sh" "-c" "echo app- && ls app && …   0B        buildkit.dockerfile.v0
012) <missing>      2 years ago     /bin/sh -c apk add --no-cache curl              1.59MB    
013) <missing>      3 years ago     /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B        
014) <missing>      3 years ago     /bin/sh -c #(nop) ADD file:da3ddeca2212f561c…   5.3MB     
015) 
015) docker container run <이전_레이어_식별자>
  1. 005: 컨테이너를 실행하면 파일 목록을 출력한다. Dockerfile 스크립트에서 docs 디렉터리의 파일을 삭제했으니 최종 이미지의 파일 시스템에서는 이 디렉터리에 아무 파일도 없다.
  2. 010: 이 레이어는 COPY 인스트럭션으로 생성됐다. docs 디렉터리의 모든 파일은 이 레이어에 들어 있다.
  3. 015: 교재에는 레이어 이미지 고유값이 있는데 나는 없다?

예제 17-2 필요한 파일만 복사하도록 최적화된 Dockerfile 스크립트

FROM diamol/base
CMD echo app- && ls app && echo docs- && ls docs
COPY ./app ./app
  • 이 스크립트로 이미지를 빌드해 보면 이미지 크기가 줄어들었음을 알 수 있다.
  • 하지만 아직 최적화의 여지가 남아 있다.
  • 도커의 빌드 과정은 엔진에 빌드 컨텍스트(빌드를 실행한 디렉터리)를 압축하고 Dockerfile 스크립트를 함께 보내면서 시작된다.
  • 이러한 빌드 과정 덕분에 로컬 컴퓨터에서 원격 엔진에 이미지 빌드 명령을 내릴 수 있는 것이다.
  • 이 빌드 컨텍스트에는 불필요한 파일이 포함된 경우가 많다.
  • .dockerignore 파일에 불필요한 디렉터리나 파일 목록(와일드카드도 사용할 수 있다)을 기재하면 빌드 컨텍스트에서 이들 파일을 제외할 수 있다.

실습 .dockerignore 파일을 작성해 빌드 컨텍스트의 크기를 출인 다음 최적화된 이미지를 다시 빌드해 보자.

# 최적화된 이미지를 빌드한다고 하지만 컨텍스트에 아직 불필요한 파일이 있다 docker image build -t diamol/ch17-build-context:v3 -f ./Dockerfile.v3 .
[+] Building 2.9s (8/8) FINISHED                                                                                
 => exporting to image                                                                                     0.0s
 => => naming to docker.io/diamol/ch17-build-context:v3 

# 미리 작성해 둔 ignore 파일의 이름을 바꿔 유효하게 한다 mv rename.dockerignore .dockerignore   cat .dockerignore 
docs/
Dockerfile*%                                                                                                    

# 다시 한 번 똑같이 이미지를 빌드한다 docker image build -t diamol/ch17-build-context:v3 -f ./Dockerfile.v3 .
[+] Building 1.0s (7/7) FINISHED                                                                                
 => exporting to image                                                                                     0.0s
 => => naming to docker.io/diamol/ch17-build-context:v3                                                    0.0s
  • 첫 번째 빌드에서는 엔진에 전달된 빌드 컨텍스트의 용량이 2MB였다.
  • 두 번째 빌드에서는 현재 디렉터리에 빌드 컨텍스트에서 제외할 파일 목록이 정의된 .dockerignore 파일이 있는 상태에서 빌드가 실행됐다.
  • 이때의 빌드 컨텍스트 용량은 4KB에 불과했다.

links

social