Найшвидший спосіб зіпсувати собі післяобідній час — ввести docker compose up -d, поки ваша оболонка вказує на неправильний демон.
Ви думаєте, що перезапускаєте стік для розробки; продакшен тихо погоджується і робить саме те, про що ви попросили.
Docker contexts існують саме для цього. Вони дають іменовані, інспектовані кінцеві точки з явним перемиканням, а також достатньо метаданих, щоб
запит «куди я розгортаю?» можна було відповісти до того, як щось загориться.
Для чого потрібні контексти (і чому DOCKER_HOST — це рушниця з порожнім патроном)
Якщо ви давно працюєте з Docker, мабуть, використовували DOCKER_HOST або посипали скрипти docker -H tcp://... як приправу.
Це працює. Але це також створює стан, який ви не бачите, не можете аудіювати і не можете легко зберігати під контролем версій. Ваш термінал стає ризиком.
Docker contexts виправляють це, роблячи «вибір цільового демона» первинною концепцією: ви називаєте його, можете перелічити, інспектувати,
експортувати/імпортувати і змусити інструменти використовувати його. Останнє особливо важливо під час реагування на інциденти:
вам потрібні менше неявних глобальних змінних, а не більше.
Контексти також уніфікують кілька типів кінцевих точок. На практиці ви побачите:
- Локальні (за замовчуванням) — для Docker Desktop на робочій машині або сокета демона Linux.
- SSH — до віддаленого хоста без відкриття TCP API Docker у інтернеті.
- TCP/TLS — для застарілих налаштувань або контрольованих мереж (будьте обережні, більше про це далі).
- Метадані оркестратора (історично для інтеграцій зі Swarm/Kubernetes; сьогодні здебільшого для обліку кінцевих точок).
Контекст — це не «просто зручність». Це поруччя безпеки. Це також інструмент підзвітності:
ви можете будувати робочі процеси, де «prod» — це те, що треба явно вибрати, а не випадковість, в яку ви потрапляєте.
Жарт №1: Єдина річ більш постійна, ніж тимчасове обхідне рішення — це Docker CLI, що вказує на продакшен.
Цікаві факти та коротка історія
- Віддалений API Docker існував до контекстів: раннє віддалене керування здебільшого було через
DOCKER_HOSTі TCP API, що робило «упс» розгортання звичайними. - Контексти стали масовими з CLI Docker v19.03, коли команди почали ставитися до кількох середовищ як до норми, а не винятку.
- SSH-контексти покладаються на клієнт OpenSSH: ви отримуєте пересилання агенту, перевірку known_hosts і свою існуючу SSH-конфігурацію без додаткових зусиль (і з її гострими краями теж).
- Docker Desktop використовує абстракцію, схожу на контекст, щоб направляти команди до демона у віртуальній машині; контексти роблять цю концепцію явною для вас.
- Swarm був раннім драйвером для «кілька кінцевих точок, один CLI», навіть якщо багато компаній пізніше перейшли на Kubernetes або керовані платформи.
- Демон має права, схожі на root: користувач, який може звертатися до Docker сокета, зазвичай може стати root на тому хості. Контексти цього не змінюють; вони лише допомагають свідомо вказувати цю силу.
- Контексти зберігаються на стороні клієнта (в каталозі конфігурації Docker), тому експорт/імпорт важливий для ноутбуків, епемерних CI раннерів і аварійних jump‑боксів.
- Compose поважає контексти:
docker composeговорить з тим контекстом, який налаштований в CLI, тож «неправильний контекст» впливає на весь ваш робочий процес.
Ментальна модель: що таке контекст насправді
Думайте про Docker context як про іменований кортеж:
(endpoint, auth, TLS/SSH plumbing, metadata).
Це не рушій. Це не кластер. Це не змінна оточення, про яку ви забуваєте.
Це об’єкт конфігурації, підкріплений файлом, до якого CLI звертається перед будь-якою дією.
Що всередині
Коли ви інспектуєте контекст, зазвичай бачите:
- Кінцеві точки: зазвичай
dockerзHost, наприкладunix:///var/run/docker.sockабоssh://user@host. - TLS-матеріали (якщо використовується TCP/TLS): сертифікати та прапорці перевірки.
- Оркестратор: часто поля
swarmабоkubernetesзалежно від епохи; у багатьох сучасних налаштуваннях він присутній, але не використовується. - Опис: який вам справді варто заповнити, бо люди теж потребують поруччя.
Пріоритети: хто перемагає?
Це важливо, бо відмови в продакшені люблять баги пріоритетів. Приблизно:
docker --context X ...має перевагу для того виклику.DOCKER_CONTEXTможе перевизначити «поточний» контекст.docker context use Xвстановлює поточний контекст для майбутніх команд.DOCKER_HOSTможе обійти контексти зовсім для деяких інструментів або скриптів, залежно від того, як вони написані.
Позиція: забороніть DOCKER_HOST в інтерактивних шелах. Дозволяйте його лише в жорстко контрольованій автоматизації,
і навіть там віддавайте перевагу --context для ясності.
Одна надійна цитата з опсів
«Сподівання — не стратегія.» — парафраз ідеї Джина Кранца
Контексти — це спосіб припинити «сподіватися», що ви говорите з правильним демоном.
Основні команди, важливі в продакшені
Вам не потрібно запам’ятовувати 50 підкоманд. Потрібна невелика кількість, яку ви зможете виконати під тиском,
і розуміти, що означає вивід.
Золоте правило
Перед будь-якою руйнівною командою (rm, down, system prune, volume rm, «давайте просто перевпровадимо»),
виконуйте перевірку контексту. Зробіть це автоматично.
Імена, які варто прийняти
dev,staging,prod(буденно, але добре)prod-eu-west,prod-us-eastякщо ви дійсно працюєте у кількох регіонахbuildkitабоbuilderякщо ви використовуєте віддалені білдери
Уникайте креативних назв. Ваш майбутній я під час pager-чергової не буде вражений.
Практичні завдання: 12+ речей, які ви справді робитимете
Нижче — реальні операційні завдання з командами, прикладами виводу, що це означає, і рішенням, яке ви з цього робите.
Ставте це як вправи, що формують м’язову пам’ять.
Завдання 1: Перелічити контексти й визначити поточний
cr0x@server:~$ docker context ls
NAME DESCRIPTION DOCKER ENDPOINT ERROR
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
staging Staging host via SSH ssh://deploy@stg-01
prod Production host via SSH ssh://deploy@prod-01
Що означає вивід: зірочка позначає активний контекст. «DOCKER ENDPOINT» показує, як CLI дістатиметься до демона.
Рішення: якщо ви збираєтеся працювати з продакшеном, має бути видно prod * і нічого іншого. Якщо ні — зупиніться.
Завдання 2: Інспектувати контекст перед використанням
cr0x@server:~$ docker context inspect prod
[
{
"Name": "prod",
"Metadata": {},
"Endpoints": {
"docker": {
"Host": "ssh://deploy@prod-01",
"SkipTLSVerify": false
}
},
"TLSMaterial": {},
"Storage": {
"MetadataPath": "/home/cr0x/.docker/contexts/meta/7c1a3c2b6f",
"TLSPath": "/home/cr0x/.docker/contexts/tls/7c1a3c2b6f"
}
}
]
Що означає вивід: це SSH-контекст; TLS-матеріали порожні, оскільки SSH забезпечує безпеку транспорту.
Рішення: підтвердіть, що пара користувач/хост правильна і відповідає очікуванням вашої SSH-конфігурації.
Якщо там написано root@prod-01, ви тримаєте заряджену зброю.
Завдання 3: Явно переключити контексти
cr0x@server:~$ docker context use staging
staging
cr0x@server:~$ docker context ls
NAME DESCRIPTION DOCKER ENDPOINT ERROR
default Current DOCKER_HOST based configuration unix:///var/run/docker.sock
staging * Staging host via SSH ssh://deploy@stg-01
prod Production host via SSH ssh://deploy@prod-01
Що означає вивід: ваша сесія тепер вказує на staging для всіх майбутніх Docker-команд.
Рішення: у спільних терміналах (tmux, screen, перехідні хости) відображайте свій контекст у prompt або рядку статусу. Тиша породжує помилки.
Завдання 4: Використати одноразовий контекст без зміни сесії
cr0x@server:~$ docker --context prod ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a12b3c4d5e6f nginx:1.25 "/docker-entrypoint.…" 2 days ago Up 2 days 0.0.0.0:80->80/tcp web
Що означає вивід: тільки ця команда зверталася до prod; ваш поточний контекст залишився незмінним.
Рішення: віддавайте перевагу такому підходу в автоматизації та в runbook’ах для копіювання/вставки.
Так легше не «забути, де ви».
Завдання 5: Створити контекст через SSH (здравий за замовчуванням)
cr0x@server:~$ docker context create prod --docker "host=ssh://deploy@prod-01"
prod
cr0x@server:~$ docker context ls
NAME DESCRIPTION DOCKER ENDPOINT ERROR
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
prod Production host via SSH ssh://deploy@prod-01
Що означає вивід: ви визначили віддалену кінцеву точку без експонування TCP API Docker.
Рішення: використовуйте SSH-контексти, якщо немає вагомої причини інакше. «Тому що так було в 2017» — не вагома причина.
Завдання 6: Перевірити, що ви говорите з потрібним рушієм (дешева перевірка ідентичності)
cr0x@server:~$ docker --context prod info --format 'Name={{.Name}} Server={{.ServerVersion}} RootDir={{.DockerRootDir}}'
Name=prod-01 Server=25.0.3 RootDir=/var/lib/docker
Що означає вивід: ви отримали три сигнали ідентичності: ім’я демона, версію і кореневий каталог.
Рішення: вбудуйте це у передпольотні перевірки. Якщо ім’я невірне — ви на неправильному хості. Якщо версія неочікувана — готуйтеся до змін у поведінці.
Завдання 7: Виявити «контекст працює, але SSH бреше вам» (невідповідність ключа хоста / конфігурації)
cr0x@server:~$ docker --context prod ps
error during connect: Get "http://docker.example/v1.45/containers/json": command [ssh -o ConnectTimeout=30 -T -l deploy prod-01 docker system dial-stdio] exit status 255
Що означає вивід: CLI намагався виконати docker system dial-stdio по SSH і зазнав невдачі. Це транспорт, а не Docker.
Рішення: поруч запустіть простий SSH-команду, щоб ізолювати проблему: якщо SSH не працює — виправляйте SSH (ключі, бастіон, ключ хоста).
Якщо SSH працює, але Docker падає — виправляйте права доступу до демона.
Завдання 8: Довести базову SSH-зв’язність (без Docker посередині)
cr0x@server:~$ ssh -o BatchMode=yes deploy@prod-01 'hostname; id; docker version --format "{{.Server.Version}}"'
prod-01
uid=1001(deploy) gid=1001(deploy) groups=1001(deploy),998(docker)
25.0.3
Що означає вивід: користувач може запускати docker і входить до групи docker. Це фактично права root на цій машині.
Рішення: ставтеся до членства в групі docker як до sudo. Надавайте його свідомо, аудитуйте та видаляйте, коли не потрібно.
Завдання 9: Експортувати контекст для аварійного ноутбука або CI раннера
cr0x@server:~$ docker context export prod -o prod.dockercontext
cr0x@server:~$ ls -l prod.dockercontext
-rw------- 1 cr0x cr0x 2840 Jan 3 10:12 prod.dockercontext
Що означає вивід: ви створили портативний бандл контексту.
Рішення: зберігайте його як секрет. Якщо він містить TLS-матеріали — це фактично доступ. Навіть для SSH‑лише кінцевих точок це оперативні метадані, які не хочеться, щоб ширялися.
Завдання 10: Імпортувати контекст на іншу машину
cr0x@server:~$ docker context import prod -i prod.dockercontext
prod
cr0x@server:~$ docker context ls
NAME DESCRIPTION DOCKER ENDPOINT ERROR
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
prod Production host via SSH ssh://deploy@prod-01
Що означає вивід: ваш CLI тепер знає, як дістатися до продакшена так само, як і машина-джерело.
Рішення: для CI краще генерувати контексти під час виконання (з епемерними обліковими даними), аніж імпортувати довгоживучі.
Але для реагування на інциденти імпорт відомого доброго контексту — золото.
Завдання 11: Видалити контекст, якому більше не довіряєте
cr0x@server:~$ docker context rm staging
staging
cr0x@server:~$ docker context ls
NAME DESCRIPTION DOCKER ENDPOINT ERROR
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
prod Production host via SSH ssh://deploy@prod-01
Що означає вивід: метадані контексту зникли з клієнта.
Рішення: видаляйте контексти, коли хости виводяться з експлуатації, переміщуються або перебираються. Старі контексти — шлях до розгортання на переробленому імені хоста.
Завдання 12: Швидко порівняти два середовища (зображення, контейнери, диск)
cr0x@server:~$ docker --context staging system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 18 6 5.2GB 2.7GB (51%)
Containers 9 6 210MB 0B (0%)
Local Volumes 14 9 22.4GB 3.1GB (13%)
Build Cache 0 0 0B 0B
Що означає вивід: ви отримуєте швидке уявлення про тиск на зберігання і чи варто чистити.
Рішення: якщо домінують томи, не робіть необачний system prune. Ваші дані, мабуть, у томах. Плануйте цілеспрямоване очищення.
Завдання 13: Запустити ту саму перевірку на продакшені без перемикання контекстів
cr0x@server:~$ docker --context prod system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 42 18 14.8GB 1.1GB (7%)
Containers 31 27 1.8GB 0B (0%)
Local Volumes 66 55 640.2GB 12.4GB (1%)
Build Cache 0 0 0B 0B
Що означає вивід: продакшен сильно залежить від томів і майже не підлягає звільненню. Це нормально для stateful сервісів, і також нагадування, що диск — це план ємності, а не кнопка для очищення.
Рішення: якщо сигналізації по диску спрацьовують, очищення не врятує. Потрібна дисципліна життєвого циклу томів, політики збереження або більші диски.
Завдання 14: Перевірити, що розгортання Compose націлене на потрібний хост
cr0x@server:~$ docker --context prod compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
app-web-1 registry/app:web "/entrypoint.sh" web 3 hours ago Up 3 hours 0.0.0.0:443->443/tcp
app-db-1 postgres:16 "docker-entrypoint.s…" db 3 hours ago Up 3 hours 5432/tcp
Що означає вивід: Compose говорить з продакшеном. Запущені сервіси перераховані від того демона.
Рішення: коли сумніваєтесь, куди дивиться Compose, не гадіть — спитайте його за допомогою compose ps з --context.
Завдання 15: Діагностувати «неправильний контекст» через prompt з явним маркером
cr0x@server:~$ docker context show
prod
Що означає вивід: CLI друкує ім’я активного контексту, і нічого більше.
Рішення: інтегруйте це в prompt оболонки (PS1) або в статус-бар tmux. Хочеться бачити контекст як вашу поточну гілку git.
Завдання 16: Переглянути стрім подій на віддаленому демонові (корисно під час інцидентів)
cr0x@server:~$ docker --context prod events --since 10m
2026-01-03T10:02:21.223456789Z container die a12b3c4d5e6f (exitCode=137, image=registry/app:web, name=app-web-1)
2026-01-03T10:02:24.019283746Z container start 9f8e7d6c5b4a (image=registry/app:web, name=app-web-1)
Що означає вивід: ви бачите життєвий цикл контейнерів; exit 137 зазвичай означає SIGKILL, часто OOM-kill або ручне вбивство процесу.
Рішення: якщо бачите повторні збої/старт-цикли, припиніть перевпровадження. Дивіться на ліміти пам’яті, журнали OOM ядра або збої додатка.
Жарт №2: «Це лише швидкий рестарт» — операційний еквівалент «Я візьму лише одне печиво».
Безпека й контроль доступу: тримайте демон на повідку
Контексти Docker нічого автоматично не захищають. Вони полегшують використання безпечних транспортів і ускладнюють випадкові дурниці.
Демон залишається високопривілейованою контрольною площею. Ставтеся до нього як до поєднання SSH і sudo.
SSH-контексти: стандарт, який вам потрібен
З ssh:// контекстами Docker запускає допоміжну команду на віддаленому хості, щоб встановити тунельоване з’єднання.
Це дає вам:
- Аутентифікацію на основі ключів SSH і ваші звичайні корпоративні засоби (бастіони, MFA-обгортки, запис сесій).
- Перевірку ключа хоста (якщо ви не відключили її як чудовисько).
- Немає потреби відкривати TCP-порт Docker API.
TCP-контексти: використовуйте лише з TLS і лише за вагомої причини
Якщо у вас є застаріле середовище, яке вимагає tcp://host:2376 з TLS-сертифікатами, ви можете представити його як контекст.
Але пам’ятайте: незахищений TCP API Docker — це фактично «root у мережі».
Не робіть tcp://0.0.0.0:2375, якщо ваша модель загроз не «нам подобається хаос».
Найменше привілеїв (настільки, наскільки дозволяє Docker)
На класичному Docker Engine кожен, хто має доступ до API Docker, зазвичай може примонтувати файлову систему, запускати привілейовані контейнери
і ескалювати права. Ваші реальні засоби контролю:
- Хто може SSH до хоста (і звідки).
- Який обліковий запис використовується для контекстів (окремі «deploy» ідентичності кращі за персональні акаунти).
- Аудит змін (події, системні логи, і пайплайни розгортання).
- Загартування хоста: AppArmor/SELinux, rootless mode де можливо й ретельно підібрані настройки демона.
Операційна гігієна, яка окупається
- Використовуйте окремі контексти для окремих середовищ. Не використовуйте «prod» для кількох хостів.
- Вкажіть назву середовища в описі контексту і в банері віддаленого хоста (motd), якщо можете.
- Робіть переключення контекстів явним у runbook’ах і скриптах: використовуйте
--context. - Логуйте «який контекст використовували» у виводі CI/CD. Це банально, але допомагає при безпригнічному розслідуванні.
Три корпоративні історії з передової
Інцидент через хибне припущення: «default» означав «dev»
Команда мала jump‑хост, який «усі використовували» для операцій з контейнерами. Його підтримувала інфраструктурна група, і на ньому був встановлений Docker.
Припущення — ніколи не проголошене, але завжди імпліцитне — було в тому, що Docker на jump‑хості це просто зручність для інструментів. Люди використовували його для запуску лінтерів, завантаження образів, можливо тестування Compose.
Один інженер отримав пейдж за проблемою в staging. Він SSH‑нув на jump‑хост, виконав docker ps, побачив купу контейнерів і вирішив, що staging здоровий.
Потім він зробив прибирання: docker system prune -af. Команда виконалась швидко. Надто швидко.
Демон Docker на jump‑хості не був «локальним dev». Він був налаштований — через старий, експортований DOCKER_HOST у /etc/profile.d — щоб вказувати на спільний продакшен‑рушій.
Контейнери, які він бачив, були продакшен‑контейнерами. Prune видалив образи і кеш збірки у продакшені, що спричинило каскад завантажень образів і рестартів під час пікового трафіку.
Постмортем не був про «хто ввів команду». Він був про невидимий стан і крихкі припущення.
Виправлення було простим і трохи принизливим: видалити глобальний DOCKER_HOST, визначити контексти і оновити prompt jump‑хоста, щоб показувати docker context show.
Вони також додали невеликий обгорток: руйнівні команди вимагали явного --context.
Це не усунуло всі помилки, але зупинило цілий клас «Я думав, що я на dev» помилок.
Оптимізація, яка обернулася проти: віддалена TCP‑кінцева точка «ради швидкості»
Інша організація хотіла прискорити CI‑зборки. Хтось помітив, що SSH‑контексти додають оверхед: встановлення SSH сесії, латентність, інколи дивні проблеми з бастіонами.
Тому вони «оптимізували», відкривши демон Docker по TCP всередині внутрішньої мережі. Він стояв за фаєрволом, і обіцяли додати TLS пізніше.
Це працювало. Збірки стали швидшими. Команда відсвяткувала, збільшивши число паралельних джобів, що підвищило навантаження на Docker API, збільшило CPU демона і знову все сповільнилося.
Тим часом «TLS потім» тихо перетворився на «TLS ніколи», бо пайплайн вже залежав від незахищеної кінцевої точки.
Реальна відмова сталася через місяці під час проєкту сегментації мережі.
Правила фаєрвола змінилися, і раптом частина раннерів могла все ще дістатися Docker API, а інші — ні. Зборки стали ненадійними, а повтори ще більше навантажили демон.
Інженери витратили дні на дебаг «Docker ненадійний», коли проблема була в «ви побудували центральний віддалений демон з крихкою мережною залежністю».
Остаточне рішення не було гламурним: повернути SSH‑контексти для ad‑hoc доступу і перенести CI на per‑runner білдери або правильно керований кластер збірки.
Контексти все ще використовувалися, але стратегія кінцевої точки змінилася. Оптимізація націлювалася на невірне вузьке місце.
Урок: знімати мілісекунди з каналу контролю рідко вирішує реальну проблему продуктивності. Зазвичай вам потрібна локальність, кешування і ємність — не широко відкритий порт демона.
Нудна, але правильна практика, що виручила команду
Більш зріла команда мала правило: у кожній команді в runbook був вказаний --context. Усі команди.
Це було трохи дратівливо. Люди скаржилися. Потім вони перестали помічати, як автозастібка.
Однієї ночі в них стався інцидент у продакшені через неконтрольований лог‑том, який заповнив диск.
Інженер на чергуванні мав відкритий staging у вкладці терміналу і production в іншій. У стресі це — рецепт перехресних помилок.
Вони слідували runbook’у. Кожна команда була прив’язана: docker --context prod ....
Вони перевірили використання томів, зупинили правильний шумний контейнер і перезапустили його з обмеженням логування, яке вже перевірили в staging.
Найкраща частина: під час постінцидентного огляду вони мали чисті журнали терміналу і CI, які показували, який контекст використовувався для кожної дії.
Ніякої форензики «я майже певен, що був у prod». Запис був чітким.
Нудні практики не потрапляють у доповіді на конференціях. Вони також забезпечують вам роботу.
Швидкий план діагностики (знайти вузьке місце швидко)
Коли «Docker повільний» або «віддалений контекст нестабільний», не змінюйте налаштування навмання. Тріажуйте як дорослий:
визначте, чи вузьке місце у транспорті, здоров’ї демона, реєстрі/завантаженні образів,
зберіганні або вашій локальній машині.
По-перше: підтвердіть, що ви налагоджуєте правильну ціль
cr0x@server:~$ docker context show
prod
Рішення: якщо контекст не те середовище, яке ви думаєте, зупиніться. Виправте це спочатку. Усе інше — шум.
По-друге: виміряйте базову латентність контрольної площини
cr0x@server:~$ time docker --context prod version
Client: Docker Engine - Community
Version: 25.0.3
API version: 1.45
...
real 0m0.612s
user 0m0.078s
sys 0m0.021s
Що це означає: субсекунда — нормально. Кілька секунд вказують на проблеми з SSH/бастіоном/DNS або на перевантаження демона.
Рішення: якщо це повільно, не починайте з «тонкого налаштування зберігання Docker». Почніть з мережі/SSH і навантаження демона.
По-третє: перевірте здоров’я демона та ресурси
cr0x@server:~$ docker --context prod info | sed -n '1,35p'
Client:
Version: 25.0.3
Context: prod
Debug Mode: false
Server:
Containers: 31
Running: 27
Paused: 0
Stopped: 4
Images: 42
Server Version: 25.0.3
Storage Driver: overlay2
Logging Driver: json-file
Cgroup Driver: systemd
...
Рішення: підтвердіть storage driver, logging driver і загальну кількість контейнерів/образів. Якщо вони відрізняються між середовищами — і поведінка також відрізнятиметься.
По-четверте: визначте, чи справді зберігання — це причина
cr0x@server:~$ docker --context prod system df -v | sed -n '1,40p'
Images space usage:
REPOSITORY TAG IMAGE ID CREATED SIZE SHARED SIZE UNIQUE SIZE CONTAINERS
registry/app web 2aa1b3c4d5e6 3 hours ago 412.5MB 0B 412.5MB 4
...
Рішення: якщо велика кількість образів змінюється часто, фокусуйтеся на швидкості pull, продуктивності реєстру й кешуванні.
Якщо домінують томи — працюйте над життєвим циклом/ретеншнами і продуктивністю файлової системи.
По-п’яте: спостерігайте за циклом контейнерів і перезапусками
cr0x@server:~$ docker --context prod ps --format 'table {{.Names}}\t{{.Status}}\t{{.RunningFor}}'
NAMES STATUS RUNNING FOR
app-web-1 Up 3 hours (healthy) 3 hours
app-db-1 Up 3 hours 3 hours
worker-1 Restarting (1) 5 seconds 8 minutes
Рішення: цикли перезапуску роблять усе «повільним», бо демон постійно створює/видаляє ресурси.
Виправте падаючий контейнер перш ніж налаштовувати інше.
По-шосте: якщо SSH‑контексти падають періодично, ізолюйте SSH
cr0x@server:~$ ssh -o ServerAliveInterval=5 -o ServerAliveCountMax=2 deploy@prod-01 'echo ok'
ok
Рішення: якщо це підкидає з’єднання, проблема в мережевому шляху, стабільності бастіона або SSH‑таймаутах — а не в контекстах Docker.
Поширені помилки: симптом → корінна причина → виправлення
Помилка 1: «Я розгорнув на неправильному хості»
Симптом: зміни у staging з’являються в prod або зміни в prod ніде не видно.
Корінна причина: неявний поточний контекст або DOCKER_HOST, що перевизначає те, що ви думали активним.
Виправлення: використовуйте docker --context ... у runbook’ах/скриптах; видаліть глобальний DOCKER_HOST; показуйте контекст у prompt; вимагайте явного вибору для руйнівних дій.
Помилка 2: «docker context use prod» працює, але команди зависають
Симптом: CLI зависає на ps, info, pull або compose up.
Корінна причина: проблема шляху SSH (бастіон, DNS, MTU) або віддалений демон під навантаженням CPU/пам’яті.
Виправлення: заміряйте docker --context prod version; протестуйте plain SSH; перевірте навантаження віддаленого хоста; розгляньте SSH keepalives.
Помилка 3: «Сказано: відмова в доступі до демона Docker»
Симптом: помилки віддаленого контексту на кшталт «permission denied while trying to connect to the Docker daemon socket.»
Корінна причина: віддалений користувач може SSH, але не має доступу до /var/run/docker.sock (не в групі docker, rootless демон).
Виправлення: надайте правильне членство в групі (обережно), або свідомо використовуйте rootless Docker; перевірте командою ssh host 'docker ps'.
Помилка 4: «Мій контекст вказує на старий хост після перебудови»
Симптом: контекст підключається, але ви бачите свіжий пустий демон або несподіване ім’я/версію рушія.
Корінна причина: ім’я хоста перероблено, DNS оновлено або нова інстанція отримала те саме ім’я.
Виправлення: перевірте ідентичність через docker info --format 'Name=...'; прив’яжіть SSH‑конфіг до стабільних ключів хоста; оновіть контексти після перебудов.
Помилка 5: «Експортований контекст працює на одному ноуті, але не на іншому»
Симптом: імпортований контекст існує, але не вдається підключитися через SSH.
Корінна причина: агент/ключі SSH відрізняються, SSH‑конфіг різниться або known_hosts не співпадає.
Виправлення: переконайтеся, що імпортуюча машина має потрібний SSH-ідентифікатор і конфіг; протестуйте plain SSH; уникайте залежності від agent‑forwarding в автоматизації.
Помилка 6: «Compose поводиться інакше, ніж docker»
Симптом: docker ps показує одне середовище, а docker compose впливає на інше (або навпаки).
Корінна причина: змішане використання DOCKER_HOST, DOCKER_CONTEXT та «поточний контекст», або різні шелли з різними змінними оточення.
Виправлення: стандартизуйте використання --context; друкуйте env у відладкових шеллах; уникайте експорту DOCKER_HOST у профілях.
Помилка 7: «Список контекстів показує ERROR»
Симптом: docker context ls показує заповнену колонку error для контексту.
Корінна причина: кінцева точка недоступна або неправильно налаштована; CLI Docker намагався валідувати її і зазнав невдачі.
Виправлення: інспектуйте контекст; тестуйте SSH; перезавантажте контекст, якщо рядок кінцевої точки неправильний; видаліть застарілі контексти.
Помилка 8: «Ми використовували TCP, бо це внутрішньо; тепер безпека сердиться»
Симптом: аудиторське зауваження: Docker API відкритий без TLS, широкі правила фаєрвола, незрозумілий доступ до демона.
Корінна причина: дизайн кінцевої точки, спричинений зручністю; віддалений API сприймали як нешкідливу службу.
Виправлення: переходьте на SSH-контексти або кінцеві точки з TLS‑аутентифікацією; обмежуйте мережні шляхи; обертайте облікові дані; ставтеся до доступу до демона як до привілейованого.
Контрольні списки / покроковий план
Покроково: впровадити контексти, не зламавши всіх
- Інвентаризація кінцевих точок: перелічіть, куди зараз потрапляють Docker‑команди (ноутбуки розробників, jump‑хости, CI‑раннери).
- Видалити приховані глобалі: шукайте
DOCKER_HOSTу профілях шелла і в інжекціях середовища CI. - Створіть іменовані контексти: як мінімум
dev,staging,prod. Використовуйте SSH‑кінцеві точки. - Додайте описи: включіть середовище, регіон і власність. Люди помиляються; метадані допомагають.
- Уніфікуйте runbook’и: оновіть кожну команду, щоб вона включала
--context. - Зробіть контекст видимим: інтеграція в prompt/tmux, щоб завжди знати, де ви.
- Визначіть процедуру аварійного доступу: потік експорту/імпорту контексту, обробка облікових даних і очікування аудиту.
- Дисципліна CI/CD: використовуйте явні контексти або явні кінцеві точки в кожній job; уникайте залежності від «поточний контекст».
- Ротація доступу: якщо раніше використовували TCP без TLS, вважайте це потенційно скомпрометованим і проведіть ротацію.
- Тренуйтеся за сценаріями: практикуйте «перемкни контекст, перевір ідентичність, виконай команду», поки це не стане автоматизмом.
Операційний чекліст: перед тим як виконати ризиковану команду
- Запустіть
docker context show. - Запустіть
docker info --format 'Name={{.Name}}'для цього контексту. - Підтвердіть, що ви в правильній вкладці/вікні терміналу (виглядає дурно; рятує від аварій).
- Віддавайте перевагу
docker --context X ...для ризикової команди. - Для очищення: спочатку інспектуйте
docker system df; не робіть prune навмання.
Чекліст жорсткої політики: ускладніть шлях до помилки
- Окремі облікові записи для розгортання і адміністрування; не використовуйте персональні SSH‑ключі для автоматизації.
- Використовуйте SSH‑контексти; уникайте експонування Docker TCP API.
- Примушуйте перевірку ключів хоста; керуйте known_hosts централізовано, де доречно.
- Обмежуйте, хто може дістатися до Docker хостів (мережеві ACL, бастіони, проксі з автентифікацією).
- Аудитуйте членство в групі
docker, як аудитуєте sudoers.
Питання й відповіді
1) Чи Docker context — те саме, що Kubernetes context?
Ні. Kubernetes‑контексти живуть у kubeconfig і вибирають кластери/простори імен/користувачів для kubectl.
Docker contexts вибирають кінцеві точки CLI Docker (локальний сокет, SSH, TCP/TLS). Схожа ідея, інша екосистема.
2) Чи варто використовувати docker context чи DOCKER_HOST?
Використовуйте контексти для людей і більшості автоматизації. Резервуйте DOCKER_HOST для застарілого інструменту, який ви не можете змінити,
і тримайте його жорстко в межах процесу, а не в експортованих профілях.
3) Який найбезпечніший спосіб керувати доступом до продакшену?
Використовуйте SSH‑контексти з виділеним deploy‑акаунтом, жорстко обмеженими мережними шляхами (бастіон) і аудиту керування ключами.
Робіть кожну продкоманду явною через --context prod.
4) Чому Docker по SSH інколи відчувається повільніше?
Бо він робить більше: налаштовує SSH, аутентифікується і встановлює тунель stdio. Якщо латентність заважає,
справжнє рішення зазвичай — кращі мережні шляхи, постійні control masters або перенесення збірок ближче до демона.
5) Чи можна зберігати контексти в git?
Не комітьте експортовані контексти. Вони можуть містити чутливі TLS‑матеріали і операційні кінцеві точки.
Краще зберігайте інструкції для створення контекстів і генеруйте їх під час виконання.
6) Як запобігти сюрпризам «поточний контекст» у скриптах?
Використовуйте docker --context NAME у кожній команді. Скрипти повинні бути детерміновані.
Якщо скрипт залежить від стану вашої інтерактивної оболонки — це не скрипт, а порада.
7) Чи допоможуть контексти з розгортаннями в кількох регіонах?
Так. Створіть контексти на кшталт prod-eu-west і prod-us-east, а потім виконуйте ті самі команди явно для кожного.
Просто дотримуйтеся дисципліни іменування та перевірок ідентичності.
8) Чому docker context ls показує помилку для одного контексту?
Кінцева точка недоступна або неправильно налаштована, або Docker намагався й зазнав помилки при перевірці підключення.
Інспектуйте контекст, вручну перевірте SSH і перезбережіть контекст, якщо рядок хоста неправильний.
9) Чи контексти спільні між користувачами на одній машині?
Зазвичай ні. Контексти зберігаються в директорії конфігурації Docker користувача. Це добре: уникає несподіваної крос‑користувацької залежності.
Але це також означає, що їх потрібно керувати окремо на спільних jump‑хостах.
10) Чи роблять контексти Docker «безпечним» для мульти‑тенантних хостів?
Контексти — це селектор на стороні клієнта. Безпека мульти‑тена залежить від налаштування демона, ізоляції ядра і контролю доступу.
Контексти допомагають уникати операторських помилок; вони не забезпечують ізоляції орендарів.
Наступні кроки, які варто зробити цього тижня
Якщо ви оперуєте більше ніж одним Docker‑хостом, ви вже в «землі з кількома цілями». Поводьтеся відповідно.
- Створіть контексти для кожного середовища, використовуючи SSH‑кінцеві точки. Називайте їх просто.
- Зробіть контекст видимим у prompt оболонки або статус‑барі tmux.
- Оновіть runbook’и, щоб кожна команда фіксувалася через
--context. - Видаліть глобальний
DOCKER_HOSTз інтерактивних середовищ і спільних jump‑хостів. - Додайте передпольотну перевірку ідентичності:
docker --context X info --format 'Name={{.Name}} Server={{.ServerVersion}}'. - Аудит доступу: хто може дістатися продакшен‑хостів, хто в групі docker і як керуються ключі.
Контексти не запобіжать усім помилкам. Вони запобігають дурним помилкам. Саме ті, що постійно будять о 2‑й годині ночі.