Причина многоступенчатой ​​сборки — уменьшить размер изображения.

На самом деле было очень распространено иметь один Dockerfile для разработки (который содержал все необходимое для создания вашего приложения) и уменьшенный файл для использования в рабочей среде, который содержал только ваше приложение и именно то, что было необходимо для его запуска. Это называется «шаблон строителя». Поддерживать два файла Dockerfile не идеально.

Многоэтапные сборки | Документация по докеру

Однако, в моем случае, время сборки более серьезно, чем размер изображения.
Это потому, что язык, который я использую чаще всего, язык сценариев.

Однако кажется, что эта многоэтапная сборка при правильном использовании может значительно сократить время сборки.

Давайте попробуем. Используя в качестве примера простую среду ресурсов Ruby on Rails и Node.js, мы начнем с одноэтапной сборки и попытаемся улучшить ее.

FROM ruby:3.1
RUN curl -fsSL  | bash - && apt-get install -y nodejs
RUN npm install --global yarn@1.22.19
RUN gem install bundler
RUN mkdir -p /rails
WORKDIR /rails
COPY . .
RUN bundle install
RUN yarn install
RUN RAILS_ENV=production bundle exec rails assets:precompile
CMD ["bin/rails", "s"].
Войти в полноэкранный режим

Выйти из полноэкранного режима

Наконец, рельсы

RUN bundle install
RUN yarn install
RUN RAILS_ENV=production bundle exec rails assets:precompile
Войти в полноэкранный режим

Выйти из полноэкранного режима

Сделано, но это, скорее всего, займет больше всего времени.
Еще более раздражает то, что если какой-либо из исходников изменен,

COPY . .
Войти в полноэкранный режим

Выйти из полноэкранного режима

Кэш слоя будет очищен, поэтому обязательно используйте

RUN bundle install
RUN yarn install
RUN RAILS_ENV=production bundle exec rails assets:precompile
Войти в полноэкранный режим

Выйти из полноэкранного режима

будет казнен.
Это всегда так из-за механизма кэширования слоев.

Как только кеш становится недействительным, все последующие команды Dockerfile генерируют новые изображения, а кеш не используется.

Dockerfile Рекомендации по написанию файлов Dockerfile

Следующим шагом для решения этой проблемы является подготовка builder сцена.

FROM ruby:3.1 as builder
WORKDIR /tmp
RUN curl -fsSL  | bash - && apt-get install -y nodejs
RUN npm install --global yarn@1.22.19
RUN gem install bundler
COPY Gemfile Gemfile.lock . / /
RUN bundle install
COPY package.json yarn.lock . /
RUN yarn install
COPY app/assets app/assets
COPY app/javascript app/javascript
COPY bin bin
COPY config config
COPY Rakefile vite.config.ts . /
RUN RAILS_ENV=production bundle exec rails assets:precompile

FROM ruby:3.1 as app
RUN mkdir -p /rails
WORKDIR /rails
COPY --from=builder /usr/local/bundle /usr/local/bundle
COPY --from=builder /tmp/public/vite public/vite
COPY . .
CMD ["bin/rails", "s"].
Войти в полноэкранный режим

Выйти из полноэкранного режима

Примечательно здесь.

COPY --from=builder /usr/local/bundle /usr/local/bundle
COPY --from=builder /tmp/public/vite public/vite
COPY . .
Войти в полноэкранный режим

Выйти из полноэкранного режима

--from позволяет копировать файлы с других стадий, но проблема это COPY заказ**.
Во-первых, вам нужно скопировать потенциально трудоемкий

COPY --from=builder /usr/local/bundle /usr/local/bundle
COPY --from=builder /tmp/public/vite public/vite
Войти в полноэкранный режим

Выйти из полноэкранного режима

сначала пишется, а потом:

COPY . .
Войти в полноэкранный режим

Выйти из полноэкранного режима

В настоящее время bundle install не будет выполнено, пока не будет выполнена одна из Gemfile Gemfile.lock изменен.

Однако проблема остается.
Если вы измените какой-либо из Gemfile Gemfile.lockон даже будет работать yarn install.

Итак, давайте перейдем к окончательной форме на данный момент.

FROM ruby:3.1 as builder
RUN curl -fsSL  | bash - && apt-get install -y nodejs
RUN npm install --global yarn@1.22.19

FROM ruby:3.1 as bundler
WORKDIR /tmp
RUN gem install bundler
COPY Gemfile Gemfile.lock . /tmp
RUN bundle install

FROM node as yarn
WORKDIR /tmp
COPY package.json yarn.lock . / / RUN yarn install
RUN yarn install

FROM builder as assets
WORKDIR /tmp
COPY --from=bundler /usr/local/bundle /usr/local/bundle
COPY --from=yarn /tmp/node_modules node_modules
COPY app/assets app/assets
COPY app/javascript app/javascript
COPY bin bin
COPY config config
COPY Rakefile Gemfile Gemfile.lock package.json yarn.lock vite.config.ts . /
RUN RAILS_ENV=production bundle exec rails assets:precompile

FROM ruby:3.1 as app
RUN mkdir -p /rails
WORKDIR /rails
COPY --from=bundler /usr/local/bundle /usr/local/bundle
COPY --from=assets /tmp/public/vite public/vite
COPY . .
CMD ["bin/rails", "s"].
Войти в полноэкранный режим

Выйти из полноэкранного режима

👍

В этом Dockerfile.

  • Управляет кэшированием, фиксируя изменения только в файлах, от которых зависит выполнение процесса..

что достигается за счет Dockerfile. Теперь, например, если Gemfile.lock изменен, yarn install выполняться не будет.

более того.

Возможно, вы заметили, что yarn этап и bundler стадии обрабатываются параллельно.

Структура исполнения такова.

  • COPY --from=bundler /usr/local/bundle /usr/local/bundle.

  • COPY --from=bundler /usr/local/bundle /usr/local/bundle

    • --from=yarn /tmp/node_modules node_modules

и теперь мы можем запускать необходимые процессы параллельно при разрешении --from!


  • Многоэтапные сборки могут в полной мере использовать кэширование слоев..
  • Многоэтапные сборки могут обеспечить параллельную обработку.

Спасибо за чтение.