Докеризация веб-приложения Node.js
Цель этого примера — показать, как поместить приложение Node.js в Docker-контейнер. Это руководство предназначено для разработки, но не для прямого использования в продакшене. Мы также предполагаем, что вы успешно установили Docker на свой ПК и имеете базовое представление о структуре Node.js приложения.
В первой части руководства мы создадим простое Node.js приложение, затем мы сделаем для него docker-образ, и, наконец, инициализируем экземпляр контейнера из этого образа.
Docker позволяет вам упаковать приложение вместе с его окружением и всеми зависимостями в "коробку", называемую контейнером. Обычно контейнер состоит из приложения, работающего в упрощенной версии ОС Linux. Образ — это шаблон для контейнера, контейнер — это работающий экземпляр образа.
Создание приложения Node.js
Для начала создадим новую директорию, в которой будут находиться все файлы приложения. В этой директории
создайте файл package.json
, в котором описано приложение и его зависимости:
{
"name": "docker_web_app",
"version": "1.0.0",
"description": "node.js on docker",
"author": "first last <first.last@example.com>",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.16.1"
}
}
После создания файла package.json
, выполните команду npm install
. Если вы используете npm
версии 5 или выше, это также создаст файл package-lock.json
, который будет скопирован в ваш docker-образ.
Далее создайте файл server.js
, который определяет веб-приложение на основе
фреймворка Express.js:
'use strict';
const express = require('express');
// константы
const port = 8080;
const host = '0.0.0.0';
// приложение
const app = express();
app.get('/', (req, res) => {
res.send('Hello World');
});
app.listen(PORT, HOST, () => {
console.log(`Running on http://${HOST}:${PORT}`);
});
Далее мы рассмотрим, как можно запускать это приложение внутри Docker-контейнера, используя официальный образ Docker'а. Сначала давайте создадим Docker-образ с нашим приложением.
Создание файла Dockerfile
Создайте пустой файл с именем Dockerfile
:
touch Dockerfile
Откройте этот файл в вашем любимом текстовом редакторе.
Первое, что нам надо сделать — определить базовый образ,
который будет взят за основу. Мы будем использовать образ node
последней версии
LTS* (версии с долгосрочной поддержкой) — 12
,
доступный на Docker Hub.
* Прим. переводчика: на момент написания статьи.
FROM node:12
Затем создадим директорию для кода приложения внутри образа. Это будет рабочая папка для вашего приложения.
# создание директории приложения
WORKDIR /usr/src/app
Образ, который мы используем, поставляется с уже предустановленным Node.js и NPM.
Поэтому мы можем просто установить зависимости приложения с помощью команд npm
.
Обратите внимание, если вы используете npm
4 или ниже, файл package-lock.json
не будет сгенерирован.
# установка зависимостей
# символ астериск ("*") используется для того чтобы по возможности
# скопировать оба файла: package.json и package-lock.json
COPY package*.json ./
RUN npm install
# Если вы создаете сборку для продакшн
# RUN npm ci --only=production
Обратите внимание, что вместо того, чтобы копировать весь рабочий каталог,
мы копируем только файл package.json
. Это позволяет воспользоваться
кэшированием слоев в Docker. Здесь
bitJudo дал хорошее объяснение того, как это работает. Более того,
команда npm ci
, указанная в комментарии, позволяет создавать
более быстрые, надежные, воспроизводимые сборки для продакшена.
вы можете прочесть больше об этой команде здесь.
Чтобы отправить исходный код вашего приложения внутрь Docker-образа,
используйте директиву COPY
.
# копируем исходный код
COPY . .
Сервер привязан к 8080
порту, поэтому мы будем использовать
инструкцию EXPOSE
, чтобы проинформировать Docker о том, что в контейнере
имеется приложение, прослушивающее этот порт.
EXPOSE 8080
Последняя, но не менее важная команда CMD
содержит все необходимые
переменные среды и инструкции для запуска приложения.
Здесь мы просто используем node server.js
для запуска.
CMD [ "node", "server.js" ]
Ваш Dockerfile
теперь должен выглядеть примерно так:
FROM node:12
# создание директории приложения
WORKDIR /usr/src/app
# установка зависимостей
# символ астериск ("*") используется для того чтобы по возможности
# скопировать оба файла: package.json и package-lock.json
COPY package*.json ./
RUN npm install
# Если вы создаете сборку для продакшн
# RUN npm ci --only=production
# копируем исходный код
COPY . .
EXPOSE 8080
CMD [ "node", "server.js" ]
Файл .dockerignore
Создайте файл .dockerignore
в той же директории, что и Dockerfile
,
со следующим содержимым:
node_modules
npm-debug.log
Это предотвратит копирование локально установленных модулей и дебаг-логов в Docker-образ и возможную перезапись модулей установленных внутри образа.
Сборка образа
Перейдите в директорию, в которой находится ваш Dockerfile
и запустите
следующую команду, чтобы собрать Docker-образ. Флаг -t
позволяет поставить
тэг к вашему образу, чтобы его позже было проще найти при помощи команды
docker images
:
docker build . -t <your username>/node-web-app
Созданный образ теперь будет отображаться в списке всех образов:
$ docker images
# пример вывода
repository tag id created
node 12 1934b0b038d1 5 days ago
<your username>/node-web-app latest d64d3505b0d2 1 minute ago
Запуск образа
Запуск образа с флагом -d
позволяет контейнеру работать в фоновом режиме.
Флаг -p
перенаправляет публичный порт на приватный порт внутри контейнера.
Запустите образ, который вы ранее создали:
docker run -p 49160:8080 -d <your username>/node-web-app
Отобразите логи вашего приложения:
# отобразить все контейнеры, чтобы получить id нужного нам
$ docker ps
# отобразить логи
$ docker logs <container_id>
# пример логов
running on http://localhost:8080
Если вам нужно попасть внутрь контейнера, используйте команду exec
:
# войти в контейнер в интерактивном режиме
$ docker exec -it <container id> /bin/bash
Проверка
Чтобы проверить ваше приложение, используйте публичный порт, к которому привязан контейнер:
$ docker ps
# пример вывода
id image command ... ports
ecce33b30ebf <your username>/node-web-app:latest npm start ... 49160->8080
В примере выше docker связал порт 8080
внутри контейнера с портом 49160
на вашем компьютере.
Вы можете сделать запрос к вашему приложению с помощью утилиты curl
(установите ее, если требуется с помощью команды: sudo apt-get install curl
):
$ curl -i localhost:49160
http/1.1 200 ok
x-powered-by: express
content-type: text/html; charset=utf-8
content-length: 12
etag: w/"c-m6twob/y57lesdjquheb1p/qtv0"
date: mon, 13 nov 2017 20:53:59 gmt
connection: keep-alive
hello world
Надеемся, что эта инструкция помогла вам настроить и запустить простое приложение Node.js с помощью Docker.
Вы можете найти больше информации о Docker и Node.js в docker по следующим ссылкам: