Что такое докер?
Докер – это открытая платформа для разработки, запуска и управления контейнерами на сервере и в облаке. Думайте о докер как о CLI, но для облака.
Для примера приложения в этом руководстве мы будем использовать Next.js, и потом создадим Dockerfile чтобы “докерезировать” приложение.
Требования
Для использования докера в вашем Next.js проекте вам понадобится:
Установленный Docker на вашем компьютере
Установленные Node.js и npm/yarn в вашей системе для создания приложения на Next
Создание приложения на Next.js
Если у вас уже есть приложение, которое мы будем “докереизровать”, тогда переходить к следующему шагу, в ином случае давайте создадим его.
Выполните данную команду в терминале:
yarn create next-app
Данная команда подготовит файлы и конфигурацию, которые необходимы для запуска вашего next.js приложения
Создание Dockerfile
Для начала, давайте откроем наше приложение в VS Code или в любом другом редакторе на ваш выбор.
И запустим данные команды:
cd <имя проекта>
code .
(Надеюсь, что у вас настроен vscode)
Здесь вы увидите структуру вашего приложения. Должно выглядеть примерно так.
Примечание: я использую typescript, вот почему вы видите tsconfig.json и файлы, которые заканчиваются на .ts.
Продолжим, и создадим новый файл с названием Dockerfile. По умолчанию данный файл будет распознан докером, и он выполнит команды и инструкции, которые мы пропишем в файле.
Запомните: команды будут запущены в том порядке, в котором они записаны.
Пропишите данный код внутри Dockerfile. Я пробегусь по командам и объясню, как они работают в конце гайда.
Примечание: я использую yarn для руководства, вы можете использовать npm, для этого вам всего лишь нужно заменить yarn на npm в файле.
FROM node:lts as dependencies
WORKDIR /<имя проекта>
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
FROM node:lts as builder
WORKDIR /<имя проекта>
COPY . .
COPY --from=dependencies /<имя проекта>/node_modules ./node_modules
RUN yarn build
FROM node:lts as runner
WORKDIR /<имя проекта>
ENV NODE_ENV production
COPY --from=builder /<имя проекта>/public ./public
COPY --from=builder /<имя проекта>/package.json ./package.json
COPY --from=builder /<имя проекта>/.next ./.next
COPY --from=builder /<имя проекта>/node_modules ./node_modules
EXPOSE 3000
CMD ["yarn", "start"]
Создание докер образа
Выполните данную команду для создания образа докера.
docker build . -t <имя проекта>
Данная команда создаст образ докера с названием <имя проекта>.
Запустить образ докера после завершения сборки можно прописав команду:
docker run -p 3000:3000 <имя проекта>
Теперь откройте ваш бразуер, и перейдите по http://localhost:3000, чтобы увидеть ваш проект.
Поздравляю! Вы успешно “докерезировали” своё приложение!
Поговорим о содержимом Dockerfile
Пройдемся по коду, который содержится в Dockerfile.
Напомним, код выполняется на основание того, как он написан, сверху-вниз.
Разобьём весь код на 3 логические части:
Установка зависимостей
Сборка нашего Next.js приложения
Настройка среды выполнения для приложения
1. Установка зависимостей
FROM node:lts as dependencies
WORKDIR /<имя проекта>
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
Что же происходит в данном коде?
Первое, нам нужно определить какой образ мы хотим собрать и откуда, для этого мы используем последнюю версию node, с помощью команды node:lts.
Вы можете использовать необходимую версию node. Для примера: FROM node:16 будет создавать ваш образ с версией Node 16. Мы также используем as dependencies для того, чтобы экспортировать данный код, и использовать его в дальнейшем при сборке нашего приложения в докер.
Во-вторых, мы хотим создать место, в котором будет храниться код нашего приложения, для используется WORKDIR.
В-третьих, нам нужно скопировать наши package.json и yarn.lock файлы, что даст нам примущество в кэшировании слоев докера. Хорошее объяснение кэширования в докере вы можете найти тут.
И наконец, чтобы установить все зависимости для проекта нужно выполнить команду yarn install. Мы используем --frozen-lockfile потому, что наш yarn.lock или package-lock.json может получить обновления при запуске yarn install (или npm install). А мы не хотим проверять эти изменения.
Если вы используете npm вам нужно использовать npm ci (ci означает чистую установку / используйте это для продакшена или просто используйте RUN npm install)
Для yarn это --frozen-lockfile.
2. Сборка нашего Next.js приложения
FROM node:lts as builder
WORKDIR /<имя проекта>
COPY --from=dependencies /<имя проекта>/node_modules ./node_modules
RUN yarn build
Взглянем на процесс сборки.
Мы создаем наше приложение с помощью копирования зависимостей из node_modules.
И затем собираем его. Если вы используете npm, тогда используйте RUN npm build.
FROM node:lts as runner
WORKDIR /<имя проекта>
ENV NODE_ENV production
После сборки нашего проекта мы хотим запустить его, для этого перейдем в 3 пункт.
3. Настройка среды выполнения для приложения
COPY --from=builder /<имя проекта>/public ./public
COPY --from=builder /<имя проекта>/package.json ./package.json
COPY --from=builder /<имя проекта>/.next ./.next
COPY --from=builder /<имя проекта>/node_modules ./node_modules
EXPOSE 3000
CMD ["yarn", "start"]
На данном этапе мы хотим поместить исходный код нашего приложения в образ докера, вот почему мы используем COPY.
Финальным пунктом нам нужно запустить приложение, для этого используется CMD, в которой мы определяем среду выполнения.
Для нашей среды выполнения мы используем yarn команды.
Если у вас установлено докер приложение, то вы можете видеть там все ваши контейнеры, и запускать их оттуда. Выглядит это примерно так.
На этом руководство заканчивается, спасибо за прочтение!
Комментарии (9)
build_your_web
15.04.2022 22:05+1Как роуты будут работать после статической сборки?
Doberman2029 Автор
15.04.2022 22:55+1Не совсем понял вашего вопроса. В контейнере будет запускаться точная копия вашего проекта, на навигацию это никак не повлияет
uyrij
16.04.2022 01:47+1Почему нельзя один раз
COPY . .
?Можно ещё забиндить фолдер, чтобы .env с секретами не класть в докер. И это можно в той же командной строке, как у вас или в докер-компоузе
OnYourLips
16.04.2022 04:11+2Почему нельзя один раз
COPY . .
?Чтобы ускорить сборку за счёт кэша. Сначала собираем зависимости и они сохраняются в виде слоя. И при изменении файлов проекта их не надо пересобирать.
Exclipt
16.04.2022 09:37+2node_modules точно нужны для сбилженного проекта?
Doberman2029 Автор
16.04.2022 16:31Простой ответ, для сбилженного проекта node_modules не нужен.
Более сложный ответ. Мы копируем node_modules перед стадией билда. Часть кода, который мы импортируем из библиотек, находится в node_modules, и без присутствия данной папки в корне, перед билдом, мы не сможем собрать рабочее приложение.
Но, если у нас простой проект, у которого нет сторонних зависимостей, т.е. прям чистый js вообще без всего, то, конечно, и отпадает необходимость в node_modules, там ведь ничего нет :). Да и в докере необходимости тогда также нет, легче просто передать минифицированный код
kricha
Я бы сразу заменил lts на конкретную версию.