Создание приложения Node.js с помощью Docker [Краткое руководство]

Введение

В этом обучающем руководстве мы создадим образ приложения для статического сайта, который использует веб-фреймворки Express и Bootstrap. Затем вы создадите контейнер с использованием этого образа, разместите его в Docker Hub и используете его для сборки другого контейнера, продемонстрировав способ воссоздания и масштабирования вашего приложения.

Более подробные указания с детальными разъяснениями каждого этапа приведены в обучающем руководстве Создание приложения Node.js с помощью Docker.

Предварительные требования

Для данного обучающего руководства вам потребуется следующее:

  • Пользователь sudo на сервере или в локальной среде.
  • Docker.
  • Node.js и npm.
  • Учетная запись Docker Hub.

Шаг 1 — Установка зависимостей вашего приложения

Вначале создайте для вашего проекта директорию в домашней директории пользователя без привилегий root:

  • mkdir node_project

Перейдите в эту директорию:

  • cd node_project

Это будет корневая директория проекта.

Затем создайте файл package.json с зависимостями вашего проекта:

  • nano package.json

Добавьте в файл следующую информацию о проекте; обязательно измените данные автора собственным именем и контактными данными:

~/node_project/package.json

{   "name": "nodejs-image-demo",   "version": "1.0.0",   "description": "nodejs image demo",   "author": "Sammy the Shark <[email protected]>",   "license": "MIT",   "main": "app.js",   "scripts": {     "start": "node app.js",     "test": "echo "Error: no test specified" && exit 1"   },   "keywords": [     "nodejs",     "bootstrap",     "express"   ],   "dependencies": {     "express": "^4.16.4"   } } 

Установите зависимости вашего проекта:

  • npm install

Шаг 2 — Создание файлов приложения

Мы создадим сайт, который предоставляет пользователям данные об акулах.

Откройте файл app.js в главной директории проекта, чтобы определить маршруты проекта:

  • nano app.js

Добавьте в файл следующее содержание, чтобы создать приложение Express и объекты Router, определите базовую директорию, порт и хост как переменные, задайте маршруты и смонтируйте промежуточное ПО router вместе со статическими ресурсами приложения:

~/node_project/app.js

var express = require("express"); var app = express(); var router = express.Router();  var path = __dirname + '/views/';  // Constants const PORT = 8080; const HOST = '0.0.0.0';  router.use(function (req,res,next) {   console.log("/" + req.method);   next(); });  router.get("/",function(req,res){   res.sendFile(path + "index.html"); });  router.get("/sharks",function(req,res){   res.sendFile(path + "sharks.html"); });  app.use(express.static(path)); app.use("/", router);  app.listen(8080, function () {   console.log('Example app listening on port 8080!') }) 

Далее добавим в приложение статичный контент. Создайте директорию views:

  • mkdir views

Откройте файл index.html:

  • nano views/index.html

Добавьте в файл следующий код, который импортирует Boostrap и создаст компонент jumbotron со ссылкой на страницу подробной информации о sharks.html:

~/node_project/views/index.html

<!DOCTYPE html> <html lang="en">    <head>       <title>About Sharks</title>       <meta charset="utf-8">       <meta name="viewport" content="width=device-width, initial-scale=1">       <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">       <link href="css/styles.css" rel="stylesheet">       <link href='https://fonts.googleapis.com/css?family=Merriweather:400,700' rel='stylesheet' type='text/css'>       <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>       <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>    </head>    <body>       <nav class="navbar navbar-inverse navbar-static-top">          <div class="container">             <div class="navbar-header">                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">                <span class="sr-only">Toggle navigation</span>                <span class="icon-bar"></span>                <span class="icon-bar"></span>                <span class="icon-bar"></span>                </button>                <a class="navbar-brand" href="#">Everything Sharks</a>             </div>             <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">                <ul class="nav navbar-nav mr-auto">                   <li class="active"><a href="/">Home</a></li>                   <li><a href="/sharks">Sharks</a></li>                </ul>             </div>          </div>       </nav>       <div class="jumbotron">          <div class="container">             <h1>Want to Learn About Sharks?</h1>             <p>Are you ready to learn about sharks?</p>             <br>             <p><a class="btn btn-primary btn-lg" href="/sharks" role="button">Get Shark Info</a></p>          </div>       </div>       <div class="container">          <div class="row">             <div class="col-md-6">                <h3>Not all sharks are alike</h3>                <p>Though some are dangerous, sharks generally do not attack humans. Out of the 500 species known to researchers, only 30 have been known to attack humans.</p>             </div>             <div class="col-md-6">                <h3>Sharks are ancient</h3>                <p>There is evidence to suggest that sharks lived up to 400 million years ago.</p>             </div>          </div>       </div>    </body> </html> 

