개요



Docker 이미지를 빌드하다 보면 의도치 않게 용량이 커지는 경우가 많습니다. 대부분의 원인은 불필요하게 생성된 레이어에 있습니다. 이 글은 docker history 명령어를 사용하여 이미지의 '족보'를 확인하고, 이를 통해 실제 이미지를 경량화했던 최적화 경험을 공유합니다.

이 명령어를 활용하면 무엇이 이미지를 무겁게 만드는지 정확히 찾아내고, 더 효율적인 이미지를 만들 수 있습니다.


docker history: 이미지의 족보 확인하기

docker history는 특정 이미지가 어떻게 만들어졌는지, 그 구성 내역을 보여주는 명령어입니다. Dockerfile의 각 명령어가 어떤 레이어(layer)로 쌓였는지, 그리고 각 레이어가 생성된 시점과 용량까지 확인할 수 있습니다.

기본 사용법은 매우 간단합니다.

docker history [옵션] <이미지 이름:태그>

예를 들어 로컬의 my-app:latest 이미지 히스토리를 확인하는 명령어는 다음과 같습니다.

docker history my-app:latest

출력 결과를 보면 이미지의 맨 위 레이어(최신)부터 베이스 이미지(가장 오래된)까지 순서대로 보여줍니다.

IMAGE          CREATED         CREATED BY                                      SIZE
a6215f271958   5 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>      7 weeks ago     /bin/sh -c #(nop) ADD file:f28242cf608f6...   7.81MB
  • CREATED BY: 이 레이어를 생성한 Dockerfile 명령어

  • SIZE: 해당 레이어가 차지하는 용량

유용한 팁: --no-trunc로 명령어 전체 보기

docker history의 기본 출력은 CREATED BY 열의 명령어가 너무 길면 중간에 잘려서 보입니다. 이때 --no-trunc 옵션을 함께 사용하면, 잘림 없이 전체 명령어를 모두 확인할 수 있어 정확한 분석에 필수적입니다.

docker history --no-trunc my-app:latest

레이어 분석이 중요한 이유: 실제 최적화 경험



Docker 이미지는 Dockerfile의 명령어 한 줄당 하나의 레이어를 생성하는 것이 기본 원칙입니다. 그리고 각 레이어는 이전 레이어 위에 쌓이는 '변경 사항'입니다.

문제는, 불필요하게 레이어를 나누면 이미지 용량이 급격히 증가한다는 것입니다.

사례: COPYRUN chown의 함정

Dockerfile을 작성할 때, 프로젝트 파일들을 컨테이너로 복사(COPY)한 뒤, 해당 파일들의 소유권을 특정 유저(예: appuser)로 변경(RUN chown)하는 경우가 많습니다.

비효율적인 방법: 2개의 레이어

처음에는 Dockerfile을 다음과 같이 작성했습니다.

# 1. 파일을 일단 복사 (root 소유로 복사됨)
COPY . .

# 2. 소유권 변경 (별도 명령어로 실행)
RUN chown -R appuser:appgroup /app

docker history로 빌드된 이미지의 내역을 확인해 보니, 두 개의 레이어가 생성되었습니다.

IMAGE          CREATED BY                                        SIZE
<layer_id_2>   /bin/sh -c chown -R appuser:appgroup /app        150MB  <-- (문제!)
<layer_id_1>   /bin/sh -c #(nop) COPY dir:abc in /app           150MB

여기서 심각한 문제가 발생합니다.

  1. COPY . . 명령으로 150MB 크기의 파일들이 레이어 1에 추가되었습니다.

  2. RUN chown 명령은 레이어 1의 150MB 파일들을 그대로 복사한 뒤, 소유권 정보만 변경하여 레이어 2에 새롭게 저장합니다.

파일 내용은 동일하지만, 하나는 root 소유, 하나는 appuser 소유로 각각 다른 레이어에 저장된 것입니다. 결과적으로 이 두 레이어만으로 이미지 총용량은 300MB(150MB + 150MB)가 됩니다.

효율적인 방법: 1개의 레이어

이 문제는 COPY 명령어의 --chown 플래그를 사용하여 간단히 해결할 수 있습니다.

# 1. 복사와 동시에 소유권 지정
COPY --chown=appuser:appgroup . .

Dockerfile을 이렇게 수정한 뒤 docker history로 다시 확인했습니다.

IMAGE          CREATED BY                                             SIZE
<layer_id_1>   /bin/sh -c #(nop) COPY --chown=appuser... dir:abc     150MB

단 하나의 레이어가 생성되었고, 이미지의 총용량은 150MB로 줄었습니다. 단지 명령어 두 줄을 한 줄로 합쳤을 뿐인데, 이미지 용량이 절반 가까이 줄어든 것입니다.


결론

docker history는 단순히 이미지의 생성 내역을 보는 것을 넘어, 이미지 최적화를 위한 핵심 분석 도구입니다.

Dockerfile을 수정한 뒤에는 습관적으로 docker history --no-trunc를 실행하여 의도한 대로 레이어가 생성되었는지, 불필요하게 용량을 차지하는 레이어는 없는지 확인하는 것이 좋습니다. 이 작은 습관이 쌓여 가볍고 효율적인 이미지를 만들 수 있습니다.