|
| 1 | +--- |
| 2 | +title: Докеризация веб-приложения Node.js |
| 3 | +layout: docs.hbs |
| 4 | +--- |
| 5 | + |
| 6 | +# Докеризация веб-приложения Node.js |
| 7 | + |
| 8 | +Цель этого примера — показать, как поместить приложение Node.js в Docker-контейнер. |
| 9 | +Это руководство предназначено для разработки, но не для прямого использования в |
| 10 | +продакшене. Мы также предполагаем, что вы успешно [установили Docker](https://docs.docker.com/install/) на свой ПК и |
| 11 | +имеете базовое представление о структуре Node.js приложения. |
| 12 | + |
| 13 | +В перовой части руководства мы создадим простое Node.js приложение, затем |
| 14 | +мы сделаем для него docker-образ, и, наконец, инициализируем экземпляр контейнера |
| 15 | +из этого образа. |
| 16 | + |
| 17 | +Docker позволяет вам упаковать приложение вместе с его окружением и всеми зависимостями в |
| 18 | +"коробку", называемую контейнером. Обычно контейнер состоит из приложения, работающего в |
| 19 | +упрощенной версии ОС Linux. Образ — это шаблон для контейнера, контейнер — это работающий |
| 20 | +экземпляр образа. |
| 21 | + |
| 22 | +## Создание приложения Node.js |
| 23 | + |
| 24 | +Для начала создадим новую директорию, в которой будут находиться все файлы приложения. В этой директории |
| 25 | +создайте файл `package.json`, в котором описано приложение и его зависимости: |
| 26 | + |
| 27 | +```json |
| 28 | +{ |
| 29 | + "name": "docker_web_app", |
| 30 | + "version": "1.0.0", |
| 31 | + "description": "node.js on docker", |
| 32 | + "author": "first last <first.last@example.com>", |
| 33 | + "main": "server.js", |
| 34 | + "scripts": { |
| 35 | + "start": "node server.js" |
| 36 | + }, |
| 37 | + "dependencies": { |
| 38 | + "express": "^4.16.1" |
| 39 | + } |
| 40 | +} |
| 41 | +``` |
| 42 | + |
| 43 | +После создания файла `package.json`, выполните команду `npm install`. Если вы используете `npm` |
| 44 | +версии 5 или выше, это также создаст файл `package-lock.json`, который будет скопирован в ваш docker-образ. |
| 45 | + |
| 46 | +Далее создайте файл `server.js`, который определяет веб-приложение на основе |
| 47 | +фреймворка [Express.js](https://expressjs.com/): |
| 48 | + |
| 49 | +```javascript |
| 50 | +'use strict'; |
| 51 | + |
| 52 | +const express = require('express'); |
| 53 | + |
| 54 | +// константы |
| 55 | +const port = 8080; |
| 56 | +const host = '0.0.0.0'; |
| 57 | + |
| 58 | +// приложение |
| 59 | +const app = express(); |
| 60 | +app.get('/', (req, res) => { |
| 61 | + res.send('hello world\n'); |
| 62 | +}); |
| 63 | + |
| 64 | +app.listen(port, host); |
| 65 | +console.log(`running on http://${host}:${port}`); |
| 66 | +``` |
| 67 | + |
| 68 | +Далее мы рассмотрим, как можно запускать это приложение внутри Docker-контейнера, |
| 69 | +используя официальный образ Docker'а. Сначала давайте создадим Docker-образ с нашим приложением. |
| 70 | + |
| 71 | +## Создание файла Dockerfile |
| 72 | + |
| 73 | +Создайте пустой файл с именем `Dockerfile`: |
| 74 | + |
| 75 | +```markup |
| 76 | +touch Dockerfile |
| 77 | +``` |
| 78 | + |
| 79 | +Откройте этот файл в вашем любимом текстовом редакторе. |
| 80 | + |
| 81 | +Первое, что нам надо сделать — определить базовый образ, |
| 82 | +который будет взят за основу. Мы будем использовать образ `node` последней версии |
| 83 | +LTS* (версии с долгосрочной поддержкой) — `10`, |
| 84 | +доступный на [Docker Hub](https://hub.docker.com/). |
| 85 | + |
| 86 | +\* Прим. переводчика: на момент написания статьи. |
| 87 | + |
| 88 | +```docker |
| 89 | +FROM node:10 |
| 90 | +``` |
| 91 | + |
| 92 | +Затем создадим директорию для кода приложения внутри образа. |
| 93 | +Это будет рабочая папка для вашего приложения. |
| 94 | + |
| 95 | +```docker |
| 96 | +# создание директории приложения |
| 97 | +WORKDIR /usr/src/app |
| 98 | +``` |
| 99 | + |
| 100 | +Образ, который мы используем, поставляется с уже предустановленным Node.js и NPM. |
| 101 | +Поэтому мы можем просто установить зависимости приложения с помощью команд `npm`. |
| 102 | +Обратите внимание, если вы используете `npm` 4 или ниже, файл `package-lock.json` |
| 103 | +не будет сгенерирован. |
| 104 | + |
| 105 | +```docker |
| 106 | +# установка зависимостей |
| 107 | +# символ астериск ("*") используется для того чтобы по возможности |
| 108 | +# скопировать оба файла: package.json и package-lock.json |
| 109 | +COPY package*.json ./ |
| 110 | +
|
| 111 | +RUN npm install |
| 112 | +# Если вы создаете сборку для продакшн |
| 113 | +# RUN npm ci --only=production |
| 114 | +``` |
| 115 | + |
| 116 | +Обратите внимание, что вместо того, чтобы копировать весь рабочий каталог, |
| 117 | +мы копируем только файл `package.json`. Это позволяет воспользоваться |
| 118 | +кэшированием слоев в Docker. [Здесь](http://bitjudo.com/blog/2014/03/13/building-efficient-dockerfiles-node-dot-js/) |
| 119 | +bitJudo дал хорошее объяснение того, как это работает. Более того, |
| 120 | +команда `npm ci`, указанная в комментарии, позволяет создавать |
| 121 | +более быстрые, надежные, воспроизводимые сборки для продакшена. |
| 122 | +вы можете прочесть больше об этой команде [здесь](https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable). |
| 123 | + |
| 124 | +Чтобы отправить исходный код вашего приложения внутрь Docker-образа, |
| 125 | +используйте директиву `COPY`. |
| 126 | + |
| 127 | +```docker |
| 128 | +# копируем исходный код |
| 129 | +COPY . . |
| 130 | +``` |
| 131 | + |
| 132 | +Сервер привязан к `8080` порту, поэтому мы будем использовать |
| 133 | +инструкцию `EXPOSE`, чтобы проинформировать Docker о том, что в контейнере |
| 134 | +имеется приложение, прослушивающее этот порт. |
| 135 | + |
| 136 | +```docker |
| 137 | +EXPOSE 8080 |
| 138 | +``` |
| 139 | + |
| 140 | +Последняя, но не менее важная команда `CMD` содержит все необходимые |
| 141 | +переменные среды и инструкции для запуска приложения. |
| 142 | +Здесь мы просто используем `node server.js` для запуска. |
| 143 | + |
| 144 | +```docker |
| 145 | +CMD [ "node", "server.js" ] |
| 146 | +``` |
| 147 | + |
| 148 | +Ваш `Dockerfile` теперь должен выглядеть примерно так: |
| 149 | + |
| 150 | +```docker |
| 151 | +FROM node:10 |
| 152 | +
|
| 153 | +# создание директории приложения |
| 154 | +WORKDIR /usr/src/app |
| 155 | +
|
| 156 | +# установка зависимостей |
| 157 | +# символ астериск ("*") используется для того чтобы по возможности |
| 158 | +# скопировать оба файла: package.json и package-lock.json |
| 159 | +COPY package*.json ./ |
| 160 | +
|
| 161 | +RUN npm install |
| 162 | +# Если вы создаете сборку для продакшн |
| 163 | +# RUN npm ci --only=production |
| 164 | +
|
| 165 | +# копируем исходный код |
| 166 | +COPY . . |
| 167 | +
|
| 168 | +EXPOSE 8080 |
| 169 | +CMD [ "node", "server.js" ] |
| 170 | +``` |
| 171 | + |
| 172 | +## Файл .dockerignore |
| 173 | + |
| 174 | +Создайте файл `.dockerignore` в той же директории, что и `Dockerfile`, |
| 175 | +со следующим содержимым: |
| 176 | + |
| 177 | +``` |
| 178 | +node_modules |
| 179 | +npm-debug.log |
| 180 | +``` |
| 181 | + |
| 182 | +Это предотвратит копирование локально установленных модулей и дебаг-логов |
| 183 | +в Docker-образ и возможную перезапись модулей установленных внутри образа. |
| 184 | + |
| 185 | +## Сборка образа |
| 186 | + |
| 187 | +Перейдите в директорию, в которой находится ваш `Dockerfile` и запустите |
| 188 | +следующую команду, чтобы собрать Docker-образ. Флаг `-t` позволяет поставить |
| 189 | +тэг к вашему образу, чтобы его позже было проще найти при помощи команды |
| 190 | +`docker images`: |
| 191 | + |
| 192 | +```bash |
| 193 | +docker build -t <your username>/node-web-app . |
| 194 | +``` |
| 195 | + |
| 196 | +Созданный образ теперь будет отображаться в списке всех образов: |
| 197 | + |
| 198 | +```bash |
| 199 | +$ docker images |
| 200 | + |
| 201 | +# пример вывода |
| 202 | +repository tag id created |
| 203 | +node 10 1934b0b038d1 5 days ago |
| 204 | +<your username>/node-web-app latest d64d3505b0d2 1 minute ago |
| 205 | +``` |
| 206 | + |
| 207 | +## Запуск образа |
| 208 | + |
| 209 | +Запуск образа с флагом `-d` позволяет контейнеру работать в фоновом режиме. |
| 210 | +Флаг `-p` перенаправляет публичный порт на приватный порт внутри контейнера. |
| 211 | +Запустите образ, который вы ранее создали: |
| 212 | + |
| 213 | +```bash |
| 214 | +docker run -p 49160:8080 -d <your username>/node-web-app |
| 215 | +``` |
| 216 | + |
| 217 | +Отобразите логи вашего приложения: |
| 218 | + |
| 219 | +```bash |
| 220 | +# отобразить все контейнеры, чтобы получить id нужного нам |
| 221 | +$ docker ps |
| 222 | + |
| 223 | +# отобразить логи |
| 224 | +$ docker logs <container_id> |
| 225 | + |
| 226 | +# пример логов |
| 227 | +running on http://localhost:8080 |
| 228 | +``` |
| 229 | + |
| 230 | +Если вам нужно попасть внутрь контейнера, используйте команду `exec`: |
| 231 | + |
| 232 | +```bash |
| 233 | +# войти в контейнер в интерактивном режиме |
| 234 | +$ docker exec -it <container id> /bin/bash |
| 235 | +``` |
| 236 | + |
| 237 | +## Проверка |
| 238 | + |
| 239 | +Чтобы проверить ваше приложение, используйте публичный порт, к которому привязан контейнер: |
| 240 | + |
| 241 | +```bash |
| 242 | +$ docker ps |
| 243 | + |
| 244 | +# пример вывода |
| 245 | +id image command ... ports |
| 246 | +ecce33b30ebf <your username>/node-web-app:latest npm start ... 49160->8080 |
| 247 | +``` |
| 248 | + |
| 249 | +В примере выше docker связал порт `8080` внутри контейнера с портом `49160` |
| 250 | +на вашем компьютере. |
| 251 | + |
| 252 | +Вы можете сделать запрос к вашему приложению с помощью утилиты `curl` |
| 253 | +(установите ее, если требуется с помощью команды: `sudo apt-get install curl`): |
| 254 | + |
| 255 | +```bash |
| 256 | +$ curl -i localhost:49160 |
| 257 | + |
| 258 | +http/1.1 200 ok |
| 259 | +x-powered-by: express |
| 260 | +content-type: text/html; charset=utf-8 |
| 261 | +content-length: 12 |
| 262 | +etag: w/"c-m6twob/y57lesdjquheb1p/qtv0" |
| 263 | +date: mon, 13 nov 2017 20:53:59 gmt |
| 264 | +connection: keep-alive |
| 265 | + |
| 266 | +hello world |
| 267 | +``` |
| 268 | + |
| 269 | +Надеемся, что эта инструкция помогла вам настроить и запустить простое приложение |
| 270 | +Node.js с помощью Docker. |
| 271 | + |
| 272 | +Вы можете найти больше информации о Docker и Node.js в docker по следующим ссылкам: |
| 273 | + |
| 274 | +* [Официальный docker-образ Node.js](https://hub.docker.com/_/node/) |
| 275 | +* [Руководство по лучшим практикам Node.js в Docker](https://github.com/nodejs/docker-node/blob/master/docs/bestpractices.md) |
| 276 | +* [Официальная документация Docker](https://docs.docker.com/) |
| 277 | +* [Тэг Docker на stack overflow](https://stackoverflow.com/questions/tagged/docker) |
| 278 | +* [Канал Docker на reddit](https://reddit.com/r/docker) |
0 commit comments