Здравейте на всички!
Много искам веднага да започна с темата, но правилно би било да споделя малко за моята история:
Въведение
Аз съм програмист с опит в разработването на 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:localhost:5432 user@example.com
Използването на отдалечен сървър решава проблема с разработката в екип. Такъв сървър може да се използва от няколко разработчика, не е нужно да знаят как да настроят 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 образа от различни хора. Тези хора не са разработвали самия nginx, те просто добавиха официалния nginx в своя docker образ и го подправиха със своите конфигурации за удобство на стартиране на контейнерите.
Общо взето може да се съхранява просто в tgz, ако на някой му е необходимо да го стартира в docker, нека добави tgz в Dockerfile, наследява от нужната среда и създава допълнителни добавки, които не променят самото приложение в tgz. Онзи, който ще създава docker образ, ще знае какво е това tgz и какво му е нужно за работа. Именно така използвам docker.
Извод: не ми е нужен docker registry, ще ползвам някакво S3 или просто файлово хранилище като google drive/dropbox.
Docker в CI
Всички компании, в които съм работил, се оприличават една на друга. Обикновено са продуктов тип. Тоест имат някакво приложение, един стек технологии (може би две-три програмни езика).
Тези компании използват docker на своите сървъри, където се стартира CI процеса. Въпросът е — защо е необходимо да се събират проекти в docker контейнер на собствените сървъри? Защо просто не подготвите среда за компилация, например, да напишете Ansible плейбук, който да инсталира нужните версии на nodejs, php, jdk, и да копира ssh ключовете и др. на сървъра, където ще се извършва компилацията?
Сега разбирам, че това е стр shooting себе си в крака, защото 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:
- Преди време се натъкнах на и казват, че работи много добре с Ansible и позволява унифициране на процеса на създаване на образи (включително docker image)
Благодаря, че прочетохте, пожелавам ви прозрачни решения в бизнеса и продуктивни работни дни!
Източник: habr.com
