Docker це іграшка чи ні? Чи все-таки так?

Всім привіт!

Дуже хочеться відразу приступити до теми, але правильніше буде трохи розповісти про мою історію:

Вступ

Я програміст з досвідом розробки frontend односторінкових додатків, scala/java та nodejs на сервері.

Досить довго (уже точно пару - трійку років), я дотримувався думки, що docker це небесна манна і взагалі дуже крутий інструмент і абсолютно кожен розробник повинен вміти користуватися ним. А звідси випливає, що й у кожного розробника має стояти docker на локальній машині. Так що там про мою думку, ви погортаєте вакансії, які розміщуються на тому ж hh. У кожній другій є згадка про docker і якщо ви володієте — це буде вашою конкурентною перевагою 😉

На своєму шляху я зустрічався з багатьма людьми, з їхнім різним ставленням до docker та його екосистеми. Одні казали, що це зручна річ, яка гарантує кроссплатформенність. Другі не розуміли, навіщо їм запускатися в контейнерах і який профіт від цього, третім було взагалі пофіг і вони не парилися (просто писали код і йшли додому — заздрю, до речі, їм 🙂)

Причини використання

Чому я використав docker? Напевно, з наступних причин:

  • запуск бази даних, 99% додатків користуються ними
  • запуск nginx для роздачі frontend та проксіювання на backend
  • можна запакувати додаток у docker образ, таким чином моя програма буде працювати скрізь, де є docker, проблема дистрибутації вирішена вже відразу
  • service discovery з коробки, можна робити мікросервіси, кожен контейнер (підключений до загальної мережі) легко достукається до іншого аліасом, дуже зручно
  • прикольно створити контейнер і погратися в ньому.

