One place for hosting & domains

      приложения

      Создание приложения Node.js с помощью Docker


      Введение

      Платформа Docker позволяет разработчикам упаковывать и запускать приложения как контейнеры. Контейнер — это изолированный процесс, выполняемый в общей операционной системе, и представляющий из себя облегченную альтернативу виртуальным машинам. Хотя концепция контейнеров существует уже давно, обеспечиваемые ими преимущества изоляции процессов и стандартизации среды становятся все более важными по мере того, как все больше разработчиков начинают использовать распределенные архитектуры приложений.

      При создании и масштабировании приложений Docker вначале обычно создается образ приложения, который можно запустить в контейнере. Образ включает код приложения, библиотеки, файлы конфигурации, переменные среды и исполняемый модуль. Благодаря использованию образа среда в контейнере стандартизирована и содержит только то, что необходимо для сборки и выполнения приложения.

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

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

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

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

      Чтобы создать образ, нужно сначала выполнить сборку файлов приложения, а затем скопировать их в контейнер. Эти файлы будут включать статический контент, код и зависимости вашего приложения.

      Создайте для вашего проекта каталог в начальном каталоге пользователя, не являющегося пользователем root. Мы назовем наш проект node_project, но вы можете заменить это название на другое:

      Перейдите в этот каталог:

      Это будет корневой каталог проекта.

      Далее создайте файл package.json с зависимостями пакета и другой идентификационной информацией. Откройте файл с помощью nano или своего любимого редактора:

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

      ~/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",
        "keywords": [
          "nodejs",
          "bootstrap",
          "express"
        ],
        "dependencies": {
          "express": "^4.16.4"
        }
      }
      

      Файл содержит название проекта, автора и лицензию, по которой он распространяется. Npm рекомендует использовать краткие и содержательные названия проектов и избегать использования дубликатов в реестре npm. Мы указали лицензию MIT в поле license, что дает нам право на свободное использование и распространение кода приложения.

      Кроме того в файле указано следующее:

      • "main": точка входа приложения, app.js. Затем вы создадите этот файл.
      • "dependencies": зависимости проекта — в данном случае, Express 4.16.4 или более поздняя версия.

      Хотя этот файл не указан в хранилище, вы можете добавить его в соответствии со следующими указаниями по добавлению хранилища в файл package.json. Это хорошее дополнение, если вы задаете версии своего приложения.

      Сохраните и закройте файл, когда закончите вносить изменения.

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

      Пакеты, перечисленные вами в файле package.json, будут установлены в каталог вашего проекта.

      Теперь можно перейти к сборке файлов приложения.

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

      Мы создадим сайт, который предоставляет пользователям данные об акулах. В нашем приложении будет основная точка входа, app.js, и каталог views, где будут находиться статичные активы проекта. Начальная страница index.html будет предоставлять пользователям предварительную информацию и ссылку на страницу с более подробной информацией об акулах, sharks.html. В каталоге views мы создадим начальную страницу и файл sharks.html.

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

      Первая часть файла будет создавать приложение Express и объекты Router, а также определять базовый каталог и порт как постоянные величины:

      ~/node_project/app.js

      const express = require('express');
      const app = express();
      const router = express.Router();
      
      const path = __dirname + '/views/';
      const port = 8080;
      

      Функция require загружает модуль express, который мы используем для создания объектов app и router. Объект router будет выполнять функцию маршрутизации в приложении. Определяя маршруты методов HTTP, мы будем добавлять их в этот объект, чтобы определить, как наше приложение будет обрабатывать запросы.

      В этом разделе файла также содержатся две константы, path и port:

      • path: определяет базовый каталог, в данном случае подкаталог views в каталоге текущего проекта.
      • port: указывает приложению прослушивать и выполнить привязку к порту 8080.

      Затем настройте маршруты для приложения с помощью объекта router:

      ~/node_project/app.js

      ...
      
      router.use(function (req,res,next) {
        console.log("https://www.digitalocean.com/" + req.method);
        next();
      });
      
      router.get("https://www.digitalocean.com/", function(req,res){
        res.sendFile(path + 'index.html');
      });
      
      router.get("https://www.digitalocean.com/sharks", function(req,res){
        res.sendFile(path + 'sharks.html');
      });
      

      Функция router.use загружает промежуточную функцию, которая будет регистрировать запросы маршрутизатора и передавать их на маршруты приложения. Они определяются в последующих функциях, который указывают, что запрос GET базового URL проекта должен возвращать страницу index.html, а запрос GET для маршрута /sharks должен возвращать страницу sharks.html.

      Наконец, смонтируйте промежуточный уровень router и статичные ресурсы приложения и укажите приложению прослушивать порт 8080:

      ~/node_project/app.js

      ...
      
      app.use(express.static(path));
      app.use("https://www.digitalocean.com/", router);
      
      app.listen(port, function () {
        console.log('Example app listening on port 8080!')
      })
      

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

      ~/node_project/app.js

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

      Сохраните файл и закройте его после завершения.

      Далее добавим в приложение статичный контент. Вначале создадим каталог 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://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
          <link href="https://www.digitalocean.com/css/styles.css" rel="stylesheet">
          <link href="https://fonts.googleapis.com/css?family=Merriweather:400,700" rel="stylesheet" type="text/css">
      </head>
      
      <body>
          <nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md">
              <div class="container">
                  <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span>
                  </button> <a class="navbar-brand" href="https://www.digitalocean.com/#">Everything Sharks</a>
                  <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                      <ul class="nav navbar-nav mr-auto">
                          <li class="active nav-item"><a href="https://www.digitalocean.com/" class="nav-link">Home</a>
                          </li>
                          <li class="nav-item"><a href="https://www.digitalocean.com/sharks" class="nav-link">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="https://www.digitalocean.com/sharks" role="button">Get Shark Info</a>
                  </p>
              </div>
          </div>
          <div class="container">
              <div class="row">
                  <div class="col-lg-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-lg-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>
      

      Навигационная панель верхнего уровня позволяет пользователям переключаться между страницами Home и Sharks. В субкомпоненте navbar-nav мы используем active класс Bootstrap, чтобы указать пользователю текущую страницу. Также мы указали маршруты наших статичных страниц, что соответствует маршрутам, определенным в файле app.js:

      ~/node_project/views/index.html

      ...
      <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
         <ul class="nav navbar-nav mr-auto">
            <li class="active nav-item"><a href="https://www.digitalocean.com/" class="nav-link">Home</a>
            </li>
            <li class="nav-item"><a href="https://www.digitalocean.com/sharks" class="nav-link">Sharks</a>
            </li>
         </ul>
      </div>
      ...
      

      Кроме того, мы создали ссылку на страницу с информацией об акулах в нашей кнопке jumbotron:

      ~/node_project/views/index.html

      ...
      <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="https://www.digitalocean.com/sharks" role="button">Get Shark Info</a>
            </p>
         </div>
      </div>
      ...
      

      Также в заголовке имеется ссылка на пользовательскую таблицу стилей:

      ~/node_project/views/index.html

      ...
      <link href="https://www.digitalocean.com/css/styles.css" rel="stylesheet">
      ...
      

      Мы создадим эту таблицу стилей в конце данного шага.

      Сохраните файл и закройте его после завершения.

      Подготовив начальную страницу приложения, мы можем создать страницу с информацией об акулах, 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://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
          <link href="https://www.digitalocean.com/css/styles.css" rel="stylesheet">
          <link href="https://fonts.googleapis.com/css?family=Merriweather:400,700" rel="stylesheet" type="text/css">
      </head>
      <nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md">
          <div class="container">
              <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span>
              </button> <a class="navbar-brand" href="https://www.digitalocean.com/">Everything Sharks</a>
              <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                  <ul class="nav navbar-nav mr-auto">
                      <li class="nav-item"><a href="https://www.digitalocean.com/" class="nav-link">Home</a>
                      </li>
                      <li class="active nav-item"><a href="https://www.digitalocean.com/sharks" class="nav-link">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-lg-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-lg-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>
      
      </html>
      

      В этом файле мы снова используем active класс для индикации текущей страницы.

      Сохраните файл и закройте его после завершения.

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

      Откройте таблицу стилей:

      • nano views/css/styles.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;
      }
      

      В дополнение к настройке шрифта и цвета этот файл также ограничивает размер изображений, указывая max-width 80%. Благодаря этому они не будут занимать больше места на странице, чем нам бы хотелось.

      Сохраните файл и закройте его после завершения.

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

      Если вы следовали указаниям руководства по первоначальной настройке сервера, указанного в предварительных условиях, у вас установлен активный брандмауэр, на котором разрешен только трафик SSH. Чтобы разрешить трафик на порт 8080, выполните команду:

      Чтобы запустить приложение, перейдите в каталог root вашего проекта:

      Запустите приложение с node app.js:

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

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

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

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

      Ваше приложение запущено и работает. Когда вы будете готовы, покиньте сервер, нажав CTRL+C. Теперь мы можем перейти к созданию файла Dockerfile, который позволит нам воссоздать и масштабировать это приложение, когда это потребуется.

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

      Ваш файл Dockerfile указывает, что будет включено в контейнер приложения при его выполнении. Использование Dockerfile позволяет определить среду контейнера и избежать расхождений с зависимостями и версиями модуля исполнения.

      В соответствии с этими указаниями по построению оптимизированных контейнеров, мы сделаем наше изображение максимально эффективным, минимизируем количество слоев образа и воссоздадим файлы нашего приложения и статичный контент.

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

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

      Мы будем использовать образ node:10-alpine, поскольку на момент написания это рекомендуемая версия LTS Node.js. Образ alpine является производным проекта Alpine Linux, и это помогает уменьшить размер образа. Дополнительную информацию о том, стоит ли использовать образ alpine в вашем проекте, можно получить в полном обсуждении в разделе *Image Variants *(Варианты образов) на странице образов Docker Hub Node.

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

      ~/node_project/Dockerfile

      FROM node:10-alpine
      

      Этот образ включает Node.js и npm. Каждый Dockerfile должен начинаться с команды FROM.

      По умолчанию образ Docker Node включает пользователя node, не являющегося пользователем root, которого вы можете использовать, чтобы контейнер вашего приложения не запускался как root. Для безопасности рекомендуется не запускать контейнеры как пользователь root и ограничить возможности контейнера теми, которые необходимы для запуска его процессов. Мы используем домашний каталог пользователя node как рабочий каталог нашего приложения и зададим его как пользователя внутри контейнера. Дополнительную информацию об оптимальной практике работы с образом Docker Node можно найти в этом руководстве по передовым практикам.

      Для тонкой настройки разрешений кода приложения в контейнере создадим подкаталог node_modules в каталоге /home/node вместе с каталогом app. Создание этих каталогов обеспечит наличие желаемых разрешений, что будет важно при создании локальных модулей узла в контейнере с помощью команды npm install. В дополнение к созданию этих каталогов мы зададим пользователя node как их владельца:

      ~/node_project/Dockerfile

      ...
      RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
      

      Дополнительную информацию о полезности консолидации команд RUN можно найти в этой дискуссии об управлении слоями контейнеров.

      Далее установите рабочий каталог приложения /home/node/app:

      ~/node_project/Dockerfile

      ...
      WORKDIR /home/node/app
      

      Если WORKDIR не задан, Docker создаст рабочий каталог по умолчанию, и поэтому лучше явно задать его.

      Далее скопируйте файлы package.json и package-lock.json (для npm 5+):

      ~/node_project/Dockerfile

      ...
      COPY package*.json ./
      

      Добавление этой команды COPY перед запуском npm install или копированием кода приложения позволяет использовать механизм кэширования Docker. На каждом этапе сборки Docker проверяет наличие кэшированного слоя для этой конкретной команды. Если мы изменим файл package.json, этот слой будет построен заново, но если мы не будем его менять, данная команда позволит Docker использовать существующий слой образа и пропустить повторную установку модулей узла.

      Чтобы все файлы приложения принадлежали пользователю node, не являющемуся пользователем root, включая содержимое каталога node_modules, переключитесь на пользователя *node *перед запуском npm install:

      ~/node_project/Dockerfile

      ...
      USER node
      

      После копирования зависимостей проекта и переключения пользователя можно запустить npm install:

      ~/node_project/Dockerfile

      ...
      RUN npm install
      

      Затем скопируйте код приложения с надлежащими разрешениями в каталог приложения в контейнере:

      ~/node_project/Dockerfile

      ...
      COPY --chown=node:node . .
      

      В этом случае файлы приложения будут принадлежать пользователю node, не являющемуся пользователем root.

      Наконец, откройте порт 8080 в контейнере и запустите приложение:

      ~/node_project/Dockerfile

      ...
      EXPOSE 8080
      
      CMD [ "node", "app.js" ]
      

      Команда EXPOSE не публикует порт, но служит для документирования портов контейнера, которые будут публиковаться во время исполнения. CMD выполняет команду пуска приложения, в данном случае node app.js. Обратите винмание, что в каждом файле Dockerfile должна быть только одна команда CMD. Если вы включите несколько команд, действовать будет только последняя.

      С помощью Dockerfile можно сделать много разных вещей. Полный список команд можно найти в справочной документации по Dockerfile.

      Полный файл 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" ]
      

      Сохраните и закройте файл после завершения редактирования.

      Прежде чем строить образ приложения, добавим файл .dockerignore. Работая аналогично файлу .gitignore, файл .dockerignore указывает, какие файлы и каталоги в каталоге проекта не следует копировать в контейнер.

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

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

      ~/node_project/.dockerignore

      node_modules
      npm-debug.log
      Dockerfile
      .dockerignore
      

      Если вы работаете с Git, также следует добавить каталог .git и файл .gitignore.

      Сохраните файл и закройте его после завершения.

      Теперь вы готовы к созданию образа прложения с помощью команды docker build. Использование флага -t с командой docker build позволяет присвоить образу метку с запоминающимся названием. Поскольку мы планируем размещать образ в Docker Hub, добавим в метку имя пользователя Docker Hub. Мы пометим образ меткой nodejs-image-demo, но вы можете использовать любое другое название на свое усмотрение. Также замените your_dockerhub_username своим именем пользователя Docker Hub:

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

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

      Создание образа займет одну или две минуты. После завершения проверьте образы:

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

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE your_dockerhub_username/nodejs-image-demo latest 1c723fb2ef12 8 seconds ago 73MB node 10-alpine f09e7c96b6de 3 weeks ago 70.7MB

      Теперь вы можете создать контейнер с этим образом, используя команду docker run. Мы добавим к этой команде три флага:

      • -p: публикует порт контейнера и сопоставляет его с портом хоста. Мы используем порт 80 на нашем хосте, но вы можете использовать любой другой порт, если этот порт занят каким-то другим процессом. Дополнительную информацию по принципам привязки портов можно найти в соответствующей документации Docker.
      • -d: запускает контейнер в фоновом режиме.
      • --name: позволяет присвоить контейнеру запоминающееся имя.

      Запустите следующую команду для построения контейнера:

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

      После запуска контейнера вы можете проверить список запущенных контейнеров с помощью команды docker ps:

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

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e50ad27074a7 your_dockerhub_username/nodejs-image-demo "node app.js" 8 seconds ago Up 7 seconds 0.0.0.0:80->8080/tcp nodejs-image-demo

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

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

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

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

      При публикации образа приложения в таком реестре как Docker Hub вы делаете его доступным для последующего использования при построении и масштабировании контейнеров. Для примера мы покажем, как разместить образ приложения в хранилище и использовать его для воссоздания контейнера.

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

      • docker login -u your_dockerhub_username

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

      Теперь вы можете записать образ приложения в Docker Hub, используя ранее созданную метку your_dockerhub_username/nodejs-image-demo:

      • docker push your_dockerhub_username/nodejs-image-demo

      Давайте проверим использование реестра образов. Для этого уничтожим текущий контейнер приложения и образ и воссоздадим их на основе образа из хранилища.

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

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

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e50ad27074a7 your_dockerhub_username/nodejs-image-demo "node app.js" 3 minutes ago Up 3 minutes 0.0.0.0:80->8080/tcp nodejs-image-demo

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

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

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

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE your_dockerhub_username/nodejs-image-demo latest 1c723fb2ef12 7 minutes ago 73MB <none> <none> 2e3267d9ac02 4 minutes ago 72.9MB <none> <none> 8352b41730b9 4 minutes ago 73MB <none> <none> 5d58b92823cb 4 minutes ago 73MB <none> <none> 3f1e35d7062a 4 minutes ago 73MB <none> <none> 02176311e4d0 4 minutes ago 73MB <none> <none> 8e84b33edcda 4 minutes ago 70.7MB <none> <none> 6a5ed70f86f2 4 minutes ago 70.7MB <none> <none> 776b2637d3c1 4 minutes ago 70.7MB node 10-alpine f09e7c96b6de 3 weeks ago 70.7MB

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

      Введите y в диалоговом окне, чтобы подтвердить удаление остановленного контейнера и образов. Помните, что при этом также будет удален кэш вашей сборки.

      Теперь вы удалили контейнер с образом приложения и сам образ. Дополнительную информацию об удалении контейнеров Docker, образов и томов можно найти в документе «Удаление образов, контейнеров и томов Docker».

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

      • docker pull your_dockerhub_username/nodejs-image-demo

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

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

      Output

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

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

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

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

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f6bc2f50dff6 your_dockerhub_username/nodejs-image-demo "node app.js" 4 seconds ago Up 3 seconds 0.0.0.0:80->8080/tcp nodejs-image-demo

      Посетите http://your_server_ip еще раз, чтобы просмотреть запущенное приложение.

      Заключение

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

      Если вы хотите узнать больше о работе с такими инструментами, как Docker Compose и Docker Machine для создания мультиконтейнерных систем, вы можете ознакомиться со следующими руководствами:

      Общие советы по работе с данными контейнера можно найти здесь:

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



      Source link

      Создание и развертывание приложения Flask с использованием Docker в Ubuntu 18.04


      Автор выбрал Tech Education Fund для получения пожертвования в рамках программы Write for DOnations.

      Введение

      Docker — это приложение с открытым исходным кодом, позволяющее администраторам создавать, развертывать и воспроизводить приложения с помощью контейнеров. Контейнеры — это пакеты, в которых содержатся все зависимости, необходимые для запуска приложения на уровне операционной системы. Это означает, что каждое приложение, развернутое с помощью Docker, имеет собственную среду, и его требования обрабатываются отдельно.

      Flask — это веб-микроструктура, построенная на базе Python. Она называется микроструктурой, потому что не требует для работы специальных инструментов или плагинов. Микроструктура Flask отличается компактностью, гибкостью и высоким уровнем структурирования, за счет чего она более предпочтительна по сравнению с другими программными структурами.

      Развертывание приложения Flask с помощью Docker позволит вам воспроизводить приложение на разных серверах с минимальными изменениями конфигурации.

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

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

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

      Шаг 1 — Настройка приложения Flask

      Вначале вы создадите структуру каталогов, где будет размещено ваше приложение Flask. В этом обучающем модуле мы создадим каталог TestApp в каталоге /var/www, но вы можете изменить команду и использовать любое другое название.

      • sudo mkdir /var/www/TestApp

      Перейдите в созданный каталог TestApp:

      Создайте базовую структуру папок для приложения Flask:

      • sudo mkdir -p app/static app/templates

      Флаг -p означает, что команда mkdir создаст каталог и все его родительские каталоги, которых еще не существует. В данном случае команда mkdir создаст родительский каталог app в процессе создания каталогов static и templates.

      В каталоге app будут находиться все файлы, связанные с приложением Flask, в том числе views и blueprints. Views — это создаваемый вами код, обеспечивающий ответы на запросы вашего приложения. Blueprints создает компоненты приложения и поддерживает стандартные шаблоны внутри приложения или для нескольких разных приложений.

      В каталоге static хранятся различные ресурсы, в том числе файлы изображений, CSS и JavaScript. В каталоге templates хранятся шаблоны HTML для вашего проекта.

      Теперь базовая структура папок готова, и вы можете создать все файлы, необходимые для запуска приложения Flask. Вначале создайте файл __init__.py в каталоге app. Этот файл сообщает интерпретатору Python, что каталог app является пакетом, и его следует рассматривать именно как пакет.

      Запустите следующую команду для создания файла:

      • sudo nano app/__init__.py

      Пакеты в Python позволяют группировать модули в логические пространства имен или иерархии. Этот подход позволяет разбивать код на отдельные управляемые блоки, которые выполняют конкретные функции.

      Затем вы добавитье в файл __init__.py код, который создаст экземпляр Flask и импортирует логику из файла views.py, которы вы создадите после сохранения этого файла. Добавьте в новый файл следующий код:

      /var/www/TestApp/__init__.py

      from flask import Flask
      app = Flask(__name__)
      from app import views
      

      После добавления этого кода сохраните и закройте файл.

      После создания файла __init__.py вы будете готовы создать файл views.py в каталоге app. В этом файле будет содержаться большая часть логики вашего приложения.

      Затем добавьте код в файл views.py. Этот код будет возвращать фразу hello world! строка для пользователей, посещающих вашу веб-страницу:

      /var/www/TestApp/app/views.py

      from app import app
      
      @app.route('/')
      def home():
         return "hello world!"
      

      Строка @app.route над функцией называется декоратором. Декораторы изменяют функцию, которая следует за ними. В данном случае декторатор указывает Flask, какой URL активирует функцию home(). Текст hello world, возвращаемый функцией home, будет отображаться пользователю в браузере.

      Создав файл views.py, вы готовы к созданию файла uwsgi.ini. Этот файл будет содержать конфигурации uWSGI для нашего приложения. uWSGI — это опция развертывания Nginx, представляющая собой как протокол, так и сервер приложений, который может обслуживать протоколы uWSGI, FastCGI и HTTP.

      Для создания этого файла запустите следующую команду:

      Затем добавьте в файл следующее содержание для настройки сервера uWSGI:

      /var/www/TestApp/uwsgi.ini

      [uwsgi]
      module = main
      callable = app
      master = true
      

      Этот код определяет модуль, из которого будет обслуживаться приложение Flask. В данном случае это файл main.py, который здесь указывается как main. Опция callable указывает uWSGI использовать экземпляр app, экспортированный основным приложением. Параметр master позволяет вашему приложению продолжать работать, и поэтому даже при перезагрузке всего приложения время простоя будет минимальным.

      Теперь создайте файл main.py, который будет главной точкой входа в приложение. Точка входа сообщает uWSGI, как следует взаимодействовать с приложением.

      Далее скопируйте и вставьте в файл следующий код. Этот код импортирует экземпляр Flask под названием app из пакета приложения, созданного на предыдущих шагах.

      /var/www/TestApp/main.py

      from app import app
      

      Наконец, создайте файл requirements.txt, чтобы указать, какие зависимости диспетчер пакетов pip установит в вашу среду Docker:

      • sudo nano requirements.txt

      Добавьте следующую строку для добавления Flask в качестве зависимости:

      /var/www/TestApp/app/requirements.txt

      Flask==1.0.2
      

      В нем указывается устанавливаемая версия Flask. На момент составления настоящего обучающего модуля последней версией Flask была версия 1.0.2. Вы можете проверить обновления Flask на официальном сайте.

      Сохраните и закройте файл. Вы успешно настроили свое приложение Flask и готовы к настройке Docker.

      Шаг 2 — Настройка Docker

      На этом шаге вы создадите два файла для развертывания Docker, Dockerfile и start.sh. Dockerfile — это текстовый документ, содержащий команды, используемые для сборки образа. Файл start.sh — это скрипт оболочки, который построит образ и создаст контейнер из файла Dockerfile.

      Вначале создайте файл Dockerfile.

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

      /var/www/TestApp/Dockerfile

      FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7
      RUN apk --update add bash nano
      ENV STATIC_URL /static
      ENV STATIC_PATH /var/www/app/static
      COPY ./requirements.txt /var/www/requirements.txt
      RUN pip install -r /var/www/requirements.txt
      

      В этом примере образ Docker будет построен на основе существующего образа tiangolo/uwsgi-nginx-flask, который можно найти на ресурсе DockerHub. Этот конкретный образ Docker лучше многих других, потому что он поддерживает широкий спектр версий Python и образов ОСs.

      В первых двух строках указывается родительский образ, который вы будете использовать для запуска приложений и установки процессора команд bash и текстового редактора nano. Также он устанавливает клиент git для связи со службами хостинга контроля версий, такими как GitHub, GitLab и Bitbucket. ENV STATIC_URL /static — переменная среды, используемая для конкретного образа Docker. Она определяет статичную папку, где хранятся все ресурсы, включая образы, файлы CSS и файлы JavaScript.

      Последние две строки копируют в контейнер файл requirements.txt, чтобы его можно было выполнить, а затем выполняют синтаксический анализ файла requirements.txt для установки указанных зависимостей.

      Сохраните и закройте файл после добавления вашей конфигурации.

      Теперь вы установили файл Dockerfile и уже почти готовы написать скрипт start.sh, который построит для вас контейнер Docker. Прежде чем создавать скрипт start.sh, убедитесь, что у вас имеется открытый порт для использования в конфигурации. Чтобы проверить, свободен ли порт, запустите следующую команду:

      • sudo nc localhost 56733 < /dev/null; echo $?

      Если вывод команды больше 1, это означает, что порт свободен и готов к использованию. В противном случае, вам нужно будет выбрать другой порт для использования в файле конфигурации start.sh.

      Когда вы найдете открытый порт для использования, создайте скрипт start.sh:

      Скрипт start.sh — это скрипт оболочки, создающий образ из файла Dockerfile и создающий контейнер на основе полученного образа Docker. Добавьте свою конфигурацию в новый файл:

      /var/www/TestApp/start.sh

      #!/bin/bash
      app="docker.test"
      docker build -t ${app} .
      docker run -d -p 56733:80 
        --name=${app} 
        -v $PWD:/app ${app}
      

      Первая строка называется shebang. Она указывает, что это файл bash, и что его нужно выполнять как команды. В следующей строке указывается, какое имя вы хотите присвоить образу и контейнеру, а также выполняется сохранение этого имени в переменной app. Следующая строка указывает Docker построить образ из файла Dockerfile, находящегося в текущем каталоге. В этом примере будет создан образ с именем docker.test.

      Последние три строки создают новый контейнер с именем docker.test с открытым портом 56733. Наконец, текущий каталог связывается с каталогом /var/www directory в контейнере.

      Флаг -d используется для запуска контейнера в режиме демона или в качестве фонового процесса. Флаг -p используется для привязки порта на сервере к конкретному порту контейнера Docker. В данном случае вы привязываете порт 56733 к порту 80 контейнера Docker. Флаг -v указывает, какой том Docker следует монтировать на контейнер. В данном случае вы монтируете весь каталог проекта в папку /var/www в контейнере Docker.

      Запустите скрипт start.sh для создания образа Docker и построения контейнера на основе этого образа:

      После завершения выполнения скрипта используйте следующую команду для вывода списка всех запущенных контейнеров:

      В результате будет выведен список контейнеров:

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 58b05508f4dd docker.test "/entrypoint.sh /sta…" 12 seconds ago Up 3 seconds 443/tcp, 0.0.0.0:56733->80/tcp docker.test

      Вы увидите, что контейнер docker.test запущен и работает. Теперь, когда контейнер работает, откройте в браузере IP-адрес на указанном порту: http://ip-address:56733

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

      Главная страница

      На этом шаге вы успешно развернули свое приложение Flask в контейнере Docker. Теперь вы используете шаблоны, чтобы показать пользователям контент.

      Шаг 3 — Работа с файлами шаблонов

      Шаблоны — это файлы, показывающие статичный и динамический контент пользователям вашего приложения. На этом шаге вы создадите шаблон HTML для создания главной страницы приложения.

      Вначале создайте файл home.html в каталоге app/templates:

      • sudo nano app/templates/home.html

      Добавьте код для вашего шаблона. Этот код создаст страницу HTML5, содержащую заголовок и текст.

      /var/www/TestApp/app/templates/home.html

      
      <!doctype html>
      
      <html lang="en-us">   
        <head>
          <meta charset="utf-8">
          <meta http-equiv="x-ua-compatible" content="ie=edge">
          <title>Welcome home</title>
        </head>
      
        <body>
          <h1>Home Page</h1>
          <p>This is the home page of our application.</p>
        </body>
      </html>
      

      После добавления шаблона сохраните и закройте файл.

      Теперь измените файл app/views.py, чтобы обслуживать созданный файл:

      Вначале добавьте в начале файла следующую строку для импорта метода render_template из Flask. Этот метод проводит синтаксический анализ файла HTML для рендеринга веб-страницы для пользователя.

      /var/www/TestApp/app/views.py

      from flask import render_template
      ...
      

      В конце файла вы добавите новый маршрут для рендеринга файла шаблона. Данный код указывает, что пользователям выводится содержимое файла home.html всегда, когда они посещают маршрут /template в вашем приложении.

      /var/www/TestApp/app/views.py

      ...
      
      @app.route('/template')
      def template():
          return render_template('home.html')
      

      Обновленный файл app/views.py будет выглядеть примерно следующим образом:

      /var/www/TestApp/app/views.py

      from flask import render_template
      from app import app
      
      @app.route('/')
      def home():
          return "Hello world!"
      
      @app.route('/template')
      def template():
          return render_template('home.html')
      

      Сохраните и закройте файл после завершения.

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

      • sudo docker stop docker.test && sudo docker start docker.test

      Откройте свое приложение по адресу http://your-ip-address:56733/template, чтобы увидеть, как выводится новый шаблон.

      главная страница

      Вы создали файл шаблона Docker, который будет выводиться посетителям вашего приложения. На следующем шаге вы увидите. как вносимые вами в приложение изменения могут вступить в силу без необходимости перезапуска контейнера Docker.

      Шаг 4 — Обновление приложения

      Иногда в приложение бывает нужно внести изменения. Это может быть установка новых требований, обновление контейнера Docker или внесение изменений в код HTML и логику. В этом разделе вы настроите команду touch-reload для внесения этих зменений без перезапуска контейнера Docker.

      Функция автоматической перезагрузки Python отслеживает изменения во всей файловой системе и обновляет приложение при обнаружении изменений. Автоматическая перезагрузка не рекомендуется в производственной среди, поскольку она может очень быстро увеличить нагрузку на ресурсы системы. На этом шаге вы используете команду touch-reload для отслеживания изменений определенного файла и перезагрузке контейнера в случае обновления или замены файла.

      Для реализации этой функции откройте файл uwsgi.ini:

      Добавьте в конец файла выделенную строку:

      /var/www/TestApp/uwsgi.ini

      module = main
      callable = app
      master = true
      touch-reload = /app/uwsgi.ini
      

      Эта строка указывает файл, изменение которого запускает перезагрузку приложения. После внесения изменений сохраните и закройте файл.

      Чтобы продемонстрировать это, внесите в ваше приложение небольшое изменение. Для начала откройте файл app/views.py:

      Замените строку, возвращаемую функцией home:

      /var/www/TestApp/app/views.py

      from flask import render_template
      from app import app
      
      @app.route('/')
      def home():
          return "<b>There has been a change</b>"
      
      @app.route('/template')
      def template():
          return render_template('home.html')
      

      Сохраните и закройте файл после внесения изменения.

      Если вы откроете главную страницу приложения по адресу http://ip-address:56733, вы увидите, что изменения не отражаются. Это связано с тем, что условием перезагрузки будет изменение в файле uwsgi.ini. Чтобы перезагрузить приложение, используйте команду touch для активации условия:

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

      Главная страница обновлена

      На этом шаге вы выберете условие команды touch-reload, с которым приложение будет обновляться после внесения изменений.

      Заключение

      В этом обучающем модуле вы создали и развернули приложение Flask в контейнере Docker. Также вы настроили команду touch-reload для обновления приложения без необходимости перезапуска контейнера.

      Новое приложение в Docker можно будет легко масштабировать. Чтобы узнать больше об использовании Docker, ознакомьтесь с официальной документацией.



      Source link

      Настройка приложения Node.js для работы в среде Ubuntu 18.04


      Введение

      Node.js — среда исполнения JavaScript с открытым исходным кодом, предназначенная для построения серверных и сетевых приложений. Данная платформа работает в операционных системах Linux, macOS, FreeBSD и Windows. Хотя вы можете запускать приложения Node.js через командную строку, этот обучающий модуль посвящен их запуску в качестве службы. Это означает, что они будут перезапускаться при перезагрузке системы или неисправности, и что их можно безопасно использовать в производственной среде.

      В этом обучающем модуле вы научитесь создавать готовую производственную среду Node.js на одном сервере Ubuntu 18.04. Этот сервер будет выполнять приложение Node.js под управлением PM2 и предоставлять пользователям безопасный доступ к приложению через обратный прокси-сервер Nginx. Сервер Nginx обеспечивает поддержку HTTPS с использованием бесплатного сертификата от Let’s Encrypt.

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

      Этот обучающий модуль предполагает, что у вас имеется следующее:

      Если предварительные требования выполнены, у вас должен быть сервер, обслуживающий используемую по умолчанию страницу назначения вашего домена по адресу https://example.com/.

      Шаг 1 — Установка Node.js

      Для начала мы установим самый быстрый выпуск LTS Node.js, используя архивы пакетов NodeSource.

      Вначале мы установим NodeSource PPA, чтобы получить доступ к его содержимому. Перейдите в каталог home и используйте curl для получения скрипта установки архивов Node.js 8.x:

      • cd ~
      • curl -sL https://deb.nodesource.com/setup_8.x -o nodesource_setup.sh

      Вы можете просмотреть содержимое скрипта с помощью nano или предпочитаемого текстового редактора:

      Завершив проверку скрипта, запустите его от имени пользователя sudo:

      • sudo bash nodesource_setup.sh

      Архив PPA будет добавлен в вашу конфигурацию и кэш локальных пакетов автоматически обновится. После запуска скрипта установки Nodesource вы можете установить пакет Node.js:

      Чтобы проверить номер версии Node.js, установленной на начальном шаге, введите:

      Output

      v8.11.3

      Примечание. При установке из NodeSource PPA исполняемый файл Node.js имеет имя nodejs, а не node.

      Пакет nodejs содержит двоичный файл nodejs, а также диспетчер пакетов npm для модулей Node, так что отдельно устанавливать npm не нужно.

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

      Output

      5.6.0

      Для работы некоторых пакетов npm (например, требующих компиляцию кода из источника) потребуется установить пакет build-essential:

      • sudo apt install build-essential

      Теперь у вас есть необходимые инструменты для работы с пакетами npm, которые требуют компиляции кода из источника.

      Установив исполняемый модуль Node.js, мы можем перейти к написанию приложения Node.js.

      Шаг 2 — Создание приложения Node.js

      Напишем приложение Hello World, возвращающее «Hello World» в ответ на любые запросы HTTP. Этот образец приложения поможет вам выполнить настройку Node.js. Вы можете заменить его собственным приложением, но при этом обязательно измените приложение для прослушивания подходящих IP-адресов и портов.

      Вначале создадим образец приложения под именем hello.js:

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

      ~/hello.js

      const http = require('http');
      
      const hostname = 'localhost';
      const port = 3000;
      
      const server = http.createServer((req, res) => {
        res.statusCode = 200;
        res.setHeader('Content-Type', 'text/plain');
        res.end('Hello World!n');
      });
      
      server.listen(port, hostname, () => {
        console.log(`Server running at http://${hostname}:${port}/`);
      });
      

      Сохраните файл и выйдите из редактора.

      Это приложение Node.js прослушивает заданный адрес (localhost) и порт (3000) и возвращает текст «Hello World!» с кодом успешного выполнения a 200 HTTP. Поскольку мы прослушиваем localhost, удаленные клиенты не смогут подключиться к нашему приложению.

      Чтобы протестировать приложение, введите:

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

      Output

      Server running at http://localhost:3000/

      Примечание. Такой способ запуска приложения Node.js блокирует дополнительные команды, пока приложение не будет закрыто нажатием CTRL+C.

      Чтобы протестировать приложение, откройте на сервере другой сеанс терминала и подключитесь к localhost с помощью команды curl:

      • curl http://localhost:3000

      Если вы увидите следующий результат, приложение работает нормально и прослушивает правильные адрес и порт:

      Output

      Hello World!

      Если вы не видите ожидаемого результата, убедитесь, что ваше приложение Node.js запущено и настроено для прослушивание правильных адреса и порта.

      Убедившись, что приложение работает, остановите его (если еще не сделали этого) нажатием CTRL+C.

      Шаг 3 — Установка PM2

      Теперь установим диспетчер процессов PM2, предназначенный для приложений Node.js. PM2 позволяет преобразовывать приложения в демонов, чтобы они работали как службы в фоновом режиме.

      Используйте npm для установки последней версии PM2 на своем сервере:

      • sudo npm install pm2@latest -g

      Опция -g указывает npm выполнить глобальную установку модуля, чтобы он был доступен в масштабе всей системы.

      Вначале используем команду pm2 для запуска вашего приложения hello.js в фоновом режиме:

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

      Output

      [PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2 [PM2] PM2 Successfully daemonized [PM2] Starting /home/sammy/hello.js in fork_mode (1 instance) [PM2] Done. ┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬───────┬──────────┐ │ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ ├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼───────┼──────────┤ │ hello │ 0 │ fork │ 1338 │ online │ 0 │ 0s │ 0% │ 23.0 MB │ sammy │ disabled │ └──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴───────┴──────────┘ Use `pm2 show <id|name>` to get more details about an app

      Как видите, PM2 автоматически назначает App name (по имени файла, без расширения .js и идентификатор PM2 id. PM2 также обслуживает и другие данные, в том числе PID процесса, данные о текущем состоянии и использовании памяти.

      Приложения, запускаемые через PM2, автоматически перезапускаются в случае сбоя или прекращения работы приложения, но мы можем выполнить дополнительный шаг, чтобы запускать приложение при запуске системы с помощью субкоманды startup. Эта субкоманда генерирует и настраивает скрипт запуска PM2 и управляемых им процессов при загрузке сервера:

      Последняя строка результатов содержит команду, которую нужно запустить с привилегиями суперпользователя для настройки запуска PM2 при загрузке:

      Output

      [PM2] Init System found: systemd [PM2] To setup the Startup Script, copy/paste the following command: sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

      Запустите команду из результатов, указав свое имя пользователя вместо sammy:

      • sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

      Дополнительно мы можем сохранить список процессов PM2 и соответствующие среды:

      Теперь вы создали блок systemd, который запускает pm2 для вашего пользователя при загрузке. Этот экземпляр pm2 запускает hello.js.

      Запустите службу с помощью команды systemctl:

      • sudo systemctl start pm2-sammy

      Проверьте состояние блока systemd:

      • systemctl status pm2-sammy

      Подробный обзор systemd можно найти в документе «Основы работы с Systemd: работа со службами, блоками и журналом».

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

      Остановите приложение с помощью этой команды (укажите имя приложения PM2 или id):

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

      • pm2 restart app_name_or_id

      Выведем список приложений, управление которыми осуществляет PM2:

      Получим информацию об определенном приложении по App name:

      Монитор процесса PM2 запускается с помощью субкоманды monit. При этом отображается состояние приложение, использование ресурсов ЦП и использование памяти:

      При запуске команды pm2 без аргументов отображается страница справки с примерами использования.

      Теперь ваше приложение Node.js запущено и управляется PM2, и мы можем настроить обратный прокси-сервер.

      Шаг 4 — Настройка Nginx в качестве обратного прокси-сервера

      Ваше приложение запущено и прослушивает localhost, но вам нужно дать пользователям возможность доступа к нему. Для этой цели мы настроим веб-сервер Nginx в качестве обратного прокси-сервера.

      В предварительных обучающих модулях вы настроили конфигурацию Nginx в файле /etc/nginx/sites-available/example.com. Откройте этот файл для редактирования:

      • sudo nano /etc/nginx/sites-available/example.com

      В блоке server должен содержаться блок location /. Замените содержимое этого блока следующей конфигурацией. Если ваше приложение настроено для прослушивания другого порта, измените номер порта в выделенной части на подходящий:

      /etc/nginx/sites-available/example.com

      server {
      ...
          location / {
              proxy_pass http://localhost:3000;
              proxy_http_version 1.1;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection 'upgrade';
              proxy_set_header Host $host;
              proxy_cache_bypass $http_upgrade;
          }
      ...
      }
      

      Так сервер настраивается для ответа на запросы root. Если наш сервер доступен по адресу example.com, при попытке доступа к https://example.com/ через браузер будет отправлен запрос hello.js с прослушиванием порта 3000 хоста localhost.

      Вы можете добавить в этот же серверный блок дополнительные блоки location, чтобы предоставить другим приложениям доступ к этому же серверу. Например, если вы используете другое приложение Node.js на порту 3001, вы сможете добавить следующий блок location, чтобы разрешить доступ к нему через https://example.com/app2:

      /etc/nginx/sites-available/example.com — Optional

      server {
      ...
          location /app2 {
              proxy_pass http://localhost:3001;
              proxy_http_version 1.1;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection 'upgrade';
              proxy_set_header Host $host;
              proxy_cache_bypass $http_upgrade;
          }
      ...
      }
      

      Завершив добавление блоков location для ваших приложений, сохраните файл и закройте редактор.

      Убедитесь в отсутствии ошибок синтаксиса с помощью следующей команды:

      Перезапустите Nginx:

      • sudo systemctl restart nginx

      Если ваше приложение Node.js запущено и конфигурации вашего приложения и Nginx настроены правильно, вы должны иметь возможность доступа к вашему приложению через обратный прокси-сервер Nginx. Попробуйте открыть URL вашего сервера (публичный IP-адрес или доменное имя).

      Заключение

      Поздравляем! Теперь у вас есть приложение Node.js, работающее за обратным прокси-сервером Nginx на сервере Ubuntu 18.04. Настройка обратного прокси-сервера достаточно гибкая, чтобы предоставить вашим пользователям доступ к другим приложениям или статическому веб-контенту, который вы хотите опубликовать.



      Source link