(издание 2018)


Miguel Grinberg




Туда Сюда


Это девятнадцатая часть серии мега-учебника Flask, в которой я собираюсь развернуть Microblog на платформе Docker.


Под спойлером приведен список всех статей этой серии 2018 года.



Примечание 1: Если вы ищете старые версии данного курса, это здесь.


Примечание 2: Если вдруг Вы захотели бы выступить в поддержку моей(Мигеля) работы, или просто не имеете терпения дожидаться статьи неделю, я (Мигель Гринберг)предлагаю полную версию данного руководства(на английском языке) в виде электронной книги или видео. Для получения более подробной информации посетите learn.miguelgrinberg.com.


В главе 17 Вы узнали о традиционных развертывании, в котором следует заботиться о каждом маленьком аспекте конфигурации сервера. После чего в главе 18 я привел вас к другой крайности, когда познакомил Вас с Heroku, сервисом, который полностью контролирует задачи настройки и развертывания. В этой главе пришло время узнать о стратегии развертывания сторонних приложений на основе контейнеров, в частности на платформе контейнеров Docker. Этот третий вариант — "золотая середина", между двумя другими.


Контейнеры построены на основе упрощенной технологии виртуализации, которая позволяет приложению вместе с его зависимостями и конфигурацией работать в полной изоляции, но без необходимости использования полнофункционального решения виртуализации, такого как виртуальные машины, которые нуждаются в значительно большем объеме ресурсов и могут иногда иметь значительное снижение производительности по сравнению с хостом. Система, настроенная в качестве узла контейнера, может выполнять множество контейнеров, все из которых делят ядро хоста и имеют прямой доступ к оборудованию хоста. Это в отличие от виртуальных машин, которые должны эмулировать полную систему, включая процессор, диск, другое оборудование, ядро и т.д.


Несмотря на то, что мы не разделяем ядро, уровень изоляции в контейнере довольно высок. Контейнер имеет свою собственную файловую систему и может основываться на операционной системе, отличной от той, которая используется узлом контейнера. Например, можно запускать контейнеры на основе Ubuntu Linux на узле Fedora или наоборот. Не смотря на то, что контейнеры являются технологией, которая является родной для операционной системы Linux, благодаря виртуализации можно запускать Linux контейнеры на Windows и Mac OS X хостах. Это позволяет тестировать развертывания в системе разработки, а также включать контейнеры в рабочий процесс разработки, если только оно вам надо.


Ссылки GitHub для этой главы: Browse, Zip, Diff.


Установка Docker CE


Хотя Docker не единственная контейнерная Платформа, она на сегодняшний день является самой популярной, так что это будет мой выбор. Существует два выпуска Docker, выпуск Free community edition (CE) и выпуск Enterprise edition (EE) на основе подписки. Для целей этого учебника Docker CE вполне адекватен.


Чтобы работать с Docker CE, вам сначала нужно установить его в свою систему. Есть инсталляторы для Windows, Mac OS X и нескольких дистрибутивов Linux, доступных на веб-сайте Docker. Если вы работаете в системе Microsoft Windows, важно отметить, что Docker CE требует Hyper-V. Установщик включит это для вас, если это необходимо, но имейте в виду, что включение Hyper-V предотвращает работу других технологий виртуализации, таких как VirtualBox.


После установки Docker CE в системе проверить успешность установки можно, введя следующую команду в окне терминала или командной строке:


$ docker version
Client:
 Version:      17.09.0-ce
 API version:  1.32
 Go version:   go1.8.3
 Git commit:   afdb6d4
 Built:        Tue Sep 26 22:40:09 2017
 OS/Arch:      darwin/amd64

Server:
 Version:      17.09.0-ce
 API version:  1.32 (minimum version 1.12)
 Go version:   go1.8.3
 Git commit:   afdb6d4
 Built:        Tue Sep 26 22:45:38 2017
 OS/Arch:      linux/amd64
 Experimental: true

Построение образа контейнера


