[Перевод] Полное практическое руководство по Docker: с нуля до кластера на AWS
Содержание
- Вопросы и ответы
- Введение
- Пре-реквизиты
- Настройка компьютера
- 1.0 Играем с Busybox
- 1.1 Docker Run
- 1.2 Терминология
- 2.0 Веб-приложения и Докер
- 2.1 Статические сайты
- 2.2 Образы
- 2.3 Наш первый образ
- 2.4 Dockerfile
- 2.5 Docker на AWS
- 3.0 Многоконтейнерные окружения
- 3.1 SF Food Trucks
- 3.2 Сети Docker
- 3.3 Docker Compose
- 3.4 AWS Elastic Container Service
- 4.0 Заключение
- 4.1 Следующие шаги
- 4.2 Фидбек автору
Вопросы и ответы
Что такое Докер?
Определение Докера в Википедии звучит так:
программное обеспечение для автоматизации развёртывания и управления приложениями в среде виртуализации на уровне операционной системы; позволяет «упаковать» приложение со всем его окружением и зависимостями в контейнер, а также предоставляет среду по управлению контейнерами.
Ого! Как много информации. Простыми словами, Докер это инструмент, который позволяет разработчикам, системными администраторам и другим специалистам деплоить их приложения в песочнице (которые называются контейнерами), для запуска на целевой операционной системе, например, 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. Спасибо!
Пре-реквизиты
Все, что нужно для прохождения этого пособия это базовые навыки с командной строкой и текстовым редактором. Опыт разработки веб-приложений будет полезен, но не обязателен. В течение работы мы столкнемся с несколькими облачными сервисами. Вам понадобится создать аккаунт на этих сайтах:
- Amazon Web Services
- Docker Hub
Настройка компьютера
Установка и настройка всех необходимых инструментов может быть тяжелой задачей, но, к счастью, Докер стал довольно стабильным, и установка и запуск его на любой ОС стало очень простой задачей. Итак, установим Докер.
Докер
Еще несколько релизов назад запуск Докера на 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
command fetches the busybox image from the Docker registry and saves it to our system. You can use the docker images
command to see a list of all images on your system.
$ 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-приложения выглядит следующим образ