[Docker] Dockerfile로 도커 이미지를 빌드할 때 레이어 캐시 때문에 생긴 파일 다운로드 문제

Dockerfile로 도커 이미지를 빌드할 때 다운로드할 파일이 변경되었어도 캐싱된 레이어를 사용해 변경된 파일이 적용되지 않는 경우에 대해서 정리


환경

  • Linux
  • Docker


문제 및 해결 방법

문제 상황

  • Dockerfile를 통해서 도커 이미지를 빌드할 때 RUN에서 curl을 이용해 파일을 다운로드 받는 부분이 있다. 이때, 새로운 이미지 빌드시 파일이 변경되었음에도 처음에 캐싱된 레이어의 파일이 들어가서 이전 파일이 이미지에 포함되는 문제가 발생한다.

문제 상황 예시

  • 파일 확인
$ curl https://twpower.me/test.txt
test1
  • Dockerfile 예시
$ cat Dockerfile
FROM ubuntu:18.04
RUN apt-get update -y
RUN apt-get install curl -y
RUN curl https://twpower.me/test.txt -o test.txt
CMD cat test.txt
  • 도커 이미지 빌드
$ sudo docker build --tag test:1.0 .
  • 빌드된 이미지 실행
$ sudo docker run test:1.0
test1
  • 변경된 파일 확인
$ curl https://twpower.me/test.txt
test2
  • 이미지 다른 버전으로 빌드
  • 하단에 캐시 이용하는거 확인
$ sudo docker build --tag test:2.0 .
Sending build context to Docker daemon  2.048kB
Step 1/5 : FROM ubuntu:18.04
 ---> 56def654ec22
Step 2/5 : RUN apt-get update -y
 ---> Using cache
 ---> 47696d4f4d5f
Step 3/5 : RUN apt-get install curl -y
 ---> Using cache
 ---> 15080e39cb8b
Step 4/5 : RUN curl https://twpower.me/test.txt -o test.txt
 ---> Using cache
 ---> 75bbac2b003f
Step 5/5 : CMD cat test.txt
 ---> Using cache
 ---> 3ce1a5c10a5b
Successfully built 3ce1a5c10a5b
Successfully tagged test:2.0
  • 빌드된 이미지 실행
  • 파일은 변경되었으나 변경된 파일이 적용되지 않은 문제 발생!
$ sudo docker run test:2.0
test1
$ curl https://twpower.me/test.txt
test2


원인

  • Dockerfile에서는 명령어 한줄 한줄을 레이어(Layer)로 판단하며 해당 레이어(Layer)별로 캐싱을 진행하기 때문에 만약 특정줄에 해당하는 명령어와 이전 명령어들이 동일하다면 동일한 레이어(Layer)로 판단하기 때문에 캐싱되어 있는 부분을 가져오기 때문이다.
  • 위의 예제에서는 파일이 변경되었어도 명령어 RUN curl https://twpower.me/test.txt -o test.txt는 동일하다.
  • 공식 홈페이지 문서 https://docs.docker.com/develop/develop-images/dockerfile_best-practices/에 따르면 “A Docker image consists of read-only layers each of which represents a Dockerfile instruction. The layers are stacked and each one is a delta of the changes from the previous layer.”라고 나와있다.


해결 방법

방법 1

  • --no-cache를 이용해 도커 이미지 빌드시 캐시를 사용하지 않도록 설정
$ sudo docker build --no-cache --tag test:3.0 .

방법 2

  • (파일 제공자측) 사용하는 파일명 뒤에 버전을 태깅


참고자료