Затем откройте файл с именем sharks.html:

  • nano views/sharks.html

Добавьте следующий код, который импортирует Bootstrap и пользовательскую таблицу стилей и предлагает пользователям подробную информацию об определенных акулах:

~/node_project/views/sharks.html

<!DOCTYPE html> <html lang="en">    <head>       <title>About Sharks</title>       <meta charset="utf-8">       <meta name="viewport" content="width=device-width, initial-scale=1">       <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">       <link href="css/styles.css" rel="stylesheet">       <link href='https://fonts.googleapis.com/css?family=Merriweather:400,700' rel='stylesheet' type='text/css'>       <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>       <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>    </head>    <nav class="navbar navbar-inverse navbar-static-top">       <div class="container">          <div class="navbar-header">             <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">             <span class="sr-only">Toggle navigation</span>             <span class="icon-bar"></span>             <span class="icon-bar"></span>             <span class="icon-bar"></span>             </button>             <a class="navbar-brand" href="#">Everything Sharks</a>          </div>          <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">             <ul class="nav navbar-nav mr-auto">                <li><a href="/">Home</a></li>                <li class="active"><a href="/sharks">Sharks</a></li>             </ul>          </div>       </div>    </nav>    <div class="jumbotron text-center">       <h1>Shark Info</h1>    </div>    <div class="container">       <div class="row">          <div class="col-md-6">             <p>             <div class="caption">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.</div>             <img src="https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg" alt="Sawshark">             </p>          </div>          <div class="col-md-6">             <p>             <div class="caption">Other sharks are known to be friendly and welcoming!</div>             <img src="https://assets.digitalocean.com/articles/docker_node_image/sammy.png" alt="Sammy the Shark">             </p>          </div>       </div>     </div>    </body> </html> 

Наконец, создайте пользовательскую таблицу стилей CSS, на которую вы разместили ссылки в файлах index.html и sharks.html. Для этого вначале создайте папку css в директории views:

  • mkdir views/css

Откройте таблицу стилей и добавьте следующий код, который задает желаемые цвет и шрифт для наших страниц:

~/node_project/views/css/styles.css

