В этой статье я покажу вам, как всего за семь шагов выполнить Dockerize готового к производству NodeJS-приложения, следуя некоторым лучшим практикам.
Необходимые условия:
-
Базовый опыт работы с Docker
-
Базовый опыт работы с NodeJS
-
Ваша любимая IDE или текстовый редактор.
Начало работы:
Что такое Docker?
Docker — это проект с открытым исходным кодом, который позволяет легко создавать контейнеры и приложения на основе контейнеров. Первоначально Docker был создан для Linux, но теперь он работает на Windows и macOS. Чтобы понять, как работает Docker, давайте рассмотрим некоторые компоненты для разработки приложений на основе Docker-контейнеров.
Dockerfile
Каждый контейнер Docker начинается с Dockerfile. Dockerfile — это текстовый файл, написанный на простом синтаксисе, который содержит инструкции по созданию образа Docker. В Dockerfile указывается операционная система, на которой будет работать контейнер, языки, переменные окружения, расположение файлов, сетевые порты и другие необходимые компоненты, а также то, что будет делать контейнер после запуска.
Образ Docker
После того как вы написали Dockerfile, вы вызываете утилиту сборки Docker для создания образа на основе этого Dockerfile. В то время как Dockerfile — это набор инструкций, указывающих сборщику, как создать образ, образ Docker — это переносимый файл, содержащий спецификации того, какие программные компоненты и каким образом будут запущены в контейнере. Поскольку Dockerfile, вероятно, будет включать инструкции по получению некоторых программных пакетов из онлайн-репозиториев, вам следует позаботиться о том, чтобы явно указать нужные версии, иначе ваш Dockerfile может создавать несовместимые образы в зависимости от того, когда он будет вызван. Но как только образ создан, он становится статичным.
Достаточно разговоров о docker и образах. Давайте перейдем к делу. Откройте VSCode и создайте файл с именем Dockerfile
. Он содержит все команды командной строки, которые мы можем использовать для сборки образа.
Шаг 1:
FROM node:16-bullseye-slim
: Мы указываем базовый образ для процесса сборки. Он должен быть указан в первой строке Dockerfile
. Однако вы можете использовать его столько раз, сколько захотите. Возможно, вы слышали, что alphine
имеет один из самых маленьких образов. Это правда, но я не рекомендую использовать его в производстве. На это есть много причин, но самая важная для меня заключается в том, что он не находится на Tier1 поддержке команды Node.js. Что касается моего использования node:16-bullseye-slim
. У него лучше количество CVE, и он также имеет поддержку Tier 1 от команды NodeJS.
Шаг 2:
RUN mkdir /app && chown -R node:node /app
: RUN mkdir необходим, потому что WORKDIR не уважает USER при создании каталогов, а USER — это способ не использовать пользователя ROOT; я объясню это в ближайшее время.
Шаг 3:
WORKDIR /app
: Эта команда используется для указания текущего рабочего каталога контейнера Docker. В приведенном выше фрагменте мы указываем каталог app
в качестве рабочего каталога.
Шаг 4:
USER node
: При выполнении наших контейнерных веб-приложений Node.js мы всегда должны придерживаться принципа наименьших привилегий; это политика безопасности, которая существует с первых дней существования Unix. Если злоумышленник скомпрометирует ваше веб-приложение, запуск процесса от имени root может заставить злоумышленника выполнить практически все действия в контейнере. В то время как запуск от имени пользователя узла ограничит атаку, поскольку пользователь узла не имеет привилегий root.
Шаг 5:
COPY --chown=node:node . /app
: Это копирует наш каталог файлов в WORKDIR
, который мы установили выше, а флаг --chown=node:node
для COPY гарантирует, что файлы будут принадлежать непривилегированному пользователю node, а не root, который используется по умолчанию.
Шаг 6:
RUN npm ci --only=production && npm cache clean --force
: Это обеспечит установку только производственных зависимостей и очистит кэш в npm.
Шаг 7:
CMD ["node", "entrypoint.js"]
: Команда CMD определяет команду, которая будет выполняться внутри контейнера. Вы можете спросить, разве мы не используем менеджер процессов, например nodemon
или pm2
? Это не подходит для производства; они добавляют ненужную сложность. Если вам требуется больше копий вашего контейнера, запустите дополнительные контейнеры через ваш оркестратор.
Если собрать все вместе, вот как выглядит ваш Dockerfile:
FROM node:16-bullseye-slim
RUN mkdir /app && chown -R node:node /app
WORKDIR /app
USER node
COPY --chown=node:node . /app
RUN npm ci --only=production && npm cache clean --force
CMD ["node", "entrypoint.js"]
Бонус: Хотите избежать ненужных файлов в вашем Docker-образе? Добавьте .dockerignore
в корневой каталог вашего исходного кода и добавьте .git и node_modules, чтобы избежать ненужных файлов в вашем образе.
Заключение
Вот и все на сегодня! Надеюсь, вам понравилось. Не забывайте делиться, реагировать и общаться со мной в разделе комментариев.