Первым шагом в создании контейнера для микроблога является создание для него образа. Образ контейнера — это шаблон, который используется для создания контейнера. Он содержит полное представление файловой системы контейнера, а также различные настройки, относящиеся к сети, запуск вариантов и т.д.


Самый простой способ создать образ контейнера для приложения-запустить контейнер для базовой операционной системы, которую вы хотите использовать (Ubuntu, Fedora и т. д.).), подключитесь к запущенному в нем процессу оболочки bash, а затем вручную установите приложение, возможно, следуя рекомендациям, которые я представил в главе 17 для традиционного развертывания. После установки всего можно сделать снимок контейнера, который станет образом. Этот тип рабочего процесса поддерживается командой docker, но я не собираюсь обсуждать его, потому что не удобно вручную устанавливать приложение каждый раз, когда вам нужно создать новый образ.


Лучшим подходом является создание образа контейнера с помощью сценария. Команда, создающая образы контейнеров со сценариями, — это docker build. Эта команда считывает и выполняет инструкции сборки из файла Dockerfile, который мне ещё предстоит создать. Dockerfile-это фактически сценарий установки, который выполняет шаги установки для развертывания приложения, а также некоторые параметры контейнера.


Вот базовый Dockerfile для Микроблога:


Dockerfile: Dockerfile for Microblog.

FROM python:3.6-alpine

RUN adduser -D microblog

WORKDIR /home/microblog

COPY requirements.txt requirements.txt
RUN python -m venv venv
RUN venv/bin/pip install -r requirements.txt
RUN venv/bin/pip install gunicorn

COPY app app
COPY migrations migrations
COPY microblog.py config.py boot.sh ./
RUN chmod +x boot.sh

ENV FLASK_APP microblog.py

RUN chown -R microblog:microblog ./
USER microblog

EXPOSE 5000
ENTRYPOINT ["./boot.sh"]

Каждая строка в Dockerfile является командой. Команда FROM указывает базовый образ контейнера, на основе которого будет построен новый образ. Идея состоит в том, что вы начинаете с существующего образа, добавляете или изменяете некоторые особенности, и в конечном итоге получаете производный образ. На образ ссылаются именем и тегом, разделенными двоеточием. Тег используется в качестве механизма управления версиями, позволяя образу контейнера предоставлять несколько вариантов. Имя выбранного образа-python, который является официальным образом Docker для Python. Теги для этого образа позволяют указать версию интерпретатора и базовую операционную систему. Тег 3.6-alpine выбирает интерпретатор Python 3.6, установленный в Alpine Linux. Дистрибутив Alpine Linux часто используется вместо более популярных, таких как Ubuntu из-за его небольшого размера. Вы можете увидеть, какие теги доступны для образа Python в Python image repository.


Команда RUN выполняет произвольную команду в контексте контейнера. Это похоже на ввод команды в командной строке оболочки. Команда adduser-D microblog создает нового пользователя с именем microblog. Большинство образов контейнеров имеют root в качестве пользователя по умолчанию, однако не рекомендуется запускать приложение от имени root, поэтому я создаю собственного пользователя.


Команда WORKDIR задает каталог по умолчанию, в котором будет установлено приложение. Когда я создал пользователя microblog выше, был создан домашний каталог, поэтому теперь я делаю этот каталог по умолчанию. Новый каталог по умолчанию будет применяться ко всем оставшимся командам в Dockerfile, а также позже при выполнении контейнера.


Команда COPY передает файлы с компьютера в файловую систему контейнера. Эта команда принимает два или более аргументов, исходный и конечный файлы или каталоги. Исходный файл(ы) должен быть относительно каталога, в котором находится Dockerfile. Назначение может быть абсолютным путем или путем относительно каталога, заданного в предыдущей команде WORKDIR. В этой первой команде копирования я копирую файл requirements.txt в домашний каталог пользователя microblog в файловой системе контейнера.


Теперь у меня есть файл requirements.txt в контейнере и я могу создать виртуальную среду, используя команду RUN. Сначала я создаю его, а затем устанавливаю все требования. Поскольку файл требований содержит только общие зависимости, я затем явно устанавливаю gunicorn, который я собираюсь использовать в качестве веб-сервера. В качестве альтернативы, я мог бы добавить gunicorn к моим файлам в requirements.txt.


Три команды COPY, которые следуют за установкой приложения в контейнер, копируя пакет app, каталог migrations с миграциями базы данных и скрипты microblog.py и config.py из каталога верхнего уровня. Кроме того, я копирую новый файл boot.sh, о котором я расскажу ниже.


Команда RUN chmod гарантирует, что этот неизвестный доселе файл boot.sh установлен правильно, как исполняемый файл. Если вы находитесь в файловой системе на основе Unix, и ваш исходный файл уже имеет признак исполняемого файла, то в скопированном файле также будет установлен исполняемый бит. Я добавил явную установку, потому что в Windows сложнее присвоить исполняемые биты. Если вы работаете в Mac OS X или Linux, вероятно это все не нужно, но не помешает в любом случае.


Команда ENV задает переменную среды внутри контейнера. Мне нужно установить FLASK_APP, который необходим для использования команды flask.


Следующая команда RUN chown задает владельца всех каталогов и файлов, которые были сохранены в /home/microblog, как нового пользователя microblog. Несмотря на то, что я создал этого пользователя в корне Dockerfile, Пользователь по умолчанию для всех команд остался root, поэтому все эти файлы должны быть переключены на пользователя microblog, чтобы этот пользователь мог работать с ними при запуске контейнера.


Команда USER в следующей строке делает этого нового пользователя microblog по умолчанию для любых последующих инструкций, а также при запуске контейнера.


Команда EXPOSE настраивает порт для своего сервера. Это необходимо, чтобы Docker мог нужным образом настроить Сеть в контейнере. Я выбрал стандартный порт 5000, но это может быть любой порт.


Наконец, команда ENTRYPOINT определяет умолчание, для команды которая должна выполняться при запуске контейнера. Это команда, которая запустит веб-сервер приложений. Чтобы все было хорошо организовано, я решил создать для этого отдельный скрипт, и это boot.sh файл, который я скопировал в контейнер ранее. Вот содержимое этого скрипта:


boot.sh: Docker container start-up script.

#!/bin/sh
source venv/bin/activate
flask db upgrade
flask translate compile
exec gunicorn -b :5000 --access-logfile - --error-logfile - microblog:app

Это довольно стандартный сценарий запуска, который довольно похож на то, как были запущены развертывания в главе 17 и главе 18. Я активирую виртуальную среду, Обновляю базу данных через платформу миграции, компилирую переводы языков и, наконец, запускаю сервер с gunicorn.


Обратите внимание на exec, который предшествует команде gunicorn. В сценарии оболочки exec запускает процесс, выполняющий сценарий, который должен быть заменен заданной командой, вместо того, чтобы запускать его как новый процесс. Это важно, потому что Docker связывает жизнь контейнера с первым процессом, который выполняется на нем. В случаях, подобных этому, когда процесс запуска не является основным процессом контейнера, необходимо убедиться, что основной процесс занимает место этого первого процесса, чтобы убедиться, что контейнер не завершается рано Docker.


Интересным аспектом Docker является то, что все выводимые данные контейнера, которые пишутся в stdout или stderr, будут захвачены и сохранены как журналы контейнера. По этой причине ключи --access-logfile и --error-logfile имеют в конце символ -, который направляет журнал в стандартный вывод и хранит в виде журнала Docker.


С помощью созданного Dockerfile теперь можно создать образ контейнера:


$ docker build -t microblog:latest .

Аргумент -t, передаваемый команде docker build, задает имя и тег для нового образа контейнера. . указывает базовый каталог, в котором должен быть создан контейнер. Это каталог, в котором находится файл Docker. Процесс сборки будет оценивать все команды в файле Docker и создавать образ, который будет храниться на вашей собственной машине.


Вы можете получить список образов, которые вы локально используете с помощью команды docker images:


$ docker images
REPOSITORY    TAG          IMAGE ID        CREATED              SIZE
microblog     latest       54a47d0c27cf    About a minute ago   216MB
python        3.6-alpine   a6beab4fa70b    3 months ago         88.7MB

Этот список включает ваш новый образ, а также базовый, на котором он был построен. При внесении изменений в приложение можно обновить образ контейнера, выполнив команду build еще раз.


Запуск контейнера


С уже созданным образом теперь можно запустить версию контейнера приложения. Это делается с помощью команды docker run, которая обычно принимает большое количество аргументов. Для начала я покажу вам простой пример:


$ docker run --name microblog -d -p 8000:5000 --rm microblog:latest
021da2e1e0d390320248abf97dfbbe7b27c70fefed113d5a41bb67a68522e91c

Параметр --name предоставляет имя для нового контейнера. Параметр -d указывает Docker запускать контейнер в фоновом режиме. Без ключа -d контейнер выполняется как приложение переднего плана, блокируя командную строку. Параметр -p сопоставляет порты контейнера с портами хоста. Первый порт-это порт на хост-компьютере, а порт справа-это порт внутри контейнера. Приведенный выше пример предоставляет порт 5000 в контейнере на порту 8000 в узле, таким образом, вы будете обращаться к приложению на 8000, даже при том, что внутренне контейнер использует 5000. Параметр --rm удаляет контейнер после его завершения. Хотя это не требуется, контейнеры, которые заканчиваются или прерываются, обычно больше не нужны, поэтому их можно автоматически удалить. Последним аргументом является имя образа контейнера и тег, используемый для контейнера. После выполнения приведенной выше команды, вы можете получить доступ к приложению на http://localhost:8000.


Результатом docker run является идентификатор (ID), назначенный новому контейнеру. Это длинная шестнадцатеричная строка, которую вы можете использовать, когда вам нужно ссылаться на контейнер в последующих командах. Фактически, только первые несколько символов необходимы, чтобы сделать идентификатор уникальным.


Если вы хотите увидеть, какие контейнеры запущены, вы можете использовать команду docker ps:


$ docker ps
CONTAINER ID  IMAGE             COMMAND      PORTS                   NAMES
021da2e1e0d3  microblog:latest  "./boot.sh"  0.0.0.0:8000->5000/tcp  microblog

Как видите, даже команда docker ps сокращает идентификаторы контейнеров. Если теперь необходимо остановить контейнер, используйте docker stop:


$ docker stop 021da2e1e0d3
021da2e1e0d3

Напомню вам что, в конфигурации приложения есть несколько параметров, которые получены из переменных среды. Например, параметры секретного ключа Flask, URL базы данных и сервера электронной почты импортируются из переменных среды. В примере docker run выше я не беспокоился о них, поэтому все эти параметры конфигурации будут использовать значения по умолчанию.


В более реалистичном примере эти переменные среды будут устанавливаться внутри контейнера. Вы видели в предыдущем разделе, что установку переменных среды в Dockerfile выполняет команда ENV, и это удобная опция для переменных, которые будут статическими. Тем не менее, для переменных, зависящих от установки, не представляется возможным использовать их как часть процесса сборки, потому что хотелось бы иметь образ контейнера, который легко переносить. Если вы хотите передать свое приложение другому пользователю в качестве образа контейнера, вы хотите, чтобы этот человек мог использовать его как есть, а не перестраивать его с помощью других переменных.


Таким образом, переменные среды build-time могут быть полезны, но также необходимо иметь переменные среды run-time, которые можно задать с помощью команды docker run, и для этих переменных используется ключ -e. Следующий пример задает secret-key и электронную почту для аккаунта Gmail:


$ docker run --name microblog -d -p 8000:5000 --rm -e SECRET_KEY=my-secret-key     -e MAIL_SERVER=smtp.googlemail.com -e MAIL_PORT=587 -e MAIL_USE_TLS=true     -e MAIL_USERNAME=<your-gmail-username> -e MAIL_PASSWORD=<your-gmail-password>     microblog:latest

Такая длина для docker run в командной строке не редкость из-за наличия множества определений переменных среды.


Использование сторонних «Контейнерных» сервисов


Контейнерная версия Microblog выглядит неплохо, но я пока еще не очень много думал о хранении. Проблема в том, что я не задал переменную среды DATABASE_URL, и приложение использует базу данных SQLite по умолчанию, которая поддерживается файлом на диске. Как вы думаете, что произойдет с этим SQLite-файлом, когда вы остановите и удалите контейнер? Файл исчезнет!


Файловая система в контейнере является эфемерной, то есть она исчезает вместе с остановкой контейнера. Вы можете записывать данные в файловую систему, и данные будут доступны, если контейнер должен ее прочитать, но если по какой-либо причине вам нужно переработать контейнер и заменить его новым, любые данные, сохраненные приложением на диск будет потеряны навсегда.


Хорошей стратегией проектирования для приложения-контейнера является создание контейнеров приложения не зависящих от состояния (stateless). Если у вас есть контейнер, который имеет код приложения и не имеет данных, вы можете выбросить его и заменить новым без каких-либо проблем, контейнер становится действительно одноразовым, что является большим достижением с точки зрения упрощения развертывания обновлений.


Но, конечно, это означает, что данные должны быть помещены где-то за пределами контейнера приложения. Именно здесь вступает в игру фантастическая экосистема Docker. Реестр контейнеров Docker содержит большое разнообразие образов контейнеров. Я уже рассказал вам об образе контейнера Python, который я использую в качестве базового образа для своего контейнера Микроблога. Кроме того, Docker поддерживает образы для многих других языков, баз данных и других служб в реестре Docker, и если этого недостаточно, реестр также позволяет компаниям публиковать образы контейнеров для своих продуктов, а также обычным пользователям, таким как вы или я, публиковать свои собственные образы. Это означает, что усилия по установке сторонних служб сводятся к поиску соответствующего образа в реестре и запуску его с помощью команды docker run с соответствующими аргументами.


Итак, теперь я создам два дополнительных контейнера: один для базы данных MySQL и еще один для службы Elasticsearch, а затем я выполню длиннющую командную строку, которая запустит контейнер Microblog с кучей параметров, которые разрешат мне доступ к этим двум новым контейнерам.


Добавление контейнера MySQL


Как и многие другие продукты и услуги, MySQL имеет общедоступные образы контейнеров, доступные в реестре Docker. Как и мой собственный контейнер Микроблог, MySQL полагается на переменные среды, которые должны быть переданы в docker run. Это настройки типа пароля, имени базы данных и т.д. Не смотря на то, что есть много образов MySQL в реестре, я решил использовать тот, который официально поддерживается командой MySQL. Вы можете найти подробную информацию об образе контейнера MySQL на его странице реестра: https://hub.docker.com/r/mysql/mysql-server/.


Если вы помните трудоемкий процесс настройки MySQL в главе 17, то вы оцените Docker, увидев, как легко развернуть MySQL. Вот команда docker run, которая запускает сервер MySQL:


$ docker run --name mysql -d -e MYSQL_RANDOM_ROOT_PASSWORD=yes     -e MYSQL_DATABASE=microblog -e MYSQL_USER=microblog     -e MYSQL_PASSWORD=<database-password>     mysql/mysql-server:5.7

Вот и все! На любой машине, на которой установлен Docker, вы можете выполнить приведенную выше команду и получить полностью установленный сервер MySQL со случайно сгенерированным паролем root, совершенно новую базу данных под названием microblog и пользователя с тем же именем и настройками полного доступа к базе данных. Обратите внимание, что вам нужно будет ввести правильный пароль в качестве значения для переменной среды MYSQL_PASSWORD.


Теперь на стороне приложения, как и для традиционного развертывания на Ubuntu, мне нужно добавить клиентский пакет MySQL. Я снова буду использовать pymysql, который я могу добавить в Dockerfile:


Dockerfile: Add pymysql to Dockerfile.

# ...
RUN venv/bin/pip install gunicorn pymysql
# ...

При каждом изменении приложения или файла Dockerfile образ контейнера необходимо перестроить:


$ docker build -t microblog:latest .

Теперь я могу снова запустить Microblog, но на этот раз со ссылкой на контейнер базы данных, чтобы обе могли общаться через сеть:


$ docker run --name microblog -d -p 8000:5000 --rm -e SECRET_KEY=my-secret-key     -e MAIL_SERVER=smtp.googlemail.com -e MAIL_PORT=587 -e MAIL_USE_TLS=true     -e MAIL_USERNAME=<your-gmail-username> -e MAIL_PASSWORD=<your-gmail-password>     --link mysql:dbserver     -e DATABASE_URL=mysql+pymysql://microblog:<database-password>@dbserver/microblog     microblog:latest

Параметр --link указывает Docker сделать еще один контейнер доступным. Аргумент содержит два имени, разделенных двоеточием. Первая часть-это имя или идентификатор контейнера для связи, в данном случае mysql, который я создал выше. Вторая часть определяет имя хоста, которое может использоваться в этом контейнере для ссылок (link-ов). Здесь я использую dbserver в качестве универсального имени, которое представляет сервер баз данных.


Когда связь между двумя контейнерами установлена, я могу установить переменную окружения DATABASE_URL, для направления SQLAlchemy на использование базы данных MySQL в другом контейнере. URL-адрес базы данных будет использовать dbserver-в качестве имени хоста базы данных, microblog-как имена базы данных и пользователя, и пароль-который вы выбрали при запуске MySQL.


Я заметил одну особенность, когда экспериментировал с контейнером MySQL, которая заключается в том, что запуск этого контейнера занимает несколько секунд до готовности принять соединения с базой данных. Если вы запустите подряд контейнер MySQL и контейнер приложения сразу после попытки скрипта boot.sh запустить flask db migrate может произойти сбой из-за того, что база данных не готова принимать подключения. Чтобы сделать мое решение более надежным, я решил добавить цикл повтора в boot.sh:


boot.sh: Повтор попыток подключения к базе данных.

#!/bin/sh
source venv/bin/activate
while true; do
    flask db upgrade
    if [[ "$?" == "0" ]]; then
        break
    fi
    echo Upgrade command failed, retrying in 5 secs...
    sleep 5
done
flask translate compile
exec gunicorn -b :5000 --access-logfile - --error-logfile - microblog:app

Этот цикл проверки кода выхода команды flask db upgrade, и если он не равен нулю, значит, что что-то пошло не так, поэтому он делает паузу пять секунд, а затем повторяет попытку.


Добавление контейнера Elasticsearch


В документации Elasticsearch для Docker представлен вариант запуска службы единым узлом для разработки и развертывания, готовый к работе с двумя узлами (two-node). Сейчас я собираюсь запустить docker с опцией single-node и использовать образ "oss", который имеет только движок с открытым исходным кодом. Контейнер запускается следующей командой:


$ docker run --name elasticsearch -d -p 9200:9200 -p 9300:9300 --rm     -e "discovery.type=single-node"     docker.elastic.co/elasticsearch/elasticsearch-oss:6.1.1

Эта команда docker run имеет много общего с теми, которые я использовал для Microblog и MySQL, но есть несколько интересных различий. Во-первых, здесь два варианта -p, а это означает, что этот контейнер будет прослушивать два порта вместо одного. Оба порта 9200 и 9300 сопоставляются с теми же портами на хост-компьютере.


Следующее различие заключается в синтаксисе ссылки на образ контейнера. Для образов, которые я создавал локально, синтаксис был <name>:<tag>. Контейнер MySQL использует несколько более полный синтаксис с форматом <account>/<name>:<tag>, который подходит для ссылки на образы контейнеров в реестре Docker. Образ Elasticsearch, который я использую, соответствует шаблону <registry>/<account><name>:<tag>, который включает ещё и адрес реестра в качестве первого компонента. Этот синтаксис используется для образов, не размещенных в реестре Docker. В этом случае Elasticsearch запускает собственную службу реестра контейнеров в docker.elastic.co вместо использования основного реестра, поддерживаемого Docker.


Теперь, когда у меня работает служба Elasticsearch, я могу изменить команду запуска для моего контейнера Microblog, чтобы создать ссылку на неё и установить URL службы Elasticsearch:


$ docker run --name microblog -d -p 8000:5000 --rm -e SECRET_KEY=my-secret-key     -e MAIL_SERVER=smtp.googlemail.com -e MAIL_PORT=587 -e MAIL_USE_TLS=true     -e MAIL_USERNAME=<your-gmail-username> -e MAIL_PASSWORD=<your-gmail-password>     --link mysql:dbserver     -e DATABASE_URL=mysql+pymysql://microblog:<database-password>@dbserver/microblog     --link elasticsearch:elasticsearch     -e ELASTICSEARCH_URL=http://elasticsearch:9200     microblog:latest

Перед выполнением этой команды не забудьте остановить предыдущий контейнер Микроблога, если он все еще запущен. И, пожалуйста, будьте внимательны при настройке правильных паролей для базы данных и службы Elasticsearch в соответствующих местах команды.


Теперь у вас должна появиться возможность посетить http://localhost:8000 и использовать функцию поиска. При возникновении ошибок их можно устранить, просмотрев журналы контейнеров. Скорее всего, вы захотите увидеть журналы для контейнера микроблога, где будут отображаться любые трассировки стека Python:


$ docker logs microblog

Реестр контейнеров Docker


Итак, теперь у меня есть полное приложение, работающее на Docker, используя три контейнера, два из которых общедоступные сторонние образы. Если вы хотите сделать свои собственные образы контейнеров доступными для других пользователей, то вы должны отправить их в реестр Docker, откуда любой может их заполучить.


Чтобы получить доступ к реестру Docker, перейдите по ссылке https://hub.docker.com и создайте учетную запись для себя. Убедитесь, что вы выбираете имя пользователя, которое вам нравится, потому что это будет использоваться во всех образах, которые вы публикуете.


Для доступа к учетной записи из командной строки необходимо войти в систему с помощью команды docker login:


$ docker login

Если вы следовали моим инструкциям, теперь у вас есть образ под названием microblog:latest, хранящийся локально на вашем компьютере. Чтобы быть в состоянии добавить этот образ к реестру Docker, он должен быть переименован, чтобы использовать учетную запись, как образ от MySQL. Это делается с помощью команды docker tag:


$ docker tag microblog:latest <your-docker-registry-account>/microblog:latest

Если вы снова заглянете в реестр образов с помощью docker images, вы не найдете там две нужные записи для Микроблога, исходную с именем microblog:latest и новую, которая также включает имя Вашей учетной записи. Это два псевдонима для одного и того же образа.


Чтобы опубликовать образ в реестре Docker, используйте команду docker push:


$ docker push <your-docker-registry-account>/microblog:latest

Теперь ваш образ является общедоступным, и вам следует добавить документацию, как его установить и запустить из реестра Docker так же, как это делают MySQL и другие.


Развертывание контейнерных приложений


Одна из лучших особенностей работы приложения в контейнерах Docker заключается в том, что после локального тестирования контейнеров их можно перенести на любую платформу, предлагающую поддержку Docker. Например, вы можете использовать те же серверы, которые я рекомендовал в главе 17 из Digital Ocean, Linode или Amazon Lightsail. Даже самое дешевое предложение от этих поставщиков достаточно для запуска Docker с несколькими контейнерами.


Amazon Container Service (ECS) позволяет создать кластер узлов контейнеров, на которых будут работать контейнеры, в полностью интегрированной среде AWS с поддержкой масштабирования и балансировки нагрузки, а также использовать частный реестр контейнеров для образов контейнеров.


Наконец, платформа для комбинирования контейнеров, такая как Kubernetes, обеспечивает еще больший уровень автоматизации и удобства, позволяя вам описывать развертывания нескольких контейнеров в простых текстовых файлах в формате YAML с балансировкой нагрузки, масштабированием, управлением безопасности и последовательными обновлениями с возможностью отката в исходное состояние.


Туда Сюда

Комментарии (0)