Dockerfile에 이러한 문제가 있습니까?

3999 단어 devopsrailsdockerruby
Docker는 이미지를 만드는 데 필요한 모든 지침이 포함된 Dockerfile을 사용하여 이미지를 빌드합니다. 각 명령어는 이전 레이어 위에 쌓인 읽기 전용 레이어에 매핑되며 이전 레이어의 변경 사항에 대한 델타입니다.

이 캐싱 메커니즘은 이미지를 빌드할 때 성능과 효율성을 향상시킵니다. 그러나 때로는 의도하지 않은 문제가 발생할 수 있습니다. 이 게시물은 그러한 경우를 거의 설명하지 않습니다.

1. 캐시된 리포지토리에서 패키지 설치



Dockerfile에 다음 명령이 있다고 가정해 보겠습니다.

RUN apt-get update
RUN apt-get install sqlite3


한 달 후; 이미지에 nginx를 추가하고 Dockerfile을 다음과 같이 업데이트하려고 합니다.

RUN apt-get update
RUN apt-get install sqlite3 nginx


Dockerfile은 명령을 순서대로 나열하므로 각 명령은 이전 명령 위에 구축됩니다. Docker는 이미지를 빌드할 때 Dockerfile의 각 단계를 캐시합니다. Dockerfile을 변경하거나 파일 시스템을 변경하면 캐시가 무효화됩니다. 따라서 Docker는 변경 사항이 있는 Dockerfile의 첫 번째 명령에서만 다시 빌드하면 됩니다.

Docker only needs to rebuild from the first instruction in the Dockerfile where there was a change.



위의 예에서 apt-get update 명령어는 변경되지 않았습니다. 따라서 Docker는 마지막으로 이미지를 빌드하고 nginx의 이전 버전을 설치할 때 캐시한 이전 패키지 저장소를 사용합니다.

이를 방지하려면 항상 apt-get updateapt-get install 명령을 단일 명령으로 결합하십시오.

RUN apt-get update && apt-get install sqlite3 nginx


이렇게 하면 새 패키지를 추가할 때마다 Docker가 최신 패키지 리포지토리를 가져오도록 강제할 수 있습니다.

2. 필요하지 않을 때 Gem 설치



위의 문제를 해결했다고 가정하고 이제 Dockerfile은 다음과 같습니다.

FROM ruby                                         

RUN apt-get update && apt-get install sqlite3 nginx                                 

COPY . /app/                                    

WORKDIR /app                                    
RUN bundle install


이제 routes.rb와 같이 프로젝트의 파일을 편집하고 이미지를 다시 빌드합니다. Gemfile 를 건드리지 않았음에도 Docker가 모든 gem을 다시 설치했음을 알 수 있습니다.

범인은 현재 디렉터리의 콘텐츠를 컨테이너에 복사하는 세 번째 명령COPY . /app/입니다. routes.rb 파일을 편집한 후 Docker 데몬은 복사되는 파일을 이전에 복사한 파일과 비교했습니다. 그것들이 다르기 때문에 Docker는 캐시를 무효화했습니다.

앞서 언급했듯이 명령의 캐시가 무효화되면 향후 명령에 대한 모든 캐시도 무효화됩니다. 따라서 Docker는 파일 시스템 변경이 Gemfile에서 gem을 추가/제거하지 않았음을 보장할 수 없으므로 모든 gem을 다시 설치합니다. 그러나 이것은 느리고 중복됩니다. 프로젝트에서 임의의 파일을 변경하면 트리거되지 않습니다bundle install.

트리거하는 파일bundle install을 트리거하지 않는 파일과 분리하여 이 문제를 해결할 수 있습니다.

FROM ruby                                         

RUN apt-get update && apt-get install sqlite3 nginx                                 

# copy Gemfile and Gemfile.lock
COPY Gemfile* /app/                                    
WORKDIR /app                                    
RUN bundle install

# copy remaining files
COPY . /app/

Gemfile 복사 명령을 분리하면 독립적으로 캐시되는 별도의 계층이 생성됩니다. 따라서 나중에 routes.rb 파일에서 무언가를 변경할 때 캐시가 무효화되지 않습니다.

gem은 Gemfile에서 변경한 경우에만 다시 설치됩니다. 다른 모든 파일을 변경하면 마지막 지침의 캐시만 무효화됩니다. 이 시점에서 Docker가 이미 gem을 설치했으므로 괜찮습니다.

무언가를 변경하고 이미지를 다시 빌드하면 gem을 다시 설치할 필요가 없으므로 빠르게 빌드됩니다. 정돈된.

도움이 되길 바랍니다.

좋은 웹페이지 즐겨찾기