Пролог
Я много и часто пишу про self-hosted сервисы и про то, как я их поднимаю. Понятно, что их пpиходится ещё как-то обслуживать. Я уже когда-то писал, какие программы я использую именно при работе с сервисами. С тех пор практически ничего не поменялось: я, по-прежнему, чаще всего использую командную строку. И вот почему.
Стек Docker Compose и Docker Compose UI
Все мои сервисы реализованы в виде стеков Docker Compose - настраиваются при помощи docker-compose.yml
, запускаются, останавливаются и обновляются при помощи CLI docker-compose
. Из всех просмотренных мною программ, предоставляющих web интерфейс, самым близким к идеальному решению мне показался Docker Compose UI. Она (программа) мне нравится, но есть некоторые особенности, которые мешают мне полноценно её использовать.
На самом деле, этой особенностью является организация её рабочего окружения - Docker Compose UI
требует, чтобы все docker-compose.yml
файлы находились каждый в своей подпапке, которые, в свою очередь, находились бы в одной родительской папке. Именно эта папка и настраивается в качестве основной для Docker Compose UI
- начиная с неё осуществляется просмотр дерева каталогов в поисках docker-compose.yml
. И программа, ожидаемо, может работать только с теми, которые нашла.
Эта концепция взаимодействия с файлами конфигурации docker-compose.yml
привела, в конечном итоге, к тому, что я оставил все эти файлы в каталогах пользователей, под которыми запускаются соответствующие сервисы, а в основном каталоге Docker Compose UI
(это каталог на моей виртуалке, примонтированный к контейнеру Docker Compose UI
) создал на них "жёсткие" ссылки (hard links
). Почему "жёсткие"? "Мягкие" (soft links
) ссылки почему-то игнорировались сканером Docker Compose UI
.
В конечном итоге, Docker Compose UI
отображает список работающих сервисов, может управлять ими, отображать их состояние и журналы. Но если попытаться внести изменения в файл конфигурации, создаётся файл-дубликат, и, в результате, содержимое исходного файла в каталоге пользователя и файла в основном каталоге Docker Compose UI
начинают различаться по содержимому. Именно это стало причиной того, что я не использую Docker Compose UI
так часто, как мог (и как хотелось бы).
Portainer
Ещё одна программа, которую я использую, но тоже не в полную силу, это Portainer. Он замечательно работает с отдельными контейнерами, и не только (например, с образами), но не может полноценно работать со стеками Docker Compose. То есть, он их определяет, отображает запущенные контейнеры, но не может работать со стеком, как единым целым. Ещё он не позволяет просматривать содержимое соответствующих файлов docker-compose.yml
, что уж говорить про их редактирование. Правда, у него есть возможность создавать свои стеки, с которыми он взаимодействует не в пример лучше - по крайней мере, должен.
Совсем недавно я поднимал сервис мониторинга за обновлениями Docker
образов. Этот сервис основан на программе Watchtower, и, по своей реализации, весь сервис - это контейнер, запущенный из Docker образа. Но так как даже такие сервисы (основанные на единственном контейнере) я поднимаю при помощи Docker Compose, то первым делом надо было определить его конфигурацию - создать файл docker-compose.yml
. И тут, совершенно случайно, я вспомнил про Portainer
, после чего решил немного сменить стратегию. Как? Сейчас объясню.
Я уже выше писал, что Portainer
не очень хорош при работе с "оригинальными" стеками контейнеров Docker Compose, но в нём есть возможность создавать собственные стеки контейнеров и полноценно управлять ими. И, что самое важное, формат описания стеков Portainer
совпадает с форматом YML
файлов Docker Compose версии 2
. То есть, можно создать обычный файл docker-compose.yml
, только храниться он будет в Portainer
.
Собственно, я решил попробовать использовать эту функциональность Portainer
для запуска контейнера Watchtower
. Итак, начнём.
Работа со стеками в Portainer
Для начала, воспользуемся кнопкой создания стека:
Советую, также, обратить внимание на обведённую колонку Control
- Portainer
честно предупреждает, что контроль над этими стеками у него ограничен, а стеки эти - мои сервисы, которые я поднимаю при помощи Docker Compose
.
После нажатия на кнопку создания стека на экране появляется окно, в котором и происходят все основные действия по конфигурированию стека Portainer
.
Собственно, конфигурирование ничего сложного из себя не представляет, особенно, если вы знакомы с правилами написания YAML
файлов для Docker Compose
. Всё, что вам потребуется, это:
- указать имя сервиса
- при помощи текстового редактора записать содержимое
compose
файла (учитывая, что в настоящее время можно использовать возможности, соответствующие версии2
) - нажать кнопку
Deploy the stack
Справедливости ради надо отметить, что есть возможность также указывать значения для переменных окружения, импортировать compose
файл из репозитория Git
или просто из локальной папки вашего компьютера. Кроме того, можно настроить права для управления создаваемым стеком.
После создания стека Portainer
сразу видна разница между стеками последнего и Docker Compose
:
Если же копнуть чуть глубже, то разница станет ещё более очевидной:
Как видно из последнего рисунка, со стеком Docker Compose
нельзя сделать вообще ничего, просто просмотреть информацию, а вот со стеком Portainer
можно выполнять различные операции, как-то:
- Редактировать конфигурацию (на закладке
Editor
) - Останавливать или удалять стек целиком, или же создавать из него шаблон, который можно будет использовать при создании новых стеков
- Дублировать или переносить стек на другой хост
Что интересно, Portainer
, "под капотом", так сказать, поступает точно так же как и Docker Compose UI
- для стеков, описанных в нём, он создаёт структуру подкаталогов, и в каждом таком подкаталоге размещает файл docker-compose.yml
. А в этих файлах - то самое описание сервиса, которое вводилось в текстовом редакторе при создании стека.
Эпилог
Наверное, это не всё, что можно провернуть при работе со стеками Portainer
, но я пока только учусь, и не готов рассказывать о том, чего не знаю. На текущий момент я даже не совсем понимаю, как будет происходить обновление стека - какая альтернатива команде docker-compose pull
? Наверное, обновлять надо образы (есть такая возможность), а пересоздавать контейнеры - остановкой и повторным запуском стека. Тут, кстати, помочь может установленный недавно Watchtower - он выкачивает образы, требующие обновления, а перезапуск должен использовать эти новые версии образов для пересоздания контейнеров. Посмотрим, так ли это всё будет...
Вот, и всё, что могу пока сообщить. По мере того, как будет накапливаться опыт - а я надеюсь на это - буду дополнять рассказ о стеках новыми подробностями. Такие дела...
P.S.
Пока готовил эту статью, пару раз успел обновиться docker образ containrrr/watchtower, который я использую для отслеживания обновлений, и мне удалось проверить свою теорию - речь про то, что Watchtower выкачает новый образ и останется просто остановить и заново запустить стек. Рад сообщить, что теория полностью подтвердилась 😀👍👌