Быстрая сборка приложения Node.js с помощью Docker

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

Расширенную версию этого мануала вы найдете здесь.

Требования

1: Установка зависимостей приложения

Создайте каталог для вашего проекта в домашнем каталоге пользователя sudo.

mkdir node_project

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

cd node_project

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

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

nano package.json

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

{
"name": "nodejs-image-demo",
"version": "1.0.0",
"description": "nodejs image demo",
"author": "Sammy the Shark <sammy@example.com>",
"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"
}
}

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

npm install

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

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

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

nano app.js

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

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

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

<!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

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

nano 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

Вы попадете на посадочную страницу приложения.

Нажмите кнопку Get Shark Info, чтобы открыть вторую страницу приложения.

Теперь у вас есть запущенное приложение. Чтобы остановить сервер, нажмите Ctrl+C.

3: Написание Dockerfile

В корневом каталоге проекта создайте Dockerfile:

nano Dockerfile

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

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

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

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

node_modules
npm-debug.log
Dockerfile
.dockerignore

Теперь можно собрать образ приложения с помощью команды docker build.

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

Точка указывает, что контекстом сборки является текущий каталог.

После завершения сборки проверьте образы:

docker images
REPOSITORY                                         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

Вы увидите такой вывод:

CONTAINER ID     IMAGE                                 COMMAND       CREATED         STATUS         PORTS                  NAMES
e50ad27074a7     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. Вы снова увидите посадочную страницу своего приложения.

4: Репозиторий для работы с образами

Чтобы опубликовать свой образ, сначала нужно войти в учетную запись Docker Hub:

docker login -u your_dockerhub_username -p your_dockerhub_password

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

Теперь можно загрузить образ приложения на Docker Hub:

docker push your_dockerhub_username/nodejs-image-demo

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

Сначала просмотрите список работающих контейнеров:

docker ps
CONTAINER 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, остановите контейнер работающего приложения. Обязательно замените условный идентификатор в команде своим значением.

docker stop e50ad27074a7

Теперь просмотрите все свои контейнеры, добавив флаг -а:

docker images -a

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

REPOSITORY                                           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

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

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

Теперь можете повторно собрать контейнер с помощью этой команды:

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

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

docker ps
CONTAINER 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. Вы должны увидеть свое приложение.

Заключение

Предлагаем вам список дополнительных руководств, которые могут быть вам интересны.

Tags: , , , , ,