Docker Build가 있는 Dependency Manager 캐시

7508 단어 railsdockeryarn
이 게시물은 프로덕션 Docker 빌드에 대한 종속성 관리자 캐싱을 구현하는 방법을 설명합니다.

문맥



현재 이 주제에 대해 대부분의 가이드/게시물에서 제공하는 것은 도커 이미지를 빌드할 때 도커 이미지 레이어 캐싱을 활용하는 것입니다.

다음과 같이 보입니다.

FROM ruby

ADD Gemfile* /app
RUN bundle install
ADD . /app
Gemfile에 변경 사항이 없는 한 bundle install 명령은 캐시를 사용하여 이 단계를 빠르게 건너뜁니다.

예제의 Dockerfile은 유효하며 작동합니다. 그러나 Gemfile에서 gem을 추가하거나 제거하면 성능이 저하됩니다. 변경 사항이 아무리 작아도 해당 단계의 전체 캐시가 무효화되기 때문입니다. 변경 사항이 있을 때마다 모든 gem을 다운로드하고 설치하는 것은 일부 느린 시스템에서 특히 지루할 수 있습니다.

예를 들어 번들러를 사용하고 있지만 이 문제는 대부분의 종속성 관리자에 존재합니다.

도커 실험 기능



주변을 파헤치고 나면 이 문제에 대한 실험적인 도커 기능이 있는 것으로 보입니다.

RUN --mount=type=cache

이것이 할 수 있는 일은 각 도커 빌드에 첨부될 지정된 대상에 디렉토리를 마운트하는 것입니다. 이미 다운로드한 gem, node_modules 등을 사용할 수 있으므로 종속성 관리자에게 적합합니다.

This stackoverflow answer 또한 그것이 어떻게 아주 잘 작동하는지 설명합니다.

이것은 실험적인 기능이므로 Docker 데몬과 클라이언트에 대해 활성화해야 합니다. 시스템에서 이를 활성화하는 방법을 온라인으로 검색하십시오.

Dockerfile 상단에 실험 기능을 사용 중임을 나타내는 추가 줄이 필요합니다.



번들러

# syntax = docker/dockerfile:experimental
...
RUN --mount=target=/app/tmp/bundle,type=cache \
  bundle install --deployment --path /app/tmp/bundle --without development test \
  && cp -r tmp/bundle/ vendor
...

이 예제에서 주목해야 할 흥미로운 점은 번들러가 모든 gem을 /app/tmp/bundle 로 다운로드한다는 것입니다.

이는 RUN가 완료된 후에는 캐시를 더 이상 사용할 수 없으므로 캐시에서 무엇이든 유지하려면 캐시에서 이미지로 복사해야 하기 때문입니다.

Rails 애플리케이션은 gem 없이 실행될 수 없습니다.



# syntax = docker/dockerfile:experimental
...
# Install yarn packages
RUN --mount=target=/app/node_modules,type=cache \
  yarn install

# Compile assets
RUN --mount=target=/app/node_modules,type=cache \
  bin/rails webpacker:compile
...

이 예에서는 앱을 실행하는 데 bin/rails webpacker:compile가 필요하지 않기 때문에 탑재된 노드 모듈 캐시를 사용하여 node_modules를 실행할 수 있습니다.

이것에 대한 좋은 점은 최종 이미지의 파일 크기를 줄이는 node_modules 자체가 아니라 컴파일된 자산만 결과 이미지에 포함된다는 것입니다.

작동하는 Dockerfile



# syntax = docker/dockerfile:experimental

# Stage: Builder
FROM ruby:2.6.5-alpine as Builder

ENV RAILS_ENV production
ENV RACK_ENV production
ENV NODE_ENV production
ENV GEM_HOME=/app/vendor/bundle/ruby/2.6.0
ENV GEM_PATH=$GEM_HOME:$GEM_PATH
ENV PATH=$GEM_HOME/bin:$PATH
ENV BUNDLE_APP_CONFIG=.bundle

RUN apk add --update --no-cache \
  build-base \
  postgresql-client \
  git \
  nodejs \
  yarn \
  tzdata

WORKDIR /app

# Add the Rails app
ADD . /app

# Install gems
RUN gem install bundler

RUN --mount=target=/app/tmp/bundle,type=cache \
  bundle install -j "$(getconf _NPROCESSORS_ONLN)" --retry 3 --deployment --path /app/tmp/bundle --without development test \
  && cp -r tmp/bundle/ vendor

RUN bundle config --local path vendor/bundle

# Install yarn packages
RUN --mount=target=/app/node_modules,type=cache \
  yarn install

# Compile assets
RUN --mount=target=/app/node_modules,type=cache \
  bin/rails webpacker:compile

# Stage: Final
FROM ruby:2.6.5-alpine

RUN apk add --update --no-cache \
  postgresql-client \
  tzdata

# Copy app with local gems and compiled assets from former build stage
COPY --from=Builder /app /app

ENV GEM_HOME=/app/vendor/bundle/ruby/2.6.0
ENV GEM_PATH=$GEM_HOME:$GEM_PATH
ENV PATH=$GEM_HOME/bin:$PATH
ENV BUNDLE_APP_CONFIG=.bundle

WORKDIR /app

# Expose Puma port
EXPOSE 3000

# Start up
CMD bundle exec puma -C config/puma.rb

결론



이 솔루션은 (느린) 해결 방법에 의존하지 않고도 종속성 관리자를 사용하여 Docker 빌드 속도를 높이는 데 적합합니다.

그러나 단점은 데몬과 클라이언트에서 실험적 기능을 활성화해야 한다는 것입니다. 아마도 항상 가능하지는 않을 것입니다.

나는 도커 전문가가 아니므로 어떤 생각이나 의견이 있으면 듣고 싶습니다!

좋은 웹페이지 즐겨찾기