Docker настройка: Установка и настройка Docker в Ubuntu
Содержание
Установка и настройка Docker в Ubuntu
T-Rex
Тираннозавр Рекс
Docker — программное обеспечение для облегчения создания, развертывания и запуска приложений. Разработчик может упаковать приложение и все его зависимости в изолированную среду.
Managed Kubernetes помогает разворачивать контейнерные приложения в инфраструктуре Selectel. Сосредоточьтесь на разработке, а мы займемся рутинными операциями по обеспечению работы вашего кластера Kubernetes.
Создавая аналогичную изолированную среду, Docker схож с виртуальным сервером. Однако, в случае с Docker, значительный прирост производительности дает то, что контейнеры, в отличие от виртуальных машин, используют общее ядро Linux, разделяя его ресурсы.
Еще один важный момент — Docker имеет открытый исходный код. Это означает отсутствие необходимости внесения оплаты за лицензии и большое комьюнити, в котором легко получить ответ на любой вопрос относительно работы Docker.
В этой статье мы разберемся с установкой Docker на операционную систему Ubuntu, создадим образ контейнера на Docker Hub и запустим собственный репозиторий. Также расскажем об утилите Docker Compose для работы с мультиконтейнерными приложениями.
Перед началом установки всех необходимых компонентов, подготовим сервер. Это будет облачный сервер с готовой конфигурацией.
В консоли управления Selectel перейдем в представление Облачная платформа и нажмем на кнопку Создать сервер.
На следующем представлении вводим имя сервера, выбираем образ операционной системы (в нашем случае это Ubuntu 18.04 LTS 64-bit) и фиксированную конфигурацию сервера с 1 vCPU и 2 ГБ RAM. Для тестовых целей будет достаточно диска с 10 ГБ. Еще раз проверяем конфигурацию сервера и нажимаем Создать.
Подождем минуту или две пока сервер не перейдет в состояние Active.
Теперь можем приступать к установке Docker. Поехали!
Docker: системные требования для установки
Один из компонентов окружения Docker — Docker Engine. Эти клиент-серверное приложение, которое обеспечивает следующие компоненты:
- серверная часть с процессом-демоном dockerd;
- API-интерфейсы, которые программы могут использовать для взаимодействия с демоном Docker;
- клиента интерфейса командной строки (CLI), вызываемый командой docker.
Docker Engine поставляется в виде .deb и .rpm пакетов и может быть установлен на любые дистрибутивы семейства Linux (CentOS, Debian, Fedora, Raspbian, Ubuntu). Также есть специальная утилита Docker Desktop, которая позволяет исполнять Docker Engine на операционных системах Windows и MacOS. В обоих случаях, все равно будет использоваться ядро Linux.
Установка Docker на Ubuntu
Чтобы установить Docker на Ubuntu, выполним подготовительные действия. Для начала, обновим состав установочных пакетов, чтобы иметь представление об их актуальных версиях:
sudo apt update
Предварительно установим набор пакетов, необходимый для доступа к репозиториям по протоколу HTTPS:
- apt-transport-https — активирует передачу файлов и данных через https;
- ca-сertificates — активирует проверку сертификаты безопасности;
- curl — утилита для обращения к веб-ресурсам;
- software-properties-common — активирует возможность использования скриптов для управления программным обеспечением.
sudo apt install apt-transport-https ca-certificates curl software-properties-common
Далее добавим в систему GPG-ключ для работы с официальным репозиторием Docker:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Теперь добавим репозиторий Docker в локальный список репозиториев:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
Повторно обновим данные о пакетах операционной системы:
sudo apt update
Приступаем к установке пакета Docker.
sudo apt install docker-ce -y
После завершения установки запустим демон Docker и добавим его в автозагрузку:
sudo systemctl start docker
sudo systemctl enable docker
На этом установка Docker завершена и можно начинать с ним работу.
Установка Docker Compose на Ubuntu
Docker Compose — это инструмент для описания и запуска мультиконтейнерных приложений Docker. Инструмент позволяет пользователям запускать, выполнять, общаться и закрывать контейнеры с помощью одной команды.
Посмотрим последнюю сборку Docker Compose в репозитории на Github и загрузим ее при помощи утилиты curl со следующими параметрами:
- –L разрешает редиректы, если файл перемещен;
- –o модифицирует имя файла для удобства его запуска и указывает каталог для сохранения.
sudo curl -L "https://github.com/docker/compose/releases/download/1.28.6/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
После завершения загрузки, добавим загруженному бинарному файлу права на выполнение:
sudo chmod +x /usr/local/bin/docker-compose
Заметим, что выполнить установку Docker Compose можно было из репозитория Ubuntu командой sudo apt-get install docker-compose. Однако, в репозитории может быть не самая последняя версия. Способ, который мы описали выше, позволит загрузить актуальную версию утилиты Docker Compose.
Чтобы проверить корректность работы утилиты, выполним проверку ее версии:
sudo docker–compose –version
Если команда вернула номер версии, значит Docker Compose готов к работе.
Когда нужно удалить Docker Compose, достаточно выполнить команду удаления файла:
sudo rm /usr/local/bin/docker-compose
Если установка выполнялась через пакетный менеджер apt, нужно его вызвать с параметром purge:
sudo apt purge docker-compose
И следом удалить все невостребованные зависимости:
sudo apt autoremove
Команды Docker и работа с ним
Перед началом работы с Docker, нужно подготовить контейнер. Есть два пути: создать новый контейнер, описав его в Dockerfile или загрузить уже готовый из Docker Hub или другого репозитория. В этом разделе мы рассмотрим вариант создания собственного контейнера с нуля при помощи Dockerfile.
Dockerfile — это скрипт с инструкциями по созданию образа Docker. Эти инструкции представляют собой группу команд, автоматически выполняемых в среде Docker для создания определенного образа Docker.
Создадим новую директорию, перейдем в нее и создадим Dockerfile:
mkdir docker_images
cd docker_images
touch Dockerfile
Откроем Dockerfile и добавим в него несколько строк:
nano Dockerfile
FROM ubuntu
MAINTAINER selectel
RUN apt-get update
CMD ["echo", "Hello World"]
- FROM определяет основу создаваемого изображения. Можно начать с родительского (как в примере выше) или базового образа. При использовании родительского образа вы используете существующий образ, на котором основан новый. Использование базового образа означает, что вы начинаете с нуля (именно так его и определяют: FROM scratch).
- MAINTAINER указывает автора образа. Здесь вы можете ввести ваше имя и/или фамилию (или добавить адрес электронной почты). Также сюда можно вписать инструкцию по добавлению метаданных (LABEL) к образу.
- RUN определяет инструкции по выполнению команды при построении образа в слоях поверх него. В этом примере система ищет обновления репозитория после начала сборки образа Docker. В Dockerfile может быть несколько инструкций RUN.
- CMD отвечает за значение команды по умолчанию, которая будет исполнено. Система выполнит ее, если вы запустите контейнер без указания команды. Внутри Dockerfile может быть только одна инструкция CMD.
Сохраним изменения и выйдем из режима редактирования. Теперь можно приступать к сборке контейнера. Для этого используем утилиту Docker. Базовый синтаксис выглядит так:
sudo docker build [OPTIONS] PATH | URL | -
Запустим утилиту с параметром -t, который указывает на имя образа. Это упростит управление образами, когда их станет несколько.
sudo docker build -t my_image .
После сборки образа, проверим, что он появился в локальном каталоге образов. Получим следующий вывод:
sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my_image latest 889af78121ad 4 seconds ago 100MB
ubuntu latest 4dd97cefde62 2 weeks ago 72.9MB
Казалось бы мы создали только один образ. Откуда там появилось два? Все просто — мы создавали свой контейнер my_ubuntu на на базе образа ubuntu, поэтому вначале скачался образ ubuntu и лишь потом был создан my_image.
Запустим новый контейнер Docker на основе образа, созданного на предыдущих шагах. Назовем контейнер «test» и получим вывод «Hello world» в результате выполнения команды docker run. Ubuntu, CentOS или Debian — операционная система значения не имеет, синтаксис везде будет одинаковый.
sudo docker run --name test my_image
Hello World
После выключения контейнера, все данные, которые он генерировал за время работы удаляются. Чтобы этого не происходило, предусмотрена возможность монтирования внешних хранилищ. Docker автоматически создает каталог /var/lib/docker/volume, в который можно сохранять данные на постоянной основе и совместно их использовать между несколькими контейнерами. Создадим новое хранилище с именем «selectel»:
sudo docker volume create selectel
Теперь запустим контейнер с примонтированным внешним хранилищем:
sudo docker run --name=test --mount source=selectel,destination=/selectel my_image
Таким образом, все данные, которые появятся в директории /selectel внутри контейнера будут надежно храниться на файловой системе сервера.
Контейнеры Docker предназначены для обеспечения изолированной среды со всеми библиотеками и конфигурациями, необходимыми для работы программного обеспечения. Во время разработки их количество может хаотично, в результате появятся устаревшие и неиспользуемые контейнеры. Ниже мы покажем как удалить ненужные контейнеры.
Предварительно выведем в терминал запущенные контейнеры:
sudo docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b52480dd6110 my_image "echo 'Hello World'" 4 minutes ago Exited (0) 4 minutes ago test
Увидим контейнер, который мы только что запустили. Еще один вариант получить список запущенных контейнеров — добавить параметр -a. Так мы увидим список id контейнеров:
sudo docker container ls –aq
b52480dd6110
Можно остановить один контейнер:
sudo docker container stop [container_id]
А можно все разом:
sudo docker container stop $(docker container ls –aq)
Чтобы очистить все данные, созданные контейнером, можно выполнить следующую команду:
sudo docker container stop $(docker container ls –aq) && docker system prune –af ––volumes
Команда выполняет остановку контейнеров, перечисленных в круглых скобках. Атрибут && предписывает Docker удалить все остановленные контейнеры и тома. Параметры –af указывает, что это должно применяться ко всем контейнерам (a) без необходимости подтверждения (f).
А теперь удалим контейнер. Один или все сразу:
sudo docker container rm [container_id]
sudo docker container rm $(docker container ls –aq)
При удалении ненужных контейнеров можно также задавать фильтры. Например, в примере ниже мы удалим все контейнеры без метки мейнтейнера «selectel».
sudo docker container prune --filter=”label!=maintainer=selectel”
Фильтры имеют следующий синтаксис:
- label=<ключ>
- label=<ключ>=<значение>
- label!=<ключ>
- label!=<ключ>=<значение>
Образы Docker — это файлы, которые включают несколько слоев, используемых для запуска кода в контейнере. В процессе разработки некоторые образы могут устаревать и, соответственно, занимать место на диске. Посмотрим какие образы сейчас находятся на файловой системе:
sudo docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
my_image latest 889af78121ad 24 hours ago 100MB
ubuntu latest 4dd97cefde62 2 weeks ago 72.9MB
Чтобы удалить неиспользуемые образы, нужно воспользоваться их идентификатором из колонки IMAGE ID.
docker image rm [image_id1] [image_id2]
Аналогичным контейнерам образом, удаляемые образы можно фильтровать по меткам или по дате создания. Первая команда удаляет образы с меткой «selectel», а вторая все образы, созданные за последние 24 часа.
sudo docker image prune ––filter=”label=selectel”
sudo docker image prune –a ––filter “until=24h”
Так как контейнеры после остановки не сохраняют внутри себя никакие данные. Например, если в контейнере работала база данных и там за время работы контейнера были созданы объекты и данные, после остановки они пропадут. Для этого, к контейнеру монтируются каталоги, расположенные, непосредственно на диске операционной системы. Чтобы просмотреть все такие каталоги, выполним команду:
sudo docker volume ls
Чтобы удалить ненужные разделы Docker, воспользуемся командой:
sudo docker volume rm [VolumeName]
Сети Docker позволяют различным контейнерам свободно обмениваться данными друг с другом, а также изолировать этот трафик. Обычно это делается с помощью сетевого моста Docker. Чтобы посмотреть все имеющиеся сети, выполним:
sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
1e31297e1d6a bridge bridge local
783575476ed4 host host local
c7c5d2496494 none null local
Чтобы удалить ненужные сети Docker, воспользуемся командой:
sudo docker network rm [networkID]
Команда prune автоматически удаляет все ресурсы, не связанные с контейнером. Это упрощенный способ очистки неиспользуемых образов, контейнеров, томов и сетей.
sudo docker system prune
Можно использовать дополнительные параметры:
- -a — для удаления всех остановленных контейнеров и неиспользуемых образов.
- -f — Обойти диалоговое окно подтверждения
- —volumes — Удаляет все неиспользуемые тома.
Эту команду также можно использовать точечно для контейнеров, образов, дисковых разделов и сетей:
sudo docker container prune
sudo docker image prune
sudo docker volume prune
sudo docker network prune
Можно использовать дополнительный параметр -a, в этом случае удаляются неиспользуемые и зависшие объекты.
Работа с репозиторием Docker Hub
Docker Hub — это общедоступный репозиторий образов контейнеров Docker. Каждый раз когда вы создаете собственный контейнер (в примере выше мы делали контейнер на основе операционной системе Ubuntu), с Docker Hub загружается соответствующий образ. Но образы можно не только загружать, но и выгружать. В этом разделе мы расскажем как это сделать.
Прежде чем начать, понадобится учетная запись на Docker Hub. Регистрация бесплатная. Сейчас в нашем тестовом окружении на Docker Hub нет ни одного репозитория. Прежде чем начинать выгрузку создадим один с помощью кнопки Create Repository.
В командной строке введем специальную команду для подключения к Docker Hub. На вход подадим имя учетной записи, которое указывали при регистрации. Затем укажем пароль.
sudo docker login -u [docker-hub-username]
Осталось выгрузить образ в репозиторий. Установим образу метку, а затем зальем его в репозиторий.
sudo docker tag my_image [docker-hub-username]/my_image:0.0.1
sudo docker push [docker-hub-username]/my_image:0.0.1
The push refers to repository [docker.io/[docker-hub-username]/my_image]
8c25b6d14dcf: Pushed
c20d459170d8: Pushed
db978cae6a05: Pushed
aeb3f02e9374: Pushed
0.0.1: digest: sha256: size: 1155
В результате, образ появится в репозитории.
Работа с частным репозиторием
Частный репозиторий — это аналог Docker Hub, только находиться он будет в окружении под вашим управлением.
Запустим локальный репозиторий в контейнере:
docker run -d -p 5000:5000 --restart=always --name registry registry:2
Теперь добавим специальный тег к образу, добавляем созданный образ my_image в репозиторий и для проверки получаем его обратно:
docker tag my_image localhost:5000/my_image
docker push localhost:5000/my_image
docker pull localhost:5000/my_image
Частный репозиторий готов к работе.
Заключение
В статье мы рассмотрели работу с контейнерами на основе Docker, их создание, удаление и размещение в Docker Hub и локальном репозитории. Docker сильно упрощает работу разработчиков и системных администраторов. Легковесные контейнеры потребляют меньшее количество ресурсов (в отличие от виртуальных машин) и полноценно готовы к работе за считанные минуты.
с нуля до кластера на AWS / Хабр
Содержание
Вопросы и ответы
Что такое Докер?
Определение Докера в Википедии звучит так:
программное обеспечение для автоматизации развёртывания и управления приложениями в среде виртуализации на уровне операционной системы; позволяет «упаковать» приложение со всем его окружением и зависимостями в контейнер, а также предоставляет среду по управлению контейнерами.
Ого! Как много информации. Простыми словами, Докер это инструмент, который позволяет разработчикам, системными администраторам и другим специалистам деплоить их приложения в песочнице (которые называются контейнерами), для запуска на целевой операционной системе, например, Linux. Ключевое преимущество Докера в том, что он позволяет пользователям упаковать приложение со всеми его зависимостями в стандартизированный модуль для разработки. В отличие от виртуальных машин, контейнеры не создают такой дополнительной нагрузки, поэтому с ними можно использовать систему и ресурсы более эффективно.
Что такое контейнер?
Стандарт в индустрии на сегодняшний день — это использовать виртуальные машины для запуска приложений. Виртуальные машины запускают приложения внутри гостевой операционной системы, которая работает на виртуальном железе основной операционной системы сервера.
Виртуальные машины отлично подходят для полной изоляции процесса для приложения: почти никакие проблемы основной операционной системы не могут повлиять на софт гостевой ОС, и наоборот. Но за такую изоляцию приходится платить. Существует значительная вычислительная нагрузка, необходимая для виртуализации железа гостевой ОС.
Контейнеры используют другой подход: они предоставляют схожий с виртуальными машинами уровень изоляции, но благодаря правильному задействованию низкоуровневых механизмов основной операционной системы делают это с в разы меньшей нагрузкой.
Почему я должен использовать их?
Взлет Докера был по-настоящему эпичным. Не смотря на то, что контейнеры сами по себе — не новая технология, до Докера они не были так распространены и популярны. Докер изменил ситуацию, предоставив стандартный API, который сильно упростил создание и использование контейнеров, и позволил сообществу вместе работать над библиотеками по работе с контейнерами. В статье, опубликованной в The Register в середине 2014 говорится, что Гугл поддерживает больше двух миллиардов контейнеров в неделю.
Google Trends для слова ‘Docker’
В дополнение к продолжительному росту Докера, компания-разработчик Docker Inc. была оценена в два с лишним миллиарда долларов! Благодаря преимуществам в эффективности и портативности, Докер начал получать все больше поддержки, и сейчас стоит во главе движения по контейнеризации (containerization). Как современные разработчики, мы должны понять этот тренд и выяснить, какую пользу мы можем получить из него.
Чему меня научит это пособие?
Это единое и полное пособие по всем аспектам работы с Докером. Кроме разъяснения мифов о Докере и его экосистеме, оно позволит вам получит небольшой опыт по сборке и деплою собственных веб-приложений в облаке. Мы будем использовать Amazon Web Services для деплоя статичных сайтов, и два динамических веб-приложения задеплоим на EC2 с использованием Elastic Beanstalk и Elastic Container Service. Даже если вы никогда ничего не деплоили, это пособие даст вам все необходимое.
Как использовать этот документ
Этот документ содержит несколько разделов, каждый из которых посвящен определенному аспекту Докера. В каждом разделе мы будем вводить команды или писать код. Весь код доступен в репозитории на Гитхабе.
Введение
Внимание: В этом пособии используется версия Докера 1.12.0-rc2. Если вы столкнулись с несовместимостью, пожалуйста, отправьте issue. Спасибо!
Пре-реквизиты
Все, что нужно для прохождения этого пособия — это базовые навыки с командной строкой и текстовым редактором. Опыт разработки веб-приложений будет полезен, но не обязателен. В течение работы мы столкнемся с несколькими облачными сервисами. Вам понадобится создать аккаунт на этих сайтах:
Настройка компьютера
Установка и настройка всех необходимых инструментов может быть тяжелой задачей, но, к счастью, Докер стал довольно стабильным, и установка и запуск его на любой ОС стало очень простой задачей. Итак, установим Докер.
Докер
Еще несколько релизов назад запуск Докера на OS X и Windows был был проблемным. Но команда разработчиков проделала огромную работу, и сегодня весь процесс — проще некуда. Этот туториал getting started включает в себя подробные инструкции по установке на Мак, Linux и Windows.
Проверим, все ли установлено корректно:
$ docker run hello-world
Hello from Docker.
This message shows that your installation appears to be working correctly.
...
Python
Python обычно предустановлен на OS X и на большинстве дистрибутивов Linux. Если вам нужно установить Питон, то скачайте установщик здесь.
Проверьте версию:
$ python --version
Python 2.7.11
Мы будем использовать pip для установки пакетов для нашего приложения. Если pip не установлен, то скачайте версию для своей системы.
Для проверки запустите такую команду:
$ pip --version
pip 7.1.2 from /Library/Python/2.7/site-packages/pip-7.1.2-py2.7.egg (python 2.7)
Java (не обязательно)
Разрабатываемое нами приложение будет использовать Elasticsearch для хранения и поиска. Для локального запуска Elasticsearch вам понадобится Java. В этом пособии все будет запускаться внутри контейнера, так что локально не обязательно иметь Java. Если Java установлена, то команда java -version
должна сгенерировать подобный вывод:
$ java -version
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
1.0 Играем с Busybox
Теперь, когда все необходимое установлено, пора взяться за работу. В этом разделе мы запустим контейнер Busybox на нашей системе и попробуем запустить docker run
.
Для начала, запустите следующую команду:
$ docker pull busybox
Внимание: в зависимости от того, как вы устанавливали Докер на свою систему, возможно появление сообщения
permission denied
. Если вы на Маке, то удостоверьтесь, что движок Докер запущен. Если вы на Линуксе, то запустите эту команду сsudo
. Или можете создать группу docker чтобы избавиться от этой проблемы.
Команда pull
скачивает образ busybox из регистра Докера и сохраняет его локально. Можно использовать команду docker images
, чтобы посмотреть список образов в системе.
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
busybox latest c51f86c28340 4 weeks ago 1.109 MB
1.1 Docker Run
Отлично! Теперь давайте запустим Докер-контейнер с этим образом. Для этого используем волшебную команду docker run
:
$ docker run busybox
$
Подождите, ничего не произошло! Это баг? Ну, нет. Под капотом произошло много всего. Докер-клиент нашел образ (в нашем случае, busybox), загрузил контейнер и запустил команду внутри этого контейнера. Мы сделали docker run busybox
, но не указали никаких команд, так что контейнер загрузился, запустилась пустая команда и программа завершилась. Ну, да, как-то обидно, так что давайте сделаем что-то поинтереснее.
$ docker run busybox echo "hello from busybox"
hello from busybox
Ура, наконец-то какой-то вывод. В нашем случае клиент Докера послушно запустил команду echo
внутри контейнера, а потом вышел из него. Вы, наверное, заметили, что все произошло очень быстро. А теперь представьте себе, как нужно загружать виртуальную машину, запускать в ней команду и выключать ее. Теперь ясно, почему говорят, что контейнеры быстрые!
Теперь давайте взглянем на команду docker ps
. Она выводит на экран список всех запущенных контейнеров.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Контейнеров сейчас нет, поэтому выводится пустая строка. Не очень полезно, поэтому давайте запустим более полезный вариант: docker ps -a
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
305297d7a235 busybox "uptime" 11 minutes ago Exited (0) 11 minutes ago distracted_goldstine
ff0a5c3750b9 busybox "sh" 12 minutes ago Exited (0) 12 minutes ago elated_ramanujan
Теперь виден список всех контейнеров, которые мы запускали. В колонке STATUS
можно заметить, что контейнеры завершили свою работу несколько минут назад.
Вам, наверное, интересно, как запустить больше одной команды в контейнере. Давайте попробуем:
$ docker run -it busybox sh
/ # ls
bin dev etc home proc root sys tmp usr var
/ # uptime
05:45:21 up 5:58, 0 users, load average: 0.00, 0.01, 0.04
Команда run
с флагом -it
подключает интерактивный tty в контейнер. Теперь можно запускать сколько угодно много команд внутри. Попробуйте.
Опасно!: Если хочется острых ощущений, то можете попробовать
rm -rf bin
в контейнере. Но удостоверьтесь, что запускаете ее внутри контейнера, а не снаружи. Если сделаете это снаружи, на своем компьютере, то будет очень плохо, и команды вродеls
,echo
перестанут работать. Когда внутри контейнера все перестанет работать, просто выйдете и запустите его заново командойdocker run -it busybox sh
. Докер создает новый контейнер при запуске, поэтому все заработает снова.
На этом захватывающий тур по возможностям команды docker run
закончен. Скорее всего, вы будете использовать эту команду довольно часто. Так что важно, чтобы мы поняли как с ней обращаться. Чтобы узнать больше о run
, используйте docker run --help
, и увидите полный список поддерживаемых флагов. Скоро мы увидим еще несколько способов использования docker run
.
Перед тем, как продолжать, давайте вкратце рассмотрим удаление контейнеров. Мы видели выше, что с помощью команды docker ps -a
все еще можно увидеть остатки завершенных контейнеров. На протяжении этого пособия, вы будете запускать docker run
несколько раз, и оставшиеся, бездомные контейнеры будут съедать дисковое пространство. Так что я взял за правило удалять контейнеры после завершения работы с ними. Для этого используется команда docker rm
. Просто скопируйте ID (можно несколько) из вывода выше и передайте параметрами в команду.
$ docker rm 305297d7a235 ff0a5c3750b9
305297d7a235
ff0a5c3750b9
При удалении идентификаторы будут снова выведены на экран. Если нужно удалить много контейнеров, то вместо ручного копирования и вставления можно сделать так:
$ docker rm $(docker ps -a -q -f status=exited)
Эта команда удаляет все контейнеры, у которых статус exited
. Флаг -q
возвращает только численные ID, а флаг -f
фильтрует вывод на основе предоставленных условий. Последняя полезная деталь — команде docker run
можно передать флаг --rm
, тогда контейнер будет автоматически удаляться при завершении. Это очень полезно для разовых запусков и экспериментов с Докером.
Также можно удалять ненужные образы командой docker rmi
.
1.2 Терминология
В предыдущем разделе мы использовали много специфичного для Докера жаргона, и многих это может запутать. Перед тем, как продолжать, давайте разберем некоторые термины, которые часто используются в экосистеме Докера.
- Images (образы) — Схемы нашего приложения, которые являются основой контейнеров. В примере выше мы использовали команду
docker pull
чтобы скачать образ busybox. - Containers (контейнеры) — Создаются на основе образа и запускают само приложение. Мы создали контейнер командой
docker run
, и использовали образ busybox, скачанный ранее. Список запущенных контейнеров можно увидеть с помощью командыdocker ps
. - Docker Daemon (демон Докера) — Фоновый сервис, запущенный на хост-машине, который отвечает за создание, запуск и уничтожение Докер-контейнеров. Демон — это процесс, который запущен на операционной системе, с которой взаимодействует клиент.
- Docker Client (клиент Докера) — Утилита командной строки, которая позволяет пользователю взаимодействовать с демоном. Существуют другие формы клиента, например, Kitematic, с графическим интерфейсом.
- Docker Hub — Регистр Докер-образов. Грубо говоря, архив всех доступных образов. Если нужно, то можно содержать собственный регистр и использовать его для получения образов.
2.0 Веб-приложения и Докер
Супер! Теперь мы научились работать с docker run
, поиграли с несколькими контейнерами и разобрались в терминологии. Вооруженные этими знаниями, мы готовы переходить к реальным штукам: деплою веб-приложений с Докером!
2.1 Статические сайты
Давайте начнем с малого. Вначале рассмотрим самый простой статический веб-сайт. Скачаем образ из Docker Hub, запустим контейнер и посмотрим, насколько легко будет запустить веб-сервер.
Поехали. Для одностраничного сайта нам понадобится образ, который я заранее создал для этого пособия и разместил в регистре — prakhar1989/static-site
. Можно скачать образ напрямую командой docker run
.
$ docker run prakhar1989/static-site
Так как образа не существует локально, клиент сначала скачает образ из регистра, а потом запустит его. Если все без проблем, то вы увидите сообщение Nginx is running...
в терминале. Теперь сервер запущен. Как увидеть сайт в действии? На каком порту работает сервер? И, что самое важное, как напрямую достучаться до контейнера из хост-контейнера?
В нашем случае клиент не открывает никакие порты, так что нужно будет перезапустить команду docker run
чтобы сделать порты публичными. Заодно давайте сделаем так, чтобы терминал не был прикреплен к запущенному контейнеру. В таком случае можно будет спокойно закрыть терминал, а контейнер продолжит работу. Это называется detached mode.
$ docker run -d -P --name static-site prakhar1989/static-site
e61d12292d69556eabe2a44c16cbd54486b2527e2ce4f95438e504afb7b02810
Флаг -d
открепит (detach) терминал, флаг -P
сделает все открытые порты публичными и случайными, и, наконец, флаг --name
это имя, которое мы хотим дать контейнеру. Теперь можно увидеть порты с помощью команды docker port [CONTAINER]
.
$ docker port static-site
80/tcp -> 0.0.0.0:32769
443/tcp -> 0.0.0.0:32768
Откройте http://localhost:32769 в своем браузере.
Замечание: Если вы используете docker-toolbox, то, возможно, нужно будет использовать
docker-machine ip default
чтобы получить IP-адрес.
Также можете обозначить свой порт. Клиент будет перенаправлять соединения на него.
$ docker run -p 8888:80 prakhar1989/static-site
Nginx is running...
Чтобы остановить контейнер запустите docker stop
и укажите идентификатор (ID) контейнера.
Согласитесь, все было очень просто. Чтобы задеплоить это на реальный сервер, нужно просто установить Докер и запустить команду выше. Теперь, когда вы увидели, как запускать веб-сервер внутри образа, вам, наверное, интересно — а как создать свой Докер-образ? Мы будем изучать эту тему в следующем разделе.
2.2 Образы
Мы касались образов ранее, но в этом разделе мы заглянем глубже: что такое Докер-образы и как создавать собственные образы. Наконец, мы используем собственный образ чтобы запустить приложение локально, а потом задеплоим его на AWS, чтобы показать друзьям. Круто? Круто! Давайте начнем.
Образы это основы для контейнеров. В прошлом примере мы скачали (pull) образ под названием Busybox из регистра, и попросили клиент Докера запустить контейнер, основанный на этом образе. Чтобы увидеть список доступных локально образов, используйте команду docker images
.
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
prakhar1989/catnip latest c7ffb5626a50 2 hours ago 697.9 MB
prakhar1989/static-site latest b270625a1631 21 hours ago 133.9 MB
python 3-onbuild cf4002b2c383 5 days ago 688.8 MB
martin/docker-cleanup-volumes latest b42990daaca2 7 weeks ago 22.14 MB
ubuntu latest e9ae3c220b23 7 weeks ago 187.9 MB
busybox latest c51f86c28340 9 weeks ago 1.109 MB
hello-world latest 0a6ba66e537a 11 weeks ago 960 B
Это список образов, которые я скачал из регистра, а также тех, что я сделал сам (скоро увидим, как это делать). TAG
— это конкретный снимок или снэпшот (snapshot) образа, а IMAGE ID
— это соответствующий уникальный идентификатор образа.
Для простоты, можно относиться к образу как к git-репозиторию. Образы можно коммитить с изменениями, и можно иметь несколько версий. Если не указывать конкретную версию, то клиент по умолчанию использует latest
. Например, можно скачать определенную версию образа ubuntu
:
$ docker pull ubuntu:12.04
Чтобы получить новый Докер-образ, можно скачать его из регистра (такого, как Docker Hub) или создать собственный. На Docker Hub есть десятки тысяч образов. Можно искать напрямую из командной строки с помощью docker search
.
Важно понимать разницу между базовыми и дочерними образами:
- Base images (базовые образы) — это образы, которые не имеют родительского образа. Обычно это образы с операционной системой, такие как ubuntu, busybox или debian.
- Child images (дочерние образы) — это образы, построенные на базовых образах и обладающие дополнительной функциональностью.
Существуют официальные и пользовательские образы, и любые из них могут быть базовыми и дочерними.
- Официальные образы — это образы, которые официально поддерживаются командой Docker. Обычно в их названии одно слово. В списке выше
python
,ubuntu
,busybox
иhello-world
— базовые образы. - Пользовательские образы — образы, созданные простыми пользователями вроде меня и вас. Они построены на базовых образах. Обычно, они называются по формату
user/image-name
.
2.3 Наш первый образ
Теперь, когда мы лучше понимаем, что такое образы и какие они бывают, самое время создать собственный образ. Цель этого раздела — создать образ с простым приложением на Flask. Для этого пособия я сделал маленькое приложение, которое выводит случайную гифку с кошкой. Ну, потому что, кто не любит кошек? Склонируйте этот репозиторий к себе на локальную машину.
Вначале давайте проверим, что приложение работает локально. Войдите в директорию flask-app
командой cd
и установите зависимости.
$ cd flask-app
$ pip install -r requirements.txt
$ python app.py
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Если все хорошо, то вы увидите вывод как в примере выше. Зайдите на http://localhost:5000 чтобы увидеть приложение в действии.
Замечание: Если команда
pip install
падает с ошибками «permission denied», то попробуйте запустить ее сsudo
. Если не хотите устанавливать пользовательские пакеты на уровне системы, то используйте командуpip install --user -r requirements.txt
.
Выглядит отлично, правда? Теперь нужно создать образ с приложением. Как говорилось выше, все пользовательские образы основаны на базовом образе. Так как наше приложение написано на Питоне, нам нужен базовый образ Python 3. В частности, нам нужна версия python:3-onbuild
базового образа с Питоном.
Что за версия onbuild
, спросите вы?
Эти образы включают несколько триггеров ONBUILD, которых обычно достаточно чтобы быстро развернуть приложение. При сборке будет скопирован файл
requirements.txt
, будет запущенpip install
с этим файлом, а потом текущая директория будет скопирована в/usr/src/app
.
Другими словами, версия onbuild
включает хелперы, которые автоматизируют скучные процессы запуска приложения. Вместо того, чтобы вручную выполнять эти задачи (или писать скрипты), образы делают все за вас. Теперь у нас есть все ингредиенты для создания своего образа: работающее веб-приложение и базовый образ. Как это сделать? Ответ: использовать Dockerfile.
2.4 Dockerfile
Dockerfile — это простой текстовый файл, в котором содержится список команд Докер-клиента. Это простой способ автоматизировать процесс создания образа. Самое классное, что команды в Dockerfile почти идентичны своим аналогам в Linux. Это значит, что в принципе не нужно изучать никакой новый синтаксис чтобы начать работать с докерфайлами.
В директории с приложением есть Dockerfile, но так как мы делаем все впервые, нам нужно создать его с нуля. Создайте новый пустой файл в любимом текстовом редакторе, и сохраните его в той же директории, где находится flask-приложение. Назовите файл Dockerfile
.
Для начала укажем базовый образ. Для этого нужно использовать ключевое слово FROM
.
FROM python:3-onbuild
Дальше обычно указывают команды для копирования файлов и установки зависимостей. Но к счастью, onbuild
-версия базового образа берет эти задачи на себя. Дальше нам нужно указать порт, который следует открыть. Наше приложение работает на порту 5000, поэтому укажем его:
EXPOSE 5000
Последний шаг — указать команду для запуска приложения. Это просто python ./app.py
. Для этого используем команду CMD:
CMD ["python", "./app.py"]
Главное предназначение CMD
— это сообщить контейнеру какие команды нужно выполнить при старте. Теперь наш Dockerfile
готов. Вот как он выглядит:
# our base image
FROM python:3-onbuild
# specify the port number the container should expose
EXPOSE 5000
# run the application
CMD ["python", "./app.py"]
Теперь можно создать образ. Команда docker build
занимается сложной задачей создания образа на основе Dockerfile
.
Листинг ниже демонстрирует процесс. Перед тем, как запустите команду сами (не забудьте точку в конце), проверьте, чтобы там был ваш username вместо моего. Username должен соответствовать тому, что использовался при регистрации на Docker hub. Если вы еще не регистрировались, то сделайте это до выполнения команды. Команда docker build
довольно проста: она принимает опциональный тег с флагом -t
и путь до директории, в которой лежит Dockerfile
.
$ docker build -t prakhar1989/catnip .
Sending build context to Docker daemon 8.704 kB
Step 1 : FROM python:3-onbuild
# Executing 3 build triggers...
Step 1 : COPY requirements.txt /usr/src/app/
---> Using cache
Step 1 : RUN pip install --no-cache-dir -r requirements.txt
---> Using cache
Step 1 : COPY . /usr/src/app
---> 1d61f639ef9e
Removing intermediate container 4de6ddf5528c
Step 2 : EXPOSE 5000
---> Running in 12cfcf6d67ee
---> f423c2f179d1
Removing intermediate container 12cfcf6d67ee
Step 3 : CMD python ./app.py
---> Running in f01401a5ace9
---> 13e87ed1fbc2
Removing intermediate container f01401a5ace9
Successfully built 13e87ed1fbc2
Если у вас нет образа python:3-onbuild
, то клиент сначала скачает его, а потом возьмется за создание вашего образа. Так что, вывод на экран может отличаться от моего. Посмотрите внимательно, и найдете триггеры onbuild. Если все прошло хорошо, то образ готов! Запустите docker images
и увидите свой образ в списке.
Последний шаг — запустить образ и проверить его работоспособность (замените username на свой):
$ docker run -p 8888:5000 prakhar1989/catnip
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Зайдите на указанный URL и увидите приложение в работе.
Поздравляю! Вы успешно создали свой первый образ Докера!
2.5 Docker на AWS
Что хорошего в приложении, которое нельзя показать друзьям, правда? Так что в этом разделе мы научимся деплоить наше офигенное приложение в облако. Будем использовать AWS Elastic Beanstalk чтобы решить эту задачу за пару кликов. Мы увидим, как с помощью Beanstalk легко управлять и масштабировать наше приложение.
Docker push
Первое, что нужно сделать перед деплоем на AWS это опубликовать наш образ в регистре, чтобы можно было скачивать его из AWS. Есть несколько Docker-регистров (или можно создать собственный). Для начала, давайте используем Docker Hub. Просто выполните:
$ docker push prakhar1989/catnip
Если это ваша первая публикация, то клиент попросит вас залогиниться. Введите те же данные, что используете для входа в Docker Hub.
$ docker login
Username: prakhar1989
WARNING: login credentials saved in /Users/prakhar/.docker/config.json
Login Succeeded
Не забудьте заменить название образа на свое. Очень важно сохранить формат username/image_name
, чтобы клиент понимал, куда публиковать образ.
После этого можете посмотреть на свой образ на Docker Hub. Например, вот страница моего образа.
Замечание: один важный момент, который стоит прояснить перед тем, как продолжить — не обязательно хранить образ в публичном регистре (или в любом другом регистре вообще) чтобы деплоить на AWS. Если вы пишете код для следующего многомиллионного стартапа-единорога, то можно пропустить этот шаг. Мы публикуем свой образ чтобы упростить деплой, пропустив несколько конфигурационных шагов.
Теперь наш образ онлайн, и любой докер-клиент может поиграться с ним с помощью простой команды:
$ docker run -p 8888:5000 prakhar1989/catnip
Если в прошлом вы мучались с установкой локального рабочего окружения и попытками поделиться своей конфигурацией с коллегами, то понимаете, как круто это звучит. Вот почему Докер — это сила!
Beanstalk
AWS Elastic Beanstalk (EB) это PaaS (Platform as a Service — платформа как сервис) от Amazon Web Services. Если вы использовали Heroku, Google App Engine и т.д., то все будет привычно. Как разработчик, вы сообщаете EB как запускать ваше приложение, а EB занимается всем остальным, в том числе масштабированием, мониторингом и даже апдейтами. В апреле 2014 в EB добавили возможность запускать Докер-контейнеры, и мы будем использовать именно эту возможность для деплоя. У EB очень понятный интерфейс командной строки, но он требует небольшой конфигурации, поэтому для простоты давайте используем веб-интерфейс для запуска нашего приложения.
Чтобы продолжать, вам потребуется работающий аккаунт на AWS. Если у вас его нет, то создайте его. Для этого потребуется ввести данные кредитной карты. Но не волнуйтесь, эта услуга бесплатна, и все, что будет происходить в рамках этого пособия тоже бесплатно.
Давайте начнем:
- Войдите в свою консоль AWS.
- Нажмите на Elastic Beanstalk. Ссылка находится в секции compute, в левом верхнем углу. Или просто перейдите сюда.
- Нажмите на «Create New Application» в верхнем правом углу.
- Дайте своему приложению запоминающееся (но уникальное) имя и, если хотите, добавьте описание.
- на экране New Environment выберите Web Server Environment.
- Следующий экран показан ниже. Выберите Docker из готовых вариантов конфигурации. Можно оставить Environment type как есть. Нажмите Next.
- Тут мы будем сообщать системе EB о нашем образе. Откройте файл Dockerrun.aws.json в директории
flask-app
и изменитеName
образа, чтобы оно соответствовало названию вашего образа. Не волнуйтесь, я опишу содержание файла попозже. Потом выберите вариант «upload your own» и выберите файл. - Далее, выберите название окружения и URL. Этот URL как раз можно будет давать друзьям, так что постарайтесь придумать что-нибудь попроще.
- Пока не будем вносить никаких правок в секцию Additional Resources. Нажмите Next и переходите к Configuration Details.
- В этой секции вам нужно выбрать тип инстанса
t1.micro
. Это очень важно, потому что это бесплатный тип от AWS. Если хотите, можно выбрать пару ключей для входа. Если вы не знаете, что это значит, то не волнуйтесь и просто пропустите эту часть. Все остальное можно оставить по умолчанию и продолжать. - Также не нужно указывать никакие Environment Tags and Permissions, так что просто жмите Next два раза подряд. В конце будет экран Review. Если все выглядит нормально, то нажимайте кнопку Launch.
- На последнем экране будет несколько спиннеров. Это поднимается и настраивается ваше окружение. Обычно, нужно около пяти минут для первой настройки.
Пока ждем, давайте быстренько взглянем на файл Dockerrun.aws.json
. Это файл для AWS, в котором находится информация о приложении конфигурации Докера. EB получает информацию из этого файла.
{
"AWSEBDockerrunVersion": "1",
"Image": {
"Name": "prakhar1989/catnip",
"Update": "true"
},
"Ports": [
{
"ContainerPort": "5000"
}
],
"Logging": "/var/log/nginx"
}
Файл довольно понятный, но всегда можно обратиться к официальной документации. Мы указываем название образа, и EB будет использовать его заодно с портом.
К этому моменту инстанс уже должен быть готов. Зайдите на страницу EB и увидите зеленый индикатор успешного запуска приложения.
Зайдите на указанный URL в браузере и увидите приложение во все красе. Пошлите адрес своим друзьям, чтобы все могли насладиться гифками с кошками.
Поздравляю! Вы задеплоили свое первое Докер-приложение! Может показаться, что было очень много шагов, но с командной утилитой EB можно имитировать функциональность Хероку несколькими нажатиями клавиш. Надеюсь, вы согласитесь, что Докер сильно упрощает процесс и минимизирует болезненные моменты деплоя в облако. Я советую вам почитать документацию AWS про single-container Docker environment чтобы понимать, какие существуют возможности в EB.
В следующей, последней части пособия, мы пойдем немного дальше и задеплоим приложение, приближенное к реальному миру. В нем будет постоянное бэкэнд-хранилище. Поехали!
3.0 Многоконтейнерные окружения
В прошлом разделе мы увидели, как легко и просто запускать приложения с помощью Докера. Мы начали с простого статического сайта, а потом запустили Flask-приложение. Оба варианта можно было запускать локально или в облаке, несколькими командами. Общая черта этих приложений: каждое из них работало в одном контейнере.
Если у вас есть опыт управления сервисами в продакшене, то вы знаете, что современные приложения обычно не такие простые. Почти всегда есть база данных (или другой тип постоянного хранилища). Системы вроде Redis и Memcached стали практически обязательной частью архитектуры веб-приложений. Поэтому, в этом разделе мы научимся «докеризировать» приложения, которым требуется несколько запущенных сервисов.
В частности, мы увидим, как запускать и управлять многоконтейнерными Докер-окружениями. Почему нужно несколько контейнеров, спросите вы? Ну, одна из главных идей Докера в том, что он предоставляет изоляцию. Идея совмещения процесса и его зависимостей в одной песочнице (называемой контейнером) и делает Докер мощным инструментом.
Аналогично тому, как приложение разбивают на части, стоит содержать отдельные сервисы в отдельных контейнерах. Разным частям скорее всего требуются разные ресурсы, и требования могут расти с разной скоростью. Если мы разделим эти части и поместим в разные контейнеры, то каждую часть приложения можно строить, используя наиболее подходящий тип ресурсов. Это также хорошо совмещается с идеей микро сервисов. Это одна из причин, по которой Докер (и любая другая технология контейнеризации) находится на передовой современных микро сервисных архитектур.
3.1 SF Food Trucks
Приложение, которое мы переведем в Докер, называется SF Food Trucks (к сожалению, сейчас приложение уже не работает публично — прим. пер.). Моя цель была сделать что-то полезное (и похожее на настоящее приложение из реального мира), что-то, что использует как минимум один сервис, но не слишком сложное для этого пособия. Вот что я придумал.
Бэкэнд приложения написано на Питоне (Flask), а для поиска используется Elasticsearch. Как и все остальное в этом пособии, код находится на Github. Мы используем это приложение, чтобы научиться запускать и деплоить много-контейнерное окружение.
Теперь, когда вы завелись (надеюсь), давайте подумаем, как будет выглядеть этот процесс. В нашем приложении есть бэкэнд на Flask и сервис Elasticsearch. Очевидно, что можно поделить приложение на два контейнера: один для Flask, другой для Elasticsearch (ES). Если приложение станет популярным, то можно будет добавлять новые контейнеры в нужном месте, смотря где будет узкое место.
Отлично, значит нужно два контейнера. Это не сложно, правда? Мы уже создавали Flask-контейнер в прошлом разделе. А для Elasticsearch… давайте посмотрим, есть ли что-нибудь в хабе:
$ docker search elasticsearch
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
elasticsearch Elasticsearch is a powerful open source se... 697 [OK]
itzg/elasticsearch Provides an easily configurable Elasticsea... 17 [OK]
tutum/elasticsearch Elasticsearch image - listens in port 9200. 15 [OK]
barnybug/elasticsearch Latest Elasticsearch 1.7.2 and previous re... 15 [OK]
digitalwonderland/elasticsearch Latest Elasticsearch with Marvel & Kibana 12 [OK]
monsantoco/elasticsearch ElasticSearch Docker image 9 [OK]
Не удивительно, но существуют официальный образ для Elasticsearch. Чтобы запустить ES, нужно всего лишь выполнить docker run
, и вскоре у нас будет локальный, работающий контейнер с одним узлом ES.
$ docker run -dp 9200:9200 elasticsearch
d582e031a005f41eea704cdc6b21e62e7a8a42021297ce7ce123b945ae3d3763
$ curl 0.0.0.0:9200
{
"name" : "Ultra-Marine",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.1.1",
"build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
"build_timestamp" : "2015-12-15T13:05:55Z",
"build_snapshot" : false,
"lucene_version" : "5.3.1"
},
"tagline" : "You Know, for Search"
}
Заодно давайте запустим контейнер с Flask. Но вначале нужен Dockerfile
. В прошлой секции мы использовали образ python:3-onbuild
в качестве базового. Однако, в этом раз, кроме установки зависимостей через pip
, нам нужно, чтобы приложение генерировало минимизированный Javascript-файл для продакшена. Для этого понадобится Nodejs. Так что нужен свой билд с нуля, поэтому начнем с базового образа ubuntu
.
Замечание: если оказывается, что существующий образ не подходит для вашей задачи, то спокойно создавайте свой образ на основе другого базового образа. В большинстве случаем, для образов на Docker Hub можно найти соответствующий
Dockerfile
на Github. Почитайте существующий Докерфайлы — это один из лучших способов научиться делать свои образы.
Наш Dockerfile для Flask-приложения выглядит следующим образом:
# start from base
FROM ubuntu:14.04
MAINTAINER Prakhar Srivastav <[email protected]>
# install system-wide deps for python and node
RUN apt-get -yqq update
RUN apt-get -yqq install python-pip python-dev
RUN apt-get -yqq install nodejs npm
RUN ln -s /usr/bin/nodejs /usr/bin/node
# copy our application code
ADD flask-app /opt/flask-app
WORKDIR /opt/flask-app
# fetch app specific deps
RUN npm install
RUN npm run build
RUN pip install -r requirements.txt
# expose port
EXPOSE 5000
# start app
CMD [ "python", "./app.py" ]
Тут много всего нового. Вначале указан базовый образ Ubuntu LTS, потом используется пакетный менеджер apt-get
для установки зависимостей, в частности — Python и Node. Флаг yqq
нужен для игнорирования вывода и автоматического выбора «Yes» во всех местах. Также создается символическая ссылка для бинарного файла node. Это нужно для решения проблем обратной совместимости.
Потом мы используем команду ADD
для копирования приложения в нужную директорию в контейнере — /opt/flask-app
. Здесь будет находиться весь наш код. Мы также устанавливаем эту директорию в качестве рабочей, так что следующие команды будут выполняться в контексте этой локации. Теперь, когда наши системные зависимости установлены, пора установить зависимости уровня приложения. Начнем с Node, установки пакетов из npm и запуска команды сборки, как указано в нашем файле package.json. В конце устанавливаем пакеты Python, открываем порт и определяем запуск приложения с помощь CMD
, как в предыдущем разделе.
Наконец, можно собрать образ и запустить контейнер (замените prakhar1989
на свой username ниже).
$ docker build -t prakhar1989/foodtrucks-web .
При первом запуске нужно будет больше времени, так как клиент Докера будет скачивать образ ubuntu, запускать все команды и готовить образ. Повторный запуск docker build
после последующих изменений будет практически моментальным. Давайте попробуем запустить приложение
$ docker run -P prakhar1989/foodtrucks-web
Unable to connect to ES. Retying in 5 secs...
Unable to connect to ES. Retying in 5 secs...
Unable to connect to ES. Retying in 5 secs...
Out of retries. Bailing out...
Упс! Наше приложение не смогло запуститься, потому что оно не может подключиться к Elasticsearch. Как сообщить одному контейнеру о другом и как заставить их взаимодействовать друг с другом? Ответ — в следующей секции.
3.2 Сети Docker
Перед тем, как обсудить возможности Докера для решения описанной задачи, давайте посмотрим на возможные варианты обхода проблемы. Думаю, это поможет нам оценить удобство той функциональности, которую мы вскоре изучим.
Ладно, давайте запустим docker ps
, что тут у нас:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e931ab24dedc elasticsearch "/docker-entrypoint.s" 2 seconds ago Up 2 seconds 0.0.0.0:9200->9200/tcp, 9300/tcp cocky_spence
Итак, у нас есть контейнер ES по адресу и порту 0.0.0.0:9200
, и мы можем напрямую обращаться к нему. Если можно было бы сообщить нашему приложению подключаться к этому адресу, то оно сможет общаться с ES, верно? Давайте взглянем на код на Питоне, туда, где описано подключение.
es = Elasticsearch(host='es')
Нужно сообщить Flask-контейнеру, что контейнер ES запущен на хосте 0.0.0.0
(порт по умолчанию 9200
), и все заработает, да? К сожалению, нет, потому что IP 0.0.0.0
это адрес для доступа к контейнеру с хост-машины, то есть с моего Мака. Другой контейнер не сможет обратиться по этому адресу. Ладно, если не этот адрес, то какой другой адрес нужно использовать для работы с контейнером ES? Рад, что вы спросили.
Это хороший момент, чтобы изучить работу сети в Докере. После установки, Докер автоматически создает три сети:
$ docker network ls
NETWORK ID NAME DRIVER
075b9f628ccc none null
be0f7178486c host host
8022115322ec bridge bridge
Сеть bridge — это сеть, в которой контейнеры запущены по умолчанию. Это значит, что когда я запускаю контейнер ES, он работает в этой сети bridge. Чтобы удостовериться, давайте проверим:
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "8022115322ec80613421b0282e7ee158ec41e16f565a3e86fa53496105deb2d7",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.17.0.0/16"
}
]
},
"Containers": {
"e931ab24dedc1640cddf6286d08f115a83897c88223058305460d7bd793c1947": {
"EndpointID": "66965e83bf7171daeb8652b39590b1f8c23d066ded16522daeb0128c9c25c189",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
}
}
]
Видно, что контейнер e931ab24dedc
находится в секции Containers
. Также виден IP-адрес, выданный этому контейнеру — 172.17.0.2
. Именно этот адрес мы и искали? Давайте проверим: запустим Flask-приложение и попробуем обратиться к нему по IP:
$ docker run -it --rm prakhar1989/foodtrucks-web bash
root@35180ccc206a:/opt/flask-app# curl 172.17.0.2:9200
bash: curl: command not found
root@35180ccc206a:/opt/flask-app# apt-get -yqq install curl
root@35180ccc206a:/opt/flask-app# curl 172.17.0.2:9200
{
"name" : "Jane Foster",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.1.1",
"build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
"build_timestamp" : "2015-12-15T13:05:55Z",
"build_snapshot" : false,
"lucene_version" : "5.3.1"
},
"tagline" : "You Know, for Search"
}
root@35180ccc206a:/opt/flask-app# exit
Сейчас все должно быть понятно. Мы запустили контейнер в интерактивном режиме с процессом bash
. Флаг --rm
нужен для удобства, благодаря нему контейнер автоматически удаляется после выхода. Мы попробуем curl
, но нужно сначала установить его. После этого можно удостовериться, что по адресу 172.17.0.2:9200
на самом деле можно обращаться к ES! Супер!
Не смотря на то, что мы нашли способ наладить связь между контейнерами, существует несколько проблем с этим подходом:
- Придется добавлять записи в файл
/etc/hosts
внутри Flask-контейнера, чтобы приложение понимало, что имя хостаes
означает172.17.0.2
. Если IP-адрес меняется, то придется вручную менять запись. - Так как сеть bridge используется всеми контейнерами по умолчанию, этот метод не безопасен.
Но есть хорошие новости: в Докере есть отличное решение этой проблемы. Докер позволяет создавать собственные изолированные сети. Это решение также помогает справиться с проблемой /etc/hosts
, сейчас увидим как.
Во-первых, давайте создадим свою сеть:
$ docker network create foodtrucks
1a3386375797001999732cb4c4e97b88172d983b08cd0addfcb161eed0c18d89
$ docker network ls
NETWORK ID NAME DRIVER
1a3386375797 foodtrucks bridge
8022115322ec bridge bridge
075b9f628ccc none null
be0f7178486c host host
Команда network create
создает новую сеть bridge. Нам сейчас нужен именно такой тип. Существуют другие типы сетей, и вы можете почитать о них в официальной документации.
Теперь у нас есть сеть. Можно запустить наши контейнеры внутри сети с помощью флага --net
. Давайте так и сделаем, но сначала остановим контейнер с ElasticSearch, который был запущен в сети bridge по умолчанию.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e931ab24dedc elasticsearch "/docker-entrypoint.s" 4 hours ago Up 4 hours 0.0.0.0:9200->9200/tcp, 9300/tcp cocky_spence
$ docker stop e931ab24dedc
e931ab24dedc
$ docker run -dp 9200:9200 --net foodtrucks --name es elasticsearch
2c0b96f9b8030f038e40abea44c2d17b0a8edda1354a08166c33e6d351d0c651
$ docker network inspect foodtrucks
[
{
"Name": "foodtrucks",
"Id": "1a3386375797001999732cb4c4e97b88172d983b08cd0addfcb161eed0c18d89",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{}
]
},
"Containers": {
"2c0b96f9b8030f038e40abea44c2d17b0a8edda1354a08166c33e6d351d0c651": {
"EndpointID": "15eabc7989ef78952fb577d0013243dae5199e8f5c55f1661606077d5b78e72a",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {}
}
]
Мы сделали то же, что и раньше, но на этот раз дали контейнеру название es
. Перед тем, как запускать контейнер с приложением, давайте проверим что происходит, когда запуск происходит в сети.
$ docker run -it --rm --net foodtrucks prakhar1989/foodtrucks-web bash
root@53af252b771a:/opt/flask-app# cat /etc/hosts
172.18.0.3 53af252b771a
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.2 es
172.18.0.2 es.foodtrucks
root@53af252b771a:/opt/flask-app# curl es:9200
bash: curl: command not found
root@53af252b771a:/opt/flask-app# apt-get -yqq install curl
root@53af252b771a:/opt/flask-app# curl es:9200
{
"name" : "Doctor Leery",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.1.1",
"build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
"build_timestamp" : "2015-12-15T13:05:55Z",
"build_snapshot" : false,
"lucene_version" : "5.3.1"
},
"tagline" : "You Know, for Search"
}
root@53af252b771a:/opt/flask-app# ls
app.py node_modules package.json requirements.txt static templates webpack.config.js
root@53af252b771a:/opt/flask-app# python app.py
Index not found...
Loading data in elasticsearch ...
Total trucks loaded: 733
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
root@53af252b771a:/opt/flask-app# exit
Ура! Работает! Магическим образом Докер внес нужные правки в файл /etc/hosts
, и поэтому es:9200
можно использовать в приложении — этот адрес корректно направляет запросы в контейнер ES. Отлично! Давайте теперь запустим Flask-контейнер по-настоящему:
$ docker run -d --net foodtrucks -p 5000:5000 --name foodtrucks-web prakhar1989/foodtrucks-web
2a1b77e066e646686f669bab4759ec1611db359362a031667cacbe45c3ddb413
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a1b77e066e6 prakhar1989/foodtrucks-web "python ./app.py" 2 seconds ago Up 1 seconds 0.0.0.0:5000->5000/tcp foodtrucks-web
2c0b96f9b803 elasticsearch "/docker-entrypoint.s" 21 minutes ago Up 21 minutes 0.0.0.0:9200->9200/tcp, 9300/tcp es
$ curl -I 0.0.0.0:5000
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 3697
Server: Werkzeug/0.11.2 Python/2.7.6
Date: Sun, 10 Jan 2016 23:58:53 GMT
Зайдите на http://0.0.0.0:5000, и увидите приложение в работе. Опять же, может показаться, что было много работы, но на самом деле мы ввели всего 4 команды чтобы с нуля дойти до работающего приложения. Я собрал эти команды в bash-скрипт.
#!/bin/bash
# build the flask container
docker build -t prakhar1989/foodtrucks-web .
# create the network
docker network create foodtrucks
# start the ES container
docker run -d --net foodtrucks -p 9200:9200 -p 9300:9300 --name es elasticsearch
# start the flask app container
docker run -d --net foodtrucks -p 5000:5000 --name foodtrucks-web prakhar1989/foodtrucks-web
Теперь представьте, что хотите поделиться приложением с другом. Или хотите запустить на сервере, где установлен Докер. Можно запустить всю систему с помощью одной команды!
$ git clone https://github.com/prakhar1989/FoodTrucks
$ cd FoodTrucks
$ ./setup-docker.sh
Вот и все! По-моему, это невероятно крутой и мощный способ распространять и запускать приложения!
Docker Links
Перед тем, как завершить этот раздел, стоит отметить, что docker network
это относительно новая фича, она входит в релиз Docker 1.9 .
До того, как появился network
, ссылки были допустимым способом настройки взаимодействия между контейнерами. В соответствии с официальной документацией, linking вскоре будет переведены в статус deprecated. Если вам попадется туториал или статья, где используется link
для соединения контейнеров, то просто не забывайте использовать вместо этого network
(на момент публикации перевода links является legacy, — прим. пер.)
3.3 Docker Compose
До этого момента мы изучали клиент Докера. Но в экосистеме Докера есть несколько других инструментов с открытым исходным кодом, которые хорошо взаимодействуют с Докером. Некоторые из них это:
- Docker Machine позволяет создавать Докер-хосты на своем компьютере, облачном провайдере или внутри дата-центра.
- Docker Compose — инструмент для определения и запуска много-контейнерных приложений.
- Docker Swarm — нативное решение для кластеризации.
В этом разделе мы поговорим об одном из этих инструментов — Docker Compose, и узнаем, как он может упростить работу с несколькими контейнерами.
У Docker Compose довольно интересная предыстория. Примерно два года назад компания OrchardUp запустила инструмент под названием Fig. Идея была в том, чтобы создавать изолированные рабочие окружения с помощью Докера. Проект очень хорошо восприняли на Hacker News — я смутно помню, что читал о нем, но не особо понял его смысла.
Первый комментарий на самом деле неплохо объясняет, зачем нужен Fig и что он делает:
На самом деле, смысл Докера в следующем: запускать процессы. Сегодня у Докера есть неплохое API для запуска процессов: расшаренные между контейнерами (иными словами, запущенными образами) разделы или директории (shared volumes), перенаправление портов с хост-машины в контейнер, вывод логов, и так далее. Но больше ничего: Докер сейчас работает только на уровне процессов.
Не смотря на то, что в нем содержатся некоторые возможности оркестрации нескольких контейнеров для создания единого «приложения», в Докере нет ничего, что помогало бы с управлением такими группами контейнеров как одной сущностью. И вот зачем нужен инструмент вроде Fig: чтобы обращаться с группой контейнеров как с единой сущностью. Чтобы думать о «запуске приложений» (иными словами, «запуске оркестрированного кластера контейнеров») вместо «запуска контейнеров».
Оказалось, что многие пользователи Докера согласны с такими мыслями. Постепенно, Fig набрал популярность, Docker Inc. заметили, купили компанию и назвали проект Docker Compose.
Итак, зачем используется Compose? Это инструмент для простого определения и запуска многоконтейнерных Докер-приложений. В нем есть файл docker-compose.yml
, и с его помощью можно одной командой поднять приложение с набором сервисов.
Давайте посмотрим, сможем ли мы создать файл docker-compose.yml
для нашего приложения SF-Foodtrucks и проверим, способен ли он на то, что обещает.
Но вначале нужно установить Docker Compose. Есть у вас Windows или Mac, то Docker Compose уже установлен — он идет в комплекте с Docker Toolbox. На Linux можно установить Docker Compose следуя простым инструкциям на сайте документации. Compose написан на Python, поэтому можно сделать просто pip install docker-compose
. Проверить работоспособность так:
$ docker-compose version
docker-compose version 1.7.1, build 0a9ab35
docker-py version: 1.8.1
CPython version: 2.7.9
OpenSSL version: OpenSSL 1.0.1j 15 Oct 2014
Теперь можно перейти к следующему шагу, то есть созданию файла docker-compose.yml
. Синтаксис yml
-файлов очень простой, и в репозитории уже есть пример, который мы будем использовать
version: "2"
services:
es:
image: elasticsearch
web:
image: prakhar1989/foodtrucks-web
command: python app.py
ports:
- "5000:5000"
volumes:
- .:/code
Давайте я разберу это подробнее. На родительском уровне мы задали название неймспейса для наших сервисов: es
и web
. К каждому сервису можно добавить дополнительные параметры, среди которых image
— обязательный. Для es
мы указываем доступный на Docker Hub образ elasticsearch
. Для Flask-приложения — тот образ, который мы создали самостоятельно в начале этого раздела.
С помощью других параметров вроде command
и ports
можно предоставить информацию о контейнере. volumes
отвечает за локацию монтирования, где будет находиться код в контейнере web
. Это опциональный параметр, он полезен, если нужно обращаться к логам и так далее. Подробнее о параметрах и возможных значениях можно прочитать в документации.
Замечание: Нужно находиться в директории с файлом
docker-compose.yml
чтобы запускать большую часть команд Compose.
Отлично! Файл готов, давайте посмотрим на docker-compose
в действии. Но вначале нужно удостовериться, что порты свободны. Так что если у вас запущены контейнеры Flask и ES, то пора их остановить:
$ docker stop $(docker ps -q)
39a2f5df14ef
2a1b77e066e6
Теперь можно запускать docker-compose
. Перейдите в директорию с приложением Foodtrucks и выполните команду docker-compose up
.
$ docker-compose up
Creating network "foodtrucks_default" with the default driver
Creating foodtrucks_es_1
Creating foodtrucks_web_1
Attaching to foodtrucks_es_1, foodtrucks_web_1
es_1 | [2016-01-11 03:43:50,300][INFO ][node ] [Comet] version[2.1.1], pid[1], build[40e2c53/2015-12-15T13:05:55Z]
es_1 | [2016-01-11 03:43:50,307][INFO ][node ] [Comet] initializing ...
es_1 | [2016-01-11 03:43:50,366][INFO ][plugins ] [Comet] loaded [], sites []
es_1 | [2016-01-11 03:43:50,421][INFO ][env ] [Comet] using [1] data paths, mounts [[/usr/share/elasticsearch/data (/dev/sda1)]], net usable_space [16gb], net total_space [18.1gb], spins? [possibly], types [ext4]
es_1 | [2016-01-11 03:43:52,626][INFO ][node ] [Comet] initialized
es_1 | [2016-01-11 03:43:52,632][INFO ][node ] [Comet] starting ...
es_1 | [2016-01-11 03:43:52,703][WARN ][common.network ] [Comet] publish address: {0.0.0.0} is a wildcard address, falling back to first non-loopback: {172.17.0.2}
es_1 | [2016-01-11 03:43:52,704][INFO ][transport ] [Comet] publish_address {172.17.0.2:9300}, bound_addresses {[::]:9300}
es_1 | [2016-01-11 03:43:52,721][INFO ][discovery ] [Comet] elasticsearch/cEk4s7pdQ-evRc9MqS2wqw
es_1 | [2016-01-11 03:43:55,785][INFO ][cluster.service ] [Comet] new_master {Comet}{cEk4s7pdQ-evRc9MqS2wqw}{172.17.0.2}{172.17.0.2:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
es_1 | [2016-01-11 03:43:55,818][WARN ][common.network ] [Comet] publish address: {0.0.0.0} is a wildcard address, falling back to first non-loopback: {172.17.0.2}
es_1 | [2016-01-11 03:43:55,819][INFO ][http ] [Comet] publish_address {172.17.0.2:9200}, bound_addresses {[::]:9200}
es_1 | [2016-01-11 03:43:55,819][INFO ][node ] [Comet] started
es_1 | [2016-01-11 03:43:55,826][INFO ][gateway ] [Comet] recovered [0] indices into cluster_state
es_1 | [2016-01-11 03:44:01,825][INFO ][cluster.metadata ] [Comet] [sfdata] creating index, cause [auto(index api)], templates [], shards [5]/[1], mappings [truck]
es_1 | [2016-01-11 03:44:02,373][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,510][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,593][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,708][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:03,047][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Перейдите по IP чтобы увидеть приложение. Круто, да? Всего лишь пара строк конфигурации и несколько Докер-контейнеров работают в унисон. Давайте остановим сервисы и перезапустим в detached mode:
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Killing foodtrucks_web_1 ... done
Killing foodtrucks_es_1 ... done
$ docker-compose up -d
Starting foodtrucks_es_1
Starting foodtrucks_web_1
$ docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------
foodtrucks_es_1 /docker-entrypoint.sh elas ... Up 9200/tcp, 9300/tcp
foodtrucks_web_1 python app.py Up 0.0.0.0:5000->5000/tcp
Не удивительно, но оба контейнера успешно запущены. Откуда берутся имена? Их Compose придумал сам. Но что насчет сети? Его Compose тоже делаем сам? Хороший вопрос, давайте выясним.
Для начала, остановим запущенные сервисы. Их всегда можно вернуть одной командой:
$ docker-compose stop
Stopping foodtrucks_web_1 ... done
Stopping foodtrucks_es_1 ... done
Заодно, давайте удалим сеть foodtrucks
, которую создали в прошлый раз. Эта сеть нам не потребуется, потому что Compose автоматически сделает все за нас.
$ docker network rm foodtrucks
$ docker network ls
NETWORK ID NAME DRIVER
4eec273c054e bridge bridge
9347ae8783bd none null
54df57d7f493 host host
Класс! Теперь в этом чистом состоянии можно проверить, способен ли Compose на волшебство.
$ docker-compose up -d
Recreating foodtrucks_es_1
Recreating foodtrucks_web_1
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f50bb33a3242 prakhar1989/foodtrucks-web "python app.py" 14 seconds ago Up 13 seconds 0.0.0.0:5000->5000/tcp foodtrucks_web_1
e299ceeb4caa elasticsearch "/docker-entrypoint.s" 14 seconds ago Up 14 seconds 9200/tcp, 9300/tcp foodtrucks_es_1
Пока все хорошо. Проверим, создались ли какие-нибудь сети:
$ docker network ls
NETWORK ID NAME DRIVER
0c8b474a9241 bridge bridge
293a141faac3 foodtrucks_default bridge
b44db703cd69 host host
0474c9517805 none null
Видно, что Compose самостоятельно создал сеть foodtrucks_default
и подсоединил оба сервиса в эту сеть, так, чтобы они могли общаться друг с другом. Каждый контейнер для сервиса подключен к сети, и оба контейнера доступны другим контейнерам в сети. Они доступны по hostname, который совпадает с названием контейнера. Давайте проверим, находится ли эта информация в /etc/hosts
.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bb72dcebd379 prakhar1989/foodtrucks-web "python app.py" 20 hours ago Up 19 hours 0.0.0.0:5000->5000/tcp foodtrucks_web_1
3338fc79be4b elasticsearch "/docker-entrypoint.s" 20 hours ago Up 19 hours 9200/tcp, 9300/tcp foodtrucks_es_1
$ docker exec -it bb72dcebd379 bash
root@bb72dcebd379:/opt/flask-app# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.2 bb72dcebd379
Упс! Оказывается, файл понятия не имеет о es
. Как же наше приложение работает? Давайте попингуем его по названию хоста:
root@bb72dcebd379:/opt/flask-app# ping es
PING es (172.18.0.3) 56(84) bytes of data.
64 bytes from foodtrucks_es_1.C
--- es ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.049/0.056/0.064/0.010 ms
Вуаля! Работает! Каким-то магическим образом контейнер смог сделать пинг хоста es
. Оказывается, Docker 1.10 добавили новую сетевую систему, которая производит обнаружение сервисов через DNS-сервер. Если интересно, то почитайте подробнее о предложении и release notes.
На этом наш тур по Docker Compose завершен. С этим инструментом можно ставить сервисы на паузу, запускать отдельные команды в контейнере и даже масштабировать систему, то есть увеличивать количество контейнеров. Также советую изучать некоторые другие примеры использования Docker Compose.
Надеюсь, я продемонстрировал как на самом деле просто управлять многоконтейнерной средой с Compose. В последнем разделе мы задеплоим все на AWS!
3.4 AWS Elastic Container Service
В прошлом разделе мы использовали docker-compose
чтобы запустить наше приложение локально одной командой: docker-compose up
. Теперь, когда приложение работает, мы хотим показать его миру, заполучить юзеров, поднять кучу денег и купить большой дом в Майами. Последние три шага выходят за пределы этого пособия, так что займемся выяснением деталей о деплое многоконтейнерного приложения в облако AWS.
Если вы дочитали до этого места, то скорее всего убедились, что Docker — довольно крутая технология. И вы не одиноки. Облачные провайдеры заметили взрывной рост популярности Докера и стали добавлять поддержку в свои сервисы. Сегодня, Докер-приложения можно деплоить на AWS, Azure,Rackspace, DigitalOcean и много других. Мы уже умеем деплоить приложение с одним контейнером на Elastic Beanstalk, а в этом разделе мы изучим AWS Elastic Container Service (или ECS).
AWS ECS — это масштабируемый и гибкий сервис по управлению контейнерами, и он поддерживает Докер. С его помощью можно управлять кластером на EC2 через простой API. В Beanstalk были нормальные настройки по умолчанию, но ECS позволяет настроить каждый аспект окружения по вашим потребностям. По этой причине ECS — не самый простой инструмент в начале пути.
К счастью, у ECS есть удобный инструмент командной строки (CLI) с поддержкой Docker Compose и автоматической провизией на ECS! Так как у нас уже есть рабочий файл docker-compose.yml
, настройка и запуск на AWS должна быть достаточно легкой. Начнем!
Вначале нужно установить CLI. На момент написания этого пособия CLI-утилита не доступна на Windows. Инструкции по установке CLI на Mac и Linux хорошо описаны на сайте с официальной документацией. Установите утилиту, а потом проверьте ее работоспособность так:
$ ecs-cli --version
ecs-cli version 0.1.0 (*cbdc2d5)
Первый шаг — задать пару ключей для авторизации на инстансах. Зайдите на страницу EC2 Console и создайте новый keypair. Скачайте файл и держите его в безопасном месте. Еще один момент — имя региона. Я назвал свой ключ ecs
и указал регион us-east-1
. Я продолжу повествование с этим допущением.
Теперь настройте CLI:
$ ecs-cli configure --region us-east-1 --cluster foodtrucks
INFO[0000] Saved ECS CLI configuration for cluster (foodtrucks)
Команда configure
с именем региона, в котором хотим разместить наш кластер, и название кластера. Нужно указать тот же регион, что использовался прри создании ключей. Если у вас не настроен AWS CLI, то следуйте руководству, которое подробно описывает все шаги.
Следующий шаг позволяет утилите создавать шаблон CloudFormation.
$ ecs-cli up --keypair ecs --capability-iam --size 2 --instance-type t2.micro
INFO[0000] Created cluster cluster=foodtrucks
INFO[0001] Waiting for your cluster resources to be created
INFO[0001] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0061] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0122] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0182] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0242] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
Здесь мы указываем названия ключей, которые мы скачали (в моем случае ecs
), количество инстансов (--size
) и тип инстансов, на которых хотим запускать контейнеры. Флаг --capability-iam
говорит утилите, что мы понимаем, что эта команда может создать ресурсы IAM.
В последнем шаге мы используем файл docker-compose.yml
. Требуется небольшое изменение, так что вместо модификации файла, давайте сделаем копию и назовем ее aws-compose.yml
. Содержание этого файла (после изменений):
es:
image: elasticsearch
cpu_shares: 100
mem_limit: 262144000
web:
image: prakhar1989/foodtrucks-web
cpu_shares: 100
mem_limit: 262144000
ports:
- "80:5000"
links:
- es
Единственные отличия от оригинального файла docker-compose.yml
это параметры mem_limit
и cpu_shares
для каждого контейнера.
Также, мы убрали version
и services
, так как AWS еще не поддерживает версию 2 файлового формата Compose. Так как наше приложение будет работать на инстансах типа t2.micro
, мы задали 250 мегабайт памяти. Теперь нам нужно опубликовать образ на Docker Hub. На момент написания этого пособия, ecs-cli не поддерживает команду build
. Но Docker Compose поддерживает ее без проблем.
$ docker push prakhar1989/foodtrucks-web
Красота! Давайте запустим финальную команду, которая произведет деплой на ECS!
$ ecs-cli compose --file aws-compose.yml up
INFO[0000] Using ECS task definition TaskDefinition=ecscompose-foodtrucks:2
INFO[0000] Starting container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es
INFO[0000] Starting container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web
INFO[0000] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0000] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0036] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0048] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0048] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0060] Started container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-foodtrucks:2
INFO[0060] Started container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-foodtrucks:2
То, что вывод похож на вывод Docker Compose — не совпадение. Аргумент --file
используется для переопределения файла по умолчанию (docker-compose.yml
). Если все прошло хорошо, то вы увидите строку desiredStatus=RUNNING lastStatus=RUNNING
в самом конце.
Круто! Теперь приложение запущено. Как к нему обратиться?
ecs-cli ps
Name State Ports TaskDefinition
845e2368-170d-44a7-bf9f-84c7fcd9ae29/web RUNNING 54.86.14.14:80->5000/tcp ecscompose-foodtrucks:2
845e2368-170d-44a7-bf9f-84c7fcd9ae29/es RUNNING ecscompose-foodtrucks:2
Откройте http://54.86.14.14 в браузере, и увидите Food Trucks во всей своей желто-черной красе! Заодно, давайте взглянем на консоль AWS ECS.
Видно, что был создан ECS-кластер ‘foodtrucks’, и в нем выполняется одна задача с двумя инстансами. Советую поковыряться в этой консоли и изучить разные ее части и опции.
Вот и все. Всего несколько команд — и приложение работает на AWS!
4.0 Заключение
Мы подошли к концу. После длинного, изматывающего, но интересного пособия вы готовы захватить мир контейнеров! Если вы следовали пособию до самого конца, то можете заслуженно гордиться собой. Вы научились устанавливать Докер, запускать свои контейнеры, запускать статические и динамические веб-сайты и, самое главное, получили опыт деплоя приложений в облако.
Надеюсь, прохождение этого руководства помогло вам стать увереннее в своих способностях управляться с серверами. Когда у вас появится новая идея для сайта или приложения, можете быть уверены, что сможете показать его людям с минимальными усилиями.
4.1 Следующие шаги
Ваше путешествие в мир контейнеров только началось. Моей целью в этом руководстве было нагулять ваш аппетит и показать мощь Докера. В мире современных технологий иногда бывает сложно разобраться самостоятельно, и руководства вроде этого призваны помогать вам. Это такое пособие, которое мне хотелось бы иметь, когда я только знакомился с Докером сам. Надеюсь, ему удалось заинтересовать вас, так что теперь вы сможете следить за прогрессом в этом области не со стороны, а с позиции знающего человека.
Ниже — список дополнительных полезных ресурсов. Советую использовать Докер в вашем следующем проекте. И не забывайте — практика приводит к совершенству.
Дополнительные ресурсы
Удачи, юный падаван!
4.2 Фидбек автору
Теперь моя очередь задавать вопросы. Вам понравилось пособие? Оно показалось вам запутанным, или вам удалось научиться чему-то?
Напишите мне (автору оригинального пособия, — прим. пер.) напрямую на [email protected] или просто создайте issue. Я есть в Твиттере, так что если хотите, то можете писать туда.
(Автор оригинального пособия говорит по-английски, — прим. пер.).
Буду рад услышать ваши отзывы. Не стесняйтесь предлагать улучшения или указывать на мои ошибки. Я хочу, чтобы это пособие стало одним из лучших стартовых руководств в интернете. У меня не получится это без вашей помощи.
с нуля до кластера на AWS / Хабр
Содержание
Вопросы и ответы
Что такое Докер?
Определение Докера в Википедии звучит так:
программное обеспечение для автоматизации развёртывания и управления приложениями в среде виртуализации на уровне операционной системы; позволяет «упаковать» приложение со всем его окружением и зависимостями в контейнер, а также предоставляет среду по управлению контейнерами.
Ого! Как много информации. Простыми словами, Докер это инструмент, который позволяет разработчикам, системными администраторам и другим специалистам деплоить их приложения в песочнице (которые называются контейнерами), для запуска на целевой операционной системе, например, Linux. Ключевое преимущество Докера в том, что он позволяет пользователям упаковать приложение со всеми его зависимостями в стандартизированный модуль для разработки. В отличие от виртуальных машин, контейнеры не создают такой дополнительной нагрузки, поэтому с ними можно использовать систему и ресурсы более эффективно.
Что такое контейнер?
Стандарт в индустрии на сегодняшний день — это использовать виртуальные машины для запуска приложений. Виртуальные машины запускают приложения внутри гостевой операционной системы, которая работает на виртуальном железе основной операционной системы сервера.
Виртуальные машины отлично подходят для полной изоляции процесса для приложения: почти никакие проблемы основной операционной системы не могут повлиять на софт гостевой ОС, и наоборот. Но за такую изоляцию приходится платить. Существует значительная вычислительная нагрузка, необходимая для виртуализации железа гостевой ОС.
Контейнеры используют другой подход: они предоставляют схожий с виртуальными машинами уровень изоляции, но благодаря правильному задействованию низкоуровневых механизмов основной операционной системы делают это с в разы меньшей нагрузкой.
Почему я должен использовать их?
Взлет Докера был по-настоящему эпичным. Не смотря на то, что контейнеры сами по себе — не новая технология, до Докера они не были так распространены и популярны. Докер изменил ситуацию, предоставив стандартный API, который сильно упростил создание и использование контейнеров, и позволил сообществу вместе работать над библиотеками по работе с контейнерами. В статье, опубликованной в The Register в середине 2014 говорится, что Гугл поддерживает больше двух миллиардов контейнеров в неделю.
Google Trends для слова ‘Docker’
В дополнение к продолжительному росту Докера, компания-разработчик Docker Inc. была оценена в два с лишним миллиарда долларов! Благодаря преимуществам в эффективности и портативности, Докер начал получать все больше поддержки, и сейчас стоит во главе движения по контейнеризации (containerization). Как современные разработчики, мы должны понять этот тренд и выяснить, какую пользу мы можем получить из него.
Чему меня научит это пособие?
Это единое и полное пособие по всем аспектам работы с Докером. Кроме разъяснения мифов о Докере и его экосистеме, оно позволит вам получит небольшой опыт по сборке и деплою собственных веб-приложений в облаке. Мы будем использовать Amazon Web Services для деплоя статичных сайтов, и два динамических веб-приложения задеплоим на EC2 с использованием Elastic Beanstalk и Elastic Container Service. Даже если вы никогда ничего не деплоили, это пособие даст вам все необходимое.
Как использовать этот документ
Этот документ содержит несколько разделов, каждый из которых посвящен определенному аспекту Докера. В каждом разделе мы будем вводить команды или писать код. Весь код доступен в репозитории на Гитхабе.
Введение
Внимание: В этом пособии используется версия Докера 1.12.0-rc2. Если вы столкнулись с несовместимостью, пожалуйста, отправьте issue. Спасибо!
Пре-реквизиты
Все, что нужно для прохождения этого пособия — это базовые навыки с командной строкой и текстовым редактором. Опыт разработки веб-приложений будет полезен, но не обязателен. В течение работы мы столкнемся с несколькими облачными сервисами. Вам понадобится создать аккаунт на этих сайтах:
Настройка компьютера
Установка и настройка всех необходимых инструментов может быть тяжелой задачей, но, к счастью, Докер стал довольно стабильным, и установка и запуск его на любой ОС стало очень простой задачей. Итак, установим Докер.
Докер
Еще несколько релизов назад запуск Докера на OS X и Windows был был проблемным. Но команда разработчиков проделала огромную работу, и сегодня весь процесс — проще некуда. Этот туториал getting started включает в себя подробные инструкции по установке на Мак, Linux и Windows.
Проверим, все ли установлено корректно:
$ docker run hello-world
Hello from Docker.
This message shows that your installation appears to be working correctly.
...
Python
Python обычно предустановлен на OS X и на большинстве дистрибутивов Linux. Если вам нужно установить Питон, то скачайте установщик здесь.
Проверьте версию:
$ python --version
Python 2.7.11
Мы будем использовать pip для установки пакетов для нашего приложения. Если pip не установлен, то скачайте версию для своей системы.
Для проверки запустите такую команду:
$ pip --version
pip 7.1.2 from /Library/Python/2.7/site-packages/pip-7.1.2-py2.7.egg (python 2.7)
Java (не обязательно)
Разрабатываемое нами приложение будет использовать Elasticsearch для хранения и поиска. Для локального запуска Elasticsearch вам понадобится Java. В этом пособии все будет запускаться внутри контейнера, так что локально не обязательно иметь Java. Если Java установлена, то команда java -version
должна сгенерировать подобный вывод:
$ java -version
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
1.0 Играем с Busybox
Теперь, когда все необходимое установлено, пора взяться за работу. В этом разделе мы запустим контейнер Busybox на нашей системе и попробуем запустить docker run
.
Для начала, запустите следующую команду:
$ docker pull busybox
Внимание: в зависимости от того, как вы устанавливали Докер на свою систему, возможно появление сообщения
permission denied
. Если вы на Маке, то удостоверьтесь, что движок Докер запущен. Если вы на Линуксе, то запустите эту команду сsudo
. Или можете создать группу docker чтобы избавиться от этой проблемы.
Команда pull
скачивает образ busybox из регистра Докера и сохраняет его локально. Можно использовать команду docker images
, чтобы посмотреть список образов в системе.
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
busybox latest c51f86c28340 4 weeks ago 1.109 MB
1.1 Docker Run
Отлично! Теперь давайте запустим Докер-контейнер с этим образом. Для этого используем волшебную команду docker run
:
$ docker run busybox
$
Подождите, ничего не произошло! Это баг? Ну, нет. Под капотом произошло много всего. Докер-клиент нашел образ (в нашем случае, busybox), загрузил контейнер и запустил команду внутри этого контейнера. Мы сделали docker run busybox
, но не указали никаких команд, так что контейнер загрузился, запустилась пустая команда и программа завершилась. Ну, да, как-то обидно, так что давайте сделаем что-то поинтереснее.
$ docker run busybox echo "hello from busybox"
hello from busybox
Ура, наконец-то какой-то вывод. В нашем случае клиент Докера послушно запустил команду echo
внутри контейнера, а потом вышел из него. Вы, наверное, заметили, что все произошло очень быстро. А теперь представьте себе, как нужно загружать виртуальную машину, запускать в ней команду и выключать ее. Теперь ясно, почему говорят, что контейнеры быстрые!
Теперь давайте взглянем на команду docker ps
. Она выводит на экран список всех запущенных контейнеров.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Контейнеров сейчас нет, поэтому выводится пустая строка. Не очень полезно, поэтому давайте запустим более полезный вариант: docker ps -a
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
305297d7a235 busybox "uptime" 11 minutes ago Exited (0) 11 minutes ago distracted_goldstine
ff0a5c3750b9 busybox "sh" 12 minutes ago Exited (0) 12 minutes ago elated_ramanujan
Теперь виден список всех контейнеров, которые мы запускали. В колонке STATUS
можно заметить, что контейнеры завершили свою работу несколько минут назад.
Вам, наверное, интересно, как запустить больше одной команды в контейнере. Давайте попробуем:
$ docker run -it busybox sh
/ # ls
bin dev etc home proc root sys tmp usr var
/ # uptime
05:45:21 up 5:58, 0 users, load average: 0.00, 0.01, 0.04
Команда run
с флагом -it
подключает интерактивный tty в контейнер. Теперь можно запускать сколько угодно много команд внутри. Попробуйте.
Опасно!: Если хочется острых ощущений, то можете попробовать
rm -rf bin
в контейнере. Но удостоверьтесь, что запускаете ее внутри контейнера, а не снаружи. Если сделаете это снаружи, на своем компьютере, то будет очень плохо, и команды вродеls
,echo
перестанут работать. Когда внутри контейнера все перестанет работать, просто выйдете и запустите его заново командойdocker run -it busybox sh
. Докер создает новый контейнер при запуске, поэтому все заработает снова.
На этом захватывающий тур по возможностям команды docker run
закончен. Скорее всего, вы будете использовать эту команду довольно часто. Так что важно, чтобы мы поняли как с ней обращаться. Чтобы узнать больше о run
, используйте docker run --help
, и увидите полный список поддерживаемых флагов. Скоро мы увидим еще несколько способов использования docker run
.
Перед тем, как продолжать, давайте вкратце рассмотрим удаление контейнеров. Мы видели выше, что с помощью команды docker ps -a
все еще можно увидеть остатки завершенных контейнеров. На протяжении этого пособия, вы будете запускать docker run
несколько раз, и оставшиеся, бездомные контейнеры будут съедать дисковое пространство. Так что я взял за правило удалять контейнеры после завершения работы с ними. Для этого используется команда docker rm
. Просто скопируйте ID (можно несколько) из вывода выше и передайте параметрами в команду.
$ docker rm 305297d7a235 ff0a5c3750b9
305297d7a235
ff0a5c3750b9
При удалении идентификаторы будут снова выведены на экран. Если нужно удалить много контейнеров, то вместо ручного копирования и вставления можно сделать так:
$ docker rm $(docker ps -a -q -f status=exited)
Эта команда удаляет все контейнеры, у которых статус exited
. Флаг -q
возвращает только численные ID, а флаг -f
фильтрует вывод на основе предоставленных условий. Последняя полезная деталь — команде docker run
можно передать флаг --rm
, тогда контейнер будет автоматически удаляться при завершении. Это очень полезно для разовых запусков и экспериментов с Докером.
Также можно удалять ненужные образы командой docker rmi
.
1.2 Терминология
В предыдущем разделе мы использовали много специфичного для Докера жаргона, и многих это может запутать. Перед тем, как продолжать, давайте разберем некоторые термины, которые часто используются в экосистеме Докера.
- Images (образы) — Схемы нашего приложения, которые являются основой контейнеров. В примере выше мы использовали команду
docker pull
чтобы скачать образ busybox. - Containers (контейнеры) — Создаются на основе образа и запускают само приложение. Мы создали контейнер командой
docker run
, и использовали образ busybox, скачанный ранее. Список запущенных контейнеров можно увидеть с помощью командыdocker ps
. - Docker Daemon (демон Докера) — Фоновый сервис, запущенный на хост-машине, который отвечает за создание, запуск и уничтожение Докер-контейнеров. Демон — это процесс, который запущен на операционной системе, с которой взаимодействует клиент.
- Docker Client (клиент Докера) — Утилита командной строки, которая позволяет пользователю взаимодействовать с демоном. Существуют другие формы клиента, например, Kitematic, с графическим интерфейсом.
- Docker Hub — Регистр Докер-образов. Грубо говоря, архив всех доступных образов. Если нужно, то можно содержать собственный регистр и использовать его для получения образов.
2.0 Веб-приложения и Докер
Супер! Теперь мы научились работать с docker run
, поиграли с несколькими контейнерами и разобрались в терминологии. Вооруженные этими знаниями, мы готовы переходить к реальным штукам: деплою веб-приложений с Докером!
2.1 Статические сайты
Давайте начнем с малого. Вначале рассмотрим самый простой статический веб-сайт. Скачаем образ из Docker Hub, запустим контейнер и посмотрим, насколько легко будет запустить веб-сервер.
Поехали. Для одностраничного сайта нам понадобится образ, который я заранее создал для этого пособия и разместил в регистре — prakhar1989/static-site
. Можно скачать образ напрямую командой docker run
.
$ docker run prakhar1989/static-site
Так как образа не существует локально, клиент сначала скачает образ из регистра, а потом запустит его. Если все без проблем, то вы увидите сообщение Nginx is running...
в терминале. Теперь сервер запущен. Как увидеть сайт в действии? На каком порту работает сервер? И, что самое важное, как напрямую достучаться до контейнера из хост-контейнера?
В нашем случае клиент не открывает никакие порты, так что нужно будет перезапустить команду docker run
чтобы сделать порты публичными. Заодно давайте сделаем так, чтобы терминал не был прикреплен к запущенному контейнеру. В таком случае можно будет спокойно закрыть терминал, а контейнер продолжит работу. Это называется detached mode.
$ docker run -d -P --name static-site prakhar1989/static-site
e61d12292d69556eabe2a44c16cbd54486b2527e2ce4f95438e504afb7b02810
Флаг -d
открепит (detach) терминал, флаг -P
сделает все открытые порты публичными и случайными, и, наконец, флаг --name
это имя, которое мы хотим дать контейнеру. Теперь можно увидеть порты с помощью команды docker port [CONTAINER]
.
$ docker port static-site
80/tcp -> 0.0.0.0:32769
443/tcp -> 0.0.0.0:32768
Откройте http://localhost:32769 в своем браузере.
Замечание: Если вы используете docker-toolbox, то, возможно, нужно будет использовать
docker-machine ip default
чтобы получить IP-адрес.
Также можете обозначить свой порт. Клиент будет перенаправлять соединения на него.
$ docker run -p 8888:80 prakhar1989/static-site
Nginx is running...
Чтобы остановить контейнер запустите docker stop
и укажите идентификатор (ID) контейнера.
Согласитесь, все было очень просто. Чтобы задеплоить это на реальный сервер, нужно просто установить Докер и запустить команду выше. Теперь, когда вы увидели, как запускать веб-сервер внутри образа, вам, наверное, интересно — а как создать свой Докер-образ? Мы будем изучать эту тему в следующем разделе.
2.2 Образы
Мы касались образов ранее, но в этом разделе мы заглянем глубже: что такое Докер-образы и как создавать собственные образы. Наконец, мы используем собственный образ чтобы запустить приложение локально, а потом задеплоим его на AWS, чтобы показать друзьям. Круто? Круто! Давайте начнем.
Образы это основы для контейнеров. В прошлом примере мы скачали (pull) образ под названием Busybox из регистра, и попросили клиент Докера запустить контейнер, основанный на этом образе. Чтобы увидеть список доступных локально образов, используйте команду docker images
.
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
prakhar1989/catnip latest c7ffb5626a50 2 hours ago 697.9 MB
prakhar1989/static-site latest b270625a1631 21 hours ago 133.9 MB
python 3-onbuild cf4002b2c383 5 days ago 688.8 MB
martin/docker-cleanup-volumes latest b42990daaca2 7 weeks ago 22.14 MB
ubuntu latest e9ae3c220b23 7 weeks ago 187.9 MB
busybox latest c51f86c28340 9 weeks ago 1.109 MB
hello-world latest 0a6ba66e537a 11 weeks ago 960 B
Это список образов, которые я скачал из регистра, а также тех, что я сделал сам (скоро увидим, как это делать). TAG
— это конкретный снимок или снэпшот (snapshot) образа, а IMAGE ID
— это соответствующий уникальный идентификатор образа.
Для простоты, можно относиться к образу как к git-репозиторию. Образы можно коммитить с изменениями, и можно иметь несколько версий. Если не указывать конкретную версию, то клиент по умолчанию использует latest
. Например, можно скачать определенную версию образа ubuntu
:
$ docker pull ubuntu:12.04
Чтобы получить новый Докер-образ, можно скачать его из регистра (такого, как Docker Hub) или создать собственный. На Docker Hub есть десятки тысяч образов. Можно искать напрямую из командной строки с помощью docker search
.
Важно понимать разницу между базовыми и дочерними образами:
- Base images (базовые образы) — это образы, которые не имеют родительского образа. Обычно это образы с операционной системой, такие как ubuntu, busybox или debian.
- Child images (дочерние образы) — это образы, построенные на базовых образах и обладающие дополнительной функциональностью.
Существуют официальные и пользовательские образы, и любые из них могут быть базовыми и дочерними.
- Официальные образы — это образы, которые официально поддерживаются командой Docker. Обычно в их названии одно слово. В списке выше
python
,ubuntu
,busybox
иhello-world
— базовые образы. - Пользовательские образы — образы, созданные простыми пользователями вроде меня и вас. Они построены на базовых образах. Обычно, они называются по формату
user/image-name
.
2.3 Наш первый образ
Теперь, когда мы лучше понимаем, что такое образы и какие они бывают, самое время создать собственный образ. Цель этого раздела — создать образ с простым приложением на Flask. Для этого пособия я сделал маленькое приложение, которое выводит случайную гифку с кошкой. Ну, потому что, кто не любит кошек? Склонируйте этот репозиторий к себе на локальную машину.
Вначале давайте проверим, что приложение работает локально. Войдите в директорию flask-app
командой cd
и установите зависимости.
$ cd flask-app
$ pip install -r requirements.txt
$ python app.py
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Если все хорошо, то вы увидите вывод как в примере выше. Зайдите на http://localhost:5000 чтобы увидеть приложение в действии.
Замечание: Если команда
pip install
падает с ошибками «permission denied», то попробуйте запустить ее сsudo
. Если не хотите устанавливать пользовательские пакеты на уровне системы, то используйте командуpip install --user -r requirements.txt
.
Выглядит отлично, правда? Теперь нужно создать образ с приложением. Как говорилось выше, все пользовательские образы основаны на базовом образе. Так как наше приложение написано на Питоне, нам нужен базовый образ Python 3. В частности, нам нужна версия python:3-onbuild
базового образа с Питоном.
Что за версия onbuild
, спросите вы?
Эти образы включают несколько триггеров ONBUILD, которых обычно достаточно чтобы быстро развернуть приложение. При сборке будет скопирован файл
requirements.txt
, будет запущенpip install
с этим файлом, а потом текущая директория будет скопирована в/usr/src/app
.
Другими словами, версия onbuild
включает хелперы, которые автоматизируют скучные процессы запуска приложения. Вместо того, чтобы вручную выполнять эти задачи (или писать скрипты), образы делают все за вас. Теперь у нас есть все ингредиенты для создания своего образа: работающее веб-приложение и базовый образ. Как это сделать? Ответ: использовать Dockerfile.
2.4 Dockerfile
Dockerfile — это простой текстовый файл, в котором содержится список команд Докер-клиента. Это простой способ автоматизировать процесс создания образа. Самое классное, что команды в Dockerfile почти идентичны своим аналогам в Linux. Это значит, что в принципе не нужно изучать никакой новый синтаксис чтобы начать работать с докерфайлами.
В директории с приложением есть Dockerfile, но так как мы делаем все впервые, нам нужно создать его с нуля. Создайте новый пустой файл в любимом текстовом редакторе, и сохраните его в той же директории, где находится flask-приложение. Назовите файл Dockerfile
.
Для начала укажем базовый образ. Для этого нужно использовать ключевое слово FROM
.
FROM python:3-onbuild
Дальше обычно указывают команды для копирования файлов и установки зависимостей. Но к счастью, onbuild
-версия базового образа берет эти задачи на себя. Дальше нам нужно указать порт, который следует открыть. Наше приложение работает на порту 5000, поэтому укажем его:
EXPOSE 5000
Последний шаг — указать команду для запуска приложения. Это просто python ./app.py
. Для этого используем команду CMD:
CMD ["python", "./app.py"]
Главное предназначение CMD
— это сообщить контейнеру какие команды нужно выполнить при старте. Теперь наш Dockerfile
готов. Вот как он выглядит:
# our base image
FROM python:3-onbuild
# specify the port number the container should expose
EXPOSE 5000
# run the application
CMD ["python", "./app.py"]
Теперь можно создать образ. Команда docker build
занимается сложной задачей создания образа на основе Dockerfile
.
Листинг ниже демонстрирует процесс. Перед тем, как запустите команду сами (не забудьте точку в конце), проверьте, чтобы там был ваш username вместо моего. Username должен соответствовать тому, что использовался при регистрации на Docker hub. Если вы еще не регистрировались, то сделайте это до выполнения команды. Команда docker build
довольно проста: она принимает опциональный тег с флагом -t
и путь до директории, в которой лежит Dockerfile
.
$ docker build -t prakhar1989/catnip .
Sending build context to Docker daemon 8.704 kB
Step 1 : FROM python:3-onbuild
# Executing 3 build triggers...
Step 1 : COPY requirements.txt /usr/src/app/
---> Using cache
Step 1 : RUN pip install --no-cache-dir -r requirements.txt
---> Using cache
Step 1 : COPY . /usr/src/app
---> 1d61f639ef9e
Removing intermediate container 4de6ddf5528c
Step 2 : EXPOSE 5000
---> Running in 12cfcf6d67ee
---> f423c2f179d1
Removing intermediate container 12cfcf6d67ee
Step 3 : CMD python ./app.py
---> Running in f01401a5ace9
---> 13e87ed1fbc2
Removing intermediate container f01401a5ace9
Successfully built 13e87ed1fbc2
Если у вас нет образа python:3-onbuild
, то клиент сначала скачает его, а потом возьмется за создание вашего образа. Так что, вывод на экран может отличаться от моего. Посмотрите внимательно, и найдете триггеры onbuild. Если все прошло хорошо, то образ готов! Запустите docker images
и увидите свой образ в списке.
Последний шаг — запустить образ и проверить его работоспособность (замените username на свой):
$ docker run -p 8888:5000 prakhar1989/catnip
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Зайдите на указанный URL и увидите приложение в работе.
Поздравляю! Вы успешно создали свой первый образ Докера!
2.5 Docker на AWS
Что хорошего в приложении, которое нельзя показать друзьям, правда? Так что в этом разделе мы научимся деплоить наше офигенное приложение в облако. Будем использовать AWS Elastic Beanstalk чтобы решить эту задачу за пару кликов. Мы увидим, как с помощью Beanstalk легко управлять и масштабировать наше приложение.
Docker push
Первое, что нужно сделать перед деплоем на AWS это опубликовать наш образ в регистре, чтобы можно было скачивать его из AWS. Есть несколько Docker-регистров (или можно создать собственный). Для начала, давайте используем Docker Hub. Просто выполните:
$ docker push prakhar1989/catnip
Если это ваша первая публикация, то клиент попросит вас залогиниться. Введите те же данные, что используете для входа в Docker Hub.
$ docker login
Username: prakhar1989
WARNING: login credentials saved in /Users/prakhar/.docker/config.json
Login Succeeded
Не забудьте заменить название образа на свое. Очень важно сохранить формат username/image_name
, чтобы клиент понимал, куда публиковать образ.
После этого можете посмотреть на свой образ на Docker Hub. Например, вот страница моего образа.
Замечание: один важный момент, который стоит прояснить перед тем, как продолжить — не обязательно хранить образ в публичном регистре (или в любом другом регистре вообще) чтобы деплоить на AWS. Если вы пишете код для следующего многомиллионного стартапа-единорога, то можно пропустить этот шаг. Мы публикуем свой образ чтобы упростить деплой, пропустив несколько конфигурационных шагов.
Теперь наш образ онлайн, и любой докер-клиент может поиграться с ним с помощью простой команды:
$ docker run -p 8888:5000 prakhar1989/catnip
Если в прошлом вы мучались с установкой локального рабочего окружения и попытками поделиться своей конфигурацией с коллегами, то понимаете, как круто это звучит. Вот почему Докер — это сила!
Beanstalk
AWS Elastic Beanstalk (EB) это PaaS (Platform as a Service — платформа как сервис) от Amazon Web Services. Если вы использовали Heroku, Google App Engine и т.д., то все будет привычно. Как разработчик, вы сообщаете EB как запускать ваше приложение, а EB занимается всем остальным, в том числе масштабированием, мониторингом и даже апдейтами. В апреле 2014 в EB добавили возможность запускать Докер-контейнеры, и мы будем использовать именно эту возможность для деплоя. У EB очень понятный интерфейс командной строки, но он требует небольшой конфигурации, поэтому для простоты давайте используем веб-интерфейс для запуска нашего приложения.
Чтобы продолжать, вам потребуется работающий аккаунт на AWS. Если у вас его нет, то создайте его. Для этого потребуется ввести данные кредитной карты. Но не волнуйтесь, эта услуга бесплатна, и все, что будет происходить в рамках этого пособия тоже бесплатно.
Давайте начнем:
- Войдите в свою консоль AWS.
- Нажмите на Elastic Beanstalk. Ссылка находится в секции compute, в левом верхнем углу. Или просто перейдите сюда.
- Нажмите на «Create New Application» в верхнем правом углу.
- Дайте своему приложению запоминающееся (но уникальное) имя и, если хотите, добавьте описание.
- на экране New Environment выберите Web Server Environment.
- Следующий экран показан ниже. Выберите Docker из готовых вариантов конфигурации. Можно оставить Environment type как есть. Нажмите Next.
- Тут мы будем сообщать системе EB о нашем образе. Откройте файл Dockerrun.aws.json в директории
flask-app
и изменитеName
образа, чтобы оно соответствовало названию вашего образа. Не волнуйтесь, я опишу содержание файла попозже. Потом выберите вариант «upload your own» и выберите файл. - Далее, выберите название окружения и URL. Этот URL как раз можно будет давать друзьям, так что постарайтесь придумать что-нибудь попроще.
- Пока не будем вносить никаких правок в секцию Additional Resources. Нажмите Next и переходите к Configuration Details.
- В этой секции вам нужно выбрать тип инстанса
t1.micro
. Это очень важно, потому что это бесплатный тип от AWS. Если хотите, можно выбрать пару ключей для входа. Если вы не знаете, что это значит, то не волнуйтесь и просто пропустите эту часть. Все остальное можно оставить по умолчанию и продолжать. - Также не нужно указывать никакие Environment Tags and Permissions, так что просто жмите Next два раза подряд. В конце будет экран Review. Если все выглядит нормально, то нажимайте кнопку Launch.
- На последнем экране будет несколько спиннеров. Это поднимается и настраивается ваше окружение. Обычно, нужно около пяти минут для первой настройки.
Пока ждем, давайте быстренько взглянем на файл Dockerrun.aws.json
. Это файл для AWS, в котором находится информация о приложении конфигурации Докера. EB получает информацию из этого файла.
{
"AWSEBDockerrunVersion": "1",
"Image": {
"Name": "prakhar1989/catnip",
"Update": "true"
},
"Ports": [
{
"ContainerPort": "5000"
}
],
"Logging": "/var/log/nginx"
}
Файл довольно понятный, но всегда можно обратиться к официальной документации. Мы указываем название образа, и EB будет использовать его заодно с портом.
К этому моменту инстанс уже должен быть готов. Зайдите на страницу EB и увидите зеленый индикатор успешного запуска приложения.
Зайдите на указанный URL в браузере и увидите приложение во все красе. Пошлите адрес своим друзьям, чтобы все могли насладиться гифками с кошками.
Поздравляю! Вы задеплоили свое первое Докер-приложение! Может показаться, что было очень много шагов, но с командной утилитой EB можно имитировать функциональность Хероку несколькими нажатиями клавиш. Надеюсь, вы согласитесь, что Докер сильно упрощает процесс и минимизирует болезненные моменты деплоя в облако. Я советую вам почитать документацию AWS про single-container Docker environment чтобы понимать, какие существуют возможности в EB.
В следующей, последней части пособия, мы пойдем немного дальше и задеплоим приложение, приближенное к реальному миру. В нем будет постоянное бэкэнд-хранилище. Поехали!
3.0 Многоконтейнерные окружения
В прошлом разделе мы увидели, как легко и просто запускать приложения с помощью Докера. Мы начали с простого статического сайта, а потом запустили Flask-приложение. Оба варианта можно было запускать локально или в облаке, несколькими командами. Общая черта этих приложений: каждое из них работало в одном контейнере.
Если у вас есть опыт управления сервисами в продакшене, то вы знаете, что современные приложения обычно не такие простые. Почти всегда есть база данных (или другой тип постоянного хранилища). Системы вроде Redis и Memcached стали практически обязательной частью архитектуры веб-приложений. Поэтому, в этом разделе мы научимся «докеризировать» приложения, которым требуется несколько запущенных сервисов.
В частности, мы увидим, как запускать и управлять многоконтейнерными Докер-окружениями. Почему нужно несколько контейнеров, спросите вы? Ну, одна из главных идей Докера в том, что он предоставляет изоляцию. Идея совмещения процесса и его зависимостей в одной песочнице (называемой контейнером) и делает Докер мощным инструментом.
Аналогично тому, как приложение разбивают на части, стоит содержать отдельные сервисы в отдельных контейнерах. Разным частям скорее всего требуются разные ресурсы, и требования могут расти с разной скоростью. Если мы разделим эти части и поместим в разные контейнеры, то каждую часть приложения можно строить, используя наиболее подходящий тип ресурсов. Это также хорошо совмещается с идеей микро сервисов. Это одна из причин, по которой Докер (и любая другая технология контейнеризации) находится на передовой современных микро сервисных архитектур.
3.1 SF Food Trucks
Приложение, которое мы переведем в Докер, называется SF Food Trucks (к сожалению, сейчас приложение уже не работает публично — прим. пер.). Моя цель была сделать что-то полезное (и похожее на настоящее приложение из реального мира), что-то, что использует как минимум один сервис, но не слишком сложное для этого пособия. Вот что я придумал.
Бэкэнд приложения написано на Питоне (Flask), а для поиска используется Elasticsearch. Как и все остальное в этом пособии, код находится на Github. Мы используем это приложение, чтобы научиться запускать и деплоить много-контейнерное окружение.
Теперь, когда вы завелись (надеюсь), давайте подумаем, как будет выглядеть этот процесс. В нашем приложении есть бэкэнд на Flask и сервис Elasticsearch. Очевидно, что можно поделить приложение на два контейнера: один для Flask, другой для Elasticsearch (ES). Если приложение станет популярным, то можно будет добавлять новые контейнеры в нужном месте, смотря где будет узкое место.
Отлично, значит нужно два контейнера. Это не сложно, правда? Мы уже создавали Flask-контейнер в прошлом разделе. А для Elasticsearch… давайте посмотрим, есть ли что-нибудь в хабе:
$ docker search elasticsearch
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
elasticsearch Elasticsearch is a powerful open source se... 697 [OK]
itzg/elasticsearch Provides an easily configurable Elasticsea... 17 [OK]
tutum/elasticsearch Elasticsearch image - listens in port 9200. 15 [OK]
barnybug/elasticsearch Latest Elasticsearch 1.7.2 and previous re... 15 [OK]
digitalwonderland/elasticsearch Latest Elasticsearch with Marvel & Kibana 12 [OK]
monsantoco/elasticsearch ElasticSearch Docker image 9 [OK]
Не удивительно, но существуют официальный образ для Elasticsearch. Чтобы запустить ES, нужно всего лишь выполнить docker run
, и вскоре у нас будет локальный, работающий контейнер с одним узлом ES.
$ docker run -dp 9200:9200 elasticsearch
d582e031a005f41eea704cdc6b21e62e7a8a42021297ce7ce123b945ae3d3763
$ curl 0.0.0.0:9200
{
"name" : "Ultra-Marine",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.1.1",
"build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
"build_timestamp" : "2015-12-15T13:05:55Z",
"build_snapshot" : false,
"lucene_version" : "5.3.1"
},
"tagline" : "You Know, for Search"
}
Заодно давайте запустим контейнер с Flask. Но вначале нужен Dockerfile
. В прошлой секции мы использовали образ python:3-onbuild
в качестве базового. Однако, в этом раз, кроме установки зависимостей через pip
, нам нужно, чтобы приложение генерировало минимизированный Javascript-файл для продакшена. Для этого понадобится Nodejs. Так что нужен свой билд с нуля, поэтому начнем с базового образа ubuntu
.
Замечание: если оказывается, что существующий образ не подходит для вашей задачи, то спокойно создавайте свой образ на основе другого базового образа. В большинстве случаем, для образов на Docker Hub можно найти соответствующий
Dockerfile
на Github. Почитайте существующий Докерфайлы — это один из лучших способов научиться делать свои образы.
Наш Dockerfile для Flask-приложения выглядит следующим образом:
# start from base
FROM ubuntu:14.04
MAINTAINER Prakhar Srivastav <[email protected]>
# install system-wide deps for python and node
RUN apt-get -yqq update
RUN apt-get -yqq install python-pip python-dev
RUN apt-get -yqq install nodejs npm
RUN ln -s /usr/bin/nodejs /usr/bin/node
# copy our application code
ADD flask-app /opt/flask-app
WORKDIR /opt/flask-app
# fetch app specific deps
RUN npm install
RUN npm run build
RUN pip install -r requirements.txt
# expose port
EXPOSE 5000
# start app
CMD [ "python", "./app.py" ]
Тут много всего нового. Вначале указан базовый образ Ubuntu LTS, потом используется пакетный менеджер apt-get
для установки зависимостей, в частности — Python и Node. Флаг yqq
нужен для игнорирования вывода и автоматического выбора «Yes» во всех местах. Также создается символическая ссылка для бинарного файла node. Это нужно для решения проблем обратной совместимости.
Потом мы используем команду ADD
для копирования приложения в нужную директорию в контейнере — /opt/flask-app
. Здесь будет находиться весь наш код. Мы также устанавливаем эту директорию в качестве рабочей, так что следующие команды будут выполняться в контексте этой локации. Теперь, когда наши системные зависимости установлены, пора установить зависимости уровня приложения. Начнем с Node, установки пакетов из npm и запуска команды сборки, как указано в нашем файле package.json. В конце устанавливаем пакеты Python, открываем порт и определяем запуск приложения с помощь CMD
, как в предыдущем разделе.
Наконец, можно собрать образ и запустить контейнер (замените prakhar1989
на свой username ниже).
$ docker build -t prakhar1989/foodtrucks-web .
При первом запуске нужно будет больше времени, так как клиент Докера будет скачивать образ ubuntu, запускать все команды и готовить образ. Повторный запуск docker build
после последующих изменений будет практически моментальным. Давайте попробуем запустить приложение
$ docker run -P prakhar1989/foodtrucks-web
Unable to connect to ES. Retying in 5 secs...
Unable to connect to ES. Retying in 5 secs...
Unable to connect to ES. Retying in 5 secs...
Out of retries. Bailing out...
Упс! Наше приложение не смогло запуститься, потому что оно не может подключиться к Elasticsearch. Как сообщить одному контейнеру о другом и как заставить их взаимодействовать друг с другом? Ответ — в следующей секции.
3.2 Сети Docker
Перед тем, как обсудить возможности Докера для решения описанной задачи, давайте посмотрим на возможные варианты обхода проблемы. Думаю, это поможет нам оценить удобство той функциональности, которую мы вскоре изучим.
Ладно, давайте запустим docker ps
, что тут у нас:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e931ab24dedc elasticsearch "/docker-entrypoint.s" 2 seconds ago Up 2 seconds 0.0.0.0:9200->9200/tcp, 9300/tcp cocky_spence
Итак, у нас есть контейнер ES по адресу и порту 0.0.0.0:9200
, и мы можем напрямую обращаться к нему. Если можно было бы сообщить нашему приложению подключаться к этому адресу, то оно сможет общаться с ES, верно? Давайте взглянем на код на Питоне, туда, где описано подключение.
es = Elasticsearch(host='es')
Нужно сообщить Flask-контейнеру, что контейнер ES запущен на хосте 0.0.0.0
(порт по умолчанию 9200
), и все заработает, да? К сожалению, нет, потому что IP 0.0.0.0
это адрес для доступа к контейнеру с хост-машины, то есть с моего Мака. Другой контейнер не сможет обратиться по этому адресу. Ладно, если не этот адрес, то какой другой адрес нужно использовать для работы с контейнером ES? Рад, что вы спросили.
Это хороший момент, чтобы изучить работу сети в Докере. После установки, Докер автоматически создает три сети:
$ docker network ls
NETWORK ID NAME DRIVER
075b9f628ccc none null
be0f7178486c host host
8022115322ec bridge bridge
Сеть bridge — это сеть, в которой контейнеры запущены по умолчанию. Это значит, что когда я запускаю контейнер ES, он работает в этой сети bridge. Чтобы удостовериться, давайте проверим:
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "8022115322ec80613421b0282e7ee158ec41e16f565a3e86fa53496105deb2d7",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.17.0.0/16"
}
]
},
"Containers": {
"e931ab24dedc1640cddf6286d08f115a83897c88223058305460d7bd793c1947": {
"EndpointID": "66965e83bf7171daeb8652b39590b1f8c23d066ded16522daeb0128c9c25c189",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
}
}
]
Видно, что контейнер e931ab24dedc
находится в секции Containers
. Также виден IP-адрес, выданный этому контейнеру — 172.17.0.2
. Именно этот адрес мы и искали? Давайте проверим: запустим Flask-приложение и попробуем обратиться к нему по IP:
$ docker run -it --rm prakhar1989/foodtrucks-web bash
root@35180ccc206a:/opt/flask-app# curl 172.17.0.2:9200
bash: curl: command not found
root@35180ccc206a:/opt/flask-app# apt-get -yqq install curl
root@35180ccc206a:/opt/flask-app# curl 172.17.0.2:9200
{
"name" : "Jane Foster",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.1.1",
"build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
"build_timestamp" : "2015-12-15T13:05:55Z",
"build_snapshot" : false,
"lucene_version" : "5.3.1"
},
"tagline" : "You Know, for Search"
}
root@35180ccc206a:/opt/flask-app# exit
Сейчас все должно быть понятно. Мы запустили контейнер в интерактивном режиме с процессом bash
. Флаг --rm
нужен для удобства, благодаря нему контейнер автоматически удаляется после выхода. Мы попробуем curl
, но нужно сначала установить его. После этого можно удостовериться, что по адресу 172.17.0.2:9200
на самом деле можно обращаться к ES! Супер!
Не смотря на то, что мы нашли способ наладить связь между контейнерами, существует несколько проблем с этим подходом:
- Придется добавлять записи в файл
/etc/hosts
внутри Flask-контейнера, чтобы приложение понимало, что имя хостаes
означает172.17.0.2
. Если IP-адрес меняется, то придется вручную менять запись. - Так как сеть bridge используется всеми контейнерами по умолчанию, этот метод не безопасен.
Но есть хорошие новости: в Докере есть отличное решение этой проблемы. Докер позволяет создавать собственные изолированные сети. Это решение также помогает справиться с проблемой /etc/hosts
, сейчас увидим как.
Во-первых, давайте создадим свою сеть:
$ docker network create foodtrucks
1a3386375797001999732cb4c4e97b88172d983b08cd0addfcb161eed0c18d89
$ docker network ls
NETWORK ID NAME DRIVER
1a3386375797 foodtrucks bridge
8022115322ec bridge bridge
075b9f628ccc none null
be0f7178486c host host
Команда network create
создает новую сеть bridge. Нам сейчас нужен именно такой тип. Существуют другие типы сетей, и вы можете почитать о них в официальной документации.
Теперь у нас есть сеть. Можно запустить наши контейнеры внутри сети с помощью флага --net
. Давайте так и сделаем, но сначала остановим контейнер с ElasticSearch, который был запущен в сети bridge по умолчанию.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e931ab24dedc elasticsearch "/docker-entrypoint.s" 4 hours ago Up 4 hours 0.0.0.0:9200->9200/tcp, 9300/tcp cocky_spence
$ docker stop e931ab24dedc
e931ab24dedc
$ docker run -dp 9200:9200 --net foodtrucks --name es elasticsearch
2c0b96f9b8030f038e40abea44c2d17b0a8edda1354a08166c33e6d351d0c651
$ docker network inspect foodtrucks
[
{
"Name": "foodtrucks",
"Id": "1a3386375797001999732cb4c4e97b88172d983b08cd0addfcb161eed0c18d89",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{}
]
},
"Containers": {
"2c0b96f9b8030f038e40abea44c2d17b0a8edda1354a08166c33e6d351d0c651": {
"EndpointID": "15eabc7989ef78952fb577d0013243dae5199e8f5c55f1661606077d5b78e72a",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {}
}
]
Мы сделали то же, что и раньше, но на этот раз дали контейнеру название es
. Перед тем, как запускать контейнер с приложением, давайте проверим что происходит, когда запуск происходит в сети.
$ docker run -it --rm --net foodtrucks prakhar1989/foodtrucks-web bash
root@53af252b771a:/opt/flask-app# cat /etc/hosts
172.18.0.3 53af252b771a
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.2 es
172.18.0.2 es.foodtrucks
root@53af252b771a:/opt/flask-app# curl es:9200
bash: curl: command not found
root@53af252b771a:/opt/flask-app# apt-get -yqq install curl
root@53af252b771a:/opt/flask-app# curl es:9200
{
"name" : "Doctor Leery",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.1.1",
"build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
"build_timestamp" : "2015-12-15T13:05:55Z",
"build_snapshot" : false,
"lucene_version" : "5.3.1"
},
"tagline" : "You Know, for Search"
}
root@53af252b771a:/opt/flask-app# ls
app.py node_modules package.json requirements.txt static templates webpack.config.js
root@53af252b771a:/opt/flask-app# python app.py
Index not found...
Loading data in elasticsearch ...
Total trucks loaded: 733
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
root@53af252b771a:/opt/flask-app# exit
Ура! Работает! Магическим образом Докер внес нужные правки в файл /etc/hosts
, и поэтому es:9200
можно использовать в приложении — этот адрес корректно направляет запросы в контейнер ES. Отлично! Давайте теперь запустим Flask-контейнер по-настоящему:
$ docker run -d --net foodtrucks -p 5000:5000 --name foodtrucks-web prakhar1989/foodtrucks-web
2a1b77e066e646686f669bab4759ec1611db359362a031667cacbe45c3ddb413
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a1b77e066e6 prakhar1989/foodtrucks-web "python ./app.py" 2 seconds ago Up 1 seconds 0.0.0.0:5000->5000/tcp foodtrucks-web
2c0b96f9b803 elasticsearch "/docker-entrypoint.s" 21 minutes ago Up 21 minutes 0.0.0.0:9200->9200/tcp, 9300/tcp es
$ curl -I 0.0.0.0:5000
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 3697
Server: Werkzeug/0.11.2 Python/2.7.6
Date: Sun, 10 Jan 2016 23:58:53 GMT
Зайдите на http://0.0.0.0:5000, и увидите приложение в работе. Опять же, может показаться, что было много работы, но на самом деле мы ввели всего 4 команды чтобы с нуля дойти до работающего приложения. Я собрал эти команды в bash-скрипт.
#!/bin/bash
# build the flask container
docker build -t prakhar1989/foodtrucks-web .
# create the network
docker network create foodtrucks
# start the ES container
docker run -d --net foodtrucks -p 9200:9200 -p 9300:9300 --name es elasticsearch
# start the flask app container
docker run -d --net foodtrucks -p 5000:5000 --name foodtrucks-web prakhar1989/foodtrucks-web
Теперь представьте, что хотите поделиться приложением с другом. Или хотите запустить на сервере, где установлен Докер. Можно запустить всю систему с помощью одной команды!
$ git clone https://github.com/prakhar1989/FoodTrucks
$ cd FoodTrucks
$ ./setup-docker.sh
Вот и все! По-моему, это невероятно крутой и мощный способ распространять и запускать приложения!
Docker Links
Перед тем, как завершить этот раздел, стоит отметить, что docker network
это относительно новая фича, она входит в релиз Docker 1.9 .
До того, как появился network
, ссылки были допустимым способом настройки взаимодействия между контейнерами. В соответствии с официальной документацией, linking вскоре будет переведены в статус deprecated. Если вам попадется туториал или статья, где используется link
для соединения контейнеров, то просто не забывайте использовать вместо этого network
(на момент публикации перевода links является legacy, — прим. пер.)
3.3 Docker Compose
До этого момента мы изучали клиент Докера. Но в экосистеме Докера есть несколько других инструментов с открытым исходным кодом, которые хорошо взаимодействуют с Докером. Некоторые из них это:
- Docker Machine позволяет создавать Докер-хосты на своем компьютере, облачном провайдере или внутри дата-центра.
- Docker Compose — инструмент для определения и запуска много-контейнерных приложений.
- Docker Swarm — нативное решение для кластеризации.
В этом разделе мы поговорим об одном из этих инструментов — Docker Compose, и узнаем, как он может упростить работу с несколькими контейнерами.
У Docker Compose довольно интересная предыстория. Примерно два года назад компания OrchardUp запустила инструмент под названием Fig. Идея была в том, чтобы создавать изолированные рабочие окружения с помощью Докера. Проект очень хорошо восприняли на Hacker News — я смутно помню, что читал о нем, но не особо понял его смысла.
Первый комментарий на самом деле неплохо объясняет, зачем нужен Fig и что он делает:
На самом деле, смысл Докера в следующем: запускать процессы. Сегодня у Докера есть неплохое API для запуска процессов: расшаренные между контейнерами (иными словами, запущенными образами) разделы или директории (shared volumes), перенаправление портов с хост-машины в контейнер, вывод логов, и так далее. Но больше ничего: Докер сейчас работает только на уровне процессов.
Не смотря на то, что в нем содержатся некоторые возможности оркестрации нескольких контейнеров для создания единого «приложения», в Докере нет ничего, что помогало бы с управлением такими группами контейнеров как одной сущностью. И вот зачем нужен инструмент вроде Fig: чтобы обращаться с группой контейнеров как с единой сущностью. Чтобы думать о «запуске приложений» (иными словами, «запуске оркестрированного кластера контейнеров») вместо «запуска контейнеров».
Оказалось, что многие пользователи Докера согласны с такими мыслями. Постепенно, Fig набрал популярность, Docker Inc. заметили, купили компанию и назвали проект Docker Compose.
Итак, зачем используется Compose? Это инструмент для простого определения и запуска многоконтейнерных Докер-приложений. В нем есть файл docker-compose.yml
, и с его помощью можно одной командой поднять приложение с набором сервисов.
Давайте посмотрим, сможем ли мы создать файл docker-compose.yml
для нашего приложения SF-Foodtrucks и проверим, способен ли он на то, что обещает.
Но вначале нужно установить Docker Compose. Есть у вас Windows или Mac, то Docker Compose уже установлен — он идет в комплекте с Docker Toolbox. На Linux можно установить Docker Compose следуя простым инструкциям на сайте документации. Compose написан на Python, поэтому можно сделать просто pip install docker-compose
. Проверить работоспособность так:
$ docker-compose version
docker-compose version 1.7.1, build 0a9ab35
docker-py version: 1.8.1
CPython version: 2.7.9
OpenSSL version: OpenSSL 1.0.1j 15 Oct 2014
Теперь можно перейти к следующему шагу, то есть созданию файла docker-compose.yml
. Синтаксис yml
-файлов очень простой, и в репозитории уже есть пример, который мы будем использовать
version: "2"
services:
es:
image: elasticsearch
web:
image: prakhar1989/foodtrucks-web
command: python app.py
ports:
- "5000:5000"
volumes:
- .:/code
Давайте я разберу это подробнее. На родительском уровне мы задали название неймспейса для наших сервисов: es
и web
. К каждому сервису можно добавить дополнительные параметры, среди которых image
— обязательный. Для es
мы указываем доступный на Docker Hub образ elasticsearch
. Для Flask-приложения — тот образ, который мы создали самостоятельно в начале этого раздела.
С помощью других параметров вроде command
и ports
можно предоставить информацию о контейнере. volumes
отвечает за локацию монтирования, где будет находиться код в контейнере web
. Это опциональный параметр, он полезен, если нужно обращаться к логам и так далее. Подробнее о параметрах и возможных значениях можно прочитать в документации.
Замечание: Нужно находиться в директории с файлом
docker-compose.yml
чтобы запускать большую часть команд Compose.
Отлично! Файл готов, давайте посмотрим на docker-compose
в действии. Но вначале нужно удостовериться, что порты свободны. Так что если у вас запущены контейнеры Flask и ES, то пора их остановить:
$ docker stop $(docker ps -q)
39a2f5df14ef
2a1b77e066e6
Теперь можно запускать docker-compose
. Перейдите в директорию с приложением Foodtrucks и выполните команду docker-compose up
.
$ docker-compose up
Creating network "foodtrucks_default" with the default driver
Creating foodtrucks_es_1
Creating foodtrucks_web_1
Attaching to foodtrucks_es_1, foodtrucks_web_1
es_1 | [2016-01-11 03:43:50,300][INFO ][node ] [Comet] version[2.1.1], pid[1], build[40e2c53/2015-12-15T13:05:55Z]
es_1 | [2016-01-11 03:43:50,307][INFO ][node ] [Comet] initializing ...
es_1 | [2016-01-11 03:43:50,366][INFO ][plugins ] [Comet] loaded [], sites []
es_1 | [2016-01-11 03:43:50,421][INFO ][env ] [Comet] using [1] data paths, mounts [[/usr/share/elasticsearch/data (/dev/sda1)]], net usable_space [16gb], net total_space [18.1gb], spins? [possibly], types [ext4]
es_1 | [2016-01-11 03:43:52,626][INFO ][node ] [Comet] initialized
es_1 | [2016-01-11 03:43:52,632][INFO ][node ] [Comet] starting ...
es_1 | [2016-01-11 03:43:52,703][WARN ][common.network ] [Comet] publish address: {0.0.0.0} is a wildcard address, falling back to first non-loopback: {172.17.0.2}
es_1 | [2016-01-11 03:43:52,704][INFO ][transport ] [Comet] publish_address {172.17.0.2:9300}, bound_addresses {[::]:9300}
es_1 | [2016-01-11 03:43:52,721][INFO ][discovery ] [Comet] elasticsearch/cEk4s7pdQ-evRc9MqS2wqw
es_1 | [2016-01-11 03:43:55,785][INFO ][cluster.service ] [Comet] new_master {Comet}{cEk4s7pdQ-evRc9MqS2wqw}{172.17.0.2}{172.17.0.2:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
es_1 | [2016-01-11 03:43:55,818][WARN ][common.network ] [Comet] publish address: {0.0.0.0} is a wildcard address, falling back to first non-loopback: {172.17.0.2}
es_1 | [2016-01-11 03:43:55,819][INFO ][http ] [Comet] publish_address {172.17.0.2:9200}, bound_addresses {[::]:9200}
es_1 | [2016-01-11 03:43:55,819][INFO ][node ] [Comet] started
es_1 | [2016-01-11 03:43:55,826][INFO ][gateway ] [Comet] recovered [0] indices into cluster_state
es_1 | [2016-01-11 03:44:01,825][INFO ][cluster.metadata ] [Comet] [sfdata] creating index, cause [auto(index api)], templates [], shards [5]/[1], mappings [truck]
es_1 | [2016-01-11 03:44:02,373][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,510][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,593][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,708][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:03,047][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Перейдите по IP чтобы увидеть приложение. Круто, да? Всего лишь пара строк конфигурации и несколько Докер-контейнеров работают в унисон. Давайте остановим сервисы и перезапустим в detached mode:
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Killing foodtrucks_web_1 ... done
Killing foodtrucks_es_1 ... done
$ docker-compose up -d
Starting foodtrucks_es_1
Starting foodtrucks_web_1
$ docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------
foodtrucks_es_1 /docker-entrypoint.sh elas ... Up 9200/tcp, 9300/tcp
foodtrucks_web_1 python app.py Up 0.0.0.0:5000->5000/tcp
Не удивительно, но оба контейнера успешно запущены. Откуда берутся имена? Их Compose придумал сам. Но что насчет сети? Его Compose тоже делаем сам? Хороший вопрос, давайте выясним.
Для начала, остановим запущенные сервисы. Их всегда можно вернуть одной командой:
$ docker-compose stop
Stopping foodtrucks_web_1 ... done
Stopping foodtrucks_es_1 ... done
Заодно, давайте удалим сеть foodtrucks
, которую создали в прошлый раз. Эта сеть нам не потребуется, потому что Compose автоматически сделает все за нас.
$ docker network rm foodtrucks
$ docker network ls
NETWORK ID NAME DRIVER
4eec273c054e bridge bridge
9347ae8783bd none null
54df57d7f493 host host
Класс! Теперь в этом чистом состоянии можно проверить, способен ли Compose на волшебство.
$ docker-compose up -d
Recreating foodtrucks_es_1
Recreating foodtrucks_web_1
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f50bb33a3242 prakhar1989/foodtrucks-web "python app.py" 14 seconds ago Up 13 seconds 0.0.0.0:5000->5000/tcp foodtrucks_web_1
e299ceeb4caa elasticsearch "/docker-entrypoint.s" 14 seconds ago Up 14 seconds 9200/tcp, 9300/tcp foodtrucks_es_1
Пока все хорошо. Проверим, создались ли какие-нибудь сети:
$ docker network ls
NETWORK ID NAME DRIVER
0c8b474a9241 bridge bridge
293a141faac3 foodtrucks_default bridge
b44db703cd69 host host
0474c9517805 none null
Видно, что Compose самостоятельно создал сеть foodtrucks_default
и подсоединил оба сервиса в эту сеть, так, чтобы они могли общаться друг с другом. Каждый контейнер для сервиса подключен к сети, и оба контейнера доступны другим контейнерам в сети. Они доступны по hostname, который совпадает с названием контейнера. Давайте проверим, находится ли эта информация в /etc/hosts
.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bb72dcebd379 prakhar1989/foodtrucks-web "python app.py" 20 hours ago Up 19 hours 0.0.0.0:5000->5000/tcp foodtrucks_web_1
3338fc79be4b elasticsearch "/docker-entrypoint.s" 20 hours ago Up 19 hours 9200/tcp, 9300/tcp foodtrucks_es_1
$ docker exec -it bb72dcebd379 bash
root@bb72dcebd379:/opt/flask-app# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.2 bb72dcebd379
Упс! Оказывается, файл понятия не имеет о es
. Как же наше приложение работает? Давайте попингуем его по названию хоста:
root@bb72dcebd379:/opt/flask-app# ping es
PING es (172.18.0.3) 56(84) bytes of data.
64 bytes from foodtrucks_es_1.C
--- es ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.049/0.056/0.064/0.010 ms
Вуаля! Работает! Каким-то магическим образом контейнер смог сделать пинг хоста es
. Оказывается, Docker 1.10 добавили новую сетевую систему, которая производит обнаружение сервисов через DNS-сервер. Если интересно, то почитайте подробнее о предложении и release notes.
На этом наш тур по Docker Compose завершен. С этим инструментом можно ставить сервисы на паузу, запускать отдельные команды в контейнере и даже масштабировать систему, то есть увеличивать количество контейнеров. Также советую изучать некоторые другие примеры использования Docker Compose.
Надеюсь, я продемонстрировал как на самом деле просто управлять многоконтейнерной средой с Compose. В последнем разделе мы задеплоим все на AWS!
3.4 AWS Elastic Container Service
В прошлом разделе мы использовали docker-compose
чтобы запустить наше приложение локально одной командой: docker-compose up
. Теперь, когда приложение работает, мы хотим показать его миру, заполучить юзеров, поднять кучу денег и купить большой дом в Майами. Последние три шага выходят за пределы этого пособия, так что займемся выяснением деталей о деплое многоконтейнерного приложения в облако AWS.
Если вы дочитали до этого места, то скорее всего убедились, что Docker — довольно крутая технология. И вы не одиноки. Облачные провайдеры заметили взрывной рост популярности Докера и стали добавлять поддержку в свои сервисы. Сегодня, Докер-приложения можно деплоить на AWS, Azure,Rackspace, DigitalOcean и много других. Мы уже умеем деплоить приложение с одним контейнером на Elastic Beanstalk, а в этом разделе мы изучим AWS Elastic Container Service (или ECS).
AWS ECS — это масштабируемый и гибкий сервис по управлению контейнерами, и он поддерживает Докер. С его помощью можно управлять кластером на EC2 через простой API. В Beanstalk были нормальные настройки по умолчанию, но ECS позволяет настроить каждый аспект окружения по вашим потребностям. По этой причине ECS — не самый простой инструмент в начале пути.
К счастью, у ECS есть удобный инструмент командной строки (CLI) с поддержкой Docker Compose и автоматической провизией на ECS! Так как у нас уже есть рабочий файл docker-compose.yml
, настройка и запуск на AWS должна быть достаточно легкой. Начнем!
Вначале нужно установить CLI. На момент написания этого пособия CLI-утилита не доступна на Windows. Инструкции по установке CLI на Mac и Linux хорошо описаны на сайте с официальной документацией. Установите утилиту, а потом проверьте ее работоспособность так:
$ ecs-cli --version
ecs-cli version 0.1.0 (*cbdc2d5)
Первый шаг — задать пару ключей для авторизации на инстансах. Зайдите на страницу EC2 Console и создайте новый keypair. Скачайте файл и держите его в безопасном месте. Еще один момент — имя региона. Я назвал свой ключ ecs
и указал регион us-east-1
. Я продолжу повествование с этим допущением.
Теперь настройте CLI:
$ ecs-cli configure --region us-east-1 --cluster foodtrucks
INFO[0000] Saved ECS CLI configuration for cluster (foodtrucks)
Команда configure
с именем региона, в котором хотим разместить наш кластер, и название кластера. Нужно указать тот же регион, что использовался прри создании ключей. Если у вас не настроен AWS CLI, то следуйте руководству, которое подробно описывает все шаги.
Следующий шаг позволяет утилите создавать шаблон CloudFormation.
$ ecs-cli up --keypair ecs --capability-iam --size 2 --instance-type t2.micro
INFO[0000] Created cluster cluster=foodtrucks
INFO[0001] Waiting for your cluster resources to be created
INFO[0001] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0061] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0122] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0182] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0242] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
Здесь мы указываем названия ключей, которые мы скачали (в моем случае ecs
), количество инстансов (--size
) и тип инстансов, на которых хотим запускать контейнеры. Флаг --capability-iam
говорит утилите, что мы понимаем, что эта команда может создать ресурсы IAM.
В последнем шаге мы используем файл docker-compose.yml
. Требуется небольшое изменение, так что вместо модификации файла, давайте сделаем копию и назовем ее aws-compose.yml
. Содержание этого файла (после изменений):
es:
image: elasticsearch
cpu_shares: 100
mem_limit: 262144000
web:
image: prakhar1989/foodtrucks-web
cpu_shares: 100
mem_limit: 262144000
ports:
- "80:5000"
links:
- es
Единственные отличия от оригинального файла docker-compose.yml
это параметры mem_limit
и cpu_shares
для каждого контейнера.
Также, мы убрали version
и services
, так как AWS еще не поддерживает версию 2 файлового формата Compose. Так как наше приложение будет работать на инстансах типа t2.micro
, мы задали 250 мегабайт памяти. Теперь нам нужно опубликовать образ на Docker Hub. На момент написания этого пособия, ecs-cli не поддерживает команду build
. Но Docker Compose поддерживает ее без проблем.
$ docker push prakhar1989/foodtrucks-web
Красота! Давайте запустим финальную команду, которая произведет деплой на ECS!
$ ecs-cli compose --file aws-compose.yml up
INFO[0000] Using ECS task definition TaskDefinition=ecscompose-foodtrucks:2
INFO[0000] Starting container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es
INFO[0000] Starting container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web
INFO[0000] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0000] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0036] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0048] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0048] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0060] Started container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-foodtrucks:2
INFO[0060] Started container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-foodtrucks:2
То, что вывод похож на вывод Docker Compose — не совпадение. Аргумент --file
используется для переопределения файла по умолчанию (docker-compose.yml
). Если все прошло хорошо, то вы увидите строку desiredStatus=RUNNING lastStatus=RUNNING
в самом конце.
Круто! Теперь приложение запущено. Как к нему обратиться?
ecs-cli ps
Name State Ports TaskDefinition
845e2368-170d-44a7-bf9f-84c7fcd9ae29/web RUNNING 54.86.14.14:80->5000/tcp ecscompose-foodtrucks:2
845e2368-170d-44a7-bf9f-84c7fcd9ae29/es RUNNING ecscompose-foodtrucks:2
Откройте http://54.86.14.14 в браузере, и увидите Food Trucks во всей своей желто-черной красе! Заодно, давайте взглянем на консоль AWS ECS.
Видно, что был создан ECS-кластер ‘foodtrucks’, и в нем выполняется одна задача с двумя инстансами. Советую поковыряться в этой консоли и изучить разные ее части и опции.
Вот и все. Всего несколько команд — и приложение работает на AWS!
4.0 Заключение
Мы подошли к концу. После длинного, изматывающего, но интересного пособия вы готовы захватить мир контейнеров! Если вы следовали пособию до самого конца, то можете заслуженно гордиться собой. Вы научились устанавливать Докер, запускать свои контейнеры, запускать статические и динамические веб-сайты и, самое главное, получили опыт деплоя приложений в облако.
Надеюсь, прохождение этого руководства помогло вам стать увереннее в своих способностях управляться с серверами. Когда у вас появится новая идея для сайта или приложения, можете быть уверены, что сможете показать его людям с минимальными усилиями.
4.1 Следующие шаги
Ваше путешествие в мир контейнеров только началось. Моей целью в этом руководстве было нагулять ваш аппетит и показать мощь Докера. В мире современных технологий иногда бывает сложно разобраться самостоятельно, и руководства вроде этого призваны помогать вам. Это такое пособие, которое мне хотелось бы иметь, когда я только знакомился с Докером сам. Надеюсь, ему удалось заинтересовать вас, так что теперь вы сможете следить за прогрессом в этом области не со стороны, а с позиции знающего человека.
Ниже — список дополнительных полезных ресурсов. Советую использовать Докер в вашем следующем проекте. И не забывайте — практика приводит к совершенству.
Дополнительные ресурсы
Удачи, юный падаван!
4.2 Фидбек автору
Теперь моя очередь задавать вопросы. Вам понравилось пособие? Оно показалось вам запутанным, или вам удалось научиться чему-то?
Напишите мне (автору оригинального пособия, — прим. пер.) напрямую на [email protected] или просто создайте issue. Я есть в Твиттере, так что если хотите, то можете писать туда.
(Автор оригинального пособия говорит по-английски, — прим. пер.).
Буду рад услышать ваши отзывы. Не стесняйтесь предлагать улучшения или указывать на мои ошибки. Я хочу, чтобы это пособие стало одним из лучших стартовых руководств в интернете. У меня не получится это без вашей помощи.
с нуля до кластера на AWS / Хабр
Содержание
Вопросы и ответы
Что такое Докер?
Определение Докера в Википедии звучит так:
программное обеспечение для автоматизации развёртывания и управления приложениями в среде виртуализации на уровне операционной системы; позволяет «упаковать» приложение со всем его окружением и зависимостями в контейнер, а также предоставляет среду по управлению контейнерами.
Ого! Как много информации. Простыми словами, Докер это инструмент, который позволяет разработчикам, системными администраторам и другим специалистам деплоить их приложения в песочнице (которые называются контейнерами), для запуска на целевой операционной системе, например, Linux. Ключевое преимущество Докера в том, что он позволяет пользователям упаковать приложение со всеми его зависимостями в стандартизированный модуль для разработки. В отличие от виртуальных машин, контейнеры не создают такой дополнительной нагрузки, поэтому с ними можно использовать систему и ресурсы более эффективно.
Что такое контейнер?
Стандарт в индустрии на сегодняшний день — это использовать виртуальные машины для запуска приложений. Виртуальные машины запускают приложения внутри гостевой операционной системы, которая работает на виртуальном железе основной операционной системы сервера.
Виртуальные машины отлично подходят для полной изоляции процесса для приложения: почти никакие проблемы основной операционной системы не могут повлиять на софт гостевой ОС, и наоборот. Но за такую изоляцию приходится платить. Существует значительная вычислительная нагрузка, необходимая для виртуализации железа гостевой ОС.
Контейнеры используют другой подход: они предоставляют схожий с виртуальными машинами уровень изоляции, но благодаря правильному задействованию низкоуровневых механизмов основной операционной системы делают это с в разы меньшей нагрузкой.
Почему я должен использовать их?
Взлет Докера был по-настоящему эпичным. Не смотря на то, что контейнеры сами по себе — не новая технология, до Докера они не были так распространены и популярны. Докер изменил ситуацию, предоставив стандартный API, который сильно упростил создание и использование контейнеров, и позволил сообществу вместе работать над библиотеками по работе с контейнерами. В статье, опубликованной в The Register в середине 2014 говорится, что Гугл поддерживает больше двух миллиардов контейнеров в неделю.
Google Trends для слова ‘Docker’
В дополнение к продолжительному росту Докера, компания-разработчик Docker Inc. была оценена в два с лишним миллиарда долларов! Благодаря преимуществам в эффективности и портативности, Докер начал получать все больше поддержки, и сейчас стоит во главе движения по контейнеризации (containerization). Как современные разработчики, мы должны понять этот тренд и выяснить, какую пользу мы можем получить из него.
Чему меня научит это пособие?
Это единое и полное пособие по всем аспектам работы с Докером. Кроме разъяснения мифов о Докере и его экосистеме, оно позволит вам получит небольшой опыт по сборке и деплою собственных веб-приложений в облаке. Мы будем использовать Amazon Web Services для деплоя статичных сайтов, и два динамических веб-приложения задеплоим на EC2 с использованием Elastic Beanstalk и Elastic Container Service. Даже если вы никогда ничего не деплоили, это пособие даст вам все необходимое.
Как использовать этот документ
Этот документ содержит несколько разделов, каждый из которых посвящен определенному аспекту Докера. В каждом разделе мы будем вводить команды или писать код. Весь код доступен в репозитории на Гитхабе.
Введение
Внимание: В этом пособии используется версия Докера 1.12.0-rc2. Если вы столкнулись с несовместимостью, пожалуйста, отправьте issue. Спасибо!
Пре-реквизиты
Все, что нужно для прохождения этого пособия — это базовые навыки с командной строкой и текстовым редактором. Опыт разработки веб-приложений будет полезен, но не обязателен. В течение работы мы столкнемся с несколькими облачными сервисами. Вам понадобится создать аккаунт на этих сайтах:
Настройка компьютера
Установка и настройка всех необходимых инструментов может быть тяжелой задачей, но, к счастью, Докер стал довольно стабильным, и установка и запуск его на любой ОС стало очень простой задачей. Итак, установим Докер.
Докер
Еще несколько релизов назад запуск Докера на OS X и Windows был был проблемным. Но команда разработчиков проделала огромную работу, и сегодня весь процесс — проще некуда. Этот туториал getting started включает в себя подробные инструкции по установке на Мак, Linux и Windows.
Проверим, все ли установлено корректно:
$ docker run hello-world
Hello from Docker.
This message shows that your installation appears to be working correctly.
...
Python
Python обычно предустановлен на OS X и на большинстве дистрибутивов Linux. Если вам нужно установить Питон, то скачайте установщик здесь.
Проверьте версию:
$ python --version
Python 2.7.11
Мы будем использовать pip для установки пакетов для нашего приложения. Если pip не установлен, то скачайте версию для своей системы.
Для проверки запустите такую команду:
$ pip --version
pip 7.1.2 from /Library/Python/2.7/site-packages/pip-7.1.2-py2.7.egg (python 2.7)
Java (не обязательно)
Разрабатываемое нами приложение будет использовать Elasticsearch для хранения и поиска. Для локального запуска Elasticsearch вам понадобится Java. В этом пособии все будет запускаться внутри контейнера, так что локально не обязательно иметь Java. Если Java установлена, то команда java -version
должна сгенерировать подобный вывод:
$ java -version
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
1.0 Играем с Busybox
Теперь, когда все необходимое установлено, пора взяться за работу. В этом разделе мы запустим контейнер Busybox на нашей системе и попробуем запустить docker run
.
Для начала, запустите следующую команду:
$ docker pull busybox
Внимание: в зависимости от того, как вы устанавливали Докер на свою систему, возможно появление сообщения
permission denied
. Если вы на Маке, то удостоверьтесь, что движок Докер запущен. Если вы на Линуксе, то запустите эту команду сsudo
. Или можете создать группу docker чтобы избавиться от этой проблемы.
Команда pull
скачивает образ busybox из регистра Докера и сохраняет его локально. Можно использовать команду docker images
, чтобы посмотреть список образов в системе.
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
busybox latest c51f86c28340 4 weeks ago 1.109 MB
1.1 Docker Run
Отлично! Теперь давайте запустим Докер-контейнер с этим образом. Для этого используем волшебную команду docker run
:
$ docker run busybox
$
Подождите, ничего не произошло! Это баг? Ну, нет. Под капотом произошло много всего. Докер-клиент нашел образ (в нашем случае, busybox), загрузил контейнер и запустил команду внутри этого контейнера. Мы сделали docker run busybox
, но не указали никаких команд, так что контейнер загрузился, запустилась пустая команда и программа завершилась. Ну, да, как-то обидно, так что давайте сделаем что-то поинтереснее.
$ docker run busybox echo "hello from busybox"
hello from busybox
Ура, наконец-то какой-то вывод. В нашем случае клиент Докера послушно запустил команду echo
внутри контейнера, а потом вышел из него. Вы, наверное, заметили, что все произошло очень быстро. А теперь представьте себе, как нужно загружать виртуальную машину, запускать в ней команду и выключать ее. Теперь ясно, почему говорят, что контейнеры быстрые!
Теперь давайте взглянем на команду docker ps
. Она выводит на экран список всех запущенных контейнеров.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Контейнеров сейчас нет, поэтому выводится пустая строка. Не очень полезно, поэтому давайте запустим более полезный вариант: docker ps -a
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
305297d7a235 busybox "uptime" 11 minutes ago Exited (0) 11 minutes ago distracted_goldstine
ff0a5c3750b9 busybox "sh" 12 minutes ago Exited (0) 12 minutes ago elated_ramanujan
Теперь виден список всех контейнеров, которые мы запускали. В колонке STATUS
можно заметить, что контейнеры завершили свою работу несколько минут назад.
Вам, наверное, интересно, как запустить больше одной команды в контейнере. Давайте попробуем:
$ docker run -it busybox sh
/ # ls
bin dev etc home proc root sys tmp usr var
/ # uptime
05:45:21 up 5:58, 0 users, load average: 0.00, 0.01, 0.04
Команда run
с флагом -it
подключает интерактивный tty в контейнер. Теперь можно запускать сколько угодно много команд внутри. Попробуйте.
Опасно!: Если хочется острых ощущений, то можете попробовать
rm -rf bin
в контейнере. Но удостоверьтесь, что запускаете ее внутри контейнера, а не снаружи. Если сделаете это снаружи, на своем компьютере, то будет очень плохо, и команды вродеls
,echo
перестанут работать. Когда внутри контейнера все перестанет работать, просто выйдете и запустите его заново командойdocker run -it busybox sh
. Докер создает новый контейнер при запуске, поэтому все заработает снова.
На этом захватывающий тур по возможностям команды docker run
закончен. Скорее всего, вы будете использовать эту команду довольно часто. Так что важно, чтобы мы поняли как с ней обращаться. Чтобы узнать больше о run
, используйте docker run --help
, и увидите полный список поддерживаемых флагов. Скоро мы увидим еще несколько способов использования docker run
.
Перед тем, как продолжать, давайте вкратце рассмотрим удаление контейнеров. Мы видели выше, что с помощью команды docker ps -a
все еще можно увидеть остатки завершенных контейнеров. На протяжении этого пособия, вы будете запускать docker run
несколько раз, и оставшиеся, бездомные контейнеры будут съедать дисковое пространство. Так что я взял за правило удалять контейнеры после завершения работы с ними. Для этого используется команда docker rm
. Просто скопируйте ID (можно несколько) из вывода выше и передайте параметрами в команду.
$ docker rm 305297d7a235 ff0a5c3750b9
305297d7a235
ff0a5c3750b9
При удалении идентификаторы будут снова выведены на экран. Если нужно удалить много контейнеров, то вместо ручного копирования и вставления можно сделать так:
$ docker rm $(docker ps -a -q -f status=exited)
Эта команда удаляет все контейнеры, у которых статус exited
. Флаг -q
возвращает только численные ID, а флаг -f
фильтрует вывод на основе предоставленных условий. Последняя полезная деталь — команде docker run
можно передать флаг --rm
, тогда контейнер будет автоматически удаляться при завершении. Это очень полезно для разовых запусков и экспериментов с Докером.
Также можно удалять ненужные образы командой docker rmi
.
1.2 Терминология
В предыдущем разделе мы использовали много специфичного для Докера жаргона, и многих это может запутать. Перед тем, как продолжать, давайте разберем некоторые термины, которые часто используются в экосистеме Докера.
- Images (образы) — Схемы нашего приложения, которые являются основой контейнеров. В примере выше мы использовали команду
docker pull
чтобы скачать образ busybox. - Containers (контейнеры) — Создаются на основе образа и запускают само приложение. Мы создали контейнер командой
docker run
, и использовали образ busybox, скачанный ранее. Список запущенных контейнеров можно увидеть с помощью командыdocker ps
. - Docker Daemon (демон Докера) — Фоновый сервис, запущенный на хост-машине, который отвечает за создание, запуск и уничтожение Докер-контейнеров. Демон — это процесс, который запущен на операционной системе, с которой взаимодействует клиент.
- Docker Client (клиент Докера) — Утилита командной строки, которая позволяет пользователю взаимодействовать с демоном. Существуют другие формы клиента, например, Kitematic, с графическим интерфейсом.
- Docker Hub — Регистр Докер-образов. Грубо говоря, архив всех доступных образов. Если нужно, то можно содержать собственный регистр и использовать его для получения образов.
2.0 Веб-приложения и Докер
Супер! Теперь мы научились работать с docker run
, поиграли с несколькими контейнерами и разобрались в терминологии. Вооруженные этими знаниями, мы готовы переходить к реальным штукам: деплою веб-приложений с Докером!
2.1 Статические сайты
Давайте начнем с малого. Вначале рассмотрим самый простой статический веб-сайт. Скачаем образ из Docker Hub, запустим контейнер и посмотрим, насколько легко будет запустить веб-сервер.
Поехали. Для одностраничного сайта нам понадобится образ, который я заранее создал для этого пособия и разместил в регистре — prakhar1989/static-site
. Можно скачать образ напрямую командой docker run
.
$ docker run prakhar1989/static-site
Так как образа не существует локально, клиент сначала скачает образ из регистра, а потом запустит его. Если все без проблем, то вы увидите сообщение Nginx is running...
в терминале. Теперь сервер запущен. Как увидеть сайт в действии? На каком порту работает сервер? И, что самое важное, как напрямую достучаться до контейнера из хост-контейнера?
В нашем случае клиент не открывает никакие порты, так что нужно будет перезапустить команду docker run
чтобы сделать порты публичными. Заодно давайте сделаем так, чтобы терминал не был прикреплен к запущенному контейнеру. В таком случае можно будет спокойно закрыть терминал, а контейнер продолжит работу. Это называется detached mode.
$ docker run -d -P --name static-site prakhar1989/static-site
e61d12292d69556eabe2a44c16cbd54486b2527e2ce4f95438e504afb7b02810
Флаг -d
открепит (detach) терминал, флаг -P
сделает все открытые порты публичными и случайными, и, наконец, флаг --name
это имя, которое мы хотим дать контейнеру. Теперь можно увидеть порты с помощью команды docker port [CONTAINER]
.
$ docker port static-site
80/tcp -> 0.0.0.0:32769
443/tcp -> 0.0.0.0:32768
Откройте http://localhost:32769 в своем браузере.
Замечание: Если вы используете docker-toolbox, то, возможно, нужно будет использовать
docker-machine ip default
чтобы получить IP-адрес.
Также можете обозначить свой порт. Клиент будет перенаправлять соединения на него.
$ docker run -p 8888:80 prakhar1989/static-site
Nginx is running...
Чтобы остановить контейнер запустите docker stop
и укажите идентификатор (ID) контейнера.
Согласитесь, все было очень просто. Чтобы задеплоить это на реальный сервер, нужно просто установить Докер и запустить команду выше. Теперь, когда вы увидели, как запускать веб-сервер внутри образа, вам, наверное, интересно — а как создать свой Докер-образ? Мы будем изучать эту тему в следующем разделе.
2.2 Образы
Мы касались образов ранее, но в этом разделе мы заглянем глубже: что такое Докер-образы и как создавать собственные образы. Наконец, мы используем собственный образ чтобы запустить приложение локально, а потом задеплоим его на AWS, чтобы показать друзьям. Круто? Круто! Давайте начнем.
Образы это основы для контейнеров. В прошлом примере мы скачали (pull) образ под названием Busybox из регистра, и попросили клиент Докера запустить контейнер, основанный на этом образе. Чтобы увидеть список доступных локально образов, используйте команду docker images
.
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
prakhar1989/catnip latest c7ffb5626a50 2 hours ago 697.9 MB
prakhar1989/static-site latest b270625a1631 21 hours ago 133.9 MB
python 3-onbuild cf4002b2c383 5 days ago 688.8 MB
martin/docker-cleanup-volumes latest b42990daaca2 7 weeks ago 22.14 MB
ubuntu latest e9ae3c220b23 7 weeks ago 187.9 MB
busybox latest c51f86c28340 9 weeks ago 1.109 MB
hello-world latest 0a6ba66e537a 11 weeks ago 960 B
Это список образов, которые я скачал из регистра, а также тех, что я сделал сам (скоро увидим, как это делать). TAG
— это конкретный снимок или снэпшот (snapshot) образа, а IMAGE ID
— это соответствующий уникальный идентификатор образа.
Для простоты, можно относиться к образу как к git-репозиторию. Образы можно коммитить с изменениями, и можно иметь несколько версий. Если не указывать конкретную версию, то клиент по умолчанию использует latest
. Например, можно скачать определенную версию образа ubuntu
:
$ docker pull ubuntu:12.04
Чтобы получить новый Докер-образ, можно скачать его из регистра (такого, как Docker Hub) или создать собственный. На Docker Hub есть десятки тысяч образов. Можно искать напрямую из командной строки с помощью docker search
.
Важно понимать разницу между базовыми и дочерними образами:
- Base images (базовые образы) — это образы, которые не имеют родительского образа. Обычно это образы с операционной системой, такие как ubuntu, busybox или debian.
- Child images (дочерние образы) — это образы, построенные на базовых образах и обладающие дополнительной функциональностью.
Существуют официальные и пользовательские образы, и любые из них могут быть базовыми и дочерними.
- Официальные образы — это образы, которые официально поддерживаются командой Docker. Обычно в их названии одно слово. В списке выше
python
,ubuntu
,busybox
иhello-world
— базовые образы. - Пользовательские образы — образы, созданные простыми пользователями вроде меня и вас. Они построены на базовых образах. Обычно, они называются по формату
user/image-name
.
2.3 Наш первый образ
Теперь, когда мы лучше понимаем, что такое образы и какие они бывают, самое время создать собственный образ. Цель этого раздела — создать образ с простым приложением на Flask. Для этого пособия я сделал маленькое приложение, которое выводит случайную гифку с кошкой. Ну, потому что, кто не любит кошек? Склонируйте этот репозиторий к себе на локальную машину.
Вначале давайте проверим, что приложение работает локально. Войдите в директорию flask-app
командой cd
и установите зависимости.
$ cd flask-app
$ pip install -r requirements.txt
$ python app.py
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Если все хорошо, то вы увидите вывод как в примере выше. Зайдите на http://localhost:5000 чтобы увидеть приложение в действии.
Замечание: Если команда
pip install
падает с ошибками «permission denied», то попробуйте запустить ее сsudo
. Если не хотите устанавливать пользовательские пакеты на уровне системы, то используйте командуpip install --user -r requirements.txt
.
Выглядит отлично, правда? Теперь нужно создать образ с приложением. Как говорилось выше, все пользовательские образы основаны на базовом образе. Так как наше приложение написано на Питоне, нам нужен базовый образ Python 3. В частности, нам нужна версия python:3-onbuild
базового образа с Питоном.
Что за версия onbuild
, спросите вы?
Эти образы включают несколько триггеров ONBUILD, которых обычно достаточно чтобы быстро развернуть приложение. При сборке будет скопирован файл
requirements.txt
, будет запущенpip install
с этим файлом, а потом текущая директория будет скопирована в/usr/src/app
.
Другими словами, версия onbuild
включает хелперы, которые автоматизируют скучные процессы запуска приложения. Вместо того, чтобы вручную выполнять эти задачи (или писать скрипты), образы делают все за вас. Теперь у нас есть все ингредиенты для создания своего образа: работающее веб-приложение и базовый образ. Как это сделать? Ответ: использовать Dockerfile.
2.4 Dockerfile
Dockerfile — это простой текстовый файл, в котором содержится список команд Докер-клиента. Это простой способ автоматизировать процесс создания образа. Самое классное, что команды в Dockerfile почти идентичны своим аналогам в Linux. Это значит, что в принципе не нужно изучать никакой новый синтаксис чтобы начать работать с докерфайлами.
В директории с приложением есть Dockerfile, но так как мы делаем все впервые, нам нужно создать его с нуля. Создайте новый пустой файл в любимом текстовом редакторе, и сохраните его в той же директории, где находится flask-приложение. Назовите файл Dockerfile
.
Для начала укажем базовый образ. Для этого нужно использовать ключевое слово FROM
.
FROM python:3-onbuild
Дальше обычно указывают команды для копирования файлов и установки зависимостей. Но к счастью, onbuild
-версия базового образа берет эти задачи на себя. Дальше нам нужно указать порт, который следует открыть. Наше приложение работает на порту 5000, поэтому укажем его:
EXPOSE 5000
Последний шаг — указать команду для запуска приложения. Это просто python ./app.py
. Для этого используем команду CMD:
CMD ["python", "./app.py"]
Главное предназначение CMD
— это сообщить контейнеру какие команды нужно выполнить при старте. Теперь наш Dockerfile
готов. Вот как он выглядит:
# our base image
FROM python:3-onbuild
# specify the port number the container should expose
EXPOSE 5000
# run the application
CMD ["python", "./app.py"]
Теперь можно создать образ. Команда docker build
занимается сложной задачей создания образа на основе Dockerfile
.
Листинг ниже демонстрирует процесс. Перед тем, как запустите команду сами (не забудьте точку в конце), проверьте, чтобы там был ваш username вместо моего. Username должен соответствовать тому, что использовался при регистрации на Docker hub. Если вы еще не регистрировались, то сделайте это до выполнения команды. Команда docker build
довольно проста: она принимает опциональный тег с флагом -t
и путь до директории, в которой лежит Dockerfile
.
$ docker build -t prakhar1989/catnip .
Sending build context to Docker daemon 8.704 kB
Step 1 : FROM python:3-onbuild
# Executing 3 build triggers...
Step 1 : COPY requirements.txt /usr/src/app/
---> Using cache
Step 1 : RUN pip install --no-cache-dir -r requirements.txt
---> Using cache
Step 1 : COPY . /usr/src/app
---> 1d61f639ef9e
Removing intermediate container 4de6ddf5528c
Step 2 : EXPOSE 5000
---> Running in 12cfcf6d67ee
---> f423c2f179d1
Removing intermediate container 12cfcf6d67ee
Step 3 : CMD python ./app.py
---> Running in f01401a5ace9
---> 13e87ed1fbc2
Removing intermediate container f01401a5ace9
Successfully built 13e87ed1fbc2
Если у вас нет образа python:3-onbuild
, то клиент сначала скачает его, а потом возьмется за создание вашего образа. Так что, вывод на экран может отличаться от моего. Посмотрите внимательно, и найдете триггеры onbuild. Если все прошло хорошо, то образ готов! Запустите docker images
и увидите свой образ в списке.
Последний шаг — запустить образ и проверить его работоспособность (замените username на свой):
$ docker run -p 8888:5000 prakhar1989/catnip
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Зайдите на указанный URL и увидите приложение в работе.
Поздравляю! Вы успешно создали свой первый образ Докера!
2.5 Docker на AWS
Что хорошего в приложении, которое нельзя показать друзьям, правда? Так что в этом разделе мы научимся деплоить наше офигенное приложение в облако. Будем использовать AWS Elastic Beanstalk чтобы решить эту задачу за пару кликов. Мы увидим, как с помощью Beanstalk легко управлять и масштабировать наше приложение.
Docker push
Первое, что нужно сделать перед деплоем на AWS это опубликовать наш образ в регистре, чтобы можно было скачивать его из AWS. Есть несколько Docker-регистров (или можно создать собственный). Для начала, давайте используем Docker Hub. Просто выполните:
$ docker push prakhar1989/catnip
Если это ваша первая публикация, то клиент попросит вас залогиниться. Введите те же данные, что используете для входа в Docker Hub.
$ docker login
Username: prakhar1989
WARNING: login credentials saved in /Users/prakhar/.docker/config.json
Login Succeeded
Не забудьте заменить название образа на свое. Очень важно сохранить формат username/image_name
, чтобы клиент понимал, куда публиковать образ.
После этого можете посмотреть на свой образ на Docker Hub. Например, вот страница моего образа.
Замечание: один важный момент, который стоит прояснить перед тем, как продолжить — не обязательно хранить образ в публичном регистре (или в любом другом регистре вообще) чтобы деплоить на AWS. Если вы пишете код для следующего многомиллионного стартапа-единорога, то можно пропустить этот шаг. Мы публикуем свой образ чтобы упростить деплой, пропустив несколько конфигурационных шагов.
Теперь наш образ онлайн, и любой докер-клиент может поиграться с ним с помощью простой команды:
$ docker run -p 8888:5000 prakhar1989/catnip
Если в прошлом вы мучались с установкой локального рабочего окружения и попытками поделиться своей конфигурацией с коллегами, то понимаете, как круто это звучит. Вот почему Докер — это сила!
Beanstalk
AWS Elastic Beanstalk (EB) это PaaS (Platform as a Service — платформа как сервис) от Amazon Web Services. Если вы использовали Heroku, Google App Engine и т.д., то все будет привычно. Как разработчик, вы сообщаете EB как запускать ваше приложение, а EB занимается всем остальным, в том числе масштабированием, мониторингом и даже апдейтами. В апреле 2014 в EB добавили возможность запускать Докер-контейнеры, и мы будем использовать именно эту возможность для деплоя. У EB очень понятный интерфейс командной строки, но он требует небольшой конфигурации, поэтому для простоты давайте используем веб-интерфейс для запуска нашего приложения.
Чтобы продолжать, вам потребуется работающий аккаунт на AWS. Если у вас его нет, то создайте его. Для этого потребуется ввести данные кредитной карты. Но не волнуйтесь, эта услуга бесплатна, и все, что будет происходить в рамках этого пособия тоже бесплатно.
Давайте начнем:
- Войдите в свою консоль AWS.
- Нажмите на Elastic Beanstalk. Ссылка находится в секции compute, в левом верхнем углу. Или просто перейдите сюда.
- Нажмите на «Create New Application» в верхнем правом углу.
- Дайте своему приложению запоминающееся (но уникальное) имя и, если хотите, добавьте описание.
- на экране New Environment выберите Web Server Environment.
- Следующий экран показан ниже. Выберите Docker из готовых вариантов конфигурации. Можно оставить Environment type как есть. Нажмите Next.
- Тут мы будем сообщать системе EB о нашем образе. Откройте файл Dockerrun.aws.json в директории
flask-app
и изменитеName
образа, чтобы оно соответствовало названию вашего образа. Не волнуйтесь, я опишу содержание файла попозже. Потом выберите вариант «upload your own» и выберите файл. - Далее, выберите название окружения и URL. Этот URL как раз можно будет давать друзьям, так что постарайтесь придумать что-нибудь попроще.
- Пока не будем вносить никаких правок в секцию Additional Resources. Нажмите Next и переходите к Configuration Details.
- В этой секции вам нужно выбрать тип инстанса
t1.micro
. Это очень важно, потому что это бесплатный тип от AWS. Если хотите, можно выбрать пару ключей для входа. Если вы не знаете, что это значит, то не волнуйтесь и просто пропустите эту часть. Все остальное можно оставить по умолчанию и продолжать. - Также не нужно указывать никакие Environment Tags and Permissions, так что просто жмите Next два раза подряд. В конце будет экран Review. Если все выглядит нормально, то нажимайте кнопку Launch.
- На последнем экране будет несколько спиннеров. Это поднимается и настраивается ваше окружение. Обычно, нужно около пяти минут для первой настройки.
Пока ждем, давайте быстренько взглянем на файл Dockerrun.aws.json
. Это файл для AWS, в котором находится информация о приложении конфигурации Докера. EB получает информацию из этого файла.
{
"AWSEBDockerrunVersion": "1",
"Image": {
"Name": "prakhar1989/catnip",
"Update": "true"
},
"Ports": [
{
"ContainerPort": "5000"
}
],
"Logging": "/var/log/nginx"
}
Файл довольно понятный, но всегда можно обратиться к официальной документации. Мы указываем название образа, и EB будет использовать его заодно с портом.
К этому моменту инстанс уже должен быть готов. Зайдите на страницу EB и увидите зеленый индикатор успешного запуска приложения.
Зайдите на указанный URL в браузере и увидите приложение во все красе. Пошлите адрес своим друзьям, чтобы все могли насладиться гифками с кошками.
Поздравляю! Вы задеплоили свое первое Докер-приложение! Может показаться, что было очень много шагов, но с командной утилитой EB можно имитировать функциональность Хероку несколькими нажатиями клавиш. Надеюсь, вы согласитесь, что Докер сильно упрощает процесс и минимизирует болезненные моменты деплоя в облако. Я советую вам почитать документацию AWS про single-container Docker environment чтобы понимать, какие существуют возможности в EB.
В следующей, последней части пособия, мы пойдем немного дальше и задеплоим приложение, приближенное к реальному миру. В нем будет постоянное бэкэнд-хранилище. Поехали!
3.0 Многоконтейнерные окружения
В прошлом разделе мы увидели, как легко и просто запускать приложения с помощью Докера. Мы начали с простого статического сайта, а потом запустили Flask-приложение. Оба варианта можно было запускать локально или в облаке, несколькими командами. Общая черта этих приложений: каждое из них работало в одном контейнере.
Если у вас есть опыт управления сервисами в продакшене, то вы знаете, что современные приложения обычно не такие простые. Почти всегда есть база данных (или другой тип постоянного хранилища). Системы вроде Redis и Memcached стали практически обязательной частью архитектуры веб-приложений. Поэтому, в этом разделе мы научимся «докеризировать» приложения, которым требуется несколько запущенных сервисов.
В частности, мы увидим, как запускать и управлять многоконтейнерными Докер-окружениями. Почему нужно несколько контейнеров, спросите вы? Ну, одна из главных идей Докера в том, что он предоставляет изоляцию. Идея совмещения процесса и его зависимостей в одной песочнице (называемой контейнером) и делает Докер мощным инструментом.
Аналогично тому, как приложение разбивают на части, стоит содержать отдельные сервисы в отдельных контейнерах. Разным частям скорее всего требуются разные ресурсы, и требования могут расти с разной скоростью. Если мы разделим эти части и поместим в разные контейнеры, то каждую часть приложения можно строить, используя наиболее подходящий тип ресурсов. Это также хорошо совмещается с идеей микро сервисов. Это одна из причин, по которой Докер (и любая другая технология контейнеризации) находится на передовой современных микро сервисных архитектур.
3.1 SF Food Trucks
Приложение, которое мы переведем в Докер, называется SF Food Trucks (к сожалению, сейчас приложение уже не работает публично — прим. пер.). Моя цель была сделать что-то полезное (и похожее на настоящее приложение из реального мира), что-то, что использует как минимум один сервис, но не слишком сложное для этого пособия. Вот что я придумал.
Бэкэнд приложения написано на Питоне (Flask), а для поиска используется Elasticsearch. Как и все остальное в этом пособии, код находится на Github. Мы используем это приложение, чтобы научиться запускать и деплоить много-контейнерное окружение.
Теперь, когда вы завелись (надеюсь), давайте подумаем, как будет выглядеть этот процесс. В нашем приложении есть бэкэнд на Flask и сервис Elasticsearch. Очевидно, что можно поделить приложение на два контейнера: один для Flask, другой для Elasticsearch (ES). Если приложение станет популярным, то можно будет добавлять новые контейнеры в нужном месте, смотря где будет узкое место.
Отлично, значит нужно два контейнера. Это не сложно, правда? Мы уже создавали Flask-контейнер в прошлом разделе. А для Elasticsearch… давайте посмотрим, есть ли что-нибудь в хабе:
$ docker search elasticsearch
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
elasticsearch Elasticsearch is a powerful open source se... 697 [OK]
itzg/elasticsearch Provides an easily configurable Elasticsea... 17 [OK]
tutum/elasticsearch Elasticsearch image - listens in port 9200. 15 [OK]
barnybug/elasticsearch Latest Elasticsearch 1.7.2 and previous re... 15 [OK]
digitalwonderland/elasticsearch Latest Elasticsearch with Marvel & Kibana 12 [OK]
monsantoco/elasticsearch ElasticSearch Docker image 9 [OK]
Не удивительно, но существуют официальный образ для Elasticsearch. Чтобы запустить ES, нужно всего лишь выполнить docker run
, и вскоре у нас будет локальный, работающий контейнер с одним узлом ES.
$ docker run -dp 9200:9200 elasticsearch
d582e031a005f41eea704cdc6b21e62e7a8a42021297ce7ce123b945ae3d3763
$ curl 0.0.0.0:9200
{
"name" : "Ultra-Marine",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.1.1",
"build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
"build_timestamp" : "2015-12-15T13:05:55Z",
"build_snapshot" : false,
"lucene_version" : "5.3.1"
},
"tagline" : "You Know, for Search"
}
Заодно давайте запустим контейнер с Flask. Но вначале нужен Dockerfile
. В прошлой секции мы использовали образ python:3-onbuild
в качестве базового. Однако, в этом раз, кроме установки зависимостей через pip
, нам нужно, чтобы приложение генерировало минимизированный Javascript-файл для продакшена. Для этого понадобится Nodejs. Так что нужен свой билд с нуля, поэтому начнем с базового образа ubuntu
.
Замечание: если оказывается, что существующий образ не подходит для вашей задачи, то спокойно создавайте свой образ на основе другого базового образа. В большинстве случаем, для образов на Docker Hub можно найти соответствующий
Dockerfile
на Github. Почитайте существующий Докерфайлы — это один из лучших способов научиться делать свои образы.
Наш Dockerfile для Flask-приложения выглядит следующим образом:
# start from base
FROM ubuntu:14.04
MAINTAINER Prakhar Srivastav <[email protected]>
# install system-wide deps for python and node
RUN apt-get -yqq update
RUN apt-get -yqq install python-pip python-dev
RUN apt-get -yqq install nodejs npm
RUN ln -s /usr/bin/nodejs /usr/bin/node
# copy our application code
ADD flask-app /opt/flask-app
WORKDIR /opt/flask-app
# fetch app specific deps
RUN npm install
RUN npm run build
RUN pip install -r requirements.txt
# expose port
EXPOSE 5000
# start app
CMD [ "python", "./app.py" ]
Тут много всего нового. Вначале указан базовый образ Ubuntu LTS, потом используется пакетный менеджер apt-get
для установки зависимостей, в частности — Python и Node. Флаг yqq
нужен для игнорирования вывода и автоматического выбора «Yes» во всех местах. Также создается символическая ссылка для бинарного файла node. Это нужно для решения проблем обратной совместимости.
Потом мы используем команду ADD
для копирования приложения в нужную директорию в контейнере — /opt/flask-app
. Здесь будет находиться весь наш код. Мы также устанавливаем эту директорию в качестве рабочей, так что следующие команды будут выполняться в контексте этой локации. Теперь, когда наши системные зависимости установлены, пора установить зависимости уровня приложения. Начнем с Node, установки пакетов из npm и запуска команды сборки, как указано в нашем файле package.json. В конце устанавливаем пакеты Python, открываем порт и определяем запуск приложения с помощь CMD
, как в предыдущем разделе.
Наконец, можно собрать образ и запустить контейнер (замените prakhar1989
на свой username ниже).
$ docker build -t prakhar1989/foodtrucks-web .
При первом запуске нужно будет больше времени, так как клиент Докера будет скачивать образ ubuntu, запускать все команды и готовить образ. Повторный запуск docker build
после последующих изменений будет практически моментальным. Давайте попробуем запустить приложение
$ docker run -P prakhar1989/foodtrucks-web
Unable to connect to ES. Retying in 5 secs...
Unable to connect to ES. Retying in 5 secs...
Unable to connect to ES. Retying in 5 secs...
Out of retries. Bailing out...
Упс! Наше приложение не смогло запуститься, потому что оно не может подключиться к Elasticsearch. Как сообщить одному контейнеру о другом и как заставить их взаимодействовать друг с другом? Ответ — в следующей секции.
3.2 Сети Docker
Перед тем, как обсудить возможности Докера для решения описанной задачи, давайте посмотрим на возможные варианты обхода проблемы. Думаю, это поможет нам оценить удобство той функциональности, которую мы вскоре изучим.
Ладно, давайте запустим docker ps
, что тут у нас:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e931ab24dedc elasticsearch "/docker-entrypoint.s" 2 seconds ago Up 2 seconds 0.0.0.0:9200->9200/tcp, 9300/tcp cocky_spence
Итак, у нас есть контейнер ES по адресу и порту 0.0.0.0:9200
, и мы можем напрямую обращаться к нему. Если можно было бы сообщить нашему приложению подключаться к этому адресу, то оно сможет общаться с ES, верно? Давайте взглянем на код на Питоне, туда, где описано подключение.
es = Elasticsearch(host='es')
Нужно сообщить Flask-контейнеру, что контейнер ES запущен на хосте 0.0.0.0
(порт по умолчанию 9200
), и все заработает, да? К сожалению, нет, потому что IP 0.0.0.0
это адрес для доступа к контейнеру с хост-машины, то есть с моего Мака. Другой контейнер не сможет обратиться по этому адресу. Ладно, если не этот адрес, то какой другой адрес нужно использовать для работы с контейнером ES? Рад, что вы спросили.
Это хороший момент, чтобы изучить работу сети в Докере. После установки, Докер автоматически создает три сети:
$ docker network ls
NETWORK ID NAME DRIVER
075b9f628ccc none null
be0f7178486c host host
8022115322ec bridge bridge
Сеть bridge — это сеть, в которой контейнеры запущены по умолчанию. Это значит, что когда я запускаю контейнер ES, он работает в этой сети bridge. Чтобы удостовериться, давайте проверим:
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "8022115322ec80613421b0282e7ee158ec41e16f565a3e86fa53496105deb2d7",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.17.0.0/16"
}
]
},
"Containers": {
"e931ab24dedc1640cddf6286d08f115a83897c88223058305460d7bd793c1947": {
"EndpointID": "66965e83bf7171daeb8652b39590b1f8c23d066ded16522daeb0128c9c25c189",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
}
}
]
Видно, что контейнер e931ab24dedc
находится в секции Containers
. Также виден IP-адрес, выданный этому контейнеру — 172.17.0.2
. Именно этот адрес мы и искали? Давайте проверим: запустим Flask-приложение и попробуем обратиться к нему по IP:
$ docker run -it --rm prakhar1989/foodtrucks-web bash
root@35180ccc206a:/opt/flask-app# curl 172.17.0.2:9200
bash: curl: command not found
root@35180ccc206a:/opt/flask-app# apt-get -yqq install curl
root@35180ccc206a:/opt/flask-app# curl 172.17.0.2:9200
{
"name" : "Jane Foster",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.1.1",
"build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
"build_timestamp" : "2015-12-15T13:05:55Z",
"build_snapshot" : false,
"lucene_version" : "5.3.1"
},
"tagline" : "You Know, for Search"
}
root@35180ccc206a:/opt/flask-app# exit
Сейчас все должно быть понятно. Мы запустили контейнер в интерактивном режиме с процессом bash
. Флаг --rm
нужен для удобства, благодаря нему контейнер автоматически удаляется после выхода. Мы попробуем curl
, но нужно сначала установить его. После этого можно удостовериться, что по адресу 172.17.0.2:9200
на самом деле можно обращаться к ES! Супер!
Не смотря на то, что мы нашли способ наладить связь между контейнерами, существует несколько проблем с этим подходом:
- Придется добавлять записи в файл
/etc/hosts
внутри Flask-контейнера, чтобы приложение понимало, что имя хостаes
означает172.17.0.2
. Если IP-адрес меняется, то придется вручную менять запись. - Так как сеть bridge используется всеми контейнерами по умолчанию, этот метод не безопасен.
Но есть хорошие новости: в Докере есть отличное решение этой проблемы. Докер позволяет создавать собственные изолированные сети. Это решение также помогает справиться с проблемой /etc/hosts
, сейчас увидим как.
Во-первых, давайте создадим свою сеть:
$ docker network create foodtrucks
1a3386375797001999732cb4c4e97b88172d983b08cd0addfcb161eed0c18d89
$ docker network ls
NETWORK ID NAME DRIVER
1a3386375797 foodtrucks bridge
8022115322ec bridge bridge
075b9f628ccc none null
be0f7178486c host host
Команда network create
создает новую сеть bridge. Нам сейчас нужен именно такой тип. Существуют другие типы сетей, и вы можете почитать о них в официальной документации.
Теперь у нас есть сеть. Можно запустить наши контейнеры внутри сети с помощью флага --net
. Давайте так и сделаем, но сначала остановим контейнер с ElasticSearch, который был запущен в сети bridge по умолчанию.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e931ab24dedc elasticsearch "/docker-entrypoint.s" 4 hours ago Up 4 hours 0.0.0.0:9200->9200/tcp, 9300/tcp cocky_spence
$ docker stop e931ab24dedc
e931ab24dedc
$ docker run -dp 9200:9200 --net foodtrucks --name es elasticsearch
2c0b96f9b8030f038e40abea44c2d17b0a8edda1354a08166c33e6d351d0c651
$ docker network inspect foodtrucks
[
{
"Name": "foodtrucks",
"Id": "1a3386375797001999732cb4c4e97b88172d983b08cd0addfcb161eed0c18d89",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{}
]
},
"Containers": {
"2c0b96f9b8030f038e40abea44c2d17b0a8edda1354a08166c33e6d351d0c651": {
"EndpointID": "15eabc7989ef78952fb577d0013243dae5199e8f5c55f1661606077d5b78e72a",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {}
}
]
Мы сделали то же, что и раньше, но на этот раз дали контейнеру название es
. Перед тем, как запускать контейнер с приложением, давайте проверим что происходит, когда запуск происходит в сети.
$ docker run -it --rm --net foodtrucks prakhar1989/foodtrucks-web bash
root@53af252b771a:/opt/flask-app# cat /etc/hosts
172.18.0.3 53af252b771a
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.2 es
172.18.0.2 es.foodtrucks
root@53af252b771a:/opt/flask-app# curl es:9200
bash: curl: command not found
root@53af252b771a:/opt/flask-app# apt-get -yqq install curl
root@53af252b771a:/opt/flask-app# curl es:9200
{
"name" : "Doctor Leery",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.1.1",
"build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
"build_timestamp" : "2015-12-15T13:05:55Z",
"build_snapshot" : false,
"lucene_version" : "5.3.1"
},
"tagline" : "You Know, for Search"
}
root@53af252b771a:/opt/flask-app# ls
app.py node_modules package.json requirements.txt static templates webpack.config.js
root@53af252b771a:/opt/flask-app# python app.py
Index not found...
Loading data in elasticsearch ...
Total trucks loaded: 733
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
root@53af252b771a:/opt/flask-app# exit
Ура! Работает! Магическим образом Докер внес нужные правки в файл /etc/hosts
, и поэтому es:9200
можно использовать в приложении — этот адрес корректно направляет запросы в контейнер ES. Отлично! Давайте теперь запустим Flask-контейнер по-настоящему:
$ docker run -d --net foodtrucks -p 5000:5000 --name foodtrucks-web prakhar1989/foodtrucks-web
2a1b77e066e646686f669bab4759ec1611db359362a031667cacbe45c3ddb413
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a1b77e066e6 prakhar1989/foodtrucks-web "python ./app.py" 2 seconds ago Up 1 seconds 0.0.0.0:5000->5000/tcp foodtrucks-web
2c0b96f9b803 elasticsearch "/docker-entrypoint.s" 21 minutes ago Up 21 minutes 0.0.0.0:9200->9200/tcp, 9300/tcp es
$ curl -I 0.0.0.0:5000
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 3697
Server: Werkzeug/0.11.2 Python/2.7.6
Date: Sun, 10 Jan 2016 23:58:53 GMT
Зайдите на http://0.0.0.0:5000, и увидите приложение в работе. Опять же, может показаться, что было много работы, но на самом деле мы ввели всего 4 команды чтобы с нуля дойти до работающего приложения. Я собрал эти команды в bash-скрипт.
#!/bin/bash
# build the flask container
docker build -t prakhar1989/foodtrucks-web .
# create the network
docker network create foodtrucks
# start the ES container
docker run -d --net foodtrucks -p 9200:9200 -p 9300:9300 --name es elasticsearch
# start the flask app container
docker run -d --net foodtrucks -p 5000:5000 --name foodtrucks-web prakhar1989/foodtrucks-web
Теперь представьте, что хотите поделиться приложением с другом. Или хотите запустить на сервере, где установлен Докер. Можно запустить всю систему с помощью одной команды!
$ git clone https://github.com/prakhar1989/FoodTrucks
$ cd FoodTrucks
$ ./setup-docker.sh
Вот и все! По-моему, это невероятно крутой и мощный способ распространять и запускать приложения!
Docker Links
Перед тем, как завершить этот раздел, стоит отметить, что docker network
это относительно новая фича, она входит в релиз Docker 1.9 .
До того, как появился network
, ссылки были допустимым способом настройки взаимодействия между контейнерами. В соответствии с официальной документацией, linking вскоре будет переведены в статус deprecated. Если вам попадется туториал или статья, где используется link
для соединения контейнеров, то просто не забывайте использовать вместо этого network
(на момент публикации перевода links является legacy, — прим. пер.)
3.3 Docker Compose
До этого момента мы изучали клиент Докера. Но в экосистеме Докера есть несколько других инструментов с открытым исходным кодом, которые хорошо взаимодействуют с Докером. Некоторые из них это:
- Docker Machine позволяет создавать Докер-хосты на своем компьютере, облачном провайдере или внутри дата-центра.
- Docker Compose — инструмент для определения и запуска много-контейнерных приложений.
- Docker Swarm — нативное решение для кластеризации.
В этом разделе мы поговорим об одном из этих инструментов — Docker Compose, и узнаем, как он может упростить работу с несколькими контейнерами.
У Docker Compose довольно интересная предыстория. Примерно два года назад компания OrchardUp запустила инструмент под названием Fig. Идея была в том, чтобы создавать изолированные рабочие окружения с помощью Докера. Проект очень хорошо восприняли на Hacker News — я смутно помню, что читал о нем, но не особо понял его смысла.
Первый комментарий на самом деле неплохо объясняет, зачем нужен Fig и что он делает:
На самом деле, смысл Докера в следующем: запускать процессы. Сегодня у Докера есть неплохое API для запуска процессов: расшаренные между контейнерами (иными словами, запущенными образами) разделы или директории (shared volumes), перенаправление портов с хост-машины в контейнер, вывод логов, и так далее. Но больше ничего: Докер сейчас работает только на уровне процессов.
Не смотря на то, что в нем содержатся некоторые возможности оркестрации нескольких контейнеров для создания единого «приложения», в Докере нет ничего, что помогало бы с управлением такими группами контейнеров как одной сущностью. И вот зачем нужен инструмент вроде Fig: чтобы обращаться с группой контейнеров как с единой сущностью. Чтобы думать о «запуске приложений» (иными словами, «запуске оркестрированного кластера контейнеров») вместо «запуска контейнеров».
Оказалось, что многие пользователи Докера согласны с такими мыслями. Постепенно, Fig набрал популярность, Docker Inc. заметили, купили компанию и назвали проект Docker Compose.
Итак, зачем используется Compose? Это инструмент для простого определения и запуска многоконтейнерных Докер-приложений. В нем есть файл docker-compose.yml
, и с его помощью можно одной командой поднять приложение с набором сервисов.
Давайте посмотрим, сможем ли мы создать файл docker-compose.yml
для нашего приложения SF-Foodtrucks и проверим, способен ли он на то, что обещает.
Но вначале нужно установить Docker Compose. Есть у вас Windows или Mac, то Docker Compose уже установлен — он идет в комплекте с Docker Toolbox. На Linux можно установить Docker Compose следуя простым инструкциям на сайте документации. Compose написан на Python, поэтому можно сделать просто pip install docker-compose
. Проверить работоспособность так:
$ docker-compose version
docker-compose version 1.7.1, build 0a9ab35
docker-py version: 1.8.1
CPython version: 2.7.9
OpenSSL version: OpenSSL 1.0.1j 15 Oct 2014
Теперь можно перейти к следующему шагу, то есть созданию файла docker-compose.yml
. Синтаксис yml
-файлов очень простой, и в репозитории уже есть пример, который мы будем использовать
version: "2"
services:
es:
image: elasticsearch
web:
image: prakhar1989/foodtrucks-web
command: python app.py
ports:
- "5000:5000"
volumes:
- .:/code
Давайте я разберу это подробнее. На родительском уровне мы задали название неймспейса для наших сервисов: es
и web
. К каждому сервису можно добавить дополнительные параметры, среди которых image
— обязательный. Для es
мы указываем доступный на Docker Hub образ elasticsearch
. Для Flask-приложения — тот образ, который мы создали самостоятельно в начале этого раздела.
С помощью других параметров вроде command
и ports
можно предоставить информацию о контейнере. volumes
отвечает за локацию монтирования, где будет находиться код в контейнере web
. Это опциональный параметр, он полезен, если нужно обращаться к логам и так далее. Подробнее о параметрах и возможных значениях можно прочитать в документации.
Замечание: Нужно находиться в директории с файлом
docker-compose.yml
чтобы запускать большую часть команд Compose.
Отлично! Файл готов, давайте посмотрим на docker-compose
в действии. Но вначале нужно удостовериться, что порты свободны. Так что если у вас запущены контейнеры Flask и ES, то пора их остановить:
$ docker stop $(docker ps -q)
39a2f5df14ef
2a1b77e066e6
Теперь можно запускать docker-compose
. Перейдите в директорию с приложением Foodtrucks и выполните команду docker-compose up
.
$ docker-compose up
Creating network "foodtrucks_default" with the default driver
Creating foodtrucks_es_1
Creating foodtrucks_web_1
Attaching to foodtrucks_es_1, foodtrucks_web_1
es_1 | [2016-01-11 03:43:50,300][INFO ][node ] [Comet] version[2.1.1], pid[1], build[40e2c53/2015-12-15T13:05:55Z]
es_1 | [2016-01-11 03:43:50,307][INFO ][node ] [Comet] initializing ...
es_1 | [2016-01-11 03:43:50,366][INFO ][plugins ] [Comet] loaded [], sites []
es_1 | [2016-01-11 03:43:50,421][INFO ][env ] [Comet] using [1] data paths, mounts [[/usr/share/elasticsearch/data (/dev/sda1)]], net usable_space [16gb], net total_space [18.1gb], spins? [possibly], types [ext4]
es_1 | [2016-01-11 03:43:52,626][INFO ][node ] [Comet] initialized
es_1 | [2016-01-11 03:43:52,632][INFO ][node ] [Comet] starting ...
es_1 | [2016-01-11 03:43:52,703][WARN ][common.network ] [Comet] publish address: {0.0.0.0} is a wildcard address, falling back to first non-loopback: {172.17.0.2}
es_1 | [2016-01-11 03:43:52,704][INFO ][transport ] [Comet] publish_address {172.17.0.2:9300}, bound_addresses {[::]:9300}
es_1 | [2016-01-11 03:43:52,721][INFO ][discovery ] [Comet] elasticsearch/cEk4s7pdQ-evRc9MqS2wqw
es_1 | [2016-01-11 03:43:55,785][INFO ][cluster.service ] [Comet] new_master {Comet}{cEk4s7pdQ-evRc9MqS2wqw}{172.17.0.2}{172.17.0.2:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
es_1 | [2016-01-11 03:43:55,818][WARN ][common.network ] [Comet] publish address: {0.0.0.0} is a wildcard address, falling back to first non-loopback: {172.17.0.2}
es_1 | [2016-01-11 03:43:55,819][INFO ][http ] [Comet] publish_address {172.17.0.2:9200}, bound_addresses {[::]:9200}
es_1 | [2016-01-11 03:43:55,819][INFO ][node ] [Comet] started
es_1 | [2016-01-11 03:43:55,826][INFO ][gateway ] [Comet] recovered [0] indices into cluster_state
es_1 | [2016-01-11 03:44:01,825][INFO ][cluster.metadata ] [Comet] [sfdata] creating index, cause [auto(index api)], templates [], shards [5]/[1], mappings [truck]
es_1 | [2016-01-11 03:44:02,373][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,510][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,593][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,708][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:03,047][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Перейдите по IP чтобы увидеть приложение. Круто, да? Всего лишь пара строк конфигурации и несколько Докер-контейнеров работают в унисон. Давайте остановим сервисы и перезапустим в detached mode:
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Killing foodtrucks_web_1 ... done
Killing foodtrucks_es_1 ... done
$ docker-compose up -d
Starting foodtrucks_es_1
Starting foodtrucks_web_1
$ docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------
foodtrucks_es_1 /docker-entrypoint.sh elas ... Up 9200/tcp, 9300/tcp
foodtrucks_web_1 python app.py Up 0.0.0.0:5000->5000/tcp
Не удивительно, но оба контейнера успешно запущены. Откуда берутся имена? Их Compose придумал сам. Но что насчет сети? Его Compose тоже делаем сам? Хороший вопрос, давайте выясним.
Для начала, остановим запущенные сервисы. Их всегда можно вернуть одной командой:
$ docker-compose stop
Stopping foodtrucks_web_1 ... done
Stopping foodtrucks_es_1 ... done
Заодно, давайте удалим сеть foodtrucks
, которую создали в прошлый раз. Эта сеть нам не потребуется, потому что Compose автоматически сделает все за нас.
$ docker network rm foodtrucks
$ docker network ls
NETWORK ID NAME DRIVER
4eec273c054e bridge bridge
9347ae8783bd none null
54df57d7f493 host host
Класс! Теперь в этом чистом состоянии можно проверить, способен ли Compose на волшебство.
$ docker-compose up -d
Recreating foodtrucks_es_1
Recreating foodtrucks_web_1
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f50bb33a3242 prakhar1989/foodtrucks-web "python app.py" 14 seconds ago Up 13 seconds 0.0.0.0:5000->5000/tcp foodtrucks_web_1
e299ceeb4caa elasticsearch "/docker-entrypoint.s" 14 seconds ago Up 14 seconds 9200/tcp, 9300/tcp foodtrucks_es_1
Пока все хорошо. Проверим, создались ли какие-нибудь сети:
$ docker network ls
NETWORK ID NAME DRIVER
0c8b474a9241 bridge bridge
293a141faac3 foodtrucks_default bridge
b44db703cd69 host host
0474c9517805 none null
Видно, что Compose самостоятельно создал сеть foodtrucks_default
и подсоединил оба сервиса в эту сеть, так, чтобы они могли общаться друг с другом. Каждый контейнер для сервиса подключен к сети, и оба контейнера доступны другим контейнерам в сети. Они доступны по hostname, который совпадает с названием контейнера. Давайте проверим, находится ли эта информация в /etc/hosts
.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bb72dcebd379 prakhar1989/foodtrucks-web "python app.py" 20 hours ago Up 19 hours 0.0.0.0:5000->5000/tcp foodtrucks_web_1
3338fc79be4b elasticsearch "/docker-entrypoint.s" 20 hours ago Up 19 hours 9200/tcp, 9300/tcp foodtrucks_es_1
$ docker exec -it bb72dcebd379 bash
root@bb72dcebd379:/opt/flask-app# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.2 bb72dcebd379
Упс! Оказывается, файл понятия не имеет о es
. Как же наше приложение работает? Давайте попингуем его по названию хоста:
root@bb72dcebd379:/opt/flask-app# ping es
PING es (172.18.0.3) 56(84) bytes of data.
64 bytes from foodtrucks_es_1.C
--- es ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.049/0.056/0.064/0.010 ms
Вуаля! Работает! Каким-то магическим образом контейнер смог сделать пинг хоста es
. Оказывается, Docker 1.10 добавили новую сетевую систему, которая производит обнаружение сервисов через DNS-сервер. Если интересно, то почитайте подробнее о предложении и release notes.
На этом наш тур по Docker Compose завершен. С этим инструментом можно ставить сервисы на паузу, запускать отдельные команды в контейнере и даже масштабировать систему, то есть увеличивать количество контейнеров. Также советую изучать некоторые другие примеры использования Docker Compose.
Надеюсь, я продемонстрировал как на самом деле просто управлять многоконтейнерной средой с Compose. В последнем разделе мы задеплоим все на AWS!
3.4 AWS Elastic Container Service
В прошлом разделе мы использовали docker-compose
чтобы запустить наше приложение локально одной командой: docker-compose up
. Теперь, когда приложение работает, мы хотим показать его миру, заполучить юзеров, поднять кучу денег и купить большой дом в Майами. Последние три шага выходят за пределы этого пособия, так что займемся выяснением деталей о деплое многоконтейнерного приложения в облако AWS.
Если вы дочитали до этого места, то скорее всего убедились, что Docker — довольно крутая технология. И вы не одиноки. Облачные провайдеры заметили взрывной рост популярности Докера и стали добавлять поддержку в свои сервисы. Сегодня, Докер-приложения можно деплоить на AWS, Azure,Rackspace, DigitalOcean и много других. Мы уже умеем деплоить приложение с одним контейнером на Elastic Beanstalk, а в этом разделе мы изучим AWS Elastic Container Service (или ECS).
AWS ECS — это масштабируемый и гибкий сервис по управлению контейнерами, и он поддерживает Докер. С его помощью можно управлять кластером на EC2 через простой API. В Beanstalk были нормальные настройки по умолчанию, но ECS позволяет настроить каждый аспект окружения по вашим потребностям. По этой причине ECS — не самый простой инструмент в начале пути.
К счастью, у ECS есть удобный инструмент командной строки (CLI) с поддержкой Docker Compose и автоматической провизией на ECS! Так как у нас уже есть рабочий файл docker-compose.yml
, настройка и запуск на AWS должна быть достаточно легкой. Начнем!
Вначале нужно установить CLI. На момент написания этого пособия CLI-утилита не доступна на Windows. Инструкции по установке CLI на Mac и Linux хорошо описаны на сайте с официальной документацией. Установите утилиту, а потом проверьте ее работоспособность так:
$ ecs-cli --version
ecs-cli version 0.1.0 (*cbdc2d5)
Первый шаг — задать пару ключей для авторизации на инстансах. Зайдите на страницу EC2 Console и создайте новый keypair. Скачайте файл и держите его в безопасном месте. Еще один момент — имя региона. Я назвал свой ключ ecs
и указал регион us-east-1
. Я продолжу повествование с этим допущением.
Теперь настройте CLI:
$ ecs-cli configure --region us-east-1 --cluster foodtrucks
INFO[0000] Saved ECS CLI configuration for cluster (foodtrucks)
Команда configure
с именем региона, в котором хотим разместить наш кластер, и название кластера. Нужно указать тот же регион, что использовался прри создании ключей. Если у вас не настроен AWS CLI, то следуйте руководству, которое подробно описывает все шаги.
Следующий шаг позволяет утилите создавать шаблон CloudFormation.
$ ecs-cli up --keypair ecs --capability-iam --size 2 --instance-type t2.micro
INFO[0000] Created cluster cluster=foodtrucks
INFO[0001] Waiting for your cluster resources to be created
INFO[0001] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0061] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0122] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0182] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0242] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
Здесь мы указываем названия ключей, которые мы скачали (в моем случае ecs
), количество инстансов (--size
) и тип инстансов, на которых хотим запускать контейнеры. Флаг --capability-iam
говорит утилите, что мы понимаем, что эта команда может создать ресурсы IAM.
В последнем шаге мы используем файл docker-compose.yml
. Требуется небольшое изменение, так что вместо модификации файла, давайте сделаем копию и назовем ее aws-compose.yml
. Содержание этого файла (после изменений):
es:
image: elasticsearch
cpu_shares: 100
mem_limit: 262144000
web:
image: prakhar1989/foodtrucks-web
cpu_shares: 100
mem_limit: 262144000
ports:
- "80:5000"
links:
- es
Единственные отличия от оригинального файла docker-compose.yml
это параметры mem_limit
и cpu_shares
для каждого контейнера.
Также, мы убрали version
и services
, так как AWS еще не поддерживает версию 2 файлового формата Compose. Так как наше приложение будет работать на инстансах типа t2.micro
, мы задали 250 мегабайт памяти. Теперь нам нужно опубликовать образ на Docker Hub. На момент написания этого пособия, ecs-cli не поддерживает команду build
. Но Docker Compose поддерживает ее без проблем.
$ docker push prakhar1989/foodtrucks-web
Красота! Давайте запустим финальную команду, которая произведет деплой на ECS!
$ ecs-cli compose --file aws-compose.yml up
INFO[0000] Using ECS task definition TaskDefinition=ecscompose-foodtrucks:2
INFO[0000] Starting container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es
INFO[0000] Starting container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web
INFO[0000] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0000] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0036] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0048] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0048] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0060] Started container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-foodtrucks:2
INFO[0060] Started container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-foodtrucks:2
То, что вывод похож на вывод Docker Compose — не совпадение. Аргумент --file
используется для переопределения файла по умолчанию (docker-compose.yml
). Если все прошло хорошо, то вы увидите строку desiredStatus=RUNNING lastStatus=RUNNING
в самом конце.
Круто! Теперь приложение запущено. Как к нему обратиться?
ecs-cli ps
Name State Ports TaskDefinition
845e2368-170d-44a7-bf9f-84c7fcd9ae29/web RUNNING 54.86.14.14:80->5000/tcp ecscompose-foodtrucks:2
845e2368-170d-44a7-bf9f-84c7fcd9ae29/es RUNNING ecscompose-foodtrucks:2
Откройте http://54.86.14.14 в браузере, и увидите Food Trucks во всей своей желто-черной красе! Заодно, давайте взглянем на консоль AWS ECS.
Видно, что был создан ECS-кластер ‘foodtrucks’, и в нем выполняется одна задача с двумя инстансами. Советую поковыряться в этой консоли и изучить разные ее части и опции.
Вот и все. Всего несколько команд — и приложение работает на AWS!
4.0 Заключение
Мы подошли к концу. После длинного, изматывающего, но интересного пособия вы готовы захватить мир контейнеров! Если вы следовали пособию до самого конца, то можете заслуженно гордиться собой. Вы научились устанавливать Докер, запускать свои контейнеры, запускать статические и динамические веб-сайты и, самое главное, получили опыт деплоя приложений в облако.
Надеюсь, прохождение этого руководства помогло вам стать увереннее в своих способностях управляться с серверами. Когда у вас появится новая идея для сайта или приложения, можете быть уверены, что сможете показать его людям с минимальными усилиями.
4.1 Следующие шаги
Ваше путешествие в мир контейнеров только началось. Моей целью в этом руководстве было нагулять ваш аппетит и показать мощь Докера. В мире современных технологий иногда бывает сложно разобраться самостоятельно, и руководства вроде этого призваны помогать вам. Это такое пособие, которое мне хотелось бы иметь, когда я только знакомился с Докером сам. Надеюсь, ему удалось заинтересовать вас, так что теперь вы сможете следить за прогрессом в этом области не со стороны, а с позиции знающего человека.
Ниже — список дополнительных полезных ресурсов. Советую использовать Докер в вашем следующем проекте. И не забывайте — практика приводит к совершенству.
Дополнительные ресурсы
Удачи, юный падаван!
4.2 Фидбек автору
Теперь моя очередь задавать вопросы. Вам понравилось пособие? Оно показалось вам запутанным, или вам удалось научиться чему-то?
Напишите мне (автору оригинального пособия, — прим. пер.) напрямую на [email protected] или просто создайте issue. Я есть в Твиттере, так что если хотите, то можете писать туда.
(Автор оригинального пособия говорит по-английски, — прим. пер.).
Буду рад услышать ваши отзывы. Не стесняйтесь предлагать улучшения или указывать на мои ошибки. Я хочу, чтобы это пособие стало одним из лучших стартовых руководств в интернете. У меня не получится это без вашей помощи.
с нуля до кластера на AWS / Хабр
Содержание
Вопросы и ответы
Что такое Докер?
Определение Докера в Википедии звучит так:
программное обеспечение для автоматизации развёртывания и управления приложениями в среде виртуализации на уровне операционной системы; позволяет «упаковать» приложение со всем его окружением и зависимостями в контейнер, а также предоставляет среду по управлению контейнерами.
Ого! Как много информации. Простыми словами, Докер это инструмент, который позволяет разработчикам, системными администраторам и другим специалистам деплоить их приложения в песочнице (которые называются контейнерами), для запуска на целевой операционной системе, например, Linux. Ключевое преимущество Докера в том, что он позволяет пользователям упаковать приложение со всеми его зависимостями в стандартизированный модуль для разработки. В отличие от виртуальных машин, контейнеры не создают такой дополнительной нагрузки, поэтому с ними можно использовать систему и ресурсы более эффективно.
Что такое контейнер?
Стандарт в индустрии на сегодняшний день — это использовать виртуальные машины для запуска приложений. Виртуальные машины запускают приложения внутри гостевой операционной системы, которая работает на виртуальном железе основной операционной системы сервера.
Виртуальные машины отлично подходят для полной изоляции процесса для приложения: почти никакие проблемы основной операционной системы не могут повлиять на софт гостевой ОС, и наоборот. Но за такую изоляцию приходится платить. Существует значительная вычислительная нагрузка, необходимая для виртуализации железа гостевой ОС.
Контейнеры используют другой подход: они предоставляют схожий с виртуальными машинами уровень изоляции, но благодаря правильному задействованию низкоуровневых механизмов основной операционной системы делают это с в разы меньшей нагрузкой.
Почему я должен использовать их?
Взлет Докера был по-настоящему эпичным. Не смотря на то, что контейнеры сами по себе — не новая технология, до Докера они не были так распространены и популярны. Докер изменил ситуацию, предоставив стандартный API, который сильно упростил создание и использование контейнеров, и позволил сообществу вместе работать над библиотеками по работе с контейнерами. В статье, опубликованной в The Register в середине 2014 говорится, что Гугл поддерживает больше двух миллиардов контейнеров в неделю.
Google Trends для слова ‘Docker’
В дополнение к продолжительному росту Докера, компания-разработчик Docker Inc. была оценена в два с лишним миллиарда долларов! Благодаря преимуществам в эффективности и портативности, Докер начал получать все больше поддержки, и сейчас стоит во главе движения по контейнеризации (containerization). Как современные разработчики, мы должны понять этот тренд и выяснить, какую пользу мы можем получить из него.
Чему меня научит это пособие?
Это единое и полное пособие по всем аспектам работы с Докером. Кроме разъяснения мифов о Докере и его экосистеме, оно позволит вам получит небольшой опыт по сборке и деплою собственных веб-приложений в облаке. Мы будем использовать Amazon Web Services для деплоя статичных сайтов, и два динамических веб-приложения задеплоим на EC2 с использованием Elastic Beanstalk и Elastic Container Service. Даже если вы никогда ничего не деплоили, это пособие даст вам все необходимое.
Как использовать этот документ
Этот документ содержит несколько разделов, каждый из которых посвящен определенному аспекту Докера. В каждом разделе мы будем вводить команды или писать код. Весь код доступен в репозитории на Гитхабе.
Введение
Внимание: В этом пособии используется версия Докера 1.12.0-rc2. Если вы столкнулись с несовместимостью, пожалуйста, отправьте issue. Спасибо!
Пре-реквизиты
Все, что нужно для прохождения этого пособия — это базовые навыки с командной строкой и текстовым редактором. Опыт разработки веб-приложений будет полезен, но не обязателен. В течение работы мы столкнемся с несколькими облачными сервисами. Вам понадобится создать аккаунт на этих сайтах:
Настройка компьютера
Установка и настройка всех необходимых инструментов может быть тяжелой задачей, но, к счастью, Докер стал довольно стабильным, и установка и запуск его на любой ОС стало очень простой задачей. Итак, установим Докер.
Докер
Еще несколько релизов назад запуск Докера на OS X и Windows был был проблемным. Но команда разработчиков проделала огромную работу, и сегодня весь процесс — проще некуда. Этот туториал getting started включает в себя подробные инструкции по установке на Мак, Linux и Windows.
Проверим, все ли установлено корректно:
$ docker run hello-world
Hello from Docker.
This message shows that your installation appears to be working correctly.
...
Python
Python обычно предустановлен на OS X и на большинстве дистрибутивов Linux. Если вам нужно установить Питон, то скачайте установщик здесь.
Проверьте версию:
$ python --version
Python 2.7.11
Мы будем использовать pip для установки пакетов для нашего приложения. Если pip не установлен, то скачайте версию для своей системы.
Для проверки запустите такую команду:
$ pip --version
pip 7.1.2 from /Library/Python/2.7/site-packages/pip-7.1.2-py2.7.egg (python 2.7)
Java (не обязательно)
Разрабатываемое нами приложение будет использовать Elasticsearch для хранения и поиска. Для локального запуска Elasticsearch вам понадобится Java. В этом пособии все будет запускаться внутри контейнера, так что локально не обязательно иметь Java. Если Java установлена, то команда java -version
должна сгенерировать подобный вывод:
$ java -version
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
1.0 Играем с Busybox
Теперь, когда все необходимое установлено, пора взяться за работу. В этом разделе мы запустим контейнер Busybox на нашей системе и попробуем запустить docker run
.
Для начала, запустите следующую команду:
$ docker pull busybox
Внимание: в зависимости от того, как вы устанавливали Докер на свою систему, возможно появление сообщения
permission denied
. Если вы на Маке, то удостоверьтесь, что движок Докер запущен. Если вы на Линуксе, то запустите эту команду сsudo
. Или можете создать группу docker чтобы избавиться от этой проблемы.
Команда pull
скачивает образ busybox из регистра Докера и сохраняет его локально. Можно использовать команду docker images
, чтобы посмотреть список образов в системе.
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
busybox latest c51f86c28340 4 weeks ago 1.109 MB
1.1 Docker Run
Отлично! Теперь давайте запустим Докер-контейнер с этим образом. Для этого используем волшебную команду docker run
:
$ docker run busybox
$
Подождите, ничего не произошло! Это баг? Ну, нет. Под капотом произошло много всего. Докер-клиент нашел образ (в нашем случае, busybox), загрузил контейнер и запустил команду внутри этого контейнера. Мы сделали docker run busybox
, но не указали никаких команд, так что контейнер загрузился, запустилась пустая команда и программа завершилась. Ну, да, как-то обидно, так что давайте сделаем что-то поинтереснее.
$ docker run busybox echo "hello from busybox"
hello from busybox
Ура, наконец-то какой-то вывод. В нашем случае клиент Докера послушно запустил команду echo
внутри контейнера, а потом вышел из него. Вы, наверное, заметили, что все произошло очень быстро. А теперь представьте себе, как нужно загружать виртуальную машину, запускать в ней команду и выключать ее. Теперь ясно, почему говорят, что контейнеры быстрые!
Теперь давайте взглянем на команду docker ps
. Она выводит на экран список всех запущенных контейнеров.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Контейнеров сейчас нет, поэтому выводится пустая строка. Не очень полезно, поэтому давайте запустим более полезный вариант: docker ps -a
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
305297d7a235 busybox "uptime" 11 minutes ago Exited (0) 11 minutes ago distracted_goldstine
ff0a5c3750b9 busybox "sh" 12 minutes ago Exited (0) 12 minutes ago elated_ramanujan
Теперь виден список всех контейнеров, которые мы запускали. В колонке STATUS
можно заметить, что контейнеры завершили свою работу несколько минут назад.
Вам, наверное, интересно, как запустить больше одной команды в контейнере. Давайте попробуем:
$ docker run -it busybox sh
/ # ls
bin dev etc home proc root sys tmp usr var
/ # uptime
05:45:21 up 5:58, 0 users, load average: 0.00, 0.01, 0.04
Команда run
с флагом -it
подключает интерактивный tty в контейнер. Теперь можно запускать сколько угодно много команд внутри. Попробуйте.
Опасно!: Если хочется острых ощущений, то можете попробовать
rm -rf bin
в контейнере. Но удостоверьтесь, что запускаете ее внутри контейнера, а не снаружи. Если сделаете это снаружи, на своем компьютере, то будет очень плохо, и команды вродеls
,echo
перестанут работать. Когда внутри контейнера все перестанет работать, просто выйдете и запустите его заново командойdocker run -it busybox sh
. Докер создает новый контейнер при запуске, поэтому все заработает снова.
На этом захватывающий тур по возможностям команды docker run
закончен. Скорее всего, вы будете использовать эту команду довольно часто. Так что важно, чтобы мы поняли как с ней обращаться. Чтобы узнать больше о run
, используйте docker run --help
, и увидите полный список поддерживаемых флагов. Скоро мы увидим еще несколько способов использования docker run
.
Перед тем, как продолжать, давайте вкратце рассмотрим удаление контейнеров. Мы видели выше, что с помощью команды docker ps -a
все еще можно увидеть остатки завершенных контейнеров. На протяжении этого пособия, вы будете запускать docker run
несколько раз, и оставшиеся, бездомные контейнеры будут съедать дисковое пространство. Так что я взял за правило удалять контейнеры после завершения работы с ними. Для этого используется команда docker rm
. Просто скопируйте ID (можно несколько) из вывода выше и передайте параметрами в команду.
$ docker rm 305297d7a235 ff0a5c3750b9
305297d7a235
ff0a5c3750b9
При удалении идентификаторы будут снова выведены на экран. Если нужно удалить много контейнеров, то вместо ручного копирования и вставления можно сделать так:
$ docker rm $(docker ps -a -q -f status=exited)
Эта команда удаляет все контейнеры, у которых статус exited
. Флаг -q
возвращает только численные ID, а флаг -f
фильтрует вывод на основе предоставленных условий. Последняя полезная деталь — команде docker run
можно передать флаг --rm
, тогда контейнер будет автоматически удаляться при завершении. Это очень полезно для разовых запусков и экспериментов с Докером.
Также можно удалять ненужные образы командой docker rmi
.
1.2 Терминология
В предыдущем разделе мы использовали много специфичного для Докера жаргона, и многих это может запутать. Перед тем, как продолжать, давайте разберем некоторые термины, которые часто используются в экосистеме Докера.
- Images (образы) — Схемы нашего приложения, которые являются основой контейнеров. В примере выше мы использовали команду
docker pull
чтобы скачать образ busybox. - Containers (контейнеры) — Создаются на основе образа и запускают само приложение. Мы создали контейнер командой
docker run
, и использовали образ busybox, скачанный ранее. Список запущенных контейнеров можно увидеть с помощью командыdocker ps
. - Docker Daemon (демон Докера) — Фоновый сервис, запущенный на хост-машине, который отвечает за создание, запуск и уничтожение Докер-контейнеров. Демон — это процесс, который запущен на операционной системе, с которой взаимодействует клиент.
- Docker Client (клиент Докера) — Утилита командной строки, которая позволяет пользователю взаимодействовать с демоном. Существуют другие формы клиента, например, Kitematic, с графическим интерфейсом.
- Docker Hub — Регистр Докер-образов. Грубо говоря, архив всех доступных образов. Если нужно, то можно содержать собственный регистр и использовать его для получения образов.
2.0 Веб-приложения и Докер
Супер! Теперь мы научились работать с docker run
, поиграли с несколькими контейнерами и разобрались в терминологии. Вооруженные этими знаниями, мы готовы переходить к реальным штукам: деплою веб-приложений с Докером!
2.1 Статические сайты
Давайте начнем с малого. Вначале рассмотрим самый простой статический веб-сайт. Скачаем образ из Docker Hub, запустим контейнер и посмотрим, насколько легко будет запустить веб-сервер.
Поехали. Для одностраничного сайта нам понадобится образ, который я заранее создал для этого пособия и разместил в регистре — prakhar1989/static-site
. Можно скачать образ напрямую командой docker run
.
$ docker run prakhar1989/static-site
Так как образа не существует локально, клиент сначала скачает образ из регистра, а потом запустит его. Если все без проблем, то вы увидите сообщение Nginx is running...
в терминале. Теперь сервер запущен. Как увидеть сайт в действии? На каком порту работает сервер? И, что самое важное, как напрямую достучаться до контейнера из хост-контейнера?
В нашем случае клиент не открывает никакие порты, так что нужно будет перезапустить команду docker run
чтобы сделать порты публичными. Заодно давайте сделаем так, чтобы терминал не был прикреплен к запущенному контейнеру. В таком случае можно будет спокойно закрыть терминал, а контейнер продолжит работу. Это называется detached mode.
$ docker run -d -P --name static-site prakhar1989/static-site
e61d12292d69556eabe2a44c16cbd54486b2527e2ce4f95438e504afb7b02810
Флаг -d
открепит (detach) терминал, флаг -P
сделает все открытые порты публичными и случайными, и, наконец, флаг --name
это имя, которое мы хотим дать контейнеру. Теперь можно увидеть порты с помощью команды docker port [CONTAINER]
.
$ docker port static-site
80/tcp -> 0.0.0.0:32769
443/tcp -> 0.0.0.0:32768
Откройте http://localhost:32769 в своем браузере.
Замечание: Если вы используете docker-toolbox, то, возможно, нужно будет использовать
docker-machine ip default
чтобы получить IP-адрес.
Также можете обозначить свой порт. Клиент будет перенаправлять соединения на него.
$ docker run -p 8888:80 prakhar1989/static-site
Nginx is running...
Чтобы остановить контейнер запустите docker stop
и укажите идентификатор (ID) контейнера.
Согласитесь, все было очень просто. Чтобы задеплоить это на реальный сервер, нужно просто установить Докер и запустить команду выше. Теперь, когда вы увидели, как запускать веб-сервер внутри образа, вам, наверное, интересно — а как создать свой Докер-образ? Мы будем изучать эту тему в следующем разделе.
2.2 Образы
Мы касались образов ранее, но в этом разделе мы заглянем глубже: что такое Докер-образы и как создавать собственные образы. Наконец, мы используем собственный образ чтобы запустить приложение локально, а потом задеплоим его на AWS, чтобы показать друзьям. Круто? Круто! Давайте начнем.
Образы это основы для контейнеров. В прошлом примере мы скачали (pull) образ под названием Busybox из регистра, и попросили клиент Докера запустить контейнер, основанный на этом образе. Чтобы увидеть список доступных локально образов, используйте команду docker images
.
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
prakhar1989/catnip latest c7ffb5626a50 2 hours ago 697.9 MB
prakhar1989/static-site latest b270625a1631 21 hours ago 133.9 MB
python 3-onbuild cf4002b2c383 5 days ago 688.8 MB
martin/docker-cleanup-volumes latest b42990daaca2 7 weeks ago 22.14 MB
ubuntu latest e9ae3c220b23 7 weeks ago 187.9 MB
busybox latest c51f86c28340 9 weeks ago 1.109 MB
hello-world latest 0a6ba66e537a 11 weeks ago 960 B
Это список образов, которые я скачал из регистра, а также тех, что я сделал сам (скоро увидим, как это делать). TAG
— это конкретный снимок или снэпшот (snapshot) образа, а IMAGE ID
— это соответствующий уникальный идентификатор образа.
Для простоты, можно относиться к образу как к git-репозиторию. Образы можно коммитить с изменениями, и можно иметь несколько версий. Если не указывать конкретную версию, то клиент по умолчанию использует latest
. Например, можно скачать определенную версию образа ubuntu
:
$ docker pull ubuntu:12.04
Чтобы получить новый Докер-образ, можно скачать его из регистра (такого, как Docker Hub) или создать собственный. На Docker Hub есть десятки тысяч образов. Можно искать напрямую из командной строки с помощью docker search
.
Важно понимать разницу между базовыми и дочерними образами:
- Base images (базовые образы) — это образы, которые не имеют родительского образа. Обычно это образы с операционной системой, такие как ubuntu, busybox или debian.
- Child images (дочерние образы) — это образы, построенные на базовых образах и обладающие дополнительной функциональностью.
Существуют официальные и пользовательские образы, и любые из них могут быть базовыми и дочерними.
- Официальные образы — это образы, которые официально поддерживаются командой Docker. Обычно в их названии одно слово. В списке выше
python
,ubuntu
,busybox
иhello-world
— базовые образы. - Пользовательские образы — образы, созданные простыми пользователями вроде меня и вас. Они построены на базовых образах. Обычно, они называются по формату
user/image-name
.
2.3 Наш первый образ
Теперь, когда мы лучше понимаем, что такое образы и какие они бывают, самое время создать собственный образ. Цель этого раздела — создать образ с простым приложением на Flask. Для этого пособия я сделал маленькое приложение, которое выводит случайную гифку с кошкой. Ну, потому что, кто не любит кошек? Склонируйте этот репозиторий к себе на локальную машину.
Вначале давайте проверим, что приложение работает локально. Войдите в директорию flask-app
командой cd
и установите зависимости.
$ cd flask-app
$ pip install -r requirements.txt
$ python app.py
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Если все хорошо, то вы увидите вывод как в примере выше. Зайдите на http://localhost:5000 чтобы увидеть приложение в действии.
Замечание: Если команда
pip install
падает с ошибками «permission denied», то попробуйте запустить ее сsudo
. Если не хотите устанавливать пользовательские пакеты на уровне системы, то используйте командуpip install --user -r requirements.txt
.
Выглядит отлично, правда? Теперь нужно создать образ с приложением. Как говорилось выше, все пользовательские образы основаны на базовом образе. Так как наше приложение написано на Питоне, нам нужен базовый образ Python 3. В частности, нам нужна версия python:3-onbuild
базового образа с Питоном.
Что за версия onbuild
, спросите вы?
Эти образы включают несколько триггеров ONBUILD, которых обычно достаточно чтобы быстро развернуть приложение. При сборке будет скопирован файл
requirements.txt
, будет запущенpip install
с этим файлом, а потом текущая директория будет скопирована в/usr/src/app
.
Другими словами, версия onbuild
включает хелперы, которые автоматизируют скучные процессы запуска приложения. Вместо того, чтобы вручную выполнять эти задачи (или писать скрипты), образы делают все за вас. Теперь у нас есть все ингредиенты для создания своего образа: работающее веб-приложение и базовый образ. Как это сделать? Ответ: использовать Dockerfile.
2.4 Dockerfile
Dockerfile — это простой текстовый файл, в котором содержится список команд Докер-клиента. Это простой способ автоматизировать процесс создания образа. Самое классное, что команды в Dockerfile почти идентичны своим аналогам в Linux. Это значит, что в принципе не нужно изучать никакой новый синтаксис чтобы начать работать с докерфайлами.
В директории с приложением есть Dockerfile, но так как мы делаем все впервые, нам нужно создать его с нуля. Создайте новый пустой файл в любимом текстовом редакторе, и сохраните его в той же директории, где находится flask-приложение. Назовите файл Dockerfile
.
Для начала укажем базовый образ. Для этого нужно использовать ключевое слово FROM
.
FROM python:3-onbuild
Дальше обычно указывают команды для копирования файлов и установки зависимостей. Но к счастью, onbuild
-версия базового образа берет эти задачи на себя. Дальше нам нужно указать порт, который следует открыть. Наше приложение работает на порту 5000, поэтому укажем его:
EXPOSE 5000
Последний шаг — указать команду для запуска приложения. Это просто python ./app.py
. Для этого используем команду CMD:
CMD ["python", "./app.py"]
Главное предназначение CMD
— это сообщить контейнеру какие команды нужно выполнить при старте. Теперь наш Dockerfile
готов. Вот как он выглядит:
# our base image
FROM python:3-onbuild
# specify the port number the container should expose
EXPOSE 5000
# run the application
CMD ["python", "./app.py"]
Теперь можно создать образ. Команда docker build
занимается сложной задачей создания образа на основе Dockerfile
.
Листинг ниже демонстрирует процесс. Перед тем, как запустите команду сами (не забудьте точку в конце), проверьте, чтобы там был ваш username вместо моего. Username должен соответствовать тому, что использовался при регистрации на Docker hub. Если вы еще не регистрировались, то сделайте это до выполнения команды. Команда docker build
довольно проста: она принимает опциональный тег с флагом -t
и путь до директории, в которой лежит Dockerfile
.
$ docker build -t prakhar1989/catnip .
Sending build context to Docker daemon 8.704 kB
Step 1 : FROM python:3-onbuild
# Executing 3 build triggers...
Step 1 : COPY requirements.txt /usr/src/app/
---> Using cache
Step 1 : RUN pip install --no-cache-dir -r requirements.txt
---> Using cache
Step 1 : COPY . /usr/src/app
---> 1d61f639ef9e
Removing intermediate container 4de6ddf5528c
Step 2 : EXPOSE 5000
---> Running in 12cfcf6d67ee
---> f423c2f179d1
Removing intermediate container 12cfcf6d67ee
Step 3 : CMD python ./app.py
---> Running in f01401a5ace9
---> 13e87ed1fbc2
Removing intermediate container f01401a5ace9
Successfully built 13e87ed1fbc2
Если у вас нет образа python:3-onbuild
, то клиент сначала скачает его, а потом возьмется за создание вашего образа. Так что, вывод на экран может отличаться от моего. Посмотрите внимательно, и найдете триггеры onbuild. Если все прошло хорошо, то образ готов! Запустите docker images
и увидите свой образ в списке.
Последний шаг — запустить образ и проверить его работоспособность (замените username на свой):
$ docker run -p 8888:5000 prakhar1989/catnip
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Зайдите на указанный URL и увидите приложение в работе.
Поздравляю! Вы успешно создали свой первый образ Докера!
2.5 Docker на AWS
Что хорошего в приложении, которое нельзя показать друзьям, правда? Так что в этом разделе мы научимся деплоить наше офигенное приложение в облако. Будем использовать AWS Elastic Beanstalk чтобы решить эту задачу за пару кликов. Мы увидим, как с помощью Beanstalk легко управлять и масштабировать наше приложение.
Docker push
Первое, что нужно сделать перед деплоем на AWS это опубликовать наш образ в регистре, чтобы можно было скачивать его из AWS. Есть несколько Docker-регистров (или можно создать собственный). Для начала, давайте используем Docker Hub. Просто выполните:
$ docker push prakhar1989/catnip
Если это ваша первая публикация, то клиент попросит вас залогиниться. Введите те же данные, что используете для входа в Docker Hub.
$ docker login
Username: prakhar1989
WARNING: login credentials saved in /Users/prakhar/.docker/config.json
Login Succeeded
Не забудьте заменить название образа на свое. Очень важно сохранить формат username/image_name
, чтобы клиент понимал, куда публиковать образ.
После этого можете посмотреть на свой образ на Docker Hub. Например, вот страница моего образа.
Замечание: один важный момент, который стоит прояснить перед тем, как продолжить — не обязательно хранить образ в публичном регистре (или в любом другом регистре вообще) чтобы деплоить на AWS. Если вы пишете код для следующего многомиллионного стартапа-единорога, то можно пропустить этот шаг. Мы публикуем свой образ чтобы упростить деплой, пропустив несколько конфигурационных шагов.
Теперь наш образ онлайн, и любой докер-клиент может поиграться с ним с помощью простой команды:
$ docker run -p 8888:5000 prakhar1989/catnip
Если в прошлом вы мучались с установкой локального рабочего окружения и попытками поделиться своей конфигурацией с коллегами, то понимаете, как круто это звучит. Вот почему Докер — это сила!
Beanstalk
AWS Elastic Beanstalk (EB) это PaaS (Platform as a Service — платформа как сервис) от Amazon Web Services. Если вы использовали Heroku, Google App Engine и т.д., то все будет привычно. Как разработчик, вы сообщаете EB как запускать ваше приложение, а EB занимается всем остальным, в том числе масштабированием, мониторингом и даже апдейтами. В апреле 2014 в EB добавили возможность запускать Докер-контейнеры, и мы будем использовать именно эту возможность для деплоя. У EB очень понятный интерфейс командной строки, но он требует небольшой конфигурации, поэтому для простоты давайте используем веб-интерфейс для запуска нашего приложения.
Чтобы продолжать, вам потребуется работающий аккаунт на AWS. Если у вас его нет, то создайте его. Для этого потребуется ввести данные кредитной карты. Но не волнуйтесь, эта услуга бесплатна, и все, что будет происходить в рамках этого пособия тоже бесплатно.
Давайте начнем:
- Войдите в свою консоль AWS.
- Нажмите на Elastic Beanstalk. Ссылка находится в секции compute, в левом верхнем углу. Или просто перейдите сюда.
- Нажмите на «Create New Application» в верхнем правом углу.
- Дайте своему приложению запоминающееся (но уникальное) имя и, если хотите, добавьте описание.
- на экране New Environment выберите Web Server Environment.
- Следующий экран показан ниже. Выберите Docker из готовых вариантов конфигурации. Можно оставить Environment type как есть. Нажмите Next.
- Тут мы будем сообщать системе EB о нашем образе. Откройте файл Dockerrun.aws.json в директории
flask-app
и изменитеName
образа, чтобы оно соответствовало названию вашего образа. Не волнуйтесь, я опишу содержание файла попозже. Потом выберите вариант «upload your own» и выберите файл. - Далее, выберите название окружения и URL. Этот URL как раз можно будет давать друзьям, так что постарайтесь придумать что-нибудь попроще.
- Пока не будем вносить никаких правок в секцию Additional Resources. Нажмите Next и переходите к Configuration Details.
- В этой секции вам нужно выбрать тип инстанса
t1.micro
. Это очень важно, потому что это бесплатный тип от AWS. Если хотите, можно выбрать пару ключей для входа. Если вы не знаете, что это значит, то не волнуйтесь и просто пропустите эту часть. Все остальное можно оставить по умолчанию и продолжать. - Также не нужно указывать никакие Environment Tags and Permissions, так что просто жмите Next два раза подряд. В конце будет экран Review. Если все выглядит нормально, то нажимайте кнопку Launch.
- На последнем экране будет несколько спиннеров. Это поднимается и настраивается ваше окружение. Обычно, нужно около пяти минут для первой настройки.
Пока ждем, давайте быстренько взглянем на файл Dockerrun.aws.json
. Это файл для AWS, в котором находится информация о приложении конфигурации Докера. EB получает информацию из этого файла.
{
"AWSEBDockerrunVersion": "1",
"Image": {
"Name": "prakhar1989/catnip",
"Update": "true"
},
"Ports": [
{
"ContainerPort": "5000"
}
],
"Logging": "/var/log/nginx"
}
Файл довольно понятный, но всегда можно обратиться к официальной документации. Мы указываем название образа, и EB будет использовать его заодно с портом.
К этому моменту инстанс уже должен быть готов. Зайдите на страницу EB и увидите зеленый индикатор успешного запуска приложения.
Зайдите на указанный URL в браузере и увидите приложение во все красе. Пошлите адрес своим друзьям, чтобы все могли насладиться гифками с кошками.
Поздравляю! Вы задеплоили свое первое Докер-приложение! Может показаться, что было очень много шагов, но с командной утилитой EB можно имитировать функциональность Хероку несколькими нажатиями клавиш. Надеюсь, вы согласитесь, что Докер сильно упрощает процесс и минимизирует болезненные моменты деплоя в облако. Я советую вам почитать документацию AWS про single-container Docker environment чтобы понимать, какие существуют возможности в EB.
В следующей, последней части пособия, мы пойдем немного дальше и задеплоим приложение, приближенное к реальному миру. В нем будет постоянное бэкэнд-хранилище. Поехали!
3.0 Многоконтейнерные окружения
В прошлом разделе мы увидели, как легко и просто запускать приложения с помощью Докера. Мы начали с простого статического сайта, а потом запустили Flask-приложение. Оба варианта можно было запускать локально или в облаке, несколькими командами. Общая черта этих приложений: каждое из них работало в одном контейнере.
Если у вас есть опыт управления сервисами в продакшене, то вы знаете, что современные приложения обычно не такие простые. Почти всегда есть база данных (или другой тип постоянного хранилища). Системы вроде Redis и Memcached стали практически обязательной частью архитектуры веб-приложений. Поэтому, в этом разделе мы научимся «докеризировать» приложения, которым требуется несколько запущенных сервисов.
В частности, мы увидим, как запускать и управлять многоконтейнерными Докер-окружениями. Почему нужно несколько контейнеров, спросите вы? Ну, одна из главных идей Докера в том, что он предоставляет изоляцию. Идея совмещения процесса и его зависимостей в одной песочнице (называемой контейнером) и делает Докер мощным инструментом.
Аналогично тому, как приложение разбивают на части, стоит содержать отдельные сервисы в отдельных контейнерах. Разным частям скорее всего требуются разные ресурсы, и требования могут расти с разной скоростью. Если мы разделим эти части и поместим в разные контейнеры, то каждую часть приложения можно строить, используя наиболее подходящий тип ресурсов. Это также хорошо совмещается с идеей микро сервисов. Это одна из причин, по которой Докер (и любая другая технология контейнеризации) находится на передовой современных микро сервисных архитектур.
3.1 SF Food Trucks
Приложение, которое мы переведем в Докер, называется SF Food Trucks (к сожалению, сейчас приложение уже не работает публично — прим. пер.). Моя цель была сделать что-то полезное (и похожее на настоящее приложение из реального мира), что-то, что использует как минимум один сервис, но не слишком сложное для этого пособия. Вот что я придумал.
Бэкэнд приложения написано на Питоне (Flask), а для поиска используется Elasticsearch. Как и все остальное в этом пособии, код находится на Github. Мы используем это приложение, чтобы научиться запускать и деплоить много-контейнерное окружение.
Теперь, когда вы завелись (надеюсь), давайте подумаем, как будет выглядеть этот процесс. В нашем приложении есть бэкэнд на Flask и сервис Elasticsearch. Очевидно, что можно поделить приложение на два контейнера: один для Flask, другой для Elasticsearch (ES). Если приложение станет популярным, то можно будет добавлять новые контейнеры в нужном месте, смотря где будет узкое место.
Отлично, значит нужно два контейнера. Это не сложно, правда? Мы уже создавали Flask-контейнер в прошлом разделе. А для Elasticsearch… давайте посмотрим, есть ли что-нибудь в хабе:
$ docker search elasticsearch
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
elasticsearch Elasticsearch is a powerful open source se... 697 [OK]
itzg/elasticsearch Provides an easily configurable Elasticsea... 17 [OK]
tutum/elasticsearch Elasticsearch image - listens in port 9200. 15 [OK]
barnybug/elasticsearch Latest Elasticsearch 1.7.2 and previous re... 15 [OK]
digitalwonderland/elasticsearch Latest Elasticsearch with Marvel & Kibana 12 [OK]
monsantoco/elasticsearch ElasticSearch Docker image 9 [OK]
Не удивительно, но существуют официальный образ для Elasticsearch. Чтобы запустить ES, нужно всего лишь выполнить docker run
, и вскоре у нас будет локальный, работающий контейнер с одним узлом ES.
$ docker run -dp 9200:9200 elasticsearch
d582e031a005f41eea704cdc6b21e62e7a8a42021297ce7ce123b945ae3d3763
$ curl 0.0.0.0:9200
{
"name" : "Ultra-Marine",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.1.1",
"build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
"build_timestamp" : "2015-12-15T13:05:55Z",
"build_snapshot" : false,
"lucene_version" : "5.3.1"
},
"tagline" : "You Know, for Search"
}
Заодно давайте запустим контейнер с Flask. Но вначале нужен Dockerfile
. В прошлой секции мы использовали образ python:3-onbuild
в качестве базового. Однако, в этом раз, кроме установки зависимостей через pip
, нам нужно, чтобы приложение генерировало минимизированный Javascript-файл для продакшена. Для этого понадобится Nodejs. Так что нужен свой билд с нуля, поэтому начнем с базового образа ubuntu
.
Замечание: если оказывается, что существующий образ не подходит для вашей задачи, то спокойно создавайте свой образ на основе другого базового образа. В большинстве случаем, для образов на Docker Hub можно найти соответствующий
Dockerfile
на Github. Почитайте существующий Докерфайлы — это один из лучших способов научиться делать свои образы.
Наш Dockerfile для Flask-приложения выглядит следующим образом:
# start from base
FROM ubuntu:14.04
MAINTAINER Prakhar Srivastav <[email protected]>
# install system-wide deps for python and node
RUN apt-get -yqq update
RUN apt-get -yqq install python-pip python-dev
RUN apt-get -yqq install nodejs npm
RUN ln -s /usr/bin/nodejs /usr/bin/node
# copy our application code
ADD flask-app /opt/flask-app
WORKDIR /opt/flask-app
# fetch app specific deps
RUN npm install
RUN npm run build
RUN pip install -r requirements.txt
# expose port
EXPOSE 5000
# start app
CMD [ "python", "./app.py" ]
Тут много всего нового. Вначале указан базовый образ Ubuntu LTS, потом используется пакетный менеджер apt-get
для установки зависимостей, в частности — Python и Node. Флаг yqq
нужен для игнорирования вывода и автоматического выбора «Yes» во всех местах. Также создается символическая ссылка для бинарного файла node. Это нужно для решения проблем обратной совместимости.
Потом мы используем команду ADD
для копирования приложения в нужную директорию в контейнере — /opt/flask-app
. Здесь будет находиться весь наш код. Мы также устанавливаем эту директорию в качестве рабочей, так что следующие команды будут выполняться в контексте этой локации. Теперь, когда наши системные зависимости установлены, пора установить зависимости уровня приложения. Начнем с Node, установки пакетов из npm и запуска команды сборки, как указано в нашем файле package.json. В конце устанавливаем пакеты Python, открываем порт и определяем запуск приложения с помощь CMD
, как в предыдущем разделе.
Наконец, можно собрать образ и запустить контейнер (замените prakhar1989
на свой username ниже).
$ docker build -t prakhar1989/foodtrucks-web .
При первом запуске нужно будет больше времени, так как клиент Докера будет скачивать образ ubuntu, запускать все команды и готовить образ. Повторный запуск docker build
после последующих изменений будет практически моментальным. Давайте попробуем запустить приложение
$ docker run -P prakhar1989/foodtrucks-web
Unable to connect to ES. Retying in 5 secs...
Unable to connect to ES. Retying in 5 secs...
Unable to connect to ES. Retying in 5 secs...
Out of retries. Bailing out...
Упс! Наше приложение не смогло запуститься, потому что оно не может подключиться к Elasticsearch. Как сообщить одному контейнеру о другом и как заставить их взаимодействовать друг с другом? Ответ — в следующей секции.
3.2 Сети Docker
Перед тем, как обсудить возможности Докера для решения описанной задачи, давайте посмотрим на возможные варианты обхода проблемы. Думаю, это поможет нам оценить удобство той функциональности, которую мы вскоре изучим.
Ладно, давайте запустим docker ps
, что тут у нас:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e931ab24dedc elasticsearch "/docker-entrypoint.s" 2 seconds ago Up 2 seconds 0.0.0.0:9200->9200/tcp, 9300/tcp cocky_spence
Итак, у нас есть контейнер ES по адресу и порту 0.0.0.0:9200
, и мы можем напрямую обращаться к нему. Если можно было бы сообщить нашему приложению подключаться к этому адресу, то оно сможет общаться с ES, верно? Давайте взглянем на код на Питоне, туда, где описано подключение.
es = Elasticsearch(host='es')
Нужно сообщить Flask-контейнеру, что контейнер ES запущен на хосте 0.0.0.0
(порт по умолчанию 9200
), и все заработает, да? К сожалению, нет, потому что IP 0.0.0.0
это адрес для доступа к контейнеру с хост-машины, то есть с моего Мака. Другой контейнер не сможет обратиться по этому адресу. Ладно, если не этот адрес, то какой другой адрес нужно использовать для работы с контейнером ES? Рад, что вы спросили.
Это хороший момент, чтобы изучить работу сети в Докере. После установки, Докер автоматически создает три сети:
$ docker network ls
NETWORK ID NAME DRIVER
075b9f628ccc none null
be0f7178486c host host
8022115322ec bridge bridge
Сеть bridge — это сеть, в которой контейнеры запущены по умолчанию. Это значит, что когда я запускаю контейнер ES, он работает в этой сети bridge. Чтобы удостовериться, давайте проверим:
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "8022115322ec80613421b0282e7ee158ec41e16f565a3e86fa53496105deb2d7",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.17.0.0/16"
}
]
},
"Containers": {
"e931ab24dedc1640cddf6286d08f115a83897c88223058305460d7bd793c1947": {
"EndpointID": "66965e83bf7171daeb8652b39590b1f8c23d066ded16522daeb0128c9c25c189",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
}
}
]
Видно, что контейнер e931ab24dedc
находится в секции Containers
. Также виден IP-адрес, выданный этому контейнеру — 172.17.0.2
. Именно этот адрес мы и искали? Давайте проверим: запустим Flask-приложение и попробуем обратиться к нему по IP:
$ docker run -it --rm prakhar1989/foodtrucks-web bash
root@35180ccc206a:/opt/flask-app# curl 172.17.0.2:9200
bash: curl: command not found
root@35180ccc206a:/opt/flask-app# apt-get -yqq install curl
root@35180ccc206a:/opt/flask-app# curl 172.17.0.2:9200
{
"name" : "Jane Foster",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.1.1",
"build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
"build_timestamp" : "2015-12-15T13:05:55Z",
"build_snapshot" : false,
"lucene_version" : "5.3.1"
},
"tagline" : "You Know, for Search"
}
root@35180ccc206a:/opt/flask-app# exit
Сейчас все должно быть понятно. Мы запустили контейнер в интерактивном режиме с процессом bash
. Флаг --rm
нужен для удобства, благодаря нему контейнер автоматически удаляется после выхода. Мы попробуем curl
, но нужно сначала установить его. После этого можно удостовериться, что по адресу 172.17.0.2:9200
на самом деле можно обращаться к ES! Супер!
Не смотря на то, что мы нашли способ наладить связь между контейнерами, существует несколько проблем с этим подходом:
- Придется добавлять записи в файл
/etc/hosts
внутри Flask-контейнера, чтобы приложение понимало, что имя хостаes
означает172.17.0.2
. Если IP-адрес меняется, то придется вручную менять запись. - Так как сеть bridge используется всеми контейнерами по умолчанию, этот метод не безопасен.
Но есть хорошие новости: в Докере есть отличное решение этой проблемы. Докер позволяет создавать собственные изолированные сети. Это решение также помогает справиться с проблемой /etc/hosts
, сейчас увидим как.
Во-первых, давайте создадим свою сеть:
$ docker network create foodtrucks
1a3386375797001999732cb4c4e97b88172d983b08cd0addfcb161eed0c18d89
$ docker network ls
NETWORK ID NAME DRIVER
1a3386375797 foodtrucks bridge
8022115322ec bridge bridge
075b9f628ccc none null
be0f7178486c host host
Команда network create
создает новую сеть bridge. Нам сейчас нужен именно такой тип. Существуют другие типы сетей, и вы можете почитать о них в официальной документации.
Теперь у нас есть сеть. Можно запустить наши контейнеры внутри сети с помощью флага --net
. Давайте так и сделаем, но сначала остановим контейнер с ElasticSearch, который был запущен в сети bridge по умолчанию.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e931ab24dedc elasticsearch "/docker-entrypoint.s" 4 hours ago Up 4 hours 0.0.0.0:9200->9200/tcp, 9300/tcp cocky_spence
$ docker stop e931ab24dedc
e931ab24dedc
$ docker run -dp 9200:9200 --net foodtrucks --name es elasticsearch
2c0b96f9b8030f038e40abea44c2d17b0a8edda1354a08166c33e6d351d0c651
$ docker network inspect foodtrucks
[
{
"Name": "foodtrucks",
"Id": "1a3386375797001999732cb4c4e97b88172d983b08cd0addfcb161eed0c18d89",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{}
]
},
"Containers": {
"2c0b96f9b8030f038e40abea44c2d17b0a8edda1354a08166c33e6d351d0c651": {
"EndpointID": "15eabc7989ef78952fb577d0013243dae5199e8f5c55f1661606077d5b78e72a",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {}
}
]
Мы сделали то же, что и раньше, но на этот раз дали контейнеру название es
. Перед тем, как запускать контейнер с приложением, давайте проверим что происходит, когда запуск происходит в сети.
$ docker run -it --rm --net foodtrucks prakhar1989/foodtrucks-web bash
root@53af252b771a:/opt/flask-app# cat /etc/hosts
172.18.0.3 53af252b771a
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.2 es
172.18.0.2 es.foodtrucks
root@53af252b771a:/opt/flask-app# curl es:9200
bash: curl: command not found
root@53af252b771a:/opt/flask-app# apt-get -yqq install curl
root@53af252b771a:/opt/flask-app# curl es:9200
{
"name" : "Doctor Leery",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.1.1",
"build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
"build_timestamp" : "2015-12-15T13:05:55Z",
"build_snapshot" : false,
"lucene_version" : "5.3.1"
},
"tagline" : "You Know, for Search"
}
root@53af252b771a:/opt/flask-app# ls
app.py node_modules package.json requirements.txt static templates webpack.config.js
root@53af252b771a:/opt/flask-app# python app.py
Index not found...
Loading data in elasticsearch ...
Total trucks loaded: 733
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
root@53af252b771a:/opt/flask-app# exit
Ура! Работает! Магическим образом Докер внес нужные правки в файл /etc/hosts
, и поэтому es:9200
можно использовать в приложении — этот адрес корректно направляет запросы в контейнер ES. Отлично! Давайте теперь запустим Flask-контейнер по-настоящему:
$ docker run -d --net foodtrucks -p 5000:5000 --name foodtrucks-web prakhar1989/foodtrucks-web
2a1b77e066e646686f669bab4759ec1611db359362a031667cacbe45c3ddb413
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a1b77e066e6 prakhar1989/foodtrucks-web "python ./app.py" 2 seconds ago Up 1 seconds 0.0.0.0:5000->5000/tcp foodtrucks-web
2c0b96f9b803 elasticsearch "/docker-entrypoint.s" 21 minutes ago Up 21 minutes 0.0.0.0:9200->9200/tcp, 9300/tcp es
$ curl -I 0.0.0.0:5000
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 3697
Server: Werkzeug/0.11.2 Python/2.7.6
Date: Sun, 10 Jan 2016 23:58:53 GMT
Зайдите на http://0.0.0.0:5000, и увидите приложение в работе. Опять же, может показаться, что было много работы, но на самом деле мы ввели всего 4 команды чтобы с нуля дойти до работающего приложения. Я собрал эти команды в bash-скрипт.
#!/bin/bash
# build the flask container
docker build -t prakhar1989/foodtrucks-web .
# create the network
docker network create foodtrucks
# start the ES container
docker run -d --net foodtrucks -p 9200:9200 -p 9300:9300 --name es elasticsearch
# start the flask app container
docker run -d --net foodtrucks -p 5000:5000 --name foodtrucks-web prakhar1989/foodtrucks-web
Теперь представьте, что хотите поделиться приложением с другом. Или хотите запустить на сервере, где установлен Докер. Можно запустить всю систему с помощью одной команды!
$ git clone https://github.com/prakhar1989/FoodTrucks
$ cd FoodTrucks
$ ./setup-docker.sh
Вот и все! По-моему, это невероятно крутой и мощный способ распространять и запускать приложения!
Docker Links
Перед тем, как завершить этот раздел, стоит отметить, что docker network
это относительно новая фича, она входит в релиз Docker 1.9 .
До того, как появился network
, ссылки были допустимым способом настройки взаимодействия между контейнерами. В соответствии с официальной документацией, linking вскоре будет переведены в статус deprecated. Если вам попадется туториал или статья, где используется link
для соединения контейнеров, то просто не забывайте использовать вместо этого network
(на момент публикации перевода links является legacy, — прим. пер.)
3.3 Docker Compose
До этого момента мы изучали клиент Докера. Но в экосистеме Докера есть несколько других инструментов с открытым исходным кодом, которые хорошо взаимодействуют с Докером. Некоторые из них это:
- Docker Machine позволяет создавать Докер-хосты на своем компьютере, облачном провайдере или внутри дата-центра.
- Docker Compose — инструмент для определения и запуска много-контейнерных приложений.
- Docker Swarm — нативное решение для кластеризации.
В этом разделе мы поговорим об одном из этих инструментов — Docker Compose, и узнаем, как он может упростить работу с несколькими контейнерами.
У Docker Compose довольно интересная предыстория. Примерно два года назад компания OrchardUp запустила инструмент под названием Fig. Идея была в том, чтобы создавать изолированные рабочие окружения с помощью Докера. Проект очень хорошо восприняли на Hacker News — я смутно помню, что читал о нем, но не особо понял его смысла.
Первый комментарий на самом деле неплохо объясняет, зачем нужен Fig и что он делает:
На самом деле, смысл Докера в следующем: запускать процессы. Сегодня у Докера есть неплохое API для запуска процессов: расшаренные между контейнерами (иными словами, запущенными образами) разделы или директории (shared volumes), перенаправление портов с хост-машины в контейнер, вывод логов, и так далее. Но больше ничего: Докер сейчас работает только на уровне процессов.
Не смотря на то, что в нем содержатся некоторые возможности оркестрации нескольких контейнеров для создания единого «приложения», в Докере нет ничего, что помогало бы с управлением такими группами контейнеров как одной сущностью. И вот зачем нужен инструмент вроде Fig: чтобы обращаться с группой контейнеров как с единой сущностью. Чтобы думать о «запуске приложений» (иными словами, «запуске оркестрированного кластера контейнеров») вместо «запуска контейнеров».
Оказалось, что многие пользователи Докера согласны с такими мыслями. Постепенно, Fig набрал популярность, Docker Inc. заметили, купили компанию и назвали проект Docker Compose.
Итак, зачем используется Compose? Это инструмент для простого определения и запуска многоконтейнерных Докер-приложений. В нем есть файл docker-compose.yml
, и с его помощью можно одной командой поднять приложение с набором сервисов.
Давайте посмотрим, сможем ли мы создать файл docker-compose.yml
для нашего приложения SF-Foodtrucks и проверим, способен ли он на то, что обещает.
Но вначале нужно установить Docker Compose. Есть у вас Windows или Mac, то Docker Compose уже установлен — он идет в комплекте с Docker Toolbox. На Linux можно установить Docker Compose следуя простым инструкциям на сайте документации. Compose написан на Python, поэтому можно сделать просто pip install docker-compose
. Проверить работоспособность так:
$ docker-compose version
docker-compose version 1.7.1, build 0a9ab35
docker-py version: 1.8.1
CPython version: 2.7.9
OpenSSL version: OpenSSL 1.0.1j 15 Oct 2014
Теперь можно перейти к следующему шагу, то есть созданию файла docker-compose.yml
. Синтаксис yml
-файлов очень простой, и в репозитории уже есть пример, который мы будем использовать
version: "2"
services:
es:
image: elasticsearch
web:
image: prakhar1989/foodtrucks-web
command: python app.py
ports:
- "5000:5000"
volumes:
- .:/code
Давайте я разберу это подробнее. На родительском уровне мы задали название неймспейса для наших сервисов: es
и web
. К каждому сервису можно добавить дополнительные параметры, среди которых image
— обязательный. Для es
мы указываем доступный на Docker Hub образ elasticsearch
. Для Flask-приложения — тот образ, который мы создали самостоятельно в начале этого раздела.
С помощью других параметров вроде command
и ports
можно предоставить информацию о контейнере. volumes
отвечает за локацию монтирования, где будет находиться код в контейнере web
. Это опциональный параметр, он полезен, если нужно обращаться к логам и так далее. Подробнее о параметрах и возможных значениях можно прочитать в документации.
Замечание: Нужно находиться в директории с файлом
docker-compose.yml
чтобы запускать большую часть команд Compose.
Отлично! Файл готов, давайте посмотрим на docker-compose
в действии. Но вначале нужно удостовериться, что порты свободны. Так что если у вас запущены контейнеры Flask и ES, то пора их остановить:
$ docker stop $(docker ps -q)
39a2f5df14ef
2a1b77e066e6
Теперь можно запускать docker-compose
. Перейдите в директорию с приложением Foodtrucks и выполните команду docker-compose up
.
$ docker-compose up
Creating network "foodtrucks_default" with the default driver
Creating foodtrucks_es_1
Creating foodtrucks_web_1
Attaching to foodtrucks_es_1, foodtrucks_web_1
es_1 | [2016-01-11 03:43:50,300][INFO ][node ] [Comet] version[2.1.1], pid[1], build[40e2c53/2015-12-15T13:05:55Z]
es_1 | [2016-01-11 03:43:50,307][INFO ][node ] [Comet] initializing ...
es_1 | [2016-01-11 03:43:50,366][INFO ][plugins ] [Comet] loaded [], sites []
es_1 | [2016-01-11 03:43:50,421][INFO ][env ] [Comet] using [1] data paths, mounts [[/usr/share/elasticsearch/data (/dev/sda1)]], net usable_space [16gb], net total_space [18.1gb], spins? [possibly], types [ext4]
es_1 | [2016-01-11 03:43:52,626][INFO ][node ] [Comet] initialized
es_1 | [2016-01-11 03:43:52,632][INFO ][node ] [Comet] starting ...
es_1 | [2016-01-11 03:43:52,703][WARN ][common.network ] [Comet] publish address: {0.0.0.0} is a wildcard address, falling back to first non-loopback: {172.17.0.2}
es_1 | [2016-01-11 03:43:52,704][INFO ][transport ] [Comet] publish_address {172.17.0.2:9300}, bound_addresses {[::]:9300}
es_1 | [2016-01-11 03:43:52,721][INFO ][discovery ] [Comet] elasticsearch/cEk4s7pdQ-evRc9MqS2wqw
es_1 | [2016-01-11 03:43:55,785][INFO ][cluster.service ] [Comet] new_master {Comet}{cEk4s7pdQ-evRc9MqS2wqw}{172.17.0.2}{172.17.0.2:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
es_1 | [2016-01-11 03:43:55,818][WARN ][common.network ] [Comet] publish address: {0.0.0.0} is a wildcard address, falling back to first non-loopback: {172.17.0.2}
es_1 | [2016-01-11 03:43:55,819][INFO ][http ] [Comet] publish_address {172.17.0.2:9200}, bound_addresses {[::]:9200}
es_1 | [2016-01-11 03:43:55,819][INFO ][node ] [Comet] started
es_1 | [2016-01-11 03:43:55,826][INFO ][gateway ] [Comet] recovered [0] indices into cluster_state
es_1 | [2016-01-11 03:44:01,825][INFO ][cluster.metadata ] [Comet] [sfdata] creating index, cause [auto(index api)], templates [], shards [5]/[1], mappings [truck]
es_1 | [2016-01-11 03:44:02,373][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,510][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,593][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,708][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:03,047][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Перейдите по IP чтобы увидеть приложение. Круто, да? Всего лишь пара строк конфигурации и несколько Докер-контейнеров работают в унисон. Давайте остановим сервисы и перезапустим в detached mode:
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Killing foodtrucks_web_1 ... done
Killing foodtrucks_es_1 ... done
$ docker-compose up -d
Starting foodtrucks_es_1
Starting foodtrucks_web_1
$ docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------
foodtrucks_es_1 /docker-entrypoint.sh elas ... Up 9200/tcp, 9300/tcp
foodtrucks_web_1 python app.py Up 0.0.0.0:5000->5000/tcp
Не удивительно, но оба контейнера успешно запущены. Откуда берутся имена? Их Compose придумал сам. Но что насчет сети? Его Compose тоже делаем сам? Хороший вопрос, давайте выясним.
Для начала, остановим запущенные сервисы. Их всегда можно вернуть одной командой:
$ docker-compose stop
Stopping foodtrucks_web_1 ... done
Stopping foodtrucks_es_1 ... done
Заодно, давайте удалим сеть foodtrucks
, которую создали в прошлый раз. Эта сеть нам не потребуется, потому что Compose автоматически сделает все за нас.
$ docker network rm foodtrucks
$ docker network ls
NETWORK ID NAME DRIVER
4eec273c054e bridge bridge
9347ae8783bd none null
54df57d7f493 host host
Класс! Теперь в этом чистом состоянии можно проверить, способен ли Compose на волшебство.
$ docker-compose up -d
Recreating foodtrucks_es_1
Recreating foodtrucks_web_1
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f50bb33a3242 prakhar1989/foodtrucks-web "python app.py" 14 seconds ago Up 13 seconds 0.0.0.0:5000->5000/tcp foodtrucks_web_1
e299ceeb4caa elasticsearch "/docker-entrypoint.s" 14 seconds ago Up 14 seconds 9200/tcp, 9300/tcp foodtrucks_es_1
Пока все хорошо. Проверим, создались ли какие-нибудь сети:
$ docker network ls
NETWORK ID NAME DRIVER
0c8b474a9241 bridge bridge
293a141faac3 foodtrucks_default bridge
b44db703cd69 host host
0474c9517805 none null
Видно, что Compose самостоятельно создал сеть foodtrucks_default
и подсоединил оба сервиса в эту сеть, так, чтобы они могли общаться друг с другом. Каждый контейнер для сервиса подключен к сети, и оба контейнера доступны другим контейнерам в сети. Они доступны по hostname, который совпадает с названием контейнера. Давайте проверим, находится ли эта информация в /etc/hosts
.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bb72dcebd379 prakhar1989/foodtrucks-web "python app.py" 20 hours ago Up 19 hours 0.0.0.0:5000->5000/tcp foodtrucks_web_1
3338fc79be4b elasticsearch "/docker-entrypoint.s" 20 hours ago Up 19 hours 9200/tcp, 9300/tcp foodtrucks_es_1
$ docker exec -it bb72dcebd379 bash
root@bb72dcebd379:/opt/flask-app# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.2 bb72dcebd379
Упс! Оказывается, файл понятия не имеет о es
. Как же наше приложение работает? Давайте попингуем его по названию хоста:
root@bb72dcebd379:/opt/flask-app# ping es
PING es (172.18.0.3) 56(84) bytes of data.
64 bytes from foodtrucks_es_1.C
--- es ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.049/0.056/0.064/0.010 ms
Вуаля! Работает! Каким-то магическим образом контейнер смог сделать пинг хоста es
. Оказывается, Docker 1.10 добавили новую сетевую систему, которая производит обнаружение сервисов через DNS-сервер. Если интересно, то почитайте подробнее о предложении и release notes.
На этом наш тур по Docker Compose завершен. С этим инструментом можно ставить сервисы на паузу, запускать отдельные команды в контейнере и даже масштабировать систему, то есть увеличивать количество контейнеров. Также советую изучать некоторые другие примеры использования Docker Compose.
Надеюсь, я продемонстрировал как на самом деле просто управлять многоконтейнерной средой с Compose. В последнем разделе мы задеплоим все на AWS!
3.4 AWS Elastic Container Service
В прошлом разделе мы использовали docker-compose
чтобы запустить наше приложение локально одной командой: docker-compose up
. Теперь, когда приложение работает, мы хотим показать его миру, заполучить юзеров, поднять кучу денег и купить большой дом в Майами. Последние три шага выходят за пределы этого пособия, так что займемся выяснением деталей о деплое многоконтейнерного приложения в облако AWS.
Если вы дочитали до этого места, то скорее всего убедились, что Docker — довольно крутая технология. И вы не одиноки. Облачные провайдеры заметили взрывной рост популярности Докера и стали добавлять поддержку в свои сервисы. Сегодня, Докер-приложения можно деплоить на AWS, Azure,Rackspace, DigitalOcean и много других. Мы уже умеем деплоить приложение с одним контейнером на Elastic Beanstalk, а в этом разделе мы изучим AWS Elastic Container Service (или ECS).
AWS ECS — это масштабируемый и гибкий сервис по управлению контейнерами, и он поддерживает Докер. С его помощью можно управлять кластером на EC2 через простой API. В Beanstalk были нормальные настройки по умолчанию, но ECS позволяет настроить каждый аспект окружения по вашим потребностям. По этой причине ECS — не самый простой инструмент в начале пути.
К счастью, у ECS есть удобный инструмент командной строки (CLI) с поддержкой Docker Compose и автоматической провизией на ECS! Так как у нас уже есть рабочий файл docker-compose.yml
, настройка и запуск на AWS должна быть достаточно легкой. Начнем!
Вначале нужно установить CLI. На момент написания этого пособия CLI-утилита не доступна на Windows. Инструкции по установке CLI на Mac и Linux хорошо описаны на сайте с официальной документацией. Установите утилиту, а потом проверьте ее работоспособность так:
$ ecs-cli --version
ecs-cli version 0.1.0 (*cbdc2d5)
Первый шаг — задать пару ключей для авторизации на инстансах. Зайдите на страницу EC2 Console и создайте новый keypair. Скачайте файл и держите его в безопасном месте. Еще один момент — имя региона. Я назвал свой ключ ecs
и указал регион us-east-1
. Я продолжу повествование с этим допущением.
Теперь настройте CLI:
$ ecs-cli configure --region us-east-1 --cluster foodtrucks
INFO[0000] Saved ECS CLI configuration for cluster (foodtrucks)
Команда configure
с именем региона, в котором хотим разместить наш кластер, и название кластера. Нужно указать тот же регион, что использовался прри создании ключей. Если у вас не настроен AWS CLI, то следуйте руководству, которое подробно описывает все шаги.
Следующий шаг позволяет утилите создавать шаблон CloudFormation.
$ ecs-cli up --keypair ecs --capability-iam --size 2 --instance-type t2.micro
INFO[0000] Created cluster cluster=foodtrucks
INFO[0001] Waiting for your cluster resources to be created
INFO[0001] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0061] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0122] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0182] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0242] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
Здесь мы указываем названия ключей, которые мы скачали (в моем случае ecs
), количество инстансов (--size
) и тип инстансов, на которых хотим запускать контейнеры. Флаг --capability-iam
говорит утилите, что мы понимаем, что эта команда может создать ресурсы IAM.
В последнем шаге мы используем файл docker-compose.yml
. Требуется небольшое изменение, так что вместо модификации файла, давайте сделаем копию и назовем ее aws-compose.yml
. Содержание этого файла (после изменений):
es:
image: elasticsearch
cpu_shares: 100
mem_limit: 262144000
web:
image: prakhar1989/foodtrucks-web
cpu_shares: 100
mem_limit: 262144000
ports:
- "80:5000"
links:
- es
Единственные отличия от оригинального файла docker-compose.yml
это параметры mem_limit
и cpu_shares
для каждого контейнера.
Также, мы убрали version
и services
, так как AWS еще не поддерживает версию 2 файлового формата Compose. Так как наше приложение будет работать на инстансах типа t2.micro
, мы задали 250 мегабайт памяти. Теперь нам нужно опубликовать образ на Docker Hub. На момент написания этого пособия, ecs-cli не поддерживает команду build
. Но Docker Compose поддерживает ее без проблем.
$ docker push prakhar1989/foodtrucks-web
Красота! Давайте запустим финальную команду, которая произведет деплой на ECS!
$ ecs-cli compose --file aws-compose.yml up
INFO[0000] Using ECS task definition TaskDefinition=ecscompose-foodtrucks:2
INFO[0000] Starting container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es
INFO[0000] Starting container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web
INFO[0000] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0000] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0036] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0048] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0048] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0060] Started container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-foodtrucks:2
INFO[0060] Started container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-foodtrucks:2
То, что вывод похож на вывод Docker Compose — не совпадение. Аргумент --file
используется для переопределения файла по умолчанию (docker-compose.yml
). Если все прошло хорошо, то вы увидите строку desiredStatus=RUNNING lastStatus=RUNNING
в самом конце.
Круто! Теперь приложение запущено. Как к нему обратиться?
ecs-cli ps
Name State Ports TaskDefinition
845e2368-170d-44a7-bf9f-84c7fcd9ae29/web RUNNING 54.86.14.14:80->5000/tcp ecscompose-foodtrucks:2
845e2368-170d-44a7-bf9f-84c7fcd9ae29/es RUNNING ecscompose-foodtrucks:2
Откройте http://54.86.14.14 в браузере, и увидите Food Trucks во всей своей желто-черной красе! Заодно, давайте взглянем на консоль AWS ECS.
Видно, что был создан ECS-кластер ‘foodtrucks’, и в нем выполняется одна задача с двумя инстансами. Советую поковыряться в этой консоли и изучить разные ее части и опции.
Вот и все. Всего несколько команд — и приложение работает на AWS!
4.0 Заключение
Мы подошли к концу. После длинного, изматывающего, но интересного пособия вы готовы захватить мир контейнеров! Если вы следовали пособию до самого конца, то можете заслуженно гордиться собой. Вы научились устанавливать Докер, запускать свои контейнеры, запускать статические и динамические веб-сайты и, самое главное, получили опыт деплоя приложений в облако.
Надеюсь, прохождение этого руководства помогло вам стать увереннее в своих способностях управляться с серверами. Когда у вас появится новая идея для сайта или приложения, можете быть уверены, что сможете показать его людям с минимальными усилиями.
4.1 Следующие шаги
Ваше путешествие в мир контейнеров только началось. Моей целью в этом руководстве было нагулять ваш аппетит и показать мощь Докера. В мире современных технологий иногда бывает сложно разобраться самостоятельно, и руководства вроде этого призваны помогать вам. Это такое пособие, которое мне хотелось бы иметь, когда я только знакомился с Докером сам. Надеюсь, ему удалось заинтересовать вас, так что теперь вы сможете следить за прогрессом в этом области не со стороны, а с позиции знающего человека.
Ниже — список дополнительных полезных ресурсов. Советую использовать Докер в вашем следующем проекте. И не забывайте — практика приводит к совершенству.
Дополнительные ресурсы
Удачи, юный падаван!
4.2 Фидбек автору
Теперь моя очередь задавать вопросы. Вам понравилось пособие? Оно показалось вам запутанным, или вам удалось научиться чему-то?
Напишите мне (автору оригинального пособия, — прим. пер.) напрямую на [email protected] или просто создайте issue. Я есть в Твиттере, так что если хотите, то можете писать туда.
(Автор оригинального пособия говорит по-английски, — прим. пер.).
Буду рад услышать ваши отзывы. Не стесняйтесь предлагать улучшения или указывать на мои ошибки. Я хочу, чтобы это пособие стало одним из лучших стартовых руководств в интернете. У меня не получится это без вашей помощи.
Настройка и установка Docker на Centos 7
В инструкции описан процесс установки и использования Docker на виртуальных серверах под управлением операционной системы Centos 7.
Что это такое?
Docker — это платформа для разработчиков и системных администраторов, предназначенная для разработки, развертывания и запуска приложений в контейнерах изолированных друг от друга. Использование контейнеров для развертывания приложений в Linux называется контейнеризацией. Идея контейнеризации и изоляции приложений зародилась практически сразу после появления первых компьютеров, но только в последние годы их использование широко распространилось и упростилось, благодаря высоким темпам разработки программного обеспечения во всем мире.
Для работы с Docker необходимо понимать отличия между терминами образ и контейнер:
- образ представляет собой исполняемый пакет, включающий все необходимое для запуска приложения — программный код, среду выполнения, библиотеки, переменные среды и файлы конфигурации;
- контейнер запускается из образа и является его экземпляром, т.е. из одного образа может быть запущено несколько контейнеров.
О контейнерах подробно написано в нашем блоге: В чём суть контейнеров приложений?
Образ является шаблоном доступным только для чтения. Образ Docker может быть дистрибутивом Linux или полностью сконфигурированным корпоративным программным обеспечением, готовым к запуску. Все зависит от специального файла — Dockerfile.
Dockerfile — это текстовый файл с инструкциями, написанными в формате, понятном демону Docker. Чтобы создать собственный образ, необходимо создать свой Dockerfile. После того, как Dockerfile подготовлен, можно выполнить сборку для создания соответствующего образа.
Примечание: демон является одним из компонентов Docker, который выполняет тяжелые задачи по созданию, запуску и распределению изображений после получения команд из Докер-клиента.
В общем случае запуск приложения в Docker выглядит так:
- Выбирается приложение, которое требуется запустить в контейнере.
- В конфигурационном файле Dockerfile описывается это приложение и среда выполнения согласно синтаксису.
- Формируется образ приложения, представляющий собой единый файл. Он включает в себя и исполняемые файлы приложения, и все его библиотеки (за исключением общесистемных), т.е. в дальнейшем приложение остается неизменным в контейнере.
- Запускается Docker с указанным образом прикладного приложения, которое используется для прикладных задачи.
Установка
Прежде всего следует обновить локальную базу пакетов:
sudo yum check-update
Для установки самой последней и стабильной версии Docker необходимо обратиться к официальному репозиторию Docker. Следующая команда добавит репозиторий, загрузит последнюю версию ПО и установит его:
curl -fsSL https://get.docker.com/ | sh
Примечание: если вы собираетесь использовать Docker не от имени пользователя root, то необходимо добавить пользователя в созданную после установки группу docker:
sudo usermod -aG docker <имя пользователя>
Например:
sudo usermod -aG docker cloud
Запустите демон Docker после окончания установки:
sudo systemctl start docker
Убедитесь в том, что демон стартовал без ошибок и предупреждений:
sudo systemctl status docker
В результате должно появиться подобное сообщение:
docker.service - Docker Application Container Engine Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled) Active: active (running) since Thu 2018-04-26 14:06:06 MSK; 1min 56s ago Docs: https://docs.docker.com Main PID: 1601 (dockerd) Tasks: 16 Memory: 40.0M CGroup: /system.slice/docker.service ├─1601 /usr/bin/dockerd └─1605 docker-containerd --config /var/run/docker/containerd/conta... ...
Работа с образами в Docker
Команда docker имеет следующий синтаксис, где после названия команды могут быть перечислены различные опции, команды и аргументы:
docker <option> <command> <arguments>
Чтобы вывести на экран все доступные команды и краткую информацию о них, просто используйте команду docker:
docker
По умолчанию образы извлекаются из реестра Docker Hub, дочернего проекта Docker. Любой пользователь может создавать и размещать свои образы на Docker Hub, поэтому большинство приложений, СУБД и дистрибутивов Linux имеют свои образы на Docker Hub.
Чтобы проверить, можете ли вы получать и загружать образы из Docker Hub, выполните следующую команду:
docker run hello-world
В результате должно отобразиться подобное сообщение:
Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 9bb5a5d4561a: Pull complete Digest: sha256:f5233545e43561214ca4891fd1157e1c3c563316ed8e237750d59bde73361e77 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly.
Чтобы выполнить поиск нужного образа, используйте следующий формат команды:
docker search <имя>
Например, для поиска образа nginx используйте следующую команду:
docker search nginx
В результате появится список доступных образов:
NAME DESCRIPTION STARS OFFICIAL AUTOMATED nginx Official build of Nginx. 8341 [OK] jwilder/nginx-proxy Automated Nginx reverse proxy for docker con… 1328 [OK] richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of… 547 [OK] jrcs/letsencrypt-nginx-proxy-companion LetsEncrypt container to use with nginx as p… 364 [OK] kong Open-source Microservice & API Management la… 184 [OK] webdevops/php-nginx Nginx with PHP-FPM 102 [OK]
Загрузить нужный образ можно с помощью команды следующего формата:
docker pull <имя>
Например:
docker pull nginx
Вы увидите процесс загрузки:
Using default tag: latest latest: Pulling from library/nginx f2aa67a397c4: Downloading [===============> ] 7.13MB/22.5MB 3c091c23e29d: Downloading [================> ] 7.091MB/22.11MB 4a99993b8636: Download complete
После того как образ был загружен на ваш сервер, запустить его можно с помощью опции run:
docker run <имя>
Посмотреть все загруженные образы можно с помощью опции images:
docker images
Отобразится список:
REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest ae513a47849c 8 days ago 109MB hello-world latest e38bc07ac18e 3 weeks ago 1.85kB
Работа с контейнерами в Docker
Чтобы создать контейнер с именем example на основе образа image, используйте следующую команду:
docker run --name <example> -d <image>
Примечание: комбинация ключей -i и -t дает интерактивный доступ к оболочке shell в контейнере.
Пример создания контейнера example на основе образа nginx:
docker run --name example -d nginx
Посмотреть запущенные контейнеры можно с помощью опции ps:
docker ps
Примечание: ключ -l позволяет просмотреть все существующие контейнеры.
Отобразится список:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b8f970efcc91 nginx "nginx -g 'daemon of…" 15 seconds ago Up 13 seconds 80/tcp example
Чтобы запустить созданный контейнер в фоновом режиме, используйте следующую команду:
docker container start <имя_или_id>
Например:
docker container start example
Чтобы зайти внутрь контейнера, который работает в фоновом режиме, выполните следующую команду:
sudo docker exec -i -t <имя_или_id> /bin/bash
Пример:
sudo docker exec -i -t b8f970efcc91 /bin/bash
root@b8f970efcc91:/data#
Для выхода из контейнера используйте стандартную команду exit.
Чтобы остановить созданный контейнер, используйте следующую команду:
docker container stop <имя_или_id>
Например:
docker container stop example
Чтобы удалить контейнер используйте опцию rm:
docker rm -f <имя_или_id>
Например:
docker rm -f example
Примечание: ключ -f позволяет удалять запущенные контейнеры без их предварительной остановки.
Для более подробного примера запустим приложение nginx на конкретном порту, например 80, и убедимся, что все работает. Не забудьте настроить firewall и открыть данный порт на сервере:
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables-save
Запускаем контейнер с именем example:
docker run --name example -d -p 80:80 nginx
В адресной строке браузера переходим по адресу вашего сервера с указанием порта, на изображении показан ожидаемый результат:
P. S. Другие инструкции:
Ознакомиться с другими инструкциями вы можете на нашем сайте. А чтобы попробовать услугу — кликните на кнопку ниже.
Спасибо за Вашу оценку!
К сожалению, проголосовать не получилось. Попробуйте позже
Как развернуть свое Docker хранилище в Ubuntu 20.04
В данном руководстве мы изучим, как развернуть своё собственное Docker хранилище на сервере, работающем под управлением Ubuntu 20.04.
Хранилище Docker представляет из себя приложение, которое управляет хранением и доставкой образов контейнеров Docker. Хранилища собирают образа контейнеров и снижают время сборки для разработчиков. Образы Docker обеспечивают создание одной и той же среды выполнения благодаря виртуализации, при том, что создание образа может потребовать значительных временных затрат. Другими словами, разработчики имеют возможность загрузить из хранилища сжатый образ, содержащий все необходимые компоненты, вместо того, чтобы устанавливать зависимости и пакеты отдельно для использования Docker.
У Docker есть бесплатное общедоступное хранилище, Docker Hub, которое может припарковать ваши образы Docker. Тонкость состоит в том, что не всегда есть желание хранить свои образы там, где они будут общедоступны. Образы обычно содержат весь необходимый для запуска код, поэтому использование собственного реестра предпочтительнее для хранения проприентарного программного обеспечения.
Мы будем использовать Docker Compose, чтобы определять конфигурации запуска ваших контейнеров Docker. А также, мы будем использовать веб-сервер Nginx для передачи трафика сервера из интернета в работающий контейнер Docker. Изучив содержимое данного руководства, вы сможете поместить образ Docker в своё личное хранилище, а также, безопасно извлечь его с удалённого сервера.
Подготовка серверов
В данном мануале мы будем использовать два сервера. Один из них будет выступать в качестве хоста для вашего приватного Docker хранилища, а другой – в качестве сервера-клиента. Оба VPS работают под управлением операционной системы Ubuntu 20.04. Все работы на серверах мы будем производить под учётной записью, не являющейся root-ом, но имеющей привилегии sudo. Для настройки межсетевого экрана на серверах мы будем использовать интерфейс UFW.
Так как в качестве веб-сервера мы планируем использовать Nginx, то давайте перейдём к его настройке. Действия по настройке Nginx нужно будет произвести на сервере, выступающем в качестве хоста для нашего хранилища. Сначала необходимо установить Nginx:
$ sudo apt update
$ sudo apt install nginx
Теперь добавьте Nginx в список приложений, доступ для которых разрешён в нашем брандмауэре, и проверьте статус службы Nginx:
$ sudo ufw allow 'Nginx HTTP'
$ systemctl status nginx
Если сервис запущен вы можете проверить его доступность через веб-интерфейс. Для чего в браузере наберите IP-адрес вашего сервера-хоста:
Далее, вам необходимо будет добавить виртуальный хост для вашего домена. В нашем мануале мы будем использовать домен my-domain.host
. Обратите внимание, что А-запись домена, с которым вы будете производить дальнейшие действия, должна соответствовать IP-адресу вашего сервера-хоста.
Итак, создайте каталог для вашего сайта и предоставьте ему соответствующие права:
$ sudo mkdir -p /var/www/my-domain.host/html
$ sudo chown -R $USER:$USER /var/www/my-domain.host/html
$ sudo chmod -R 755 /var/www/my-domain.host
Теперь в созданном каталоге создайте файл страницы сайта index.html
:
$ sudo nano /var/www/my-domain.host/html/index.html
Наполните его содержимым:
<html>
<head>
<title>
Domain on Nginx
</title>
</head>
<body>
<h2>
Connection to my-domain.host is created successfully!!!
</h2>
</body>
</html>
Закройте файл, сохранив изменения (Ctrl+X
, после чего Y
и Enter
).
В директории /etc/nginx/sites-available/
создайте файл my-domain.host
:
$ sudo nano /etc/nginx/sites-available/my-domain.host
Скопируйте в него следующие строки:
server
{
listen 80;
listen [::]:80;
root /var/www/my-domain.host/html;
index index.html index.htm index.nginx-debian.html;
server_name my-domain.host www.my-domain.host;
location /
{
try_files $uri $uri/ =404;
}
}
Закройте файл с сохранением изменений и создайте ссылку в /etc/nginx/sites-enabled/
:
$ sudo ln -s /etc/nginx/sites-available/my-domain.host /etc/nginx/sites-enabled/
Отредактируйте файл /etc/nginx/nginx.conf
:
$ sudo nano /etc/nginx/nginx.conf
В этом файле вам нужно будет раскомментировать строку, которая содержит server_names_hash_bucket_size
.
Для проверки корректности синтаксиса Nginx наберите:
$ sudo nginx -t
Должно быть:
Перезапустите Nginx:
$ sudo systemctl restart nginx
После этого ваш домен должен стать доступным по своему доменному имени:
И нам останется только настроить редирект всего трафика с протокола HTTP на HTTPS. Мы осуществим это при помощи центра сертификации Let’s Encrypt.
Сначала необходимо будет установить пакет snap:
$ sudo apt install snapd
Затем с его помощью проинсталлируйте Certbot:
$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
Далее, в брандмауэре необходимо разрешить трафик по протоколу HTTPS, закрыв трафик по HTTP:
$ sudo ufw allow 'Nginx Full'
$ sudo ufw delete allow 'Nginx HTTP'
$ sudo ufw status
Теперь, необходимо запустить Certbot с помощью плагина nginx
для указания доменов, которые будут использовать сертификаты:
$ sudo certbot --nginx
Здесь вам нужно будет указать свой E-mail, согласиться с предоставляемыми условиями и указать домен, для которого требуется активировать протокол HTTPS.
С этого момента подключение к вашему домену защищено:
Далее, переходим с настройке Docker.
Установка Docker
Пакет Docker будем устанавливать из официального репозитория Docker. Чтобы сделать это, мы добавим новый источник пакетов и ключ GPG от Docker, чтобы быть уверенными в валидности загрузки пакета. После чего установим пакет.
Проинсталлируйте несколько необходимых пакетов, которые позволят установщику использовать пакеты обновлений по протоколу HTTPS:
$ sudo apt install apt-transport-https ca-certificates curl software-properties-common
Теперь, добавьте в систему ключ GPG для официального репозитория Docker:
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Далее, добавьте репозиторий Docker и запустите обновление базы данных пакетов обновлений:
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
$ sudo apt update
Убедитесь, что дальнейшая установка будет произведена из репозитория Docker, а не из дефолтного репозитория Ubuntu:
$ apt-cache policy docker-ce
Обратите внимание, что docker-ce
не установлен, но готов к установке из репозитория Ubuntu 20.04.
И наконец, запустите установку Docker:
$ sudo apt install docker-ce
Теперь Docker установлен, служба запущена и процесс доступен для старта при загрузке системы. Проверьте:
$ sudo systemctl status docker
Также, нам нужно будет установить инструмент, который позволяет осуществлять запуск сред выполнения приложений с несколькими контейнерами. Это – Docker Compose. Чтобы загрузить самую свежую Docker Compose, посмотрите её номер на странице официального репозитория Github. Наберите в командой строке команду, которая загрузит исполняемый файл:
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
После этого задайте загруженному файлу соответствующие права. Это позволит сделать docker-compose
исполняемым файлом:
$ sudo chmod +x /usr/local/bin/docker-compose
Проверьте версию установленного компонента:
$ docker-compose --version
Теперь всё готово для установки и настройки Docker хранилища.
Установка и настройка Docker хранилища
В командной строке Docker очень полезен когда вы запускаете и тестируете контейнеры. Но для больших развёртываний, включающих несколько параллельно выполняющихся контейнеров, она оказывается очень громоздкой.
С помощью Docker Compose вы можете создать один файл .yml
для настройки конфигурации каждого контейнера и данных, которые нужны контейнерам для взаимодействия друг с другом. Вы можете использовать docker-compose
как инструмент командной строки для выдачи команд всем компонентам, составляющих ваше приложение, и управления ими как группой.
Docker хранилище само по себе является приложением с несколькими компонентами, поэтому для управления им вы будете использовать Docker Compose. Для запуска хранилища, необходимо будет создать файл docker-compose.yml
, который определит как хранилище, так и расположение на диске, где оно будет хранить данные.
На сервере-хосте создайте каталог docker-registry
для хранения настроек и перейдите в него:
$ mkdir ~/docker-registry
$ cd ~/docker-registry
Там создайте каталог data
, где будут храниться образы:
$ mkdir data
Создайте файл docker-compose.yml
:
$ sudo nano docker-compose.yml
Добавьте в него следующие строки, которые определят основной экземпляр хранилища:
version: '3'
services:
registry:
image: registry:2
ports:
- "5000:5000"
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
- ./data:/data
Здесь:
registry
– название первой службы;registry:2
– определение образа вregistry
версии2
;ports
– сопоставление порта5000
на хосте порту5000
на контейнере;REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY
– переменная, определяющая каталог для хранения данных;volumes
– сопоставление каталога/data
на сервере-хосте каталогу/data
в контейнере.
Теперь запустите созданную конструкцию:
$ docker-compose up
Контейнер и его зависимости будут загружены и запущены:
Обратите внимание на сообщение No HTTP secret provided
. К нему мы ещё вернёмся в данном руководстве. Последняя строка содержит сообщение о том, что запущено прослушивание на порту 5000
.
Чтобы прервать выполнение команды, нажмите Ctrl+C
.
Настройка переадресации портов Nginx
Ранее, мы уже настроили доступ к нашему домену по протоколу HTTPS. Чтобы открыть защищённое хранилище, вам необходимо будет всего лишь настроить Nginx в части перенаправления трафика от домена к контейнеру хранилища.
Откройте для редактирования созданный ранее файл, содержащий настройки вашего сервера:
$ sudo nano /etc/nginx/sites-available/my-domain.host
Найдите там блок location
:
Необходимо переадресовать трафик на порт 5000
, на котором хранилище будет слушать трафик. Также, можно добавить заголовки к запросам, направленным хранилищу, которое от имени сервера предоставляет дополнительную информацию о самом запросе. Замените содержимое блока location
следующими строками:
location / {
# Do not allow connections from docker 1.5 and earlier
# docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
return 404;
}
proxy_pass http://localhost:5000;
proxy_set_header Host $http_host; # required for docker client's sake
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900;
}
Блок if
проверяет пользовательский агент запроса, верифицирует версию клиента Docker выше 1.5 и определяет, что это не приложение Go, которое пытается получить доступ.
Сохраните файл перед его закрытием. Для применения новых настроек перезапустите Nginx:
$ sudo systemctl restart nginx
Чтобы убедиться, что Nginx правильно перенаправляет трафик в контейнер хранилища на порту 5000
, запустите его:
$ cd ~/docker-registry
$ docker-compose up
И теперь, наберите в браузере:
https://my-domain.host/v2
Вы увидите пустой объект JSON:
В терминале же вы сможете видеть, что в последней строке запрос GET
был сделан в /v2/
. Это указывает на какую конечную точку вы отправили запрос из своего браузера. Другими словами, контейнер получил запрос, который вы сделали, и вернул ответ {}
. Код http.response.status=200
в последних строках означает, что контейнер справился с запросом успешно.
Чтобы прервать выполнение команды, нажмите Ctrl+C
.
Настройка аутентификации
Nginx позволяет настроить аутентификацию HTTP для сайтов, которыми Nginx управляет. Именно это вы можете использовать для ограничения доступа к вашему хранилищу Docker. Чтобы этого добиться, необходимо создать файл аутентификации при помощи htpasswd
и добавить в него комбинацию пользователь-пароль.
Утилиту htpasswd
вы можете получить, например, установив пакет apache2-utils
:
$ sudo apt install apache2-utils
Теперь необходимо сохранить файл проверки подлинности с учетными данными в ~/docker-registry/auth/
:
$ mkdir ~/docker-registry/auth
$ cd ~/docker-registry/auth
На следующем шаге создайте своего первого пользователя, заменив user1
на какое-нибудь своё имя учётной записи. Здесь, опция -B
нужна для применения алгоритма bcrypt
:
$ htpasswd -Bc registry.password user1
Далее, введите пароль для создаваемого пользователя:
Теперь учётная запись user1
и её пароль добавлены в registry.password
.
Если вам необходимо добавить других пользователей, повторите предыдущую команду, но с другим именем пользователя и без использования флага -c
, который отвечает за создание нового файла:
$ htpasswd -B registry.password user2
Теперь нужно заставить Docker использовать созданный файл аутентификации. Для этого отредактируйте его:
$ sudo nano ~/docker-registry/docker-compose.yml
Добавьте в файл выделенные строки:
version: '3'
services:
registry:
image: registry:2
ports:
- "5000:5000"
environment:
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry
REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
- ./auth:/auth
- ./data:/data
Таким образом, мы добавили переменные окружения, указывающие на необходимость использования аутентификации HTTP, и указали путь к созданному файлу htpasswd
. Для REGISTRY_AUTH
мы указали значение htpasswd
, которое аутентифицирует используемую схему. Переменная REGISTRY_AUTH_HTPASSWD_PATH
содержит путь к файлу аутентификации. Переменная REGISTRY_AUTH_HTPASSWD_REALM
означает имя области htpasswd
.
Также, мы смонтировали каталог ./auth/
, чтобы сделать файл доступным внутри контейнера хранилища. Закройте файл сохранив внесённые изменения.
Теперь можно проверить корректность работы системы аутентификации:
$ cd ~/docker-registry
$ docker-compose up
После этого, обновите страницу браузера, в котором открыт ваш домен. Система должна попросить вас ввести имя пользователя и пароль:
Введите учётные данные и, в случае успешной аутентификации, вы увидите пустой объект JSON:
Это означает, что вы успешно прошли проверку подлинности и получили доступ к хранилищу.
Как и раньше, выход осуществляется через Ctrl+C
.
Теперь ваше хранилище защищено, и доступ к нему можно осуществить только после успешной проверки подлинности. Далее, мы настроим его на запуск в фоновом режиме, при этом хранилище будет устойчиво к перезагрузкам, запускаясь каждый раз автоматически.
Запуск Docker хранилища как службы
Для того, чтобы контейнер хранилища запускался каждый раз при загрузке системы или после её сбоя, необходимо проинструктировать Docker Compose всегда поддерживать его работу.
Отредактируйте файл docker-compose.yml
:
$ sudo nano ~/docker-registry/docker-compose.yml
Добавьте в файл выделенную строку:
version: '3'
services:
registry:
restart: always
image: registry:2
ports:
- "5000:5000"
environment:
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry
REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
- ./auth:/auth
- ./data:/data
Настройка restart
гарантирует нам, что контейнер выдержит перезапуск системы. Сохраните изменения и закройте файл.
А теперь, запустите ваше хранилище как фоновый процесс при помощи опции -d
:
$ docker-compose up -d
С этого момента ваше хранилище работает в фоновом режиме, и поэтому, вы можете спокойно закрыть сессию SSH, и даже перезагрузить сервер. Это не окажет на хранилище никакого эффекта.
Увеличение размера загружаемых файлов для Nginx
Перед тем, как помещать образ в хранилище, необходимо убедиться, что наше хранилище сможет обрабатывать загрузку файлов большого объёма.
По умолчанию предельный размер загружаемого файла в Nginx составляет 1MB. Этого явно не достаточно для образа Docker. Чтобы это исправить, необходимо внести изменения в главный конфигурационный файл Nginx. Он расположен в директории /etc/nginx/
. Откройте его для редактирования, набрав в командной строке:
$ cd /etc/nginx
$ sudo nano nginx.conf
Найдите там секцию http
и добавьте в неё выделенную строку:
http {
##
# Basic Settings
##
client_max_body_size 16384m;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
Значение параметра client_max_body_size
теперь установлено в 16384 MB. Это означает, что максимальный размер загружаемого файла равно 16GB.
Закройте файл с сохранением изменений и перезапустите Nginx:
$ sudo systemctl restart nginx
Публикация в Docker хранилище
Настало время попробовать загрузить образ на наше хранилище. Так как у нас пока нет доступных образов, мы можем, в качестве теста, использовать образ ubuntu
, который можно скачать с общедоступного Docker хранилища.
Действия по публикации образа в наше хранилище мы будем производить на нашем втором сервере, который мы обозначили как сервер-клиент.
Для начала, чтобы на этом сервере запускать команду docker
не используя полномочия sudo
, необходимо добавить вашего пользователя в группу docker
:
$ sudo usermod -aG docker your-user
Теперь, для того, чтобы загрузить образ ubuntu
, запустить его и получить доступ к его оболочке, в командной строке вашего сервера-клиента наберите:
$ docker run -t -i ubuntu /bin/bash
Опции -i
и -t
позволяют вам получить интерактивный доступ к оболочке внутри контейнера.
Теперь, когда вы подключились к оболочке, в корне системы создайте файл my.IMAGE
:
root@2b8dcf17a0db:/# touch /my.IMAGE
Создав такой файл, мы изменили первоначальный контейнер. Наличие этого файла позже позволит нам понять, что мы имеем дело именно с точно таким же контейнером.
Выход из оболочки контейнера осуществляется при помощи CNTL D
, либо командой:
root@2b8dcf17a0db:/# exit
Далее, создайте новый образ из контейнера, в который вы только что внесли изменения:
$ docker commit $(docker ps -lq) new-ubuntu-image
Новый образ теперь доступен локально, и, значит, вы можете передать его в ваше хранилище. Сначала подключитесь к нему:
$ docker login https://my-domain.host
Введите имя пользователя и пароль для получения доступа к контейнеру. В нашем случае, это данные учётной записи user1
.
В случае успешной аутентификации система выведет подобное сообщение:
Теперь, когда вы подключились, переименуйте созданный образ:
$ docker tag new-ubuntu-image my-domain.host/new-ubuntu-image
И наконец, передайте только что отмеченный образ в ваше хранилище:
$ docker push my-domain.host/new-ubuntu-image
Вы получите вывод, аналогичный следующему:
После того, как мы отправили образ в хранилище, давайте лишние образы удалим. Сначала необходимо вывести на экран список локально доступных образов:
$ docker images
Мы удалим все образы, кроме первоначально загруженного образа ubuntu
:
$ docker rmi new-ubuntu-image
$ docker rmi my-domain.host/new-ubuntu-image
Если ещё раз вывести список образов, то вы увидите, что в списке остался только образ ubuntu
:
$ docker images
Таким образом, мы проверили, как хранилище обрабатывает аутентификацию пользователей при их подключении и как позволяет пользователям, прошедшим проверку, передавать образ в хранилище. Теперь попробуем забрать образ из нашего хранилища.
Извлечение из Docker хранилища
Для загрузки образа из хранилища подключитесь к нему набрав на вашем сервере-клиенте команду:
$ docker login https://my-domain.host
Не забывайте использовать домен своего сервера-хоста вместо my-domain.host
.
Для того, чтобы принять файл образа new-ubuntu-image
, выполните следующую команду:
$ docker pull my-domain.host/new-ubuntu-image
После того, как образ загрузится, выполните команду для просмотра списка имеющихся на сервере-клиенте образов:
$ docker images
Здесь вы видите, что образ new-ubuntu-image
снова присутствует на сервере-клиенте. Значит, к нему можно подключиться:
$ docker run -t -i my-domain.host/new-ubuntu-image
Подключившись, посмотрите содержимое корня системы:
root@65c69421278c:/# ls -l
Увидев файл my.IMAGE
, можно сделать вывод, что это – экземпляр именно того образа, в который мы вносили коррективы перед загрузкой в наше хранилище.
Закрыть оболочку можно командой exit
, либо нажав Ctrl+D
.
Заключение
В данном руководстве мы увидели, как развернуть своё приватное Docker хранилище на сервере, работающем под управлением Ubuntu 20.04. Мы защитили подключение к развёрнутому хранилищу при помощи системы проверки подлинности учётных записей. А также, мы попробовали создать контейнер с образом Docker, передать его в хранилище и снова загрузить на сервер, использовавшийся нами как клиент нашего Docker хранилища.
Ориентация и настройка | Документация Docker
Приблизительное время чтения: 4 минуты
Добро пожаловать! Мы очень рады, что вы хотите изучить Docker.
Эта страница содержит пошаговые инструкции о том, как начать работу с Docker. В этом руководстве вы узнаете, как:
- Создать и запустить образ как контейнер
- Обмен изображениями с помощью Docker Hub
- Развертывание приложений Docker с использованием нескольких контейнеров с базой данных
- Запуск приложений с помощью Docker Compose
Кроме того, вы также узнаете о передовых методах создания образов, в том числе о том, как сканировать изображения на предмет уязвимостей.
Если вам нужна информация о том, как поместить приложение в контейнер с использованием вашего любимого языка, см. Руководства по началу работы для конкретных языков.
Мы также рекомендуем видео-пошаговое руководство с DockerCon 2020.
Загрузите и установите Docker
В этом руководстве предполагается, что на вашем компьютере установлена текущая версия Docker.
машина. Если у вас не установлен Docker, выберите предпочитаемую операционную систему ниже, чтобы загрузить Docker:
Mac с чипом Intel
Mac с чипом Apple
Окна
Linux
Инструкции по установке Docker Desktop см. В разделах Установка Docker Desktop на Mac и Установка Docker Desktop в Windows.
Начать обучение
Если вы уже выполнили команду, чтобы начать работу с руководством, поздравляем! Если нет, откройте командную строку или окно bash и выполните команду:
$ docker run -d -p 80:80 docker / начало работы
Вы заметите, что используются несколько флажков. Вот еще немного информации о них:
-
-d
— запустить контейнер в автономном режиме (в фоновом режиме) -
-p 80:80
— сопоставить порт 80 хоста с портом 80 в контейнере -
докер / начало работы
— образ для использования
Наконечник
Вы можете комбинировать односимвольные флаги, чтобы сократить полную команду.В качестве примера приведенную выше команду можно записать как:
$ docker run -dp 80:80 docker / начало работы
Панель мониторинга Docker
Прежде чем зайти слишком далеко, мы хотим выделить панель Docker Dashboard, которая дает
вы быстро просматриваете контейнеры, работающие на вашем компьютере. Панель мониторинга Docker доступна для Mac и Windows.
Он обеспечивает быстрый доступ к журналам контейнера, позволяет разместить оболочку внутри контейнера и позволяет
легко управлять жизненным циклом контейнера (остановка, удаление и т. д.)).
Чтобы получить доступ к панели управления, следуйте инструкциям в
Руководство Docker Desktop. Если вы откроете дашборд
теперь вы увидите, что это руководство запущено! Название контейнера ( jolly_bouman
ниже) — это
случайно созданное имя. Так что, скорее всего, у вас будет другое имя.
Что такое контейнер?
Теперь, когда вы запустили контейнер, какое значение равно контейнеру? Проще говоря, контейнер — это
просто еще один процесс на вашем компьютере, который был изолирован от всех других процессов
на хост-машине.Эта изоляция использует пространства имен ядра и контрольные группы, функции, которые были
в линуксе давно. Docker постарался сделать эти возможности доступными и простыми в использовании.
Создание контейнеров с нуля
Если вы хотите увидеть, как контейнеры создаются с нуля, Лиз Райс из Aqua Security
имеет фантастический доклад, в котором она создает контейнер с нуля на Go. Пока она делает
простой контейнер, этот разговор не касается сетей, использования изображений для файловой системы,
и более.Но он дает фантастических глубоких сведений о том, как все работает.
Что такое образ контейнера?
При запуске контейнера используется изолированная файловая система. Эта настраиваемая файловая система предоставляется
с помощью образа контейнера . Поскольку образ содержит файловую систему контейнера, он должен содержать все
необходимые для запуска приложения — все зависимости, конфигурация, скрипты, двоичные файлы и т. д.
изображение также содержит другую конфигурацию для контейнера, такую как переменные среды,
команда по умолчанию для запуска и другие метаданные.
Позже мы подробнее рассмотрим изображения, затронув такие темы, как наложение слоев, передовые методы и многое другое.
Информация
Если вы знакомы с
chroot
, подумайте о контейнере как о расширенной версииchroot
. В
файловая система просто берется из образа. Но контейнер добавляет дополнительную изоляцию, а не
доступно при простом использовании chroot.
Ссылки CLI
Дополнительную документацию по всем командам интерфейса командной строки, используемым в этой статье, см. В следующих разделах:
начало работы, настройка, ориентация, быстрый старт, введение, концепции, контейнеры, рабочий стол докера
Пример приложения | Документация Docker
Расчетное время чтения: 5 минут
В оставшейся части этого руководства мы будем работать с простым todo.
диспетчер списков, запущенный в Node.js. Если вы не знакомы с Node.js,
не волнуйся. Никакого реального опыта работы с JavaScript не требуется.
На данный момент ваша команда разработчиков довольно мала, и вы просто
создание приложения, подтверждающего ваш MVP (минимально жизнеспособный продукт). Ты хочешь
чтобы показать, как это работает и на что способно без необходимости
подумайте, как это будет работать для большой команды, нескольких разработчиков и т. д.
Скачать приложение
Прежде чем мы сможем запустить приложение, нам нужно загрузить исходный код приложения на
наша машина.Для реальных проектов вы обычно клонируете репо. Но для этого урока
мы создали ZIP-файл, содержащий приложение.
Загрузите содержимое приложения. Вы можете либо вытащить весь проект, либо загрузить его в виде zip-архива и извлечь папку приложения, чтобы начать работу с
.
После извлечения используйте свой любимый редактор кода, чтобы открыть проект. Если вам нужен
редактор, вы можете использовать Visual Studio Code. Вам следует
см. пакет.json
и два подкаталога (src
иspec
).
Создайте образ контейнера приложения
Для создания приложения нам нужно использовать Dockerfile
. А
Dockerfile — это просто текстовый сценарий инструкций, который используется для
создать образ контейнера. Если вы уже создавали Dockerfiles раньше, вы можете
увидеть несколько недостатков в Dockerfile ниже. Но не волнуйтесь. Мы пройдемся по ним.
Создайте файл с именем
Dockerfile
в той же папке, что и файлpackage.json
со следующим содержимым.# синтаксис = docker / dockerfile: 1 ОТ узла: 12-альпийский ЗАПУСК apk добавить --no-cache python g ++ make WORKDIR / приложение КОПИРОВАТЬ. . Установка пряжи RUN - производство CMD ["узел", "src / index.js"]
Убедитесь, что файл
Dockerfile
не имеет расширения, например.txt
. Некоторые редакторы могут добавлять это расширение файла автоматически, и это приведет к ошибке на следующем шаге.Если вы еще этого не сделали, откройте терминал и перейдите в каталог
app
сDockerfile
.Теперь создайте образ контейнера с помощью командыdocker build
.$ docker build -t начало работы.
Эта команда использовала Dockerfile для создания нового образа контейнера. Ты можешь
заметили, что было загружено много «слоев». Это потому, что мы проинструктировали
построитель, который мы хотели запустить с узла: образ 12-alpine
. Но, поскольку мы
на нашей машине этого не было, этот образ нужно было загрузить.После того, как изображение было загружено, мы скопировали его в нашем приложении и использовали пряжу
установить зависимости нашего приложения.ДирективаCMD
определяет значение по умолчанию
команда для запуска при запуске контейнера из этого образа.Наконец, наше изображение помечается флагом
-t
. Думайте об этом просто как об удобочитаемом имени.
для окончательного изображения. Поскольку мы назвали изображениеначало работы
, мы можем ссылаться на него
изображение, когда мы запускаем контейнер.Модель
.
в конце командыdocker build
сообщает, что Docker должен искатьDockerfile
в текущем каталоге.
Запустить контейнер приложения
Теперь, когда у нас есть изображение, давайте запустим приложение. Для этого мы будем использовать запуск докера
команда (помните это ранее?).
Запустите свой контейнер с помощью команды
docker run
и укажите имя изображения, которое мы
только что создано:$ docker run -dp 3000: 3000 начало работы
Помните флаги
-d
и-p
? Мы запускаем новый контейнер в «отключенном» режиме (в
background) и создание сопоставления между портом 3000 хоста и портом 3000 контейнера.Без сопоставления портов мы не смогли бы получить доступ к приложению.Через несколько секунд откройте в браузере адрес http: // localhost: 3000.
Вы должны увидеть наше приложение.Добавьте один или два элемента и убедитесь, что он работает так, как вы ожидаете. Вы можете отмечать предметы как
завершить и удалить элементы. Ваш интерфейс успешно хранит элементы в серверной части.
Довольно быстро и легко, да?
На этом этапе у вас должен быть запущенный менеджер списка задач с несколькими элементами, и все они созданы вами.Теперь давайте внесем несколько изменений и узнаем, как управлять нашими контейнерами.
Если вы быстро взглянете на панель Docker Dashboard, вы увидите, что сейчас запущены два ваших контейнера.
(это руководство и контейнер только что запущенного приложения).
Обзор
В этом коротком разделе мы узнали самые основы построения образа контейнера и создали
Dockerfile для этого. После создания образа мы запустили контейнер и увидели работающее приложение.
Далее мы собираемся внести изменения в наше приложение и узнать, как обновить работающее приложение.
с новым изображением.Попутно мы узнаем еще несколько полезных команд.
начало работы, настройка, ориентация, краткое руководство, введение, концепции, контейнеры, рабочий стол докера
Обзор Docker | Документация Docker
Расчетное время чтения: 7 минут
Docker — это открытая платформа для разработки, доставки и запуска приложений.
Docker позволяет отделить приложения от инфраструктуры, чтобы
вы можете быстро доставить программное обеспечение. С Docker вы можете управлять своей инфраструктурой
так же, как вы управляете своими приложениями.Воспользовавшись преимуществами Docker
методологии для быстрой доставки, тестирования и развертывания кода, вы можете
значительно сократить задержку между написанием кода и его запуском в производственной среде.
Платформа Docker
Docker предоставляет возможность упаковывать и запускать приложение в слабо изолированном
окружение называется контейнером. Изоляция и безопасность позволяют запускать многие
контейнеров одновременно на заданном хосте. Контейнеры легкие и содержат
все необходимое для запуска приложения, поэтому вам не нужно полагаться на то, что есть
в настоящее время установлен на хосте.Вы можете легко обмениваться контейнерами во время работы,
и убедитесь, что все, с кем вы делитесь, получают тот же контейнер, который работает в
так же.
Docker предоставляет инструменты и платформу для управления жизненным циклом ваших контейнеров:
- Разрабатывайте свое приложение и его вспомогательные компоненты с помощью контейнеров.
- Контейнер становится модулем для распространения и тестирования вашего приложения.
- Когда будете готовы, разверните приложение в производственной среде,
как контейнер или оркестрованный сервис.Это работает одинаково, независимо от того,
производственная среда — это локальный центр обработки данных, облачный провайдер или гибридная
из двух.
Для чего я могу использовать Docker?
Быстрая и последовательная доставка ваших приложений
Docker упрощает жизненный цикл разработки, позволяя разработчикам работать в
стандартизированные среды с использованием локальных контейнеров, которые предоставляют ваши приложения
и услуги. Контейнеры отлично подходят для непрерывной интеграции и непрерывного
рабочие процессы доставки (CI / CD).
Рассмотрим следующий пример сценария:
- Ваши разработчики пишут код локально и делятся своей работой с коллегами
с использованием контейнеров Docker. - Они используют Docker, чтобы отправить свои приложения в тестовую среду и выполнить
автоматизированные и ручные тесты. - Когда разработчики находят ошибки, они могут исправить их в среде разработки.
и повторно разверните их в тестовой среде для тестирования и проверки. - По завершении тестирования доставить исправление заказчику так же просто, как
отправка обновленного образа в производственную среду.
Адаптивное развертывание и масштабирование
Контейнерная платформа
Docker позволяет выполнять легко переносимые рабочие нагрузки. Докер
контейнеры могут работать на локальном ноутбуке разработчика, на физическом или виртуальном
машины в центре обработки данных, у поставщиков облачных услуг или в смешанных средах.
Портативность и легкий вес
Docker также упрощают динамическое
управлять рабочими нагрузками, увеличивать или отключать приложения и сервисы по мере необходимости.
бизнес-потребности диктуют, практически в реальном времени.
Выполнение дополнительных рабочих нагрузок на том же оборудовании
Docker легкий и быстрый. Это жизнеспособная и экономичная альтернатива.
к виртуальным машинам на основе гипервизора, чтобы вы могли использовать больше своих вычислительных ресурсов
способность достигать ваших бизнес-целей. Докер идеально подходит для высокой плотности
средах и для малых и средних развертываний, где вам нужно больше работать с
меньше ресурсов.
Архитектура Docker
Docker использует архитектуру клиент-сервер.Клиент Docker общается с
Docker демон , который выполняет тяжелую работу по сборке, запуску и
распространение ваших контейнеров Docker. Клиент и демон Docker может
работать в той же системе, или вы можете подключить клиент Docker к удаленному Docker
демон. Клиент Docker и демон обмениваются данными с помощью REST API через UNIX.
розетки или сетевой интерфейс. Другой клиент Docker — Docker Compose,
что позволяет работать с приложениями, состоящими из набора контейнеров.
Демон Docker
Демон Docker ( dockerd
) прослушивает запросы Docker API и управляет Docker
такие объекты, как изображения, контейнеры, сети и тома. Демон также может
общаться с другими демонами для управления службами Docker.
Клиент Docker
Клиент Docker ( docker
) — это основной способ взаимодействия многих пользователей Docker.
с докером. Когда вы используете такие команды, как docker run
, клиент отправляет эти
команды на dockerd
, который их выполняет.Команда docker
использует
Docker API. Клиент Docker может взаимодействовать более чем с одним демоном.
Реестры Docker
Реестр Docker хранит образы Docker. Docker Hub — общедоступный
реестр, который может использовать каждый, а Docker настроен на поиск образов в
Docker Hub по умолчанию. Вы даже можете запустить свой собственный частный реестр.
Когда вы используете команду docker pull
или docker run
, требуемые образы
вытащил из настроенного реестра.Когда вы используете команду docker push
,
ваш образ будет помещен в ваш настроенный реестр.
Объекты Docker
Когда вы используете Docker, вы создаете и используете образы, контейнеры, сети,
тома, плагины и другие объекты. Этот раздел представляет собой краткий обзор некоторых
этих объектов.
Изображения
Образ — это шаблон только для чтения с инструкциями по созданию Docker
контейнер. Часто образ основан на другом изображении с некоторыми дополнительными
настройка.Например, вы можете создать образ, основанный на ubuntu
образ, но устанавливает веб-сервер Apache и ваше приложение, а также
сведения о конфигурации, необходимые для запуска вашего приложения.
Вы можете создавать свои собственные изображения или использовать только изображения, созданные другими
и опубликованы в реестре. Чтобы создать свой собственный образ, вы создаете Dockerfile
с простым синтаксисом для определения шагов, необходимых для создания образа и запуска
Это. Каждая инструкция в Dockerfile создает слой в изображении.Когда ты
измените Dockerfile и перестройте образ, только те слои, которые имеют
изменены перестраиваются. Это часть того, что делает изображения такими легкими, маленькими,
и быстро по сравнению с другими технологиями виртуализации.
Контейнеры
Контейнер — это исполняемый экземпляр образа. Вы можете создавать, запускать, останавливать,
переместить или удалить контейнер с помощью Docker API или интерфейса командной строки. Вы можете подключить
контейнер в одну или несколько сетей, прикрепите к нему хранилище или даже создайте новый
изображение на основе его текущего состояния.
По умолчанию контейнер относительно хорошо изолирован от других контейнеров и
его хост-машина. Вы можете контролировать, насколько изолирована сеть контейнера, хранилище,
или другие базовые подсистемы из других контейнеров или из хоста
машина.
Контейнер определяется его образом, а также любыми параметрами конфигурации, которые вы
предоставить ему, когда вы его создаете или запускаете. Когда контейнер удален, любые изменения в
его состояния, которые не хранятся в постоянном хранилище, исчезают.
Пример
docker run
command
Следующая команда запускает контейнер ubuntu
, интерактивно подключается к вашему
локальный сеанс командной строки и запускает / bin / bash
.
$ docker run -i -t ubuntu / bin / bash
Когда вы запускаете эту команду, происходит следующее (при условии, что вы используете
конфигурация реестра по умолчанию):
Если у вас нет образа
ubuntu
локально, Docker извлекает его из вашего
настроенный реестр, как если бы вы запускалиdocker pull ubuntu
вручную.Docker создает новый контейнер, как если бы вы запустили Docker-контейнер
create
команда вручную.Docker выделяет контейнеру файловую систему для чтения и записи в качестве последнего
слой. Это позволяет работающему контейнеру создавать или изменять файлы и
каталоги в своей локальной файловой системе.Docker создает сетевой интерфейс для подключения контейнера по умолчанию
сеть, поскольку вы не указали никаких сетевых параметров. Это включает
присвоение IP-адреса контейнеру. По умолчанию контейнеры могут
подключаться к внешним сетям с помощью сетевого подключения хост-машины.Docker запускает контейнер и выполняет
/ bin / bash
. Потому что контейнер
работает в интерактивном режиме и подключен к вашему терминалу (из-за-i
и-t
flags), вы можете вводить данные с клавиатуры, пока вывод записывается в
ваш терминал.Когда вы набираете
exit
для завершения команды/ bin / bash
, контейнер
останавливается, но не удаляется. Вы можете запустить его заново или удалить.
Базовая технология
Docker написан на языке программирования Go и принимает
преимущество нескольких функций ядра Linux для обеспечения его функциональности.
Docker использует технологию под названием namespaces
для обеспечения изолированного рабочего пространства.
назвал контейнер . Когда вы запускаете контейнер, Docker создает набор
пространства имен для этого контейнера.
Эти пространства имен обеспечивают уровень изоляции. Каждый аспект контейнера работает
в отдельном пространстве имен, и его доступ ограничен этим пространством имен.
Следующие шаги
docker, введение, документация, о, технология, понимание
Docker Dashboard | Документация Docker
Расчетное время чтения: 14 минут
Docker Dashboard предоставляет простой интерфейс, который позволяет вам управлять своими контейнерами, приложениями и образами прямо с вашего компьютера без необходимости использования интерфейса командной строки для выполнения основных действий.
Представление Контейнеры / приложения обеспечивает представление времени выполнения всех ваших контейнеров и приложений.Он позволяет вам взаимодействовать с контейнерами и приложениями, а также управлять жизненным циклом ваших приложений прямо с вашего компьютера. Это представление также предоставляет интуитивно понятный интерфейс для выполнения стандартных действий по проверке, взаимодействию и управлению вашими объектами Docker, включая контейнеры и приложения на основе Docker Compose. Дополнительные сведения см. В разделе «Исследование запущенных контейнеров и приложений».
Образы Представление отображает список ваших образов Docker и позволяет запускать образ как контейнер, извлекать последнюю версию образа из Docker Hub и проверять образы.Он также отображает сводку отчета о сканировании уязвимостей с помощью Snyk. Кроме того, в представлении «Изображения» есть параметры очистки, позволяющие удалить с диска ненужные изображения и освободить место. Если вы вошли в систему, вы также можете видеть изображения, которыми вы и ваша организация поделились в Docker Hub. Для получения дополнительной информации см. Исследуйте свои изображения
.
Представление Volumes отображает список томов и позволяет легко создавать и удалять тома, а также видеть, какие из них используются. Дополнительные сведения см. В разделе «Изучение томов».
Кроме того, панель Docker Dashboard позволяет:
- С легкостью перейдите в меню настроек ( Настройки в Windows), чтобы настроить параметры рабочего стола Docker
- Доступ к меню устранения неполадок для отладки и выполнения операций перезапуска
- Войдите в Docker Hub, используя свой Docker ID
Чтобы получить доступ к панели мониторинга Docker, в меню Docker выберите Dashboard . В Windows щелкните значок Docker, чтобы открыть панель мониторинга.
Изучите запущенные контейнеры и приложения
В меню Docker выберите Dashboard . Здесь перечислены все ваши запущенные контейнеры и приложения. У вас должны быть запущенные или остановленные контейнеры и приложения, чтобы они отображались на панели мониторинга Docker.
Следующие разделы проведут вас через процесс создания образца контейнера Redis и образца приложения для демонстрации основных функций в Docker Dashboard.
Запустить контейнер Redis
Чтобы запустить контейнер Redis, откройте предпочитаемый интерфейс командной строки и выполните следующую команду:
запуск докера -dt redis
Это создает новый контейнер Redis.В меню Docker выберите Dashboard , чтобы увидеть новый контейнер Redis.
Запустить пример приложения
Давайте запустим образец приложения. Загрузите приложение «Пример голосования» со страницы примеров Docker. Пример приложения для голосования — это распределенное приложение, работающее в нескольких контейнерах Docker. В приложении содержится:
Чтобы запустить приложение, перейдите в каталог, содержащий пример приложения для голосования, в интерфейсе командной строки и запустите docker-compose up --build
.
$ docker-compose up - построить
Создание сети «пример-голосование-приложение-мастер_фронт-уровень» с драйвером по умолчанию
Создание сети «пример-голосование-приложение-мастер_бэк-ярус» с драйвером по умолчанию
Создание тома example-vote-app-master_db-data с драйвером по умолчанию
Строительное голосование
Шаг 1/7: ОТ python: 2.7-alpine
2.7-alpine: извлечение из библиотеки / python
Дайджест: sha256: d2cc8451e799d4a75819661329ea6e0d3e13b3dadd56420e25fcb8601ff6ba49
Статус: загружено более новое изображение для python: 2.7-alpine
---> 1bf48bb21060
Шаг 2/7: WORKDIR / приложение
...
Успешно построен 69da1319c6ce
Пример-голосование-app-master_worker: latest успешно помечен тегом
Создание примера-голосования-app-master_vote_1 ... готово
Создание примера-голосование-app-master_result_1 ... готово
Создание базы данных ... готово
Создание Redis ... готово
Создание примера-голосование-app-master_worker_1 ... готово
Прикрепление к базе данных, redis, пример-голосование-приложение-master_result_1, пример-голосование-приложение-мастер_vote_1, пример-голосование-приложение-мастер_worker_1
...
После успешного запуска приложения в меню Docker выберите Dashboard , чтобы увидеть пример приложения для голосования.Разверните приложение, чтобы увидеть контейнеры, работающие внутри приложения.
Теперь, когда вы видите список запущенных контейнеров и приложений на панели инструментов, давайте рассмотрим некоторые действия, которые вы можете выполнять:
- Щелкните Порт , чтобы открыть порт, предоставляемый контейнером, в браузере.
- Щелкните CLI , чтобы открыть терминал и выполнить команды в контейнере. Если вы установили iTerm2 на свой Mac, опция CLI открывает терминал iTerm2.В противном случае он открывает приложение «Терминал» на Mac или командную строку в Windows.
- Щелкните Остановить , Старт , Перезапустить или Удалить для выполнения операций жизненного цикла с контейнером.
Используйте опцию Search для поиска определенного объекта. Вы также можете сортировать свои контейнеры и приложения, используя различные параметры. Щелкните раскрывающееся меню Сортировка по , чтобы просмотреть список доступных параметров.
Взаимодействие с контейнерами и приложениями
На панели инструментов Docker выберите пример приложения для голосования, которое мы запустили ранее.
В представлении «Контейнеры / приложения » перечислены все контейнеры, запущенные в приложении, и содержится подробное представление журналов. Он также позволяет запускать, останавливать или удалять приложение. Используйте опцию Search в нижней части представления журналов для поиска в журналах приложений определенных событий или выберите значок Copy , чтобы скопировать журналы в буфер обмена.
Щелкните Открыть в Visual Studio Code , чтобы открыть приложение в VS Code. Наведите курсор на список контейнеров, чтобы увидеть некоторые из основных действий, которые вы можете выполнить.
Вид контейнера
Щелкните конкретный контейнер для получения подробной информации о контейнере. Представление контейнера отображает вкладки Журналы , Проверить и Статистика и предоставляет кнопки быстрых действий для выполнения различных действий.
Выберите Журналы , чтобы просмотреть журналы из контейнера. Вы также можете искать в журналах определенные события и копировать журналы в буфер обмена.
Выберите Проверить , чтобы просмотреть низкоуровневую информацию о контейнере.Вы можете увидеть локальный путь, номер версии образа, SHA-256, сопоставление портов и другие детали.
Выберите Stats , чтобы просмотреть информацию об использовании ресурсов контейнера. Вы можете увидеть объем ЦП, дискового ввода-вывода, памяти и сетевого ввода-вывода, используемых контейнером.
Вы также можете использовать кнопки быстрых действий на верхней панели для выполнения общих действий, таких как открытие интерфейса командной строки для выполнения команд в контейнере, и выполнения операций жизненного цикла, таких как остановка, запуск, перезапуск или удаление контейнера.
Изучите свои изображения
Образы Представление — это простой интерфейс, который позволяет управлять образами Docker без использования интерфейса командной строки. По умолчанию он отображает список всех образов Docker на вашем локальном диске. Чтобы просмотреть образы в удаленных репозиториях, нажмите Войти и подключитесь к Docker Hub. Это позволяет вам сотрудничать с вашей командой и управлять изображениями непосредственно через Docker Desktop.
Представление «Образы» позволяет выполнять основные операции, такие как запуск образа в качестве контейнера, получение последней версии образа из Docker Hub, отправка образа в Docker Hub и проверка образов.
Кроме того, в представлении «Изображения» отображаются метаданные об изображении, такие как тег, идентификатор изображения, дата создания изображения и размер изображения. Он также отображает теги In Use рядом с изображениями, используемыми запущенными и остановленными контейнерами. Это позволяет вам просмотреть список образов и использовать опцию Очистить образы , чтобы удалить все ненужные образы с диска, чтобы освободить место.
Представление «Изображения» также позволяет искать изображения на локальном диске и сортировать их, используя различные параметры.
Давайте рассмотрим различные варианты в представлении Изображения .
Если на вашем диске нет образов, запустите команду docker pull redis
в терминале, чтобы получить последний образ Redis. Эта команда извлекает последний образ Redis из Docker Hub.
Выберите Dashboard > Images , чтобы увидеть образ Redis.
Запуск образа как контейнера
Теперь, когда у вас есть образ Redis на диске, давайте запустим этот образ как контейнер:
- В меню Docker выберите Dashboard > Images .Это отображает список изображений на вашем локальном диске.
- Выберите образ Redis из списка и нажмите Выполнить .
При появлении запроса щелкните раскрывающийся список Дополнительные параметры , чтобы указать имя, порт, тома, и щелкните Выполнить .
Чтобы использовать значения по умолчанию, щелкните Выполнить без указания каких-либо дополнительных настроек. Это создает новый контейнер из образа Redis и открывает его в представлении Container / Apps .
Получить последний образ из Docker Hub
Чтобы получить последний образ из Docker Hub:
- В меню Docker выберите Dashboard > Images . Это отображает список изображений на вашем локальном диске.
- Выберите изображение из списка и нажмите кнопку «Дополнительные параметры».
- Щелчок Потяните . Это извлечет последнюю версию образа из Docker Hub.
Примечание
Репозиторий должен существовать в Docker Hub, чтобы получить последнюю версию образа.Вы должны войти в систему, чтобы получать личные изображения.
Отправить образ в Docker Hub
Чтобы отправить образ в Docker Hub:
- В меню Docker выберите Dashboard > Images . Это отображает список изображений на вашем локальном диске.
- Выберите изображение из списка и нажмите кнопку «Дополнительные параметры».
- Щелкните Push to Hub.
Примечание
Вы можете отправить образ в Docker Hub, только если он принадлежит вашему Docker ID или вашей организации.То есть образ должен содержать правильное имя пользователя / организацию в теге, чтобы можно было отправить его в Docker Hub.
Осмотрите изображение
При проверке изображения отображается подробная информация об изображении, такая как история изображения, идентификатор изображения, дата создания изображения, размер изображения и т. Д. Для проверки изображения:
- В меню Docker выберите Dashboard > Images . Это отображает список изображений на вашем локальном диске.
- Выберите изображение из списка и нажмите кнопку «Дополнительные параметры».
- Щелкните Осмотрите .
- Представление проверки изображения также предоставляет параметры для извлечения последнего изображения, отправки изображения в концентратор, удаления изображения или запуска изображения в качестве контейнера.
Удалить изображение
Вид изображений позволяет удалить ненужные изображения с диска. В строке состояния «Образы на диске» отображается количество образов и общее дисковое пространство, используемое ими.
Вы можете удалить отдельные изображения или использовать опцию Очистить для удаления неиспользуемых и болтающихся изображений.
Для удаления отдельных изображений:
- В меню Docker выберите Dashboard > Images . Это отображает список изображений на вашем локальном диске.
- Выберите изображение из списка и нажмите кнопку «Дополнительные параметры».
- Щелкните Удалить . Это удалит образ с вашего диска.
Примечание
Чтобы удалить образ, используемый работающим или остановленным контейнером, необходимо сначала удалить связанный контейнер.
Для удаления неиспользуемых и болтающихся изображений:
Неиспользуемый образ — это образ, который не используется ни в каких запущенных или остановленных контейнерах. Образ становится висящим , когда вы создаете новую версию образа с тем же тегом.
Чтобы удалить неиспользуемое или болтающееся изображение:
- В меню Docker выберите Dashboard > Images . Это отображает список изображений на вашем диске.
- Выберите опцию Очистить в строке состояния Образы на диске .
Используйте флажки Unused и Dangling , чтобы выбрать тип изображений, которые вы хотите удалить.
В строке состояния Очистить изображения отображается общее пространство, которое можно освободить, удалив выбранные изображения.
- Нажмите Удалить для подтверждения.
Взаимодействие с удаленными репозиториями
Представление «Изображения» также позволяет управлять образами в удаленных репозиториях и взаимодействовать с ними, а также позволяет переключаться между организациями.Выберите организацию из раскрывающегося списка, чтобы просмотреть список репозиториев в вашей организации.
Примечание
Если у вас есть платная подписка на Docker и включено сканирование уязвимостей в Docker Hub, результаты сканирования появятся на вкладке «Удаленные репозитории».
Параметр Pull позволяет получить последнюю версию образа из Docker Hub. Параметр View in Hub открывает страницу Docker Hub и отображает подробную информацию об образе, такую как архитектура ОС, размер образа, дата отправки образа и список слоев образа.
Для взаимодействия с удаленными репозиториями:
- Щелкните вкладку Удаленные репозитории .
- Выберите организацию из раскрывающегося списка. Это отображает список репозиториев в вашей организации.
- Щелкните изображение в списке и затем выберите Pull , чтобы получить последний образ из удаленного репозитория.
Чтобы просмотреть подробную информацию об образе в Docker Hub, выберите изображение и нажмите Просмотреть в Hub .
Параметр «Просмотр в концентраторе» открывает страницу Docker Hub и отображает подробную информацию об образе, такую как архитектура ОС, размер образа, дата отправки образа и список слоев образа.
Если у вас есть платная подписка на Docker и включена функция сканирования уязвимостей, на странице Docker Hub также отображается сводка отчета о сканировании уязвимостей и подробная информация об обнаруженных уязвимостях.
Изучите тома
Вы можете использовать тома для хранения файлов и обмена ими между контейнерами.Тома создаются и напрямую управляются Docker. Они также являются предпочтительным механизмом для сохранения данных в контейнерах и службах Docker.
Volume Management теперь доступно для всех подписок
Начиная с версии Docker Desktop 4.1.0, управление томами доступно для пользователей по любой подписке, включая Docker Personal. Обновите Docker Desktop до версии 4.1.0, чтобы начать управлять своими томами бесплатно.
Представление Volumes в Docker Dashboard позволяет легко создавать и удалять тома и видеть, какие из них используются.Вы также можете увидеть, какой контейнер использует конкретный том, и изучить файлы и папки в ваших томах.
Управление томами
По умолчанию в представлении Volumes отображается список всех томов. На томах, которые в настоящее время используются контейнером, отображается значок Используется .
Используйте поле Search для поиска любых конкретных томов. Вы также можете сортировать тома по имени, дате создания и размеру тома.
Чтобы изучить подробности определенного тома, выберите том из списка. Это открывает подробный вид.
На вкладке Используется отображается имя контейнера с использованием тома, имя образа, номер порта, используемый контейнером, и цель. Цель — это путь внутри контейнера, который дает доступ к файлам в томе.
На вкладке Data отображаются файлы и папки в томе и их размер. Чтобы сохранить файл или папку, наведите указатель мыши на файл или папку и щелкните меню дополнительных параметров.Выберите Сохранить как , а затем укажите место для загрузки файла.
Чтобы удалить файл или папку с тома, выберите Удалить в меню дополнительных параметров.
Удалить том
При удалении тома удаляется том и все его данные. Чтобы удалить том, наведите на него курсор и нажмите кнопку Удалить . Либо выберите том из списка, а затем нажмите кнопку Удалить .
Docker Dashboard, управление, контейнеры, графический интерфейс, информационная панель, изображения, kitematic
Установка Docker Desktop в Windows
Расчетное время чтения: 9 минут
Обновление условий Docker Desktop
Для профессионального использования Docker Desktop в крупных организациях (более 250 сотрудников или более 10 миллионов долларов дохода) требуется, чтобы у пользователей была платная подписка на Docker.Хотя дата вступления в силу этих условий — 31 августа 2021 года, существует льготный период до 31 января 2022 года для тех, кому требуется платная подписка. Для получения дополнительной информации см. Лицензионное соглашение Docker Desktop.
Добро пожаловать в Docker Desktop для Windows. Эта страница содержит информацию о системных требованиях Docker Desktop для Windows, URL-адрес загрузки, инструкции по установке и обновлению Docker Desktop для Windows.
Скачать Docker Desktop для Windows
Docker Desktop для Windows
Системные требования
Для успешной установки Docker Desktop ваш компьютер с Windows должен соответствовать следующим требованиям.
Серверная часть Hyper-V и контейнеры Windows
64-разрядная версия Windows 10: Pro 2004 (сборка 19041) или выше или Enterprise или Education 1909 (сборка 18363) или выше.
Для Windows 10 Домашняя см. Системные требования для серверной части WSL 2.
- Hyper-V и контейнеры Функции Windows должны быть включены.
Для успешного запуска клиента требуются следующие предварительные требования к оборудованию.
Hyper-V в Windows 10:
Примечание
Docker поддерживает Docker Desktop в Windows только для тех версий Windows 10, которые все еще находятся в рамках графика обслуживания Microsoft.
Контейнеры и образы, созданные с помощью Docker Desktop, используются всеми
учетные записи пользователей на машинах, на которых он установлен. Это потому, что все Windows
учетные записи используют одну и ту же виртуальную машину для создания и запуска контейнеров. Обратите внимание, что при использовании серверной части Docker Desktop WSL 2 невозможно обмениваться контейнерами и образами между учетными записями пользователей.
Вложенные сценарии виртуализации, такие как запуск Docker Desktop на
Экземпляр VMWare или Parallels может работать, но нет никаких гарантий.Для
дополнительные сведения см. в разделе «Запуск Docker Desktop в сценариях вложенной виртуализации».
О контейнерах Windows
Ищете информацию об использовании контейнеров Windows?
Установить рабочий стол Docker в Windows
Дважды щелкните Docker Desktop Installer.exe , чтобы запустить установщик.
Если вы еще не загрузили установщик (
Docker Desktop Installer.exe
), вы можете получить его с
Докер Хаб .Обычно он загружается в папкуЗагрузки
, или вы можете запустить его из
панель недавних загрузок в нижней части вашего веб-браузера.При появлении запроса убедитесь, что Включить компоненты Windows Hyper-V или Установить необходимые компоненты Windows для WSL 2 выбран на странице конфигурации.
Следуйте инструкциям мастера установки, чтобы авторизовать программу установки и продолжить установку.
После успешной установки нажмите Закрыть , чтобы завершить процесс установки.
Если ваша учетная запись администратора отличается от учетной записи пользователя, вы должны добавить пользователя в группу docker-users . Запустите Computer Management от имени администратора и перейдите к Local Users and Groups > Groups > docker-users . Щелкните правой кнопкой мыши, чтобы добавить пользователя в группу.Выйдите из системы и войдите снова, чтобы изменения вступили в силу.
Запустить рабочий стол Docker
Docker Desktop не запускается автоматически после установки. Для запуска Docker Desktop:
Найдите Docker и выберите Docker Desktop в результатах поиска.
Меню Docker () отображает окно Соглашения об обслуживании подписки Docker. Он включает изменение условий использования Docker Desktop.
Вот краткое изложение основных изменений:
- Наше соглашение об обслуживании подписки Docker включает изменение условий использования Docker Desktop
- It остается бесплатным для малого бизнеса (менее 250 сотрудников И менее 10 миллионов долларов дохода), личного использования, образования и некоммерческих проектов с открытым исходным кодом.
- Для профессионального использования на крупных предприятиях требуется платная подписка.
- Дата вступления в силу настоящих условий — 31 августа 2021 г.Существует льготный период до 31 января 2022 года для тех, кому потребуется платная подписка для использования Docker Desktop.
- Существующая подписка Docker Free была переименована в Docker Personal , и мы ввели подписку Docker Business.
- Подписки Docker Pro, Team и Business включают коммерческое использование Docker Desktop.
Установите флажок, чтобы указать, что вы принимаете обновленные условия, а затем нажмите Принять , чтобы продолжить.Docker Desktop запускается после того, как вы примете условия.
Важно
Если вы не согласны с обновленными условиями, приложение Docker Desktop закроется, и вы больше не сможете запускать Docker Desktop на своем компьютере. Вы можете принять условия позже, открыв Docker Desktop.
Для получения дополнительной информации см. Лицензионное соглашение Docker Desktop. Мы рекомендуем вам также прочитать блог и ответы на часто задаваемые вопросы, чтобы узнать, как это может повлиять на компании, использующие Docker Desktop.
Краткое руководство
По завершении инициализации Docker Desktop запускает Quick Start Guide . Это руководство включает в себя простое упражнение по созданию примера образа Docker, запуску его как контейнера, отправке и сохранению образа в Docker Hub.
Чтобы запустить руководство по быстрому запуску по запросу, щелкните правой кнопкой мыши значок Docker в области уведомлений (или на панели задач), чтобы открыть меню рабочего стола Docker, а затем выберите Руководство по быстрому запуску .
Поздравляем! Теперь вы успешно используете Docker Desktop в Windows.
Обновления
Когда доступно обновление, Docker Desktop отображает значок, указывающий на доступность более новой версии.
Начиная с Docker Desktop 4.1.0, раздел Software Updates на вкладке General также уведомляет вас о любых обновлениях, доступных для Docker Desktop. Вы можете сразу загрузить обновление или щелкнуть опцию Release Notes , чтобы узнать, что включено в обновленную версию.Если вы являетесь участником группы Docker или подписки Business, вы можете отключить проверку обновлений, сняв флажок Автоматически проверять наличие обновлений в общих настройках. Это также отключит значок уведомления, который отображается на панели инструментов Docker.
Чтобы побудить разработчиков оставаться в курсе последних событий, Docker Desktop отображает напоминание через две недели после того, как обновление становится доступным. Вы можете закрыть это ежедневное напоминание, нажав Отложить . Вы можете пропустить обновление при появлении напоминания, щелкнув опцию Пропустить это обновление .
Соглашение об обслуживании подписки Docker
Начиная с 31 августа 2021 г., вы должны согласиться с Соглашением об обслуживании подписки Docker, чтобы продолжить использование Docker Desktop. Прочтите блог и ответы на часто задаваемые вопросы о подписке на Docker, чтобы узнать больше об изменениях.
Щелкните Загрузить обновление Когда вы будете готовы загрузить обновление. Это загружает обновление в фоновом режиме. После загрузки обновления нажмите «Обновить » и перезапустите из меню Docker.Это установит последнее обновление и перезапустит Docker Desktop, чтобы изменения вступили в силу.
При запуске Docker Desktop отображается окно Соглашения об обслуживании подписки Docker. Прочтите информацию, представленную на экране, чтобы понять, как изменения повлияют на вас. Установите флажок, чтобы указать, что вы принимаете обновленные условия, а затем нажмите Принять , чтобы продолжить.
Важно
Если вы не согласны с условиями, приложение Docker Desktop закроется, и вы больше не сможете запускать Docker Desktop на своем компьютере.Вы можете принять условия позже, открыв Docker Desktop.
Docker Desktop запускается после того, как вы примете условия.
Удалить Docker Desktop
Чтобы удалить Docker Desktop с компьютера Windows:
- В меню Windows Пуск выберите Настройки > Приложения > Приложения и функции .
- Выберите Docker Desktop из списка Приложения и функции , а затем выберите Удалить .
- Щелкните Удалить , чтобы подтвердить свой выбор.
Важно
При удалении Docker Desktop уничтожаются контейнеры, образы, тома и тома Docker.
другие данные, связанные с Docker, локальные для машины, и удаляет созданные файлы
по приложению. Обратитесь к резервному копированию и восстановлению данных
раздел, чтобы узнать, как сохранить важные данные перед удалением.
Куда пойти дальше
- Начало работы знакомит с Docker Desktop для Windows.
- Начало работы с Docker — это руководство, которое научит вас, как
развернуть мультисервисный стек. - Устранение неполадок описывает общие проблемы, обходные пути и
как получить поддержку. - дают ответы на часто задаваемые вопросы.
- перечислены обновления компонентов, новые функции и улучшения, связанные с выпусками Docker Desktop.
- Резервное копирование и восстановление данных содержит инструкции по резервному копированию и восстановлению данных, связанных с Docker.
Часто задаваемые вопросы
В примечаниях к выпуску
windows, установить, загрузить, запустить, докер, локально
Установить Docker Desktop на Mac
Расчетное время чтения: 7 минут
Добро пожаловать в Docker Desktop для Mac. Эта страница содержит информацию о системных требованиях Docker Desktop для Mac, URL-адреса для загрузки, инструкции по установке и обновлению Docker Desktop для Mac.
Загрузить Docker Desktop для Mac
Mac с чипом Intel
Mac с чипом Apple
Системные требования
Ваш Mac должен соответствовать следующим требованиям для успешной установки Docker Desktop.
Mac с чипом Intel
macOS должна иметь версию 10.14 или новее . То есть Мохаве, Каталина или Биг-Сур. Мы рекомендуем обновить macOS до последней версии.
Если у вас возникли проблемы после обновления macOS до версии 10.15, необходимо установить последнюю версию Docker Desktop, чтобы она была совместима с этой версией macOS.
Примечание
Docker поддерживает Docker Desktop в самых последних версиях macOS.То есть текущий выпуск macOS и два предыдущих выпуска. Поскольку новые основные версии macOS становятся общедоступными, Docker перестает поддерживать самую старую версию и поддерживает новейшую версию macOS (в дополнение к двум предыдущим выпускам). Docker Desktop в настоящее время поддерживает macOS Mojave, macOS Catalina и macOS Big Sur.
Не менее 4 ГБ ОЗУ.
VirtualBox до версии 4.3.30 нельзя устанавливать, так как он несовместим с Docker Desktop.
Установите и запустите Docker Desktop на Mac
Дважды щелкните
Docker.dmg
, чтобы открыть программу установки, затем перетащите значок Docker в
папку «Приложения».Дважды щелкните
Docker.app
в папке «Приложения», чтобы запустить Docker. В приведенном ниже примере папка Applications находится в режиме просмотра «сетки».Меню Docker () отображает окно Соглашения об обслуживании подписки Docker. Он включает изменение условий использования Docker Desktop.
Вот краткое изложение основных изменений:
- Наше соглашение об обслуживании подписки Docker включает изменение условий использования Docker Desktop
- It остается бесплатным для малого бизнеса (менее 250 сотрудников И менее 10 миллионов долларов дохода), личного использования, образования и некоммерческих проектов с открытым исходным кодом.
- Для профессионального использования на крупных предприятиях требуется платная подписка.
- Дата вступления в силу этих условий — 31 августа 2021 г. Существует льготный период до 31 января 2022 г. для тех, кому потребуется платная подписка для использования Docker Desktop.
- Существующая подписка Docker Free была переименована в Docker Personal , и мы ввели подписку Docker Business.
- Подписки Docker Pro, Team и Business включают коммерческое использование Docker Desktop.
Установите флажок, чтобы указать, что вы принимаете обновленные условия, а затем нажмите Принять , чтобы продолжить. Docker Desktop запускается после того, как вы примете условия.
Важно
Если вы не согласны с условиями, приложение Docker Desktop закроется, и вы больше не сможете запускать Docker Desktop на своем компьютере. Вы можете принять условия позже, открыв Docker Desktop.
Для получения дополнительной информации см. Лицензионное соглашение Docker Desktop. Мы рекомендуем вам также прочитать блог и ответы на часто задаваемые вопросы, чтобы узнать, как это может повлиять на компании, использующие Docker Desktop.
Краткое руководство
Если вы только что установили приложение, Docker Desktop запустит краткое руководство. В учебное пособие входит простое упражнение по созданию примера образа Docker, запуску его как контейнера, отправке и сохранению образа в Docker Hub.
Поздравляем! Теперь вы успешно используете Docker Desktop.Щелкните меню Docker (), чтобы увидеть
Настройки и другие параметры. Чтобы запустить Руководство по быстрому запуску по запросу, выберите меню Docker, а затем выберите Краткое руководство .
Обновления
Когда доступно обновление, Docker Desktop отображает значок, указывающий на доступность более новой версии.
Начиная с Docker Desktop 4.1.0, раздел Software Updates на вкладке General также уведомляет вас о любых обновлениях, доступных для Docker Desktop.Вы можете сразу загрузить обновление или щелкнуть опцию Release Notes , чтобы узнать, что включено в обновленную версию. Если вы являетесь участником группы Docker или подписки Business, вы можете отключить проверку обновлений, сняв флажок Автоматически проверять наличие обновлений в общих настройках. Это также отключит значок уведомления, который отображается на панели инструментов Docker.
Чтобы побудить разработчиков оставаться в курсе последних событий, Docker Desktop отображает напоминание через две недели после того, как обновление становится доступным.Вы можете закрыть это ежедневное напоминание, нажав Отложить . Вы можете пропустить обновление при появлении напоминания, щелкнув опцию Пропустить это обновление .
Соглашение об обслуживании подписки Docker
Начиная с 31 августа 2021 г., вы должны согласиться с Соглашением об обслуживании подписки Docker, чтобы продолжить использование Docker Desktop. Прочтите блог и ответы на часто задаваемые вопросы о подписке на Docker, чтобы узнать больше об изменениях.
Щелкните Загрузить обновление Когда вы будете готовы загрузить обновление.Это загружает обновление в фоновом режиме. После загрузки обновления нажмите «Обновить » и перезапустите из меню Docker. Это установит последнее обновление и перезапустит Docker Desktop, чтобы изменения вступили в силу.
При запуске Docker Desktop отображается окно Соглашения об обслуживании подписки Docker. Прочтите информацию, представленную на экране, чтобы понять, как изменения повлияют на вас. Установите флажок, чтобы указать, что вы принимаете обновленные условия, а затем нажмите Принять , чтобы продолжить.
Важно
Если вы не согласны с условиями, приложение Docker Desktop закроется, и вы больше не сможете запускать Docker Desktop на своем компьютере. Вы можете принять условия позже, открыв Docker Desktop.
Docker Desktop запускается после того, как вы примете условия.
Удалить Docker Desktop
Для удаления Docker Desktop с Mac:
- В меню Docker выберите Устранение неполадок , а затем выберите Удалить .
- Щелкните Удалить , чтобы подтвердить свой выбор.
Примечание
При удалении Docker Desktop уничтожаются контейнеры, образы, тома и тома Docker.
другие данные, связанные с Docker, локальные для машины, и удаляет созданные файлы
по приложению. Обратитесь к резервному копированию и восстановлению данных
раздел, чтобы узнать, как сохранить важные данные перед удалением.
Куда пойти дальше
- «Приступая к работе» содержит обзор Docker Desktop на Mac, основные примеры команд Docker, способы получения справки или обратной связи, а также ссылки на другие темы о Docker Desktop на Mac.
- Docker Desktop для микросхемы Apple для получения подробной информации о микросхеме Docker Desktop для Apple.
- Устранение неполадок описывает общие проблемы, обходные пути, как
для запуска и отправки диагностики, а также для отправки проблем. - дают ответы на часто задаваемые вопросы.
- перечислены обновления компонентов, новые функции и улучшения, связанные с выпусками Docker Desktop.
- «Начало работы с Docker» содержит общее руководство по Docker.
- Резервное копирование и восстановление данных содержит инструкции
по резервному копированию и восстановлению данных, связанных с Docker.
Часто задаваемые вопросы
В примечаниях к выпуску
mac, установить, скачать, запустить, докер, локальный
Установить Docker Engine | Документация Docker
Расчетное время чтения: 6 минут
Поддерживаемые платформы
Docker Engine доступен на различных платформах Linux,
macOS и Windows 10
через Docker Desktop и как статическую двоичную установку. Находить
предпочитаемая вами операционная система ниже.
Настольный
Сервер
Docker предоставляет пакеты .deb
и .rpm
из следующих дистрибутивов Linux
и архитектур:
Другие дистрибутивы Linux
Примечание
Хотя приведенные ниже инструкции могут работать, Docker не тестирует и не проверяет
установка на производные.
- Пользователи производных Debian, таких как «BunsenLabs Linux», «Kali Linux» или
«LMDE» (Mint на основе Debian) должен следовать инструкциям по установке для
Debian, заменив версию своего дистрибутива на
соответствующий выпуск Debian.Обратитесь к документации вашего дистрибутива, чтобы найти
какой выпуск Debian соответствует вашей производной версии. - Аналогичным образом, пользователи производных Ubuntu, таких как «Kubuntu», «Lubuntu» или «Xubuntu»
следует следовать инструкциям по установке для Ubuntu,
заменяя версию своего дистрибутива на соответствующий выпуск Ubuntu.
Обратитесь к документации вашего дистрибутива, чтобы узнать, какой выпуск Ubuntu
соответствует вашей производной версии. - Некоторые дистрибутивы Linux предоставляют пакет Docker Engine через свои
репозитории пакетов.Эти пакеты создаются и поддерживаются Linux.
разработчиками пакета дистрибутива и могут иметь отличия в конфигурации
или построены из модифицированного исходного кода. Docker не участвует в выпуске этих
пакеты и ошибки или проблемы, связанные с этими пакетами, следует сообщать в
трекер проблем вашего дистрибутива Linux.
Docker предоставляет двоичные файлы для ручной установки Docker Engine.
Эти двоичные файлы статически связаны и могут использоваться в любом дистрибутиве Linux.
Каналы выпуска
Docker Engine имеет три типа каналов обновления: стабильный , тестовый ,
и в ночное время :
- Канал Stable предоставляет вам последние версии для общедоступной информации.
- Канал Test предоставляет предварительные версии, готовые к тестированию перед
общедоступность (GA). - Канал Nightly дает вам последние сборки незавершенной работы для
следующий крупный выпуск.
стабильный
Годовые релизы создаются из ветки релиза, отличной от основной.
ветвь. Ветка создается в формате <год>. <Месяц>
, например
20,10
. Название года и месяца указывает на самый ранний из возможных календарей.
месяц, чтобы ожидать, что релиз станет общедоступным.Все дальнейшие патчи
выпуски выполняются из этой ветки. Например, если v20.10.0
будет
выпущен, все последующие выпуски исправлений построены из ветки 20.10
.
Тест
При подготовке к выпуску нового года-месяца создается ветка из
главная ветвь в формате YY.mm
, когда вехи желательны
Докеры для этого релиза достигли полной функциональности. Предварительные релизы
такие как бета-версии и кандидаты на выпуск, проводятся из соответствующего выпуска
ветви.Выполняются выпуски исправлений и соответствующие предварительные выпуски
из соответствующей ветки выпуска.
Ночью
ночных сборок дают вам последние сборки, которые незавершаются для следующего крупного
выпускать. Они создаются один раз в день из основной ветки с версией
формат:
0.0.0-ГГГГммддЧЧММСС-abcdefabcdef
, где время — это время фиксации в формате UTC, а последний суффикс — это префикс.
хеша фиксации, например 0.0.0-20180720214833-f61e0f7
.
Эти сборки позволяют проводить тестирование из последнего кода в основной ветке. Нет
для ночных сборок делаются оговорки или гарантии.
Поддержка
Релизы
Docker Engine годовой ветки поддерживаются исправлениями в виде
требуется в течение одного месяца после выпуска общедоступной версии на следующий год.
Это означает, что оцениваются отчеты об ошибках и резервные копии для веток выпуска.
до даты окончания срока службы.
После того, как годовой филиал достигнет конца срока службы, филиал может быть
удален из репозитория.
Бэкпорт
Backports к продуктам Docker отдает приоритет компании Docker. А
Сотрудник Docker или сопровождающий репозитория приложат все усилия, чтобы
исправления включены в активных релизов .
Если есть важные исправления, которые следует рассмотреть для резервного копирования на
ветки активных релизов, обязательно выделите это в PR-описании
или добавив комментарий в PR.
Путь обновления
Релизы патча
всегда обратно совместимы с его версией по годам и месяцам.
Лицензирование
Docker находится под лицензией Apache License версии 2.0. Видеть
ЛИЦЕНЗИЯ на полную
текст лицензии.
Сообщение о проблемах безопасности
Сопровождающие Docker серьезно относятся к безопасности. Если вы обнаружите безопасность
вопрос, пожалуйста, сразу же обратите на это их внимание!
Пожалуйста, НЕ подавайте публичные вопросы; вместо этого отправьте свой отчет в частном порядке
по адресу security@docker.