Как создать Docker-образ NestJS для производства

При развертывании своего проекта NestJS я обнаружил, что в сети нет информации о том, как написать Dockerfile для создания образа Docker, необходимого для контейнерного развертывания.

Поэтому я написал это руководство, которое шаг за шагом расскажет вам, как создать образ Docker для вашего проекта NestJs!

Готовы? Давайте погрузимся.

P.S. Если вы хотите просто скопировать и вставить готовый Dockerfile, просто перейдите к этому разделу.

Написание Dockerfile

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

Давайте теперь добавим Dockerfile:

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

А затем добавим инструкции в Dockerfile. Смотрите комментарии, которые объясняют каждый шаг:

# Base image
FROM node:18

# Create app directory
WORKDIR /usr/src/app

# A wildcard is used to ensure both package.json AND package-lock.json are copied
COPY package*.json ./

# Install app dependencies
RUN npm install

# Bundle app source
COPY . .

# Creates a "dist" folder with the production build
RUN npm run build

# Start the server using the production build
CMD [ "node", "dist/main.js" ]
Войти в полноэкранный режим Выйти из полноэкранного режима

Аналогично файлу .gitignore, мы можем добавить файл .dockerignore, который запретит включение определенных файлов в сборку образа.

touch .dockerignore
Вход в полноэкранный режим Выйти из полноэкранного режима

Затем исключите следующие файлы из сборки образа:

Dockerfile
.dockerignore
node_modules
npm-debug.log
Войти в полноэкранный режим Выйти из полноэкранного режима

Локальное тестирование контейнера

Теперь давайте проведем локальное тестирование, чтобы проверить, ведет ли себя Dockerfile так, как мы ожидаем.

Сначала соберем образ с помощью команды в терминале в корне вашего проекта (вы можете заменить nest-cloud-run на имя вашего проекта). Не забудьте .!

docker build -t nest-cloud-run .
Вход в полноэкранный режим Выход из полноэкранного режима

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

docker images
REPOSITORY                   TAG       IMAGE ID       CREATED          SIZE
nest-cloud-run               latest    004f7f222139   31 seconds ago   1.24GB
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь запустим контейнер и запустим образ с помощью этой команды (убедитесь, что имя образа то же самое, что использовалось выше):

docker run -p80:3000 nest-cloud-run
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь вы можете получить доступ к приложению NestJS, посетив https://localhost в вашем браузере (просто https://localhost без каких-либо номеров портов).

Я столкнулся с парой проблем на своей машине при запуске контейнера, в основном из-за конфликтов с портами других запущенных контейнеров.

Если у вас возникнут подобные проблемы, вы можете попробовать выполнить команду docker rm -f $(docker ps -aq), которая остановит и удалит все запущенные контейнеры.

Оптимизация Dockerfile для производства

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

Такие инструменты развертывания, как Cloud Run, учитывают размер образа при расчете стоимости, поэтому хорошей идеей будет сохранить размер образа как можно меньше.

Выполнив команду docker images, мы получим размер нашего образа:

docker images
REPOSITORY                   TAG       IMAGE ID       CREATED          SIZE
nest-cloud-run               latest    004f7f222139   31 seconds ago   1.24GB
Вход в полноэкранный режим Выход из полноэкранного режима

1,24 ГБ – это довольно много! Давайте вернемся к нашему Dockerfile и сделаем некоторые оптимизации.

Используйте изображения узлов Alpine

Рекомендуется использовать изображения узлов Alpine, когда вы пытаетесь оптимизировать размер изображения. Использование node:18-alpine вместо node:18 само по себе уменьшает размер изображения с 1.24GB до 466MB!

Используйте многоэтапные сборки

В своем Dockerfile вы можете определить многоступенчатые сборки, что является способом последовательной сборки наиболее оптимизированного образа путем создания нескольких образов.

На практике вот как мы можем использовать многоступенчатые сборки в нашем Dockerfile:

# Base image
FROM node:18-alpine As development

# Create app directory
WORKDIR /usr/src/app

# Copy application dependency manifests to the container image.
# A wildcard is used to ensure copying both package.json AND package-lock.json (when available).
# Copying this first prevents re-running npm install on every code change.
COPY package*.json ./

# Install app dependencies
RUN npm install

# Bundle app source
COPY . .

# Creates a "dist" folder with the production build
RUN npm run build

# Base image for production
FROM node:18-alpine As production

# Create app directory
WORKDIR /usr/src/app

# Copy application dependency manifests to the container image.
# A wildcard is used to ensure copying both package.json AND package-lock.json (when available).
# Copying this first prevents re-running npm install on every code change.
COPY package*.json ./

# Install production dependencies.
# If you have a package-lock.json, speedier builds with 'npm ci', otherwise use 'npm install --only=production'
RUN npm ci --only=production

# Bundle app source
COPY . .

# Copy the bundled code
COPY --from=development /usr/src/app/dist ./dist

# Start the server using the production build
CMD [ "node", "dist/main.js" ]

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

После обновления вашего Dockerfile вам нужно будет заново выполнить команды для сборки образа:

docker build -t nest-cloud-run .
Войти в полноэкранный режим Выйти из полноэкранного режима

А затем команду для раскрутки контейнера:

docker run -p80:3000 nest-cloud-run
Enter fullscreen mode Выйти из полноэкранного режима

Если вы снова запустите docker images, чтобы проверить размер нашего изображения, вы увидите, что оно стало значительно меньше:

docker images
REPOSITORY                   TAG       IMAGE ID       CREATED          SIZE
nest-cloud-run               latest    004f7f222139   31 seconds ago   189MB
Вход в полноэкранный режим Выход из полноэкранного режима

Устранение неполадок

Вы можете столкнуться со следующими ошибками:

Ошибка: Cannot find module ‘webpack’

Скорее всего, вы используете неправильную версию node в своем базовом образе, если вы получаете ошибки, подобные приведенным ниже:

  • Error: Cannot find module 'webpack'
  • ERROR [development 6/6] RUN npm run build
  • npm ERR! nest-cloud-run@0.0.1 build: nest build

Вместо использования FROM node:14-alpine, используйте FROM node:18-alpine, чтобы решить эту проблему.

Заключение

В итоге, вот наш оптимизированный для производства образ Docker для проекта NestJS:

# Base image
FROM node:18-alpine As development

# Create app directory
WORKDIR /usr/src/app

# Copy application dependency manifests to the container image.
# A wildcard is used to ensure copying both package.json AND package-lock.json (when available).
# Copying this first prevents re-running npm install on every code change.
COPY package*.json ./

# Install app dependencies
RUN npm install

# Bundle app source
COPY . .

# Creates a "dist" folder with the production build
RUN npm run build

# Base image for production
FROM node:18-alpine As production

# Create app directory
WORKDIR /usr/src/app

# Copy application dependency manifests to the container image.
# A wildcard is used to ensure copying both package.json AND package-lock.json (when available).
# Copying this first prevents re-running npm install on every code change.
COPY package*.json ./

# Install production dependencies.
# If you have a package-lock.json, speedier builds with 'npm ci', otherwise use 'npm install --only=production'
RUN npm ci --only=production

# Bundle app source
COPY . .

# Copy the bundled code
COPY --from=development /usr/src/app/dist ./dist

# Start the server using the production build
CMD [ "node", "dist/main.js" ]

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

Есть ли у вас какие-либо дополнительные оптимизации, которые вы можете внести в приведенный выше образ? Напишите об этом в комментариях ниже!

Оцените статью
Procodings.ru
Добавить комментарий