Вступление
В последнем руководстве, How для установки и настройки Docker, мы исследовали один метод преобразования https: // www .digitalocean.com / community / tutorials / how-to-install-and-configure-docker # step-2-% E2% 80% 94-launching-Containers [Контейнеры Docker] в https://www.digitalocean.com/ community / tutorials / how-to-install-and-configure-docker # step-4-% E2% 80% 94-building-images [изображения Docker]. Хотя метод, который мы использовали, работал, он не всегда является оптимальным способом построения изображений.
Во многих случаях вы захотите перенести существующий код в образы контейнера, и вам понадобится повторяемый, согласованный механизм для создания образов Docker, которые синхронизируются с последней версией вашей кодовой базы.
Https://docs.docker.com/engine/reference/builder/[Dockerfile] отвечает этим требованиям, предоставляя декларативный и последовательный способ построения образов Docker.
Кроме того, иногда вы захотите контейнировать целые приложения, которые состоят из нескольких разнородных контейнеров, которые развертываются и управляются вместе.
Docker Compose, как и Dockerfile, использует декларативный подход, чтобы предоставить вам метод для определения всего технологического стека, включая требования к сети и хранилищу. Это не только упрощает создание контейнерных приложений, но также облегчает управление ими и их масштабирование.
В этом руководстве вы будете использовать пример веб-приложения на основе Node.js и MongoDB для создания образа Docker из файла Docker. создаст пользовательскую сеть, которая позволит вашим контейнерам Docker взаимодействовать, и вы будете использовать Docker Compose для запуска и масштабирования приложения в контейнере.
Предпосылки
Чтобы следовать этому уроку, вам понадобится:
-
Одна Ubuntu 16.04 Droplet, созданная с помощью этого Ubuntu 16.04 начальное руководство по настройке сервера, включая sudo пользователь root и брандмауэр.
-
Последняя версия Docker Community Edition установлена следующим образом: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-docker#step-4-%E2%80%94-building-images [первый урок в этой серии вебинаров].
Шаг 1 - Создание образа с помощью Dockerfile
Начните с перехода в свой домашний каталог, а затем используйте Git, чтобы клонировать образец веб-приложения этого руководства из его official репозитория. на GitHub.
cd ~
git clone https://github.com/janakiramm/todo-app.git
Это скопирует пример приложения в новый каталог с именем + todo-app +
.
Переключитесь на + todo-app +
и используйте + ls +
для просмотра содержимого каталога.
cd todo-app
ls
Новый каталог содержит две подкаталоги и два файла:
-
+ app +
- каталог, в котором хранится исходный код примера приложения -
+ compose +
- каталог, в котором хранится файл конфигурации Docker Compose -
+ Dockerfile +
- файл, содержащий инструкции для построения образа Docker -
+ README.md +
- файл, содержащий резюме из одного предложения примера приложения
Запуск + cat Dockerfile +
показывает нам следующее:
~ / TODO-приложение / Dockerfile
FROM node:slim
LABEL maintainer = "[email protected]"
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY ./app/ ./
RUN npm install
CMD ["node", "app.js"]
Давайте посмотрим на содержимое этого файла более подробно:
-
+ FROM +
указывает базовое изображение, из которого вы строите пользовательское изображение. В этом примере изображение основано на+ node: slim +
, public Node.js image, который содержит только минимальные пакеты, необходимые для запуска `+ node + `. -
+ LABEL +
- это пара ключ-значение, обычно используемая для добавления описательной информации. В этом случае он содержит адрес электронной почты сопровождающего. -
+ RUN +
выполняет команды внутри контейнера. Это включает в себя такие задачи, как создание каталогов и инициализация контейнера с помощью основных команд Linux. Первая команда+ RUN +
в этом файле используется для создания каталога+ / usr / src / app +
, который содержит исходный код. -
+ WORKDIR +
определяет каталог, в котором выполняются все команды. Обычно это каталог, в который копируется код. -
+ COPY +
копирует файлы с хост-машины в образ контейнера. В этом случае вы копируете весь каталог+ app +
в образ. -
Вторая команда
+ RUN +
выполняет+ npm install +
, чтобы установить зависимости приложения, как определено в+ package.json +
. -
+ CMD +
запускает процесс, который будет поддерживать работу контейнера. В этом примере вы выполните+ node +
с параметром+ app.js +
.
Теперь пришло время создать образ из + Dockerfile
. Используйте переключатель + -t +
, чтобы пометить изображение именем пользователя в реестре, именем изображения и необязательным тегом.
docker build -t /todo-web .
Вывод подтверждает, что изображение + успешно построено +
и помечено соответствующим образом.
Output from docker build -tSending build context to Docker daemon 8.238MB
Step 1/7 : FROM node:slim
---> 286b1e0e7d3f
Step 2/7 : LABEL maintainer = "[email protected]"
---> Using cache
---> ab0e049cf6f8
Step 3/7 : RUN mkdir -p /usr/src/app
---> Using cache
---> 897176832f4d
Step 4/7 : WORKDIR /usr/src/app
---> Using cache
---> 3670f0147bed
Step 5/7 : COPY ./app/ ./
---> Using cache
---> e28c7c1be1a0
Step 6/7 : RUN npm install
---> Using cache
---> 7ce5b1d0aa65
Step 7/7 : CMD node app.js
---> Using cache
---> 2cef2238de24
2cef2238de24
/todo-web:latest
Мы можем проверить, что образ создан, запустив команду + docker images +
.
docker images
Здесь мы можем увидеть размер изображения вместе с временем, прошедшим с момента его создания.
Output from docker imagesREPOSITORY TAG IMAGE ID CREATED SIZE
/todo-web latest 81f5f605d1ca 9 minutes ago 236MB
Поскольку нам также нужен контейнер MongoDB для запуска примера веб-приложения, давайте перенесем его на нашу машину.
docker pull mongo:latest
Вывод сообщает точно, какое изображение было извлечено вместе со статусом загрузки.
Output from docker pulllatest: Pulling from library/mongo
Digest: sha256:18b239b996e0d10f4ce2b0f64db6f410c17ad337e2cecb6210a3dcf2f732ed82
Status: Downloaded newer image for mongo:latest
Теперь у нас есть все, что нужно для запуска примера приложения, поэтому давайте создадим собственную сеть, которая позволит нашим контейнерам взаимодействовать друг с другом.
Шаг 2 - Создание сети для связи контейнеров
Если бы мы запускали контейнеры веб-приложения и базы данных независимо через команду + docker run +
, они не смогли бы найти друг друга.
Чтобы понять почему, просмотрите содержимое файла конфигурации базы данных веб-приложения.
cat app/db.js
После импорта Mongoose - библиотеки объектного моделирования MongoDB для Node.js - и определения нового https://www.digitalocean.com/community/tutorials/understanding-sql-and-nosql -databases-and-different-database-models [схема базы данных], веб-приложение пытается подключиться к базе данных по имени хоста + db +
, которого еще нет.
~ / TODO-приложение / приложение / db.js
var mongoose = require( 'mongoose' );
var Schema = mongoose.Schema;
var Todo = new Schema({
user_id : String,
content : String,
updated_at : Date
});
mongoose.model( 'Todo', Todo );
mongoose.connect( 'mongodb:///express-todo' );
Чтобы контейнеры, принадлежащие одному и тому же приложению, обнаруживали друг друга, нам нужно запустить их в одной сети.
Docker предоставляет возможность создавать собственные сети в дополнение к default сетей, созданных во время установки.
Вы можете проверить свои доступные в настоящее время сети с помощью следующей команды:
docker network ls
Каждая сеть, созданная Docker, основана на driver. В следующем выводе мы видим, что сеть с именем + bridge +
основана на драйвере + bridge +
. Область + local + `указывает, что сеть доступна только на этом хосте.
Output from docker network lsNETWORK ID NAME DRIVER SCOPE
5029df19d0cf
367330960d5c host host local
f280c1593b89 none null local
Теперь мы создадим пользовательскую сеть с именем + todo_net +
для нашего приложения, а затем запустим контейнеры в этой сети.
docker network create todo_net
Вывод сообщает нам хэш сети, которая была создана.
Output from docker network createC09f199809ccb9928dd9a93408612bb99ae08bb5a65833fefd6db2181bfe17ac
Теперь снова перечислите доступные сети.
docker network ls
Здесь мы видим, что + todo_net +
готов к использованию.
Output from docker network lsNETWORK ID NAME DRIVER SCOPE
c51377a045ff bridge bridge local
2e4106b07544 host host local
7a8b4801a712 none null local
Используя команду + docker run +
, мы теперь можем обращаться к этой сети с помощью переключателя + - network +
. Давайте запустим веб-контейнеры и контейнеры базы данных с конкретными именами хостов. Это гарантирует, что контейнеры могут соединяться друг с другом через эти имена хостов.
Сначала запустите контейнер базы данных MongoDB.
docker run -d \
--name=db \
--hostname=db \
--network=todo_net \
mongo
При более внимательном рассмотрении этой команды мы видим:
-
Переключатель
+ -d +
запускает контейнер в режиме detached. -
Переключатели
+ - name +
и+ - hostname +
назначают контейнеру определенное пользователем имя. Переключатель+ - hostname +
также добавляет запись в службу DNS, управляемую Docker. Это помогает в разрешении контейнера по имени хоста. -
Переключатель
+ - network +
указывает Docker Engine запускать контейнер в пользовательской сети вместо мостовой сети по умолчанию.
Когда мы видим длинную строку в качестве результата команды + docker run +
, мы можем предположить, что контейнер успешно запущен. Но это не может гарантировать, что контейнер действительно работает.
Output docker runaa56250f2421c5112cf8e383b68faefea91cd4b6da846cbc56cf3a0f04ff4295
Убедитесь, что контейнер + db +
запущен и работает с командой + docker logs +
.
docker logs db
Это печатает журналы контейнера в + stdout
. Последняя строка журнала указывает, что MongoDB готов и + ожидает подключения +
.
Output from docker logs2017-12-10T02:55:08.284+0000 I CONTROL [initandlisten] MongoDB starting : pid=1 port=27017 dbpath=/data/db 64-bit host=db
. . . .
2017-12-10T02:55:08.366+0000 I NETWORK [initandlisten] on port 27017
Теперь давайте запустим веб-контейнер и проверим его. На этот раз мы также включаем + - publish = 3000: 3000 +
, который публикует порт хоста + 3000 + в порт контейнера + 3000+.
docker run -d \
--name=web \
--publish=3000:3000 \
--hostname=web \
--network=todo_net \
/todo-web
Вы получите длинную строку в качестве вывода, как и раньше.
Давайте также проверим, что этот контейнер запущен и работает.
docker logs web
Вывод подтверждает, что Express - инфраструктура Node.js, на которой основано наше тестовое приложение, - "+ прослушивает порт 3000+".
Output from docker logsExpress server listening on port 3000
Убедитесь, что веб-контейнер может общаться с контейнером db с помощью команды + ping +
. Мы делаем это, выполняя команду + docker exec +
в интерактивном (+ -i +
) режиме, подключенном к псевдо-TTY (+ -t +
).
docker exec -it web ping db
Команда производит стандартный вывод + ping +
и сообщает нам, что два контейнера могут связываться друг с другом.
Output from docker exec -it web ping dbPING db (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.210 ms
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.095 ms
...
Нажмите + CTRL + C +
, чтобы остановить команду + ping +
.
Наконец, откройте пример приложения, указав в веб-браузере + http: // your_server_ip: 3000 +
. Вы увидите веб-страницу с меткой, которая гласит * Пример контейнера *, а также текстовое поле, которое принимает задачу todo в качестве входных данных.
Чтобы избежать конфликтов имен, вы можете теперь остановить контейнеры и очистить ресурсы с помощью команд + docker rm +
и + docker network remove +
.
docker rm -f db
docker rm -f web
docker network remove todo_net
На данный момент у нас есть контейнерное веб-приложение, состоящее из двух отдельных контейнеров. На следующем шаге мы рассмотрим более надежный подход.
Шаг 3 - Развертывание мультиконтейнерного приложения
Хотя мы смогли запустить связанные контейнеры, это не самый элегантный способ работы с мультиконтейнерными приложениями. Нам нужен лучший способ объявить все связанные контейнеры и управлять ими как одной логической единицей.
Docker Compose - это платформа, доступная разработчикам для работы с мультиконтейнерными приложениями. Как и Dockefile, это декларативный механизм для определения всего стека. Теперь мы преобразуем наше приложение Node.js и MongoDB в приложение на основе Docker Compose.
Начните с установки Docker Compose.
sudo apt-get install -y docker-compose
Давайте рассмотрим файл + docker-compose.yaml +
, расположенный в каталоге + compose +
примера веб-приложения.
cat compose/docker-compose.yaml
Файл + docker-compose.yaml +
объединяет все. Он определяет контейнер MongoDB в блоке + db: +
, веб-контейнер Node.js в блоке + web: +
и пользовательскую сеть в блоке + networks: +
.
Обратите внимание, что с помощью директивы + build: ../.+
мы указываем Compose на + Dockerfile +
в каталоге + app +
. Это даст команду Compose создать изображение перед запуском веб-контейнера.
~ / TODO-приложение / создавать / докер-compose.yml
version: '2'
services:
db:
image: mongo:latest
container_name: db
networks:
- todonet
web:
build: ../.
networks:
- todonet
ports:
- "3000"
networks:
todonet:
driver: bridge
Теперь перейдите в каталог + composer
и запустите приложение с помощью команды` + docker-compose up`. Как и в случае + docker run +
, переключатель + -d +
запускает контейнер в отдельном режиме.
cd compose
docker-compose up -d
Вывод сообщает, что Docker Compose создал сеть с именем + compose_todonet +
и запустил в ней оба контейнера.
Output from docker-compose up -dCreating network "compose_todonet" with driver "bridge"
Creating db
Creating compose_web_1
Обратите внимание, что мы не предоставили явное сопоставление портов хоста. Это заставит Docker Compose назначить случайный порт для показа веб-приложения на хосте. Мы можем найти этот порт, выполнив следующую команду:
docker ps
Мы видим, что веб-приложение выставлено на хост-порт + 32782 +
.
Output from docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6700761c0a1e compose_web "node app.js" 2 minutes ago Up 2 minutes 0.0.0.0:->3000/tcp compose_web_1
ad7656ef5db7 mongo:latest "docker-entrypoint..." 2 minutes ago Up 2 minutes 27017/tcp db
Проверьте это, перейдя в веб-браузер к + http: // your_server_ip: 32782 +
. Это вызовет веб-приложение так же, как вы видели его в конце ссылки: # step-2-% E2% 80% 94-создание-сеть-на-ссылку-контейнеры [Шаг 2].
Когда наше многоконтейнерное приложение запущено и работает через Docker Compose, давайте взглянем на управление и масштабирование нашего приложения.
Шаг 4 - Управление и масштабирование приложения
Docker Compose позволяет легко масштабировать веб-приложения без сохранения состояния. Мы можем запустить 10 экземпляров нашего контейнера + web +
с помощью одной команды.
docker-compose scale web=10
Вывод позволяет нам наблюдать за созданием и запуском экземпляров в реальном времени.
Output from docker-compose scaleCreating and starting compose_web_2 ... done
Creating and starting compose_web_3 ... done
Creating and starting compose_web_4 ... done
Creating and starting compose_web_5 ... done
Creating and starting compose_web_6 ... done
Creating and starting compose_web_7 ... done
Creating and starting compose_web_8 ... done
Creating and starting compose_web_9 ... done
Creating and starting compose_web_10 ... done
Убедитесь, что веб-приложение масштабировано до 10 экземпляров, запустив + docker ps +
.
docker ps
Обратите внимание, что Docker назначил случайный порт для показа каждого контейнера + web +
на хосте. Любой из этих портов может быть использован для доступа к приложению.
Output from docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cec405db568d compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:->3000/tcp compose_web_9
56adb12640bb compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:->3000/tcp compose_web_10
4a1005d1356a compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:->3000/tcp compose_web_7
869077de9cb1 compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:->3000/tcp compose_web_8
eef86c56d16f compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:->3000/tcp compose_web_4
26dbce7f6dab compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:->3000/tcp compose_web_5
0b3abd8eee84 compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:->3000/tcp compose_web_3
8f867f60d11d compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:->3000/tcp compose_web_6
36b817c6110b compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:->3000/tcp compose_web_2
6700761c0a1e compose_web "node app.js" 7 minutes ago Up 7 minutes 0.0.0.0:->3000/tcp compose_web_1
ad7656ef5db7 mongo:latest "docker-entrypoint..." 7 minutes ago Up 7 minutes 27017/tcp db
Вы также можете масштабировать веб-контейнер той же командой.
docker-compose scale web=2
На этот раз мы видим, как лишние экземпляры удаляются в режиме реального времени.
Output from docker-composeStopping and removing compose_web_3 ... done
Stopping and removing compose_web_4 ... done
Stopping and removing compose_web_5 ... done
Stopping and removing compose_web_6 ... done
Stopping and removing compose_web_7 ... done
Stopping and removing compose_web_8 ... done
Stopping and removing compose_web_9 ... done
Stopping and removing compose_web_10 ... done
Наконец, перепроверьте экземпляры.
docker ps
Вывод подтверждает, что осталось только два экземпляра.
Output from docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
36b817c6110b compose_web "node app.js" 3 minutes ago Up 3 minutes 0.0.0.0:32787->3000/tcp compose_web_2
6700761c0a1e compose_web "node app.js" 9 minutes ago Up 9 minutes 0.0.0.0:32782->3000/tcp compose_web_1
ad7656ef5db7 mongo:latest "docker-entrypoint..." 9 minutes ago Up 9 minutes 27017/tcp db
Теперь вы можете остановить приложение и, как и раньше, вы также можете очистить ресурсы, чтобы избежать конфликтов имен.
docker-compose stop
docker-compose rm -f
docker network remove compose_todonet
Заключение
Это руководство познакомило вас с Dockerfiles и Docker Compose. Мы начали с Dockerfile в качестве декларативного механизма для создания образов, а затем изучили основы работы с сетями Docker. Наконец, мы масштабировали и управляли мультиконтейнерными приложениями с помощью Docker Compose.
Чтобы расширить вашу новую настройку, вы можете добавить Nginx обратный прокси, работающий внутри другого контейнера направлять запросы в один из доступных контейнеров веб-приложений. Или вы можете воспользоваться DigitalOcean’s Block Storage и https://www.digitalocean.com/ сообщества / учебные пособия / введение в digitalocean-балансировки нагрузки [Load Balancers], чтобы обеспечить долговечность и масштабируемость для контейнерных приложений.