Докеризация веб-приложения 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 по следующим ссылкам:

Вверх