Хабрахабр

Docker — это игрушка или нет? Или всё-таки да?

Всем привет!

Ооочень хочется прям сразу приступить к теме, но правильнее будет немного рассказать про мою историю:

Вступление

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

А отсюда вытекает, что и у каждого разработчика должен стоять docker на локальной машине. Довольно долго (уже точно пару — тройку лет), я придерживался мнения, что docker это манна небесная и вообще очень крутой инструмент и абсолютно каждый разработчик должен уметь пользоваться им. В каждой второй есть упоминание про docker и если вы им владеете — это будет вашим конкурентным преимуществом 😉 Да что там про моё мнение, вы полистайте вакансии, которые размещаются на том же hh.

Одни говорили, что это удобная вещь, гарантирующая кроссплатформенность. На своем пути я встечался с многими людьми, с их разным отношением к 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-compose, потому что не хотел учить еще один инструмент экосистемы docker. Мне всегда не нравилось, что приходится слишком долго возиться с docker-ом на начальном этапе: я придумывал как запускать контейнеры, из каких образов запускаться, делал Makefile, которые содержали алиасы к длинным docker командам. Все, что я реально хотел — это просто делать продукт эффективно и быстро. И docker-compose up меня напрягала, особенно, если там еще встречались build конструкции, а не уже собранные образы. Но я никак не мог разложить по полочкам использование docker.

Знакомство с Ansible

По причинам: Недавно (тройку месяцев назад), я поработал с DevOps командой, почти каждый участник которой, негативно относился к docker.

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

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

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

Оказалось, что очень просто "пробросить" порт удаленного сервера на локальный порт. Недавно я познакомился с ssh тунелями. Если мне или моему коллеге нужна бд (или какой нибудь другой сторонний компонент), можно просто запустить сервер с этим компонентом и загасить, когда сервер не нужен. Удаленный сервер может быть как машиной в облаке, так и виртуальной машиной, запущенной в VirtualBox. Проброс портов дает такой же эффект, как и бд, запущенная в docker контейнере.

Эта команда пробрасывает мой локальный порт на удаленный сервер с postgresql:

ssh -L 9000:localhost:5432 user@example.com

Таким сервером могут пользоваться сразу несколько разработчиков, им не нужно уметь настраивать postgresql, разбираться c docker и с прочими изощрениями. Использование удаленного сервера решает проблему с разработкой в команде. Все что будет нужно разработчикам — это выдать ssh доступ! На удаленном сервере можно установить ту же бд в самом docker, если поставить спецефичную версию трудно.

Можно просто настоить OpenVPN или другие реализации VPN, настроить инфраструктуру и дать ее в пользование разработчикам. Недавно прочитал что SSH тунели это ограниченая функиональность обычного VPN! Это ведь так круто!

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

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

мне не нужен docker для этих целей. Итог: запускать бд и прочие инфрастуктурные плюшки можно и нужно на удаленных серверах или в virtualbox.

Немного про docker образы и дистрибутацию

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

Вы не задумывались, почему в dockerhub так много похожих образов? Вы видели где нибудь чтобы разработчики ПО портировали свои продукты только в docker образе?
Результат большинства продуктов это бинарные файлы под определенную платформу, именно их просто добавляют в docker образ который наследуется от нужной платформы. Эти люди не разрабатывали сам nginx, они просто в свой docker образ добавили официальный nginx и приправили своими конфигами для удобства запуска контейнеров. Вбейте например nginx, вы увидите 100500 образов от разных людей.

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

Итог: мне не нужен docker registry, воспользуюсь каким нибудь S3 или просто файловым хранилищем типа google drive/dropbox

Docker в CI

Они, как правило, продуктовые. Все компании, в которых я работал, похожи друг на друга. То есть у них есть какое то одно приложение, один стек технологий (ну может пара — тройка языков программирования).

Вопрос — зачем нужно собирать проекты в docker контейнере на своих серверах? Эти компании используют docker на своих серверах где запускается CI процесс. на сервер, в котором будет происходить сборка? Почему просто не подготовить окружение для сборки, например написать Ansible плейбук который будет ставить нужные версии nodejs, php, jdk, копировать ssh ключи и пр.

Проблемы с CI в docker с которыми я столкнулся: Сейчас я понимаю, что это стрельба себе по ногам, потому что docker не приносит никакого профита со своей изоляцией.

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

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

Вывод

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

Он не решит ваших бизнес проблем. Используйте docker только на самом последнем этапе в вашем рабочем процессе, не тащите его в проект в начале. Он только сдвинет проблемы на ДРУГОЙ уровень и будет предлагать свои варианты решения, вы будете делать двойную работу.

Когда docker нужен: пришел к мысли что docker очень хорош в оптимизации поставленного процесса но не в построении базового функционала

Если вы все-таки решили использовать docker, то:

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

PS:

Спасибо что дочитали, желаю вам прозрачных решений в ваших делах и продуктивных рабочих дней!

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть