Это девятнадцатая часть серии мега-учебника Flask, в которой я собираюсь развернуть Microblog на контейнерной платформе Docker.
Оглавление
Глава 19: Развертывание на контейнерах Docker (Эта статья)
В главе 17 вы узнали о традиционных развертываниях, при которых вам приходится заботиться о каждом незначительном аспекте конфигурации сервера. Затем в главе 18 я впал в другую крайность, когда познакомил вас с Heroku, сервисом, который берет на себя полный контроль над задачами настройки и развертывания, позволяя вам полностью сконцентрироваться на вашем приложении. В этой главе вы узнаете о третьей стратегии развертывания приложений, основанной на контейнерах, более конкретно на контейнерной платформе Docker. Этот третий вариант находится где-то посередине между двумя другими с точки зрения объема работ по развертыванию, необходимых с вашей стороны.
Контейнеры построены на облегченной технологии виртуализации, которая позволяет приложению вместе с его зависимостями и конфигурацией работать в полной изоляции, но без необходимости использовать полномасштабное решение для виртуализации, такое как виртуальные машины, которым требуется намного больше ресурсов и которые иногда могут иметь значительное снижение производительности по сравнению с хостом. Система, настроенная как хост-контейнер, может запускать множество контейнеров, все они используют ядро хоста и прямой доступ к оборудованию хоста. Это главное отличие от виртуальных машин, которые должны эмулировать всю систему, включая процессор, диск, другое оборудование, ядро и т.д.
Несмотря на необходимость совместного использования ядра, уровень изоляции в контейнере довольно высок. Контейнер имеет свою собственную файловую систему и может быть основан на операционной системе, отличной от той, которая используется хостом контейнера. Например, вы можете запускать контейнеры на основе Ubuntu Linux на хосте Fedora или наоборот. Хотя контейнеры - это технология, присущая операционной системе Linux, благодаря виртуализации также возможно запускать контейнеры Linux на хостах Windows и macOS. Это позволяет вам протестировать ваши развертывания в вашей системе разработки, а также включить контейнеры в рабочий процесс разработки, если вы того пожелаете.
Ссылки на GitHub для этой главы: Browse, Zip, Diff.
Установка Docker
Хотя Docker - не единственная контейнерная платформа, она, безусловно, самая популярная, так что это будет мой выбор.
Для работы с Docker вам сначала необходимо установить его в своей системе. На веб-сайте Docker доступны установщики для Windows, macOS и нескольких дистрибутивов Linux. Безусловно, самый простой способ настроить Docker на вашем компьютере - это использовать программу установки Docker Desktop для вашей операционной системы. Если вы работаете в системе Microsoft Windows, важно отметить, что для Docker требуется Hyper-V. При необходимости программа установки включит это для вас, но имейте в виду, что включение Hyper-V может помешать работе других технологий виртуализации, таких как VirtualBox.
После установки Docker Desktop в вашей системе вы можете убедиться, что установка прошла успешно, введя следующую команду в окне терминала или командной строке:
$ docker version
Client: Docker Engine - Community
Version: 23.0.5
API version: 1.42
Go version: go1.19.8
Git commit: bc4487a
Built: Wed Apr 26 16:17:14 2023
OS/Arch: darwin/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 23.0.5
API version: 1.42 (minimum version 1.12)
Go version: go1.19.8
Git commit: 94d3ad6
Built: Wed Apr 26 16:17:14 2023
OS/Arch: darwin/amd64
Experimental: false
containerd:
Version: 1.6.20
GitCommit: 2806fc1057397dbaeefbea0e4e17bddfbd388f38
runc:
Version: 1.1.5
GitCommit: v1.1.5-0-gf19387a
docker-init:
Version: 0.19.0
GitCommit: de40ad0
Создание образа контейнера
Первым шагом в создании контейнера для Microblog является создание для него образа. Образ контейнера - это шаблон, который используется для создания контейнера. Он содержит полное представление файловой системы контейнера, наряду с различными настройками, относящимися к сети, параметрам запуска и т.д.
Самый простой способ создать образ контейнера для вашего приложения - это запустить контейнер для базовой операционной системы, которую вы хотите использовать (Ubuntu, Fedora и т.д.), подключиться к запущенному в нем процессу оболочки bash, а затем вручную установить ваше приложение, возможно, следуя рекомендациям, которые я представил в главе 17 для традиционного развертывания. После того, как вы все установите, вы можете сделать снимок контейнера, который станет образом. Этот тип рабочего процесса поддерживается командой docker
, но я не собираюсь его обсуждать, потому что неудобно устанавливать приложение вручную каждый раз, когда вам нужно сгенерировать новый образ.
Лучшим подходом является создание образа контейнера с помощью скрипта. Команда, которая создает образы контейнеров по сценарию, является docker build
. Эта команда считывает и выполняет инструкции по сборке из файла с именем Dockerfile, который мне нужно будет создать. Dockerfile - это, по сути, установочный скрипт, который выполняет шаги установки для развертывания приложения, а также некоторые настройки, относящиеся к конкретному контейнеру.
Вот базовый файл Dockerfile для Microblog:
Dockerfile: Dockerfile для микроблога.
FROM python:slim
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
RUN pip install gunicorn
COPY app app
COPY migrations migrations
COPY microblog.py config.py boot.sh ./
RUN chmod a+x boot.sh
ENV FLASK_APP microblog.py
RUN flask translate compile
EXPOSE 5000
ENTRYPOINT ["./boot.sh"]
Каждая строка в Dockerfile является командой. Команда FROM
указывает базовый образ контейнера, на основе которого будет создан новый образ. Идея заключается в том, что вы начинаете с существующего снимка, добавляете или изменяете некоторые элементы и в итоге получаете производный снимок. Ссылки на снимки имеют название и тег, разделенные двоеточием. Тег используется как механизм управления версиями, позволяющий образу контейнера предоставлять более одного варианта. Имя выбранного мной образа - python
, который является официальным образом Docker для Python. Теги для этого образа позволяют указать версию интерпретатора и базовую операционную систему. Тег slim
выбирает образ контейнера, содержащий только минимальные пакеты, необходимые для запуска интерпретатора Python. Вы можете посмотреть, какие еще теги доступны для Python в репозитории снимков Python.
В зависимости от того, когда вы работаете над своим файлом Dockerfile, вы можете обнаружить, что некоторым пакетам не удается установить последнюю версию Python, используемую тегом slim
, это происходит потому, что когда Python выпускает новую версию, многим пакетам требуется некоторое время, чтобы выпустить для нее двоичные версии пакетов. Если вы заметили проблемы при создании образа контейнера, вы можете попробовать использовать более старую версию Python, что можно сделать, добавив желаемую версию в качестве префикса в теге. Например, тег 3.11-slim
устанавливает Python 3.11.
Команда COPY
переносит файлы с вашего компьютера в файловую систему контейнера. Эта команда принимает два или более аргументов, исходный и конечный файлы или каталоги. Исходный файл (ы) должен располагаться относительно каталога, в котором находится Dockerfile. Местом назначения может быть абсолютный путь или путь относительно текущего каталога, который по умолчанию является корневым в файловой системе контейнера. В этой первой команде COPY
я копирую файл requirements.txt в корневой каталог файловой системы контейнера.
Теперь, когда у меня есть файл requirements.txt в контейнере, я могу установить в нем все требования. Поскольку файл требований содержит только общие зависимости, я затем явно устанавливаю gunicorn
, который я собираюсь использовать в качестве веб-сервера. В качестве альтернативы я мог бы добавить пакет в свой файл requirements.txt.
Три следующие команды COPY
устанавливают приложение в контейнер путем копирования пакета приложения, каталога миграций с миграциями базы данных и файлы microblog.py и config.py из каталога верхнего уровня. Я также копирую новый файл, boot.sh, который я рассмотрю ниже.
Команда RUN chmod
гарантирует, что этот новый файл boot.sh правильно установлен в качестве исполняемого файла. Если вы используете файловую систему на базе Unix и ваш исходный файл уже помечен как исполняемый, то для скопированного файла также будет установлен бит executable . Я решил явно установить исполняемый бит, чтобы приложение могло работать в Microsoft Windows, в которой нет понятия исполняемых битов. Если вы работаете на macOS или Linux, вам, вероятно, не нужна эта инструкция, но в любом случае иметь ее не помешает.
Команда ENV
устанавливает переменную среды внутри контейнера. Мне нужно установить FLASK_APP
, которая требуется для использования команды flask
.
Следующая инструкция RUN
компилирует переводы. Это подкоманда flask
, поэтому мне пришлось сначала установить FLASK_APP
в среде, иначе команда не смогла бы найти экземпляр приложения и мои пользовательские подкоманды.
Команда EXPOSE
настраивает порт, который этот контейнер будет использовать для своего сервера. Это необходимо для того, чтобы Docker мог соответствующим образом настроить сеть в контейнере. Я выбрал стандартный порт Flask 5000, но это может быть любой порт.
Наконец, оператор ENTRYPOINT
определяет команду по умолчанию, которая должна выполняться при запуске контейнера с этим изображением. Это команда, которая запустит веб-сервер приложений. Чтобы все было хорошо организовано, я решил создать для этого отдельный скрипт, и это файл boot.sh, который я скопировал в контейнер ранее. Вот содержимое этого скрипта:
boot.sh: Сценарий запуска контейнера Docker.
#!/bin/bash
flask db upgrade
exec gunicorn -b :5000 --access-logfile - --error-logfile - microblog:app
Это довольно стандартный сценарий запуска, который аналогичен тому, как запускались развертывания в главе 17 и главе 18. Я обновляю базу данных с помощью платформы миграции и запускаю сервер с помощью Gunicorn.
Обратите внимание на exec
, который предшествует команде Gunicorn. В сценарии оболочки exec
запускает процесс, выполняющий сценарий (в данном случае интерпретатор bash
), который заменяется заданной командой, вместо запуска команды как подпроцесса. Это важно, потому что Docker связывает срок службы контейнера с первым процессом, который в нем выполняется. В случаях, подобных этому, когда процесс запуска не является основным процессом контейнера, вам необходимо убедиться, что основной процесс заменяет этот первый процесс, чтобы гарантировать, что контейнер не будет досрочно завершен Docker.
Если вы создаете файл boot.sh в Windows, убедитесь, что вы выбрали окончания строк UNIX в своем текстовом редакторе. Поскольку этот файл будет выполняться внутри контейнера под управлением Linux, он должен иметь правильные окончания строк для этой операционной системы.
Интересным аспектом Docker является то, что все, что контейнер записывает в stdout
или stderr
, будет перехвачено и сохранено в виде журналов для контейнера. По этой причине --access-logfile
и --error-logfile
оба настроены с помощью -
, который отправляет журнал в стандартный вывод, чтобы Docker сохранял их в виде журналов.
Теперь, когда файл Dockerfile создан, я могу создать образ контейнера:
$ docker build -t microblog:latest .
Аргумент -t
, который я даю команде docker build
, задает имя и тег для нового образа контейнера. .
указывает базовый каталог, в котором должен быть создан контейнер. Это каталог, в котором находится Dockerfile. В процессе сборки будут выполнены все команды в Dockerfile и создан образ, который будет сохранен на вашем собственном компьютере.
Вы можете получить список снимков, которые у вас есть локально, с помощью команды docker images
:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
python slim d7971c18b18e 7 months ago 132MB
microblog latest 03978d7e1007 27 seconds ago 259MB
Этот список будет включать ваш новый образ, а также базовый образ, на основе которого он был создан. Каждый раз, когда вы вносите изменения в приложение, вы можете обновить образ контейнера, снова запустив команду сборки.
Запуск контейнера
Теперь, когда образ уже создан, вы можете запустить контейнерную версию приложения. Это делается с помощью команды 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
является идентификатор, присвоенный новому контейнеру. Это длинная шестнадцатеричная строка, которую вы можете использовать всякий раз, когда вам нужно обратиться к контейнеру в последующих командах. Фактически, необходимы только первые несколько символов, которых достаточно, чтобы сделать идентификатор уникальным.
Если вы хотите посмотреть список запущенных контейнеров, то можно использовать команду 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
и передать или идентификатор контейнера или имя, которое было дано ему с параметром --name
:
$ docker stop microblog
microblog
Если вы помните, в конфигурации приложения есть ряд параметров, которые берутся из переменных среды. Например, секретный ключ Flask, URL базы данных и параметры сервера электронной почты импортируются из переменных среды. В представленной выше команде docker run
: я не беспокоился об этом, поэтому все эти параметры конфигурации будут использоваться по умолчанию.
В более реалистичном примере вы будете устанавливать эти переменные среды внутри контейнера. В предыдущем разделе вы видели, что команда ENV
в файле Dockerfile устанавливает переменные среды, и это удобная опция для переменных, которые должны быть статическими. Однако для переменных, которые зависят от установки, неудобно использовать их как часть процесса сборки, потому что вы хотите иметь достаточно переносимый образ контейнера. Если вы хотите передать свое приложение другому пользователю в виде образа контейнера, вы бы хотели, чтобы этот пользователь мог использовать его как есть, и ему не нужно было перестраивать его с помощью разных переменных.
Итак, переменные среды во время сборки могут быть полезны, но также необходимы переменные среды во время выполнения, которые можно задать с помощью команды docker run
, и для этих переменных можно использовать опцию -e
. В следующем примере устанавливается секретный ключ и отправка электронных писем через учетную запись 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, когда вы остановите и удалите контейнер? Файл исчезнет!
Файловая система в контейнере эфемерна, что означает, что она исчезает, когда контейнер исчезает. Вы можете записывать данные в файловую систему, и данные будут там, если контейнеру потребуется их прочитать, но если по какой-либо причине вам потребуется переработать ваш контейнер и заменить его новым, любые данные, сохраненные приложением на диске, будут потеряны навсегда.
Хорошая стратегия проектирования контейнерного приложения заключается в том, чтобы сделать контейнеры приложений без состояния. Если у вас есть контейнер, в котором есть код приложения и нет данных, вы можете выбросить его и заменить новым без каких-либо проблем. При таком использовании контейнер становится действительно одноразовым, что здорово с точки зрения упрощения развертывания обновлений.
Но, конечно, это означает, что данные должны быть размещены где-то за пределами контейнера приложения. Именно здесь вступает в игру фантастическая экосистема Docker. Реестр контейнеров Docker содержит большое разнообразие образов контейнеров. Я уже рассказывал вам об образе контейнера Python, который я использую в качестве базового образа для своего контейнера Microblog. В дополнение к этому, Docker поддерживает образы для многих других языков, баз данных и других сервисов в реестре Docker, а если этого недостаточно, реестр также позволяет компаниям публиковать изображения контейнеров для своих продуктов, а обычным пользователям, таким как вы или я, публиковать свои собственные изображения. Это означает, что усилия по установке сторонних сервисов сводятся к поиску соответствующего образа в реестре и запуску его с помощью команды docker run
с надлежащими аргументами.
Итак, что я собираюсь сделать сейчас, так это создать два дополнительных контейнера, один для базы данных MySQL, а другой для службы Elasticsearch, а затем я собираюсь сделать команду, которая запускает контейнер Microblog, еще с большим числом параметров, которые позволят ему взаимодействовать с этими двумя новыми контейнерами.
Добавление контейнера MySQL
В этом разделе я собираюсь запустить контейнер MySQL, а затем подключить его к контейнеру Microblog. Рекомендуемый способ запуска коллекции связанных контейнеров - создать для них сеть. Сеть Docker - это виртуальная конструкция, которая позволяет всем добавленным в нее контейнерам видеть друг друга. Создайте новую сеть Docker с помощью следующей команды:
$ docker network create microblog-network
Как и у многих других продуктов и сервисов, у MySQL есть общедоступные образы контейнеров, доступные в реестре Docker. Как и в моем собственном контейнере для микроблогов, MySQL полагается на переменные среды, которые необходимо передавать команде docker run
. Они настраивают пароли, имена баз данных и т.д. Хотя в реестре много образов MySQL, я решил использовать тот, который официально поддерживается командой MySQL. Подробную информацию об образе контейнера MySQL вы можете найти на его странице реестра: https://hub.docker.com/r/mysql/mysql-server/.
Если вы помните трудоемкий процесс настройки MySQL, описанный в Главе 17, вы оцените Docker по достоинству, когда увидите, насколько он прост в сравнении. Вот команда 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> \
--network microblog-network \
mysql:latest
Вот и все! На любом компьютере, на котором у вас установлен Docker, вы можете запустить приведенную выше команду, и вы получите полностью установленный сервер MySQL с случайно сгенерированным паролем root, совершенно новую базу данных под названием microblog
и пользователь с таким же именем, у которого настроены полные права доступа к базе данных. Обратите внимание, что вам нужно будет ввести правильный пароль в качестве значения для переменной окружения MYSQL_PASSWORD
.
Опция --network
указывает Docker поставить контейнер MySQL в сеть, созданную выше.
Теперь на стороне приложения мне нужно использовать клиентский пакет MySQL, как я делал для традиционного развертывания в Ubuntu. Я собираюсь использовать pymysql
еще раз, который я могу добавить в Dockerfile вместе с пакетом cryptography
, который он использует для аутентификации на сервере MySQL:
Dockerfile: Добавляем pymysql и cryptography в Dockerfile.
# ...
RUN pip install gunicorn pymysql cryptography
# ...
Каждый раз, когда вносятся изменения в приложение или Dockerfile, образ контейнера необходимо перестроить:
$ docker build -t microblog:latest .
Теперь я могу снова запустить микроблог, но на этот раз со ссылкой на контейнер базы данных, чтобы оба могли взаимодействовать по сети:
$ 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> \
--network microblog-network \
-e DATABASE_URL=mysql+pymysql://microblog:<database-password>@mysql/microblog \
microblog:latest
Параметр --network
указывает Docker включить этот контейнер в ту же сеть, что и контейнер MySQL, приведенный выше. Контейнеры, находящиеся в сети, могут ссылаться друг на друга, используя свои имена в качестве имен хостов. По этой причине параметр DATABASE_URL
использует mysql
в качестве имени хоста базы данных, поскольку это имя я дал контейнеру MySQL. Убедитесь, что вы ввели правильный пароль базы данных, который вы выбрали для контейнера MySQL в приведенной выше команде.
Одна вещь, которую я заметил, экспериментируя с контейнером MySQL, заключается в том, что контейнеру MySQL требуется несколько секунд, чтобы полностью запуститься и быть готовым принимать подключения к базе данных. Если вы запустите контейнер MySQL, а затем сразу после этого запустите контейнер приложения, то когда скрипт boot.sh попытается запуститься flask db upgrade
может произойти сбой из-за того, что база данных не готова принимать подключения. Чтобы сделать мое решение более надежным, я решил добавить цикл повторных попыток в boot.sh:
boot.sh: Повторение попытки подключения к базе данных.
#!/bin/bash
while true; do
flask db upgrade
if [[ "$?" == "0" ]]; then
break
fi
echo Upgrade command failed, retrying in 5 secs...
sleep 5
done
exec gunicorn -b :5000 --access-logfile - --error-logfile - microblog:app
Этот цикл проверяет код завершения команды flask db upgrade
, и если он ненулевой, предполагается, что что-то пошло не так, поэтому он ждет пять секунд, а затем повторяет попытку.
Добавление контейнера Elasticsearch
В документации Elasticsearch для Docker показано, как запустить службу как с одним узлом для разработки, так и с двухузловым развертыванием, готовым к производству. На данный момент я собираюсь использовать вариант с одним узлом, без шифрования или паролей. Контейнер запускается следующей командой:
$ docker run --name elasticsearch -d --rm -p 9200:9200 \
-e discovery.type=single-node -e xpack.security.enabled=false \
--network microblog-network \
-t docker.elastic.co/elasticsearch/elasticsearch:8.11.1
Итак, теперь, когда у меня запущена служба 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> \
--network microblog-network \
-e DATABASE_URL=mysql+pymysql://microblog:<database-password>@mysql/microblog \
-e ELASTICSEARCH_URL=http://elasticsearch:9200 \
microblog:latest
Перед запуском этой команды не забудьте остановить предыдущий контейнер микроблогов, если он у вас все еще запущен. Также будьте осторожны при установке правильных паролей в соответствующих местах команды.
Теперь вы должны иметь возможность посетить http://localhost:8000 и воспользоваться функцией поиска. Если у вас возникли какие-либо ошибки, вы можете устранить их, просмотрев журналы контейнеров. Скорее всего, вы захотите просмотреть журналы для контейнера Microblog, где будут отображаться любые трассировки стека Python:
$ docker logs microblog
Реестр контейнеров Docker
Итак, теперь у меня есть полное приложение, запущенное в Docker, с использованием трех контейнеров, два из которых взяты из общедоступных образов сторонних производителей. Если вы хотите сделать образы ваших собственных контейнеров доступными для других, вам нужно отправить их в реестр Docker, откуда любой может получить снимки.
Чтобы получить доступ к реестру Docker, вам нужно перейти на страницу https://hub.docker.com и создать учетную запись для себя. Убедитесь, что вы выбрали имя пользователя, которое вам нравится, потому что оно будет использоваться во всех публикуемых вами изображениях.
Чтобы получить доступ к своей учетной записи из командной строки, вам необходимо войти в систему с помощью команды docker login
:
$ docker login
Если вы следовали моим инструкциям, теперь у вас есть образ с именем microblog:latest
, хранящийся локально на вашем компьютере. Чтобы иметь возможность поместить этот образ в реестр Docker, его необходимо переименовать, чтобы включить учетную запись, которой он принадлежит. Это делается с помощью команды 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 с балансировкой нагрузки, масштабированием, безопасным управлением секретами, постоянными обновлениями и откатами.