.navbar {         margin-bottom: 0; }  body {         background: #020A1B;         color: #ffffff;         font-family: 'Merriweather', sans-serif; } h1, h2 {         font-weight: bold; } p {         font-size: 16px;         color: #ffffff; }   .jumbotron {         background: #0048CD;         color: white;         text-align: center; } .jumbotron p {         color: white;         font-size: 26px; }  .btn-primary {         color: #fff;         text-color: #000000;         border-color: white;         margin-bottom: 5px; }  img, video, audio {         margin-top: 20px;         max-width: 80%; }  div.caption: {         float: left;         clear: both; } 

Запустите приложение:

  • npm start

Откройте в браузере адрес http://your_server_ip:8080 или localhost:8080, если вы работаете локально. Вы увидите следующую начальную страницу:

Начальная страница приложения

Нажмите кнопку Get Shark Info (Получить информацию об акулах). Вы увидите следующую информационную страницу:

Страница информации об акулах

Ваше приложение запущено и работает. Когда вы будете готовы, покиньте сервер, нажав CTRL+C.

Шаг 3 — Создание файла Dockerfile

Создайте файл Dockerfile в корневой директории вашего проекта:

  • nano Dockerfile

Добавьте в файл следующий код:

~/node_project/Dockerfile

 FROM node:10-alpine  RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app  WORKDIR /home/node/app  COPY package*.json ./  USER node  RUN npm install  COPY --chown=node:node . .  EXPOSE 8080  CMD [ "node", "app.js" ] 

Этот файл Dockerfile использует базовый образ alpine и обеспечивает принадлежность файлов приложения пользователю node без привилегий root, который предоставляется по умолчанию образом Docker Node.

Затем добавьте модули локального узла, журналы npm, файл Dockerfile и .dockerignore в ваш файл .dockerignore:

~/node_project/.dockerignore

node_modules npm-debug.log Dockerfile .dockerignore 

Соберите образ приложения, используя команду docker build:

  • docker build -t your_dockerhub_username/nodejs-image-demo .

Символ . указывает, что контекст команды build — текущая директория.

Проверьте образы:

  • docker images

Результат будет выглядеть следующим образом:

OutputREPOSITORY                                         TAG                 IMAGE ID            CREATED             SIZE your_dockerhub_username/nodejs-image-demo          latest              1c723fb2ef12        8 seconds ago       895MB node                                               10                  f09e7c96b6de        17 hours ago        893MB 

Запустите следующую команду для сборки контейнера с использованием этого образа:

  • docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo

Проверьте список работающих контейнеров с помощью docker ps:

  • docker ps

Результат будет выглядеть следующим образом:

OutputCONTAINER ID        IMAGE                                                   COMMAND             CREATED             STATUS              PORTS                  NAMES e50ad27074a7        your_dockerhub_username/nodejs-image-demo               "npm start"         8 seconds ago       Up 7 seconds        0.0.0.0:80->8080/tcp   nodejs-image-demo 

При работающем контейнере вы можете открыть свое приложение, указав в браузере адрес http://your_server_ip или localhost. После этого откроется начальная страница вашего приложения:

Начальная страница приложения

Вы создали образ приложения, и теперь можете опубликовать его в Docker Hub для будущего использования.

Шаг 4 — Использование хранилища для работы с образами

Прежде всего для размещения образа следует войти в учетную запись Docker Hub:

  • docker login -u your_dockerhub_username -p your_dockerhub_password

При входе в домашней директории вашего пользователя будет создан файл ~/.docker/config.json с вашими учетными данными Docker Hub.

Разместите образ, используя свое имя пользователя вместо your_dockerhub_username:

  • docker push your_dockerhub_username/nodejs-image-demo

Если хотите, вы можете протестировать утилиту реестра образов, уничтожив существующие контейнер приложения и образ, а затем воссоздав их.

Вначале перечислите запущенные контейнеры:

  • docker ps

Результат будет выглядеть следующим образом:

OutputCONTAINER ID        IMAGE                                       COMMAND             CREATED             STATUS              PORTS                  NAMES e50ad27074a7        your_dockerhub_username/nodejs-image-demo   "npm start"         3 minutes ago       Up 3 minutes        0.0.0.0:80->8080/tcp   nodejs-image-demo 

Остановите запущенный контейнер приложения, используя идентификатор CONTAINER ID, показанный в результатах. Обязательно замените выделенный ниже идентификатор собственным идентификатором CONTAINER ID:

  • docker stop e50ad27074a7

Перечислите все образы, используя флаг -a:

  • docker images -a

Вы увидите следующие результаты с именем образа your_dockerhub_username/nodejs-image-demo, а также образом узла и другими образами из вашей сборки:

OutputREPOSITORY                                           TAG                 IMAGE ID            CREATED             SIZE your_dockerhub_username/nodejs-image-demo            latest              1c723fb2ef12        7 minutes ago       895MB <none>                                               <none>              e039d1b9a6a0        7 minutes ago       895MB <none>                                               <none>              dfa98908c5d1        7 minutes ago       895MB <none>                                               <none>              b9a714435a86        7 minutes ago       895MB <none>                                               <none>              51de3ed7e944        7 minutes ago       895MB <none>                                               <none>              5228d6c3b480        7 minutes ago       895MB <none>                                               <none>              833b622e5492        8 minutes ago       893MB <none>                                               <none>              5c47cc4725f1        8 minutes ago       893MB <none>                                               <none>              5386324d89fb        8 minutes ago       893MB <none>                                               <none>              631661025e2d        8 minutes ago       893MB node                                                 10                  f09e7c96b6de        17 hours ago        893MB 

Удалите остановленный контейнер и все образы, включая неиспользуемые или недействительные образы, с помощью следующей команды:

  • docker system prune -a

Удалив все образы и контейнеры, вы можете извлечь образ приложения из Docker Hub:

  • docker pull your_dockerhub_username/nodejs-image-demo

Еще раз перечислите образы:

  • docker images

Вы увидите образ вашего приложения:

OutputREPOSITORY                                     TAG                 IMAGE ID            CREATED             SIZE your_dockerhub_username/nodejs-image-demo      latest              1c723fb2ef12        11 minutes ago      895MB 

Теперь вы можете воссоздать свой контейнер, используя команду из шага 3:

  • docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo

Перечислите запущенные контейнеры:

  • docker ps
OutputCONTAINER ID        IMAGE                                                   COMMAND             CREATED             STATUS              PORTS                  NAMES f6bc2f50dff6        your_dockerhub_username/nodejs-image-demo               "npm start"         4 seconds ago       Up 3 seconds        0.0.0.0:80->8080/tcp   nodejs-image-demo 

Посетите http://your_server_ip или localhost еще раз для просмотра работающих приложений.

Другие обучающие руководства

Ниже представлены ссылки на более подробные материалы, связанные с настоящим обучающим руководством:

  • Установка Docker Compose в Ubuntu 18.04.
  • Выделение ресурсов и управление дистанционными хостами Docker с Docker Machine в Ubuntu 18.04.
  • Общий доступ к данным контейнеров Docker
  • Обеспечение общего доступа к данным контейнера и хоста Docker.

Также вы можете пройти более длинную серию обучающих руководств От контейнеров к Kubernetes с Node.js, на основе которой адаптировано это обучающее руководство.

Кроме того, вы можете посмотреть в Docker нашу полную библиотеку ресурсов Docker.