Введение
Платформа Docker позволяет разработчикам упаковывать и запускать приложения в виде контейнеров. Контейнер — это отдельный процесс, работающий в общей операционной системе, и представляет собой облегченную альтернативу виртуальным машинам. Хотя контейнеры не являются чем-то новым, они предлагают преимущества, включая изоляцию процессов и стандартизацию среды, которые будут становиться все более важными по мере того, как все больше разработчиков начнут использовать распределенную архитектуру приложений.
При сборке и масштабировании приложения с помощью Docker отправной точкой обычно является создание образа приложения, который затем можно запустить в контейнере. Этот образ содержит код приложения, библиотеки, файлы конфигурации, переменные среды и среду выполнения. Использование образа гарантирует стандартизацию среды контейнера и наличие только того, что необходимо для сборки и запуска приложения.
В этом руководстве вы создадите образ приложения для статического веб-сайта, использующего фреймворки Express и Bootstrap. Затем вы создадите контейнер с этим образом и разместите его в Docker Hub для дальнейшего использования. Затем вы извлечете сохранённый образ из репозитория Docker Hub и встроите его в другой контейнер, продемонстрировав, как можно рефакторить и масштабировать своё приложение.
Предпосылки
- Сервер под управлением Ubuntu, пользователь без прав root, с правами sudo и включённым брандмауэром. Для получения инструкций по настройке выберите свой дистрибутив из списка и следуйте нашему руководству по первоначальной установке сервера.
- Docker установлен на вашем сервере.
- Установлены Node.js и npm.
- Учетная запись Docker Hub.
Шаг 1 — Установка зависимостей приложения
Чтобы создать образ, сначала необходимо собрать файлы приложения, а затем скопировать их в контейнер. Эти файлы содержат статический контент, код и зависимости вашего приложения.
Сначала создайте каталог для вашего проекта в домашнем каталоге пользователя без прав root. Мы назовём наш проект node_project , но вы можете заменить его на любое другое имя:
mkdir node_projectПерейдите в этот каталог:
cd node_projectЭто будет основной каталог проекта.
Затем создайте файл package.json с зависимостями вашего проекта и другой идентификационной информацией. Откройте файл в nano или другом удобном для вас редакторе:
nano 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, которая разрешает свободное использование и распространение программного кода. Кроме того, в файле указано:
- “main”: точка входа приложения, app.js. Этот файл вы создадите позже.
- “Зависимости”: Зависимости проекта – в данном случае Express 4.16.4 или выше.
Хотя в этом файле не указан репозиторий, вы можете добавить его, следуя этим инструкциям, чтобы добавить репозиторий в файл package.json. Это полезное дополнение, если вы редактируете приложение. Сохраните и закройте файл после внесения изменений.
Чтобы установить зависимости проекта, выполните следующую команду:
npm installЭто установит пакеты, перечисленные в файле package.json, в каталог вашего проекта. Теперь мы можем собрать файлы приложения.
Шаг 2 — Создание файлов программы
Мы создадим веб-сайт, предоставляющий пользователям информацию об акулах. Наше приложение будет иметь основную запись app.js и каталог представлений, содержащий основные ресурсы проекта. Целевая страница index.html будет предоставлять пользователям основную информацию и ссылку на страницу с более подробной информацией об акулах sharks.html. В каталоге представлений мы создадим как целевую страницу, так и sharks.html.
Сначала откройте app.js в основном каталоге проекта, чтобы определить пути проекта:
nano app.jsПервая часть файла создает объекты приложений Express и Router и определяет базовый каталог и порт как константы:
const express = require('express'); const app = express(); const router = express.Router(); const path = __dirname + '/views/'; const port = 8080;
Функция require загружает модуль Express, который затем используется для создания объектов приложения и маршрутизатора. Объект маршрутизатора выполняет функцию маршрутизации приложения, и при определении маршрутов HTTP-методов мы добавляем их к этому объекту, чтобы указать, как наше приложение обрабатывает запросы.
Этот раздел файла также содержит несколько констант, Путь и Порт Наборы:
- path: определяет базовый каталог, который будет находиться под каталогом представлений в текущем каталоге проекта.
- Порт: сообщает программе о необходимости прослушивать порт 8080 и подключаться к нему.
Далее настройте маршруты приложения с помощью объекта маршрутизатора:
...
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');
});Функция router.use загружает функцию промежуточного уровня, которая регистрирует запросы маршрутизатора и перенаправляет их на маршруты приложения. Они определены в следующих функциях, которые указывают, что GET-запрос к базовому URL-адресу проекта должен возвращать страницу index.html, а GET-запрос к маршруту /sharks должен возвращать страницу sharks.html.
Наконец, смонтируйте промежуточное программное обеспечение маршрутизатора и статические ресурсы приложения и укажите приложению прослушивать порт 8080:
...
app.use(express.static(path));
app.use('/', router);
app.listen(port, function () {
console.log('Example app listening on port 8080!')
})Готовый файл 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('/' + 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(port, function () {
console.log('Example app listening on port 8080!')
})По завершении сохраните и закройте файл.
Теперь добавим в приложение статический контент. Начнём с создания каталога представлений:
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://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="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="#">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="/" class="nav-link">Home</a>
</li>
<li class="nav-item"><a href="/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="/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>Верхняя панель навигации позволяет пользователям перемещаться между страницами «Главная» и «Акулы». В компоненте navbar-nav мы используем класс Active из Bootstrap для отображения текущей страницы. Мы также указали маршруты для наших статических страниц, соответствующие маршрутам, которые мы определили в app.js:
...
<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="/" class="nav-link">Home</a>
</li>
<li class="nav-item"><a href="/sharks" class="nav-link">Sharks</a>
</li>
</ul>
</div>
...Кроме того, мы создали ссылку на нашу страницу с информацией об акулах на кнопке большого экрана:
...
<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>
...В заголовке также есть ссылка на пользовательскую таблицу стилей:
...
<link href="css/styles.css" rel="stylesheet">
...В конце этого шага мы создадим эту таблицу стилей. После этого сохраните и закройте файл. Разместив целевую страницу приложения, мы можем создать страницу с информацией об акулах под названием 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://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="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="/">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="/" class="nav-link">Home</a>
</li>
<li class="active nav-item"><a href="/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:
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;
}Помимо настройки шрифта и цвета, этот файл также ограничивает размер изображений, устанавливая максимальную ширину 80%. Это гарантирует, что они не займут больше места на странице, чем нужно. Сохраните и закройте файл по завершении.
После установки программных файлов и зависимостей проекта вы готовы запустить программу.
Если вы следовали руководству по начальной настройке сервера, описанному в разделе «Предварительные требования», у вас будет активный брандмауэр, разрешающий только SSH-трафик. Чтобы разрешить трафик на порт 8080:
sudo ufw allow 8080Чтобы запустить программу, убедитесь, что вы находитесь в корневом каталоге вашего проекта:
cd ~/node_projectЗапустите приложение с помощью узла app.js:
node app.jsОткройте в браузере http://your_server_ip:8080. Вы загрузите следующую целевую страницу:
Нажмите кнопку «Получить информацию об акулах». Загрузится следующая страница с информацией:
Теперь приложение запущено и работает. Когда будете готовы, выйдите с сервера, нажав CTRL+C. Теперь мы можем перейти к созданию Dockerfile, который позволит нам пересобирать и масштабировать это приложение по мере необходимости.
Шаг 3 — Написание Dockerfile
Dockerfile определяет, что будет включено в контейнер вашего приложения при его запуске. Использование Dockerfile позволяет определить среду контейнера и избежать конфликтов с зависимостями или версиями среды выполнения.
Следуя этим рекомендациям по созданию оптимальных контейнеров, мы делаем наш образ максимально эффективным, сводя к минимуму количество слоев образа и ограничивая функциональность образа одной целью — воссозданием файлов приложения и статического содержимого.
В корневом каталоге вашего проекта создайте Dockerfile:
nano DockerfileОбразы Docker создаются с помощью последовательных многослойных образов, которые накладываются друг на друга. Первым шагом станет добавление базового образа для нашего приложения, который станет отправной точкой для его сборки.
Давайте используем образ node:10-alpine, так как на момент написания статьи это рекомендуемая LTS-версия Node.js. Образ Alpine взят из проекта Alpine Linux и помогает нам уменьшить его размер. Подробнее о том, подходит ли образ Alpine для вашего проекта, читайте в разделе «Варианты образов» на странице образов Node в Docker Hub.
Добавьте следующую директиву FROM, чтобы задать базовый образ приложения:
FROM node:10-alpineЭтот образ включает Node.js и npm. Каждый Dockerfile должен начинаться с директивы FROM.
По умолчанию образ Docker Node включает пользователя Node без прав root, что позволяет предотвратить запуск контейнера приложения от имени root. Рекомендуемая мера безопасности — избегать запуска контейнеров от имени root и ограничивать возможности контейнера только теми, которые необходимы для запуска его процессов. Поэтому мы используем домашний каталог пользователя Node в качестве рабочего каталога для нашего приложения и настраиваем его как нашего пользователя внутри контейнера. Подробнее о передовых практиках работы с образом Docker Node см. в этом руководстве.
Чтобы точно настроить права доступа к коду нашего приложения в контейнере, создадим подкаталог node_modules в каталоге /home/node вместе с каталогом приложения. Создание этих каталогов гарантирует наличие у них необходимых прав доступа, что будет важно при создании локальных модулей Node в контейнере с помощью npm install. Помимо создания этих каталогов, мы устанавливаем их владельцами для нашего пользователя Node:
...
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/appДополнительную информацию об использовании интеграции инструкций RUN можно найти в этом обсуждении по управлению слоями контейнера.
Затем установите рабочий каталог приложения в /home/node/app:
...
WORKDIR /home/node/appЕсли WORKDIR не задан, Docker создаст его по умолчанию, поэтому рекомендуется задать его явно.
Затем скопируйте файлы package.json и package-lock.json (для npm 5+):
...
COPY package*.json ./Добавление директивы COPY перед запуском npm install или копированием кода приложения позволяет нам воспользоваться механизмом кэширования Docker. На каждом этапе сборки Docker проверяет, был ли кэширован слой для этой директивы. Если мы изменим package.json, этот слой будет пересобран, но если мы этого не сделаем, эта директива позволит Docker использовать существующий слой образа и пропустить переустановку модулей Node.
Чтобы гарантировать, что все файлы приложения принадлежат пользователю node, не являющемуся root, включая содержимое каталога node_modules, измените пользователя на node перед запуском npm install:
...
USER nodeПосле копирования зависимостей проекта и переключения пользователей мы можем запустить npm install:
...
RUN npm installЗатем скопируйте код вашего приложения с соответствующими разрешениями в каталог приложения в контейнере:
...
COPY --chown=node:node . .Это гарантирует, что файлы приложения принадлежат пользователю, не являющемуся пользователем root.
Наконец, установите порт 8080 на контейнере и запустите приложение:
...
EXPOSE 8080
CMD [ "node", "app.js" ]EXPOSE не раскрывает порт, а служит способом документирования портов, доступных контейнеру во время выполнения. CMD выполняет команду запуска приложения, в данном случае node app.js. Обратите внимание, что в каждом Dockerfile должна быть только одна команда CMD. Если вы укажете несколько команд, будет применена только последняя.
С помощью Dockerfile можно делать многое. Полный список инструкций можно найти в справочной документации Dockerfile.
Полный 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:
nano .dockerignoreВнутри файла добавьте модули локального узла, логи npm, Dockerfile и файл .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:
sudo docker build -t your_dockerhub_username/nodejs-image-demo .. Указывает, что контекстом построения является текущий каталог.
Создание изображения займёт минуту-две. После завершения проверьте свои изображения:
sudo docker imagesВы получите следующий результат:
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: Это позволяет нам дать контейнеру запоминающееся имя.
Чтобы создать контейнер, выполните следующую команду:
sudo docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demoПосле того как ваш контейнер будет запущен и запустится, вы можете проверить список запущенных контейнеров с помощью docker ps:
sudo 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Пока ваш контейнер запущен, вы можете посетить свое приложение, перейдя в браузере по IP-адресу вашего сервера без порта:
http://your_server_ip
Целевая страница вашего приложения загрузится еще раз.
Теперь, когда вы создали образ для своего приложения, вы можете загрузить его в Docker Hub для дальнейшего использования.
Шаг 4 — Использование репозитория для работы с изображениями
Размещая образ приложения в реестре, таком как Docker Hub, вы делаете его доступным для последующего использования при сборке и масштабировании контейнеров. Мы покажем вам, как это сделать, разместив образ приложения в репозитории, а затем используя его для повторного создания контейнера.
Первый шаг для отправки образа — войти в учетную запись Docker Hub, созданную вами в предварительных условиях:
sudo docker login -u your_dockerhub_usernameПри появлении запроса введите пароль вашей учётной записи Docker Hub. При таком входе в домашнем каталоге пользователя будет создан файл ~/.docker/config.json с вашими учётными данными Docker Hub.
Теперь вы можете отправить образ приложения в Docker Hub, используя созданный ранее тег your_dockerhub_username/nodejs-image-demo:
sudo docker push your_dockerhub_username/nodejs-image-demoДавайте протестируем инструмент реестра образов, уничтожив наш текущий контейнер приложения и образ и перестроив их с использованием образа в нашем репозитории.
Сначала составьте список запущенных контейнеров:
sudo docker psВы получите следующий результат:
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Остановите работающий контейнер приложения, используя идентификатор контейнера, указанный в выводе. Обязательно замените выделенный идентификатор ниже на свой собственный идентификатор контейнера:
sudo docker stop e50ad27074a7Выведите список всех ваших изображений с помощью -a:
docker images -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Остановите контейнер и удалите все образы, включая неиспользуемые или зависшие, с помощью следующей команды:
docker system prune -aПри появлении запроса на выход с просьбой подтвердить удаление контейнера и остановленных образов введите Y. Обратите внимание, что при этом также будет удален кэш сборки.
Вы удалили как контейнер, в котором запущен образ вашего приложения, так и сам образ. Подробнее об удалении контейнеров, образов и томов Docker см. в статье «Как удалить образы, контейнеры и тома Docker».
Удалив все образы и контейнеры, теперь вы можете извлечь образ приложения из Docker Hub:
docker pull your_dockerhub_username/nodejs-image-demoПеречислите свои изображения еще раз:
docker imagesНа выходе вы получите изображение своего приложения:
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Перечислите работающие контейнеры:
docker ps
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.












