Docker Compose виявився про керованість, а не про моду
Перевів Uptime Kuma і Portainer з ручного docker run у docker compose, зафіксував exact image tags і прибрав залежність від shell history як головного джерела правди.
Docker Compose виявився про керованість, а не про моду
На ранніх етапах docker run здається абсолютно достатнім. І це правда: він чудово підходить, щоб швидко перевірити ідею або просто підняти контейнер.
Але в якийсь момент контейнер перестає бути "тимчасовим експериментом" і стає частиною інфраструктури. І от саме в цей момент уже хочеться не просто запускати сервіс, а керувати ним спокійно і передбачувано.
На моєму сервері цей перехід стався з Uptime Kuma і Portainer.
Як я зрозумів, що сервіс ще не під compose
Перша перевірка була дуже прикладна. Я дивився не на відчуття, а на Docker metadata:
docker inspect portainer --format 'image={{.Config.Image}}'
docker inspect portainer --format 'compose_dir={{ index .Config.Labels "com.docker.compose.project.working_dir" }}'
docker inspect portainer --format 'project={{ index .Config.Labels "com.docker.compose.project" }}'
docker inspect portainer --format '{{range .Mounts}}{{.Type}} {{.Name}} -> {{.Destination}}{{println}}{{end}}'
docker inspect portainer --format 'restart={{.HostConfig.RestartPolicy.Name}}'
docker port portainerКлючовий сигнал був простий:
compose_dir=порожнійproject=порожній
Це означало, що контейнер запущений не через docker compose.
Саме така перевірка мені дуже сподобалась, бо вона прибирає здогадки. Не треба згадувати, "наче я колись ось так його запускав". Docker сам каже правду про свій стан.
Uptime Kuma: переведення на compose
Після оновлення я оформив Uptime Kuma як окремий stack:
- compose directory:
/home/ubuntu/docker/uptime-kuma - image:
louislam/uptime-kuma:2.2.1 - локальний bind:
127.0.0.1:3001 - volume:
uptime-kuma
Послідовність команд виглядала так:
docker stop uptime-kuma
docker rm uptime-kuma
cd /home/ubuntu/docker/uptime-kuma
docker compose up -d
docker compose ps
docker inspect uptime-kuma --format '{{ index .Config.Labels "com.docker.compose.project.working_dir" }}'
docker ps --filter name=uptime-kuma
curl -I http://127.0.0.1:3001
curl -I https://kuma.bombaworkflows.comПісля цього я вже бачив очікувану картину:
- контейнер має compose labels
compose_dirвказує на реальну робочу директорію- локальний порт працює
- публічний домен працює через
nginx
Portainer: той самий принцип, але з важливим нюансом
Portainer спочатку теж працював, але був піднятий як ручний контейнер. Переведення відбувалося за тим самим підходом:
docker ps --filter name=portainer
docker inspect portainer --format '{{ index .Config.Labels "com.docker.compose.project.working_dir" }}'
docker stop portainer
docker rm portainer
cd /home/ubuntu/docker/portainer
docker compose up -d
docker compose ps
docker inspect portainer --format '{{ index .Config.Labels "com.docker.compose.project.working_dir" }}'
curl -k -I https://127.0.0.1:9443
curl -I https://portainer.bombaworkflows.comСхема після переведення стала такою:
- compose directory:
/home/ubuntu/docker/portainer - image:
portainer/portainer-ce:2.40.0 - bind:
127.0.0.1:9443 - volume:
portainer_data
Чому я зафіксував exact version, а не залишив sts
Тут був дуже показовий урок.
Спочатку контейнер ішов на:
portainer/portainer-ce:stsПісля переведення на compose браузер почав позначати сайт як небезпечний. У той же час базові технічні перевірки виглядали нормально:
curl -Iвіддавав200- HTML сторінка грузилась
- TLS сертифікат по домену був валідний
- Portainer в логах стартував без критичних помилок
Реальне виправлення прийшло не з боку compose, а з боку exact image tag. Після того як я замінив:
image: portainer/portainer-ce:2.40.0проблема зникла.
Це дуже хороший operational урок:
docker composeне дорівнює "оновив до останнього і все буде добре"- спосіб керування сервісом і конкретний build образу - це різні речі
- плаваючі теги дають сюрпризи саме тоді, коли їх найменше хочеться
Що дає docker compose у повсякденній роботі
Після цього переходу знання про сервіси перестали жити в shell history і нарешті почали жити в конфігурації. А це вже зовсім інша якість порядку.
Тепер є:
- зрозуміла директорія під кожен сервіс
- файл
docker-compose.yml - точний image tag
- передбачуваний restart flow
- простий upgrade path
- простий rollback path
І найважливіше: якщо завтра треба буде відтворити сервіс на іншому сервері, для цього вже не доведеться відновлювати події по пам'яті.
Як я перевіряю, що compose-схема справді працює
Мінімальний набір команд, який тепер дає мені спокій:
docker compose ps
docker inspect uptime-kuma --format '{{.Config.Image}}'
docker inspect portainer --format '{{.Config.Image}}'
docker inspect uptime-kuma --format '{{ index .Config.Labels "com.docker.compose.project.working_dir" }}'
docker inspect portainer --format '{{ index .Config.Labels "com.docker.compose.project.working_dir" }}'
curl -I https://kuma.bombaworkflows.com
curl -I https://portainer.bombaworkflows.comЦе одразу відповідає на ключові запитання:
- що зараз запущено
- якою версією
- з якої директорії керується
- чи доступний сервіс локально і публічно
Висновок
Цей етап навчив мене дивитися на docker compose не як на модний інструмент, а як на спосіб навести лад.
Контейнери не стали швидшими. Інтерфейси не стали красивішими. Але інфраструктура стала:
- зрозумілішою
- відтворюваною
- спокійнішою в оновленнях
- менш залежною від випадкових ручних дій
І саме тому цей перехід виявився настільки цінним для реального DevOps-навчання.