Що мені завжди НЕ подобалося у docker:

  • щоб моя програма працювала, потрібен сам docker на сервері. А навіщо мені це, якщо мої програми працюють на jre або nodejs і оточення для них вже є на сервері?
  • якщо я хочу запустити свій (приватний) локально зібраний образ на віддаленому сервері, то мені потрібний свій docker репозиторій, потрібно, щоб десь працював registry і ще потрібно налаштувати https, тому що docker cli працює тільки https. Ох млинець… є варіанти, звичайно, зберегти образ локально через docker save і через scp просто скинути образ… Але це стільки рухів тіла. І до того ж виглядає «милицею» рішенням, поки не з'явиться свій репозиторій.
  • docker-compose. Він потрібний лише для запуску контейнерів. І все. Більше нічого не може. Docker-compose має купу версій своїх файлів, синтаксис. Яким би декларативним він не був, я не хочу читати їхню документацію. Мені вона більше ніде не знадобиться.
  • при роботі в команді, здебільшого люди пишуть Dockerfile дуже криво, не розуміють як це кешується, додають в образ все що треба і не треба, успадковуються від образів яких немає в dockerhub або приватному репозиторії, створюють якісь docker-compose файли з базами даних нічого не персистують. При цьому розробники гордо заявляють, що docker крутий, у них все працює локально і HR важливо пише у вакансії: «Ми використовуємо docker і нам потрібен кандидат із таким досвідом роботи»
  • постійно переслідують думки про підняття в docker всього і вся: postgresql, kafka, redis. Жаль, що не все працює в контейнерах, не все легко налаштувати і запустити. Підтримуються це сторонніми розробниками, а чи не самими вендорами. І до речі відразу виникає питання, чи вендора не паряться щодо підтримки своїх продуктів у docker, чому ж це, може вони щось знають?
  • завжди постає питання про персистенцію даних контейнера. і тут думаєш, мені просто примонтувати хостову директорію або створити docker volume або зробити data container який тепер deprecated? Якщо я монтую директорію то мені потрібно переконатися, що uid і gid користувача в контейнері відповідає id користувача, який запустив контейнер, інакше файли створені контейнером будуть створені з правами власника root. Якщо використовую volume то дані просто буду створені в якому-небудь /usr/* і буде така ж історія з uid та gid як у першому випадку. Якщо запускаєш сторонній компонент, то потрібно вчитуватися в документацію і шукати відповідь на запитання: «а в які директорії контейнера компонент пише файли?»

Мені завжди не подобалося, що доводиться занадто довго поратися з docker-ом на початковому етапі: я вигадував як запускати контейнери, з яких образів запускатися, робив Makefile, котрі утримували аліаси до довгих docker команд. Терпіти не міг docker-compose, тому що не хотів вивчати ще один інструмент екосистеми docker. І docker-compose up мене напружувала, особливо якщо там ще зустрічалися build конструкції, а не вже зібрані образи. Все, що я реально хотів – це просто робити продукт ефективно та швидко. Але я ніяк не міг розкласти по поличках використання docker.

Знайомство з Ansible

Нещодавно (трійку місяців тому), я попрацював з командою DevOps, майже кожен учасник якої, негативно ставився до docker. З причин:

  • docker править iptables (хоча можна відключити у daemon.json)
  • docker бажний і в проді запускати його не будемо
  • якщо docker daemon падає, то відповідно падають усі контейнери з інфраструктурою
  • у docker немає необхідності
  • навіщо docker якщо, є Ansible та віртуальні машини

На тій же роботі я познайомився з ще одним інструментом — Ansible. Колись я чув про нього, але не намагався писати свої плейбуки. А тепер я почав писати свої таски і тут моє бачення змінилося остаточно! Тому що я зрозумів: у Ansible є модулі для запуску тих же docker контейнерів, складання образів, мереж тощо, при цьому контейнери можна запустити не тільки локально, але і на віддалених серверах! Моє захоплення не було межі - я знайшов НОРМАЛЬНИЙ інструмент і викинув свої Makefile і docker-compose файли, вони були замінені на yaml таски. Було зменшено код за рахунок використання конструкцій типу loop, when, І т.д.

Docker для запуску сторонніх компонентів типу бд

Нещодавно я познайомився з ssh тунелями. Виявилося, що дуже просто "прокинути" порт віддаленого сервера на локальний порт. Видалений сервер може бути як машиною у хмарі, так і віртуальною машиною, запущеною у VirtualBox. Якщо мені чи моєму колезі потрібна бд (або якийсь інший сторонній компонент), можна просто запустити сервер із цим компонентом і загасити, коли сервер не потрібен. Прокидання портів дає такий же ефект, як і бд, запущена в контейнері docker.

Ця команда прокидає мій локальний порт на віддалений сервер з postgresql:

ssh -L 9000: локальний хост: 5432 [захищено електронною поштою]

Використання віддаленого сервера вирішує проблему розробки в команді. Таким сервером можуть користуватися відразу кілька розробників, їм не потрібно вміти налаштовувати postgresql, розбиратися з docker і з іншими витонченнями. На віддаленому сервері можна встановити ту ж бд у docker, якщо поставити специфічну версію важко. Все, що буде потрібно розробникам, - це видати ssh доступ!

Нещодавно прочитав що SSH тунелі це обмежена функціональність звичайного VPN! Можна просто наполягати на OpenVPN або інші реалізації VPN, налаштувати інфраструктуру і дати її в користування розробникам. Адже це так круто!

Благо, AWS, GoogleCloud та інші, дають рік безкоштовного використання, тож використовуйте їх! Вони копійчані, якщо їх гасити, коли не використовуються. Я завжди замислювався, в яких цілях мені знадобився б віддалений сервер типу gcloud, здається що я знайшов їх.

В якості віртуальної машини на локалі можна використовувати той же Alpine, який активно використовується в контейнерах docker. Ну або якісь інші полегшені дистрибутиви щоб швидше завантажувалася машина.

Підсумок: запускати бд та інші інфрастуктурні плюшки можна і потрібно на віддалених серверах або у virtualbox. мені не потрібний docker для цих цілей.

Трохи про docker образи та дистрибуцію

Я вже писав статтю у якій хотів донести, що використання docker образів не дає жодної гарантії. Docker образи потрібні тільки для того, щоб створити docker контейнер. Якщо ви зашиваєтеся на docker образ означає ви зашиваєтеся на використання docker контейнерів та ви будете тільки з ними.

Ви бачили де-небудь, щоб розробники ПЗ портували свої продукти тільки в docker образі?
Результат більшості продуктів – це бінарні файли під певну платформу, саме їх просто додають у docker образ, який успадковується від потрібної платформи. Ви не замислювалися, чому в dockerhub так багато схожих образів? Убийте наприклад nginx, ви побачите 100500 XNUMX образів від різних людей. Ці люди не розробляли сам nginx, вони просто в свій образ docker додали офіційний nginx і приправили своїми конфігами для зручності запуску контейнерів.

Взагалі зберігати можна просто в tgz, якщо комусь доведеться запускати це в docker то нехай в Dockerfile додають tgz, успадковуються від потрібного оточення і створюють додаткові плюшки які не змінюють самої програми в tgz. Той, хто створюватиме docker образ, буде знати, що це за tgz і що йому потрібно для роботи. Саме так я використовую docker тут

Підсумок: мені не потрібен docker registry, скористаюся якимось S3 або просто файловим сховищем типу google drive/dropbox

Docker в CI

Усі компанії, в яких я працював, схожі одна на одну. Вони, як правило, продуктові. Тобто вони мають якийсь один додаток, один стек технологій (ну може пара — трійка мов програмування).

Ці компанії використовують docker на своїх серверах, де запускається CI процес. Запитання — навіщо потрібно збирати проекти у docker контейнері на своїх серверах? Чому просто не підготувати оточення для складання, наприклад написати Ansible плейбук, який буде ставити потрібні версії nodejs, php, jdk, копіювати ssh ключі тощо на сервер, в якому відбуватиметься складання?

Зараз я розумію, що це стрілянина собі по ногах, тому що docker не приносить жодного профіту зі своєю ізоляцією. Проблеми з CI у docker з якими я зіткнувся:

  • знову потрібний docker образ для збирання. потрібно шукати образ або писати свій dockerfile.
  • 90% що потрібно прокинути якісь ssh ключі, секретні дані, які не хочеться писати в docker образ.
  • контейнер створюється і вмирає, губляться всі кеші разом із ним. наступне складання заново завантажуватиме всі залежності проекту, а це довго і не ефективно, а час — гроші.

Розробники не збирають проекти в docker контейнерах (я колись був таким фанатом правда, шкода себе в минулому xD). У java є можливість мати кілька версій та міняти однією командою на ту, яка потрібна зараз. У nodejs теж, є nvm.

Висновок

Я вважаю, що docker дуже потужний і гнучкий інструмент, в цьому його недолік (звучить дивно, так). За допомогою нього компанії легко "підсідають" на нього, використовують де потрібно і не потрібно. Розробники запускають свої контейнери, якесь своє оточення, потім це все плавно перетікає в CI, продакшн. DevOps команда пише якісь велосипеди щоб запустити ці контейнери.

Використовуйте docker тільки на останньому етапі у вашому робочому процесі, не тягніть його до проекту на початку. Він не вирішить ваших проблем бізнесу. Він тільки зрушить проблеми на ІНШИЙ рівень і буде пропонувати свої варіанти рішення, ви будете робити подвійну роботу.

Коли docker потрібен: прийшов до думки, що docker дуже хороший в оптимізації поставленого процесу, але не в побудові базового функціоналу.

Якщо ви все-таки вирішили використати docker, то:

  • будьте гранично обережні
  • не нав'язуйте використання docker розробникам
  • локалізуйте його використання в одному місці, не розмазуйте по всіх репозиторіях Dockefile та docker-compose

PS:

Дякую що дочитали, бажаю вам прозорих рішень у ваших справах та продуктивних робочих днів!

Джерело: habr.com

Додати коментар або відгук