Оптимизация образов Docker — Lean Docker Images для Next.JS

Оптимизация образов Docker — Lean Docker Images для Next.JS

3 февраля 2023 г.

Использование многоэтапных сборок для оптимизации рабочего образа Docker для более быстрого развертывания.

В этой статье

  • 🧑‍🔬 Мы обсудим, почему и где оптимизация образа Docker может иметь смысл.
  • 🙈 Мы рассмотрим, как докеризировать проект Next.js со скрытой функцией.
  • 🪄 Мы углубимся в магию оптимизации образа Docker.

Проблема

На работе я заметил, что наш конвейер развертывания работает значительно медленнее, чем я ожидал. Упрощенный конвейер состоит из следующих заданий:

GitHub Actions workflow

После некоторого исследования мы смогли выявить узкое место в производительности. Больше всего времени занимала загрузка рабочих образов в реестр Google Cloud Artifact Registry. Это произошло потому, что мы загружали в реестр большие неоптимизированные образы Docker.

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

На что влияет оптимизация образа Docker?

Мы будем использовать демо-версию DALL-E, созданную мной для моей предыдущей статьи. в качестве примера. Демо выглядит так:

Demo

<цитата>

Вы можете найти демонстрацию на GitHub. Не стесняйтесь взглянуть на репозиторий и попробовать✨

Мы создадим два файла docker:

* Dockerfile.local: базовый образ без оптимизации. * Dockerfile: оптимизированный образ

Давайте создадим образы на основе каждого файла докера. Результаты:

Docker image sizes

* Неоптимизированное изображение: 2,85 ГБ * Оптимизированное изображение: 202 МБ

Размер уменьшился на 92%. Мы можем грубо интерпретировать это как сокращение времени загрузки на 92%, потому что передача файлов по HTTPS является линейной. Теперь давайте рассмотрим, как добиться того же результата.

Поехали.

Перед оптимизацией изображения

Мы можем начать с создания простого Dockerfile, подобного этому:

# Dockerfile.local

FROM node:18-alpine
RUN apk add --no-cache libc6-compat
WORKDIR /app

COPY . ./

# Build the app
RUN yarn --frozen-lockfile
RUN yarn build

# Serve the app
CMD [ "yarn", "start" ]

В этом образе мы используем Alpine Linux Node 18 в качестве базового образа из-за его гораздо меньшего размера. по сравнению с другими базовыми изображениями. Мы также следуем рекомендации и добавляем libc6-compat для поддержки использования "process. открыть". Остальное точно так же, как мы строим и обслуживаем проект локально:

* Сначала мы устанавливаем зависимости на основе файла yarn.lock, * мы генерируем производственную сборку, * и, наконец, запускаем сервер скриптом "yarn start".

Давайте создадим образ, используя этот файл докера, и это обычно то, что вы можете увидеть в командной строке:

Un-optimized build

Сборка была завершена за 52,9 с.

Оптимизированный образ Docker

Оптимизация основана на двух функциях Docker и Next.js:

* Многоэтапные сборки Docker * Трассировка выходного файла Next.js

Идея состоит в том, чтобы использовать многоэтапную сборку, чтобы выбрать только то, что нам нужно в рабочей среде, этап по этапам. Давайте посмотрим на файл докера.

# Dockerfile

ARG NODE=node:18-alpine

# Stage 1: Install dependencies
FROM ${NODE} AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

COPY package.json yarn.lock* ./
RUN yarn --frozen-lockfile

# Stage 2: Build the app
FROM ${NODE} AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

RUN yarn build

# Stage 3: Run the production
FROM ${NODE} AS runner
WORKDIR /app

ENV NODE_ENV production

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

# copy assets and the generated standalone server
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

ENV PORT 3000

# Serve the app
CMD ["node", "server.js"]

Мы использовали тот же «node:18-alpine», что и базовое изображение.

Этап 1. Установка зависимостей

Вместо того, чтобы копировать все в образ, мы копировали только "package.json" и "yarn.lock" для установки.

Этап 2. Создание приложения

Для сборки проекта нам нужны были установленные зависимости, исходный код и все конфигурации проекта в корне проекта. Итак, мы скопировали зависимости из предыдущего этапа и все из корня проекта.

Этап 3. Запуск производства

Трассировка выходных файлов – это функция Next.js, которая помогает нам сократить развертывание. размера путем отслеживания всех файлов, необходимых для производства, во время сборки.

Как только мы включим «автономный» вывод, Next.js создаст и выведет автономный сервер Node в каталоге «.next/standalone».

module.exports = {
  output: 'standalone',
}

Результат сборки выглядит следующим образом:

![отдельная папка

](https://cdn.hackernoon.com/images/XyqHIwK0xDMOGdIf5iTNW4CrLjb2-m8e35c6.png)

На этом этапе мы всего лишь скопировали автономный сервер, ресурсы в папке "./public", фрагменты JavaScript и CSS из папки ".next/static" в рабочий каталог и запустили сервер. с портом 3000.

Магия трассировки выходного файла заключается в @vercel/nft. Он статически анализирует граф зависимостей и выводит список модулей в графе. Для иллюстрации давайте зарегистрируем зависимости для нашей страницы, API и сервера Node:

import { nodeFileTrace } from "@vercel/nft";

const files = [
  "./.next/server/app/sc/page.js",
  "./.next/server/pages/api/images.js",
  "node_modules/next/dist/server/next-server.js",
];
const { fileList } = await nodeFileTrace(files);
console.log(fileList);

Вывод выглядит следующим образом:

File output tracing

Заключительные мысли

Теперь, когда мы изучили этапы и автономный сервер, давайте создадим образ и посмотрим на результат:

optimized image build result

Сборка была завершена за 41,3 с. По сравнению с неоптимизированной сборкой мы не снизили время сборки. Это большая победа, учитывая, что мы значительно уменьшили размер сборки на 92%.

Ссылки


Хотите подключиться?

Эта статья изначально была опубликована на веб-сайте Daw-Chih.


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE