Поняв Docker

    Если вы еще никогда не поддерживали чужие приложения, или пусть даже свои, но таких размеров, что уже не помещаются в одной голове, то прошу вас расслабиться, откинуться на спинку кресла и воспринимать прочитанное как поучительную сказку с надуманными проблемами, забавным сюжетом и очевидным счастливым концом. В противном случае, если реальный боевой опыт у вас имеется, добро пожаловать в ад, но с IDDQD и IDKFA.


    К вашему сведению! В этой статье мы рассматриваем само явление docker-контейнеров, а не составляем список микросервисов, которые гнездятся внутри. Этим мы займемся в следующей серии, во имя справедливости!


    UPDATE: пришлось заменить «докер» на «docker», иначе статья не ищется. Заранее прошу прощения за все «docker'ы» в тексте. Селяви.


    Что мы имеем сегодня


    • Зоопарк дубовых VPS-хостингов.
    • Дорогие IaaS и PaaS с гарантированным vendor lock in.
    • Уникальные сервера-снежинки.
    • Ворох устаревших зависимостей на неподдерживаемой операционке.
    • Скрытые связи частей приложения.
    • Незаменимый админ полубог на скейтборде.
    • Радуга окружений: development, testing, integration, staging, production.
    • Генерация конфигов для системы управления конфигами.
    • Feature flagging.

    Удивительно то, что корень всех этих проблем только в одном: сервер дорого поднимать, а потом еще и дорого гасить. Дорогим может оказаться время потраченное на художественное плетение по конфигам, или энтерпрайз железяка просто долго стартует, или состояние серверов надо хитро бекапить и потом восстанавливать, или всё просто и быстро, но работает только на какой-то уникально дорогущей платформе, с которой не сбежишь.


    Конечно, это капитанское вступление. И цель вступления как раз в капитанстве — показать, что эти проблемы уже настолько банальны, что даже простое их перечисление заставляет кое-где болеть.


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


    Если ваши уши владеют английским, то прошу сначала послушать восторжженное Введение в docker от основателя.


    Назад к основам


    Как часто бывает, в какой-то момент состояние некой системы становится неуправляемым и требует новых технологий. В программировании, правда, часто выходит наоборот — требуется вспомнить старые технологии. Вот и в случае с docker'ом не случилось ничего нового: взяли принципы функционального программирования (другие видят ООП) и микроядерности, применили к инфраструктурному слою приложения (серверам, сети и т.п.) и получили stateless-иммутабельные-изолированные-микросервисы. Все прелести docker'а вырастают именно из этого. Как известно, функциональщина не так проста, как хотел бы Рич Хикки. Чтобы можно было каждый день пользоваться мудростью предков, нужно иметь хорошие инструменты. Docker как раз и есть такой инструмент.


    Вот базовые отличия docker-контейнера (не микросервиса, см. выше) от простого сервера.


    Стейтлес


    Конфигурация контейнера не может и не должна меняться после запуска. Все предварительные работы делаются на этапе создания образа или старта контейнера: конфиги, порты, общие папки, переменные окружения, всё это должно быть известно к моменту старта контейнера. Конечно, docker позволяет запущенному внутри контейнера процессу делать со своей памятью и файловой системой всё что тому заблагорассудится, но трогать что-то, что можно было потрогать до запуска считается плохим тоном.


    Чистый (pure)


    Контейнер ничего не знает о хост системе и не может мешать другим контейнерам: ни влезть в чужую файловую систему, ни послать сигнал чужому процессу, ни даже в случайный порт стукнуться. На то он и контейнер. Само собой, docker позволят контейнерам общаться, но только строго задекларированными способами. Еще можно запускать контейнеры наделенные какими-нибудь суперсилами, например, доступом к реальной сети или физическим девайсам.


    Ленивый


    При запуске контейнер не копирует файловую систему образа, из которого создан. Контейнер всего-лишь создает пустую файловую систему поверх образа. В docker'е это называется слоем. Так же устроены и образы. Образ состоит из списка (геологических) слоев, накладывающихся друг на друга. Отсюда такая высокая скорость запуска нового контейнера: меньше секунды.


    Декларативный


    Все свойства контейнера хранятся в декларативном виде. Этапы создания образа тоже описаны строго разделенными шагами. Параметры сети, содержимое файловой системы, объем памяти, публичные порты и так далее и тому подобное задается в Dockerfile или статичными ключами при запуске. Всё это легко читается на паре экранов текста даже для очень сложной системы.


    Функциональный


    Контейнер делает только одно дело, но делает его хорошо. Предполагается, что в контейнере будет жить всего один процесс (можно с семьёй), выполняющий всего одну функцию в приложении. За счет того, что в контейнере нет своего ядра, загрузочного раздела, init-процесса и, чаще всего, даже пользователь всего один (псевдо-root) — то есть в контейнере нет полноценной операционной системы — за счет отсутствия всего этого контейнер стартует так быстро, как стартовал бы ваш сервис будь операционная система уже полностью загружена. Это узкая специализация делает функцию реализуемую контейнером предсказуемой и масштабируемой. Так как процесс только один, ему неоткуда ждать (если только снаружи) переполнения логов, попадания в своп и тому подобного.


    Строгий


    По-умолчанию, docker запрещает контейнеру всё, кроме доступа в сеть (которую тоже можно запретить). Однако, при необходимости позволяется нарушать любые эти правила, когда нарушить правила бывает логичнее. И что интересно, разрешать доступ также просто, как и запрещать. Соединять или разъединять контейнеры в docker'е с каждой версией становится всё проще и проще, особенно радует работа с сетью, распределенной по датацентрам.


    Чем docker не является


    Docker часто путают с Vagrant’ом или OpenVZ, или даже VirtualBox’ом. Docker это всего-лишь user-space демон на языке Go, который умело жонглирует уже существующими технологиями ядра Linux. Думаю, стоит объяснить подробнее, так как сам начал знакомиться с темой с запроса «docker vs. vagrant».


    Не вагрант


    Вагрант занимается тем, что управляет виртуальными машинами (или, более приближенно к теме хостинга, виртуальными серверами). Так же как и у docker'а, у вагранта есть целая библиотека образов виртуальных машин, и он как и docker умеет их снепшотить, скачивать и заливать, настраивать и запускать. Но повторюсь, Vagrant управляет полноценными тяжелыми виртуальными машинами запущенными, например, в VirtualBox, VMWare, DigitalOcean, AWS, да где только он их не запускает. Шикарная вещь, этот вагрант, если вам нужна полноценная виртуальная машина с состоянием внутри.


    Не виртуальная машина


    И конечно, docker вовсе не является новой технологией (пара)виртуализации, как например KVM/Qemu, VirtualBox/VMWare/Parallels, XEN, etc. Docker-демон (не путать с консольной командой docker) работает только в Линуксе (и скоро в винде) поверх линуксовых же контейнеров. А контейнеры, в свою очередь, не являются полноценной виртуальной средой, так как они делят общее запущенное ядро одной физической машины. Если вы работали с OpenVZ или щупали Linux Containers то вы должны знать, как они устроены, чем хороши и плохи.


    А что же тогда docker?


    Docker состоит из трех частей:


    1. docker daemon — сердце docker'а. Это демон работающий на хост-машине и умеющий скачивать и заливать образы, запускать из них контейнеры, следить за запущенными контейнерами, собирать логи и настраивать сеть между контейнерами (а с версии 0.8 и между машинами). А еще именно демон создает образы контейнеров, хоть и может показаться, что это делает docker-client.


    2. docker это консольная утилита для управления docker-демоном по HTTP. Она устроена очень просто и работает предельно быстро. Вопреки заблуждению, управлять демоном docker'а можно откуда угодно, а не только с той же машины. В сборке нового образа консольная утилита docker принимает пассивное участие: архивирует локальную папку в tar.gz и передает по сети docker-daemon, который и делает всё работу. Именно из-за передачи контекста демону по сети лучше собирать тяжелые образы локально.


    3. Docker Hub централизованно хранит образы контейнеров. Когда вы пишете docker run ruby docker скачивает самый свежий образ с руби именно из публичного репозитория. Изначально хаба не было, его добавили уже после очевидного успеха первых двух частей.

    Что docker заменил


    Для пользы дела стоит перечислить технологии, ставшие лишними при работе с инфраструктурой после появления docker'а. Хочу заметить, что для других применений эти технологии до сих пор незаменимы (вот как, например, заменить SSH или Git используемые по назначению?).


    Chef / Puppet / Ansible


    Очевидный кандидат на вылет — системы управления конфигурацией stateful сервера. Им на смену приходит лаконичный и быстрый Dockerfile. Так как docker умеет собирать образ контейнера за секунды, а запускать сам контейнер за миллисекунды, больше не надо громоздить скрипты, поддерживающие тяжелый и дорогой сервер в актуальном состоянии. Достаточно запустить новый контейнер и погасить старый. Если вы и до прихода docker'а использовали Chef для быстрого развертывания stateless серверов, то вы уже любите docker, а статью читаете ради удовольствия и сбора аргументов против админа-слоупока, сидящего на FreeBSD 4.11.


    Upstart / SystemD / Supervisor / launchd / God.rb / SysVinit, тысячи их


    Архаичные системы запуска сервисов, основанные на статичных конфигах идут в сад. На их место приходит docker daemon, который является init-подобным процессом умеющим следить за запущенными сервисами, перезапускать отвалившиеся, хранить коды выхода, логи, а главное, скачивать любые контейнеры с любыми сервисами на любой машине, не важно какая у машины «роль».


    Ubuntu_14.04.iso / AMI-W7FIS1T / apt-get update


    Так же как и вагрант, docker позволяет, наконец, забыть про скачивание давно устаревших установочных DVD-образов (совсем недавно пришлось качать для Dell блейда), помнить панели управления разных облачных платформ и сокрушаться, что самой свежей убунты у них никогда нет. А главное, запустить свой собственный кастомный образ со всем необходимым можно за пару минут, собрав его на локальной машине и загрузив в бесплатное облако Docker Hub. И никаких больше apt-get update после установки — ваши образы всегда будут готовы к работе сразу после сборки.


    RUBY_ENV, database.dev.yml, testing vs. staging vs. backup


    Так как docker позволяет запускать контейнеры со всеми зависимостями и окружением бит-в-бит совпадающим с тем, что вы сконфигурировали, можно за пару секунд поднять точную копию продакшна прямо на своём ноутбуке. Все операционные системы, все сервера баз данных и кеширования, само приложение и версии библиотек им используемые, всё это будет точно воспроизведено на девелоперской машине или на машине тестера. Всегда мечтали иметь резервный продакшн сервер готовый к бою в случае падения главного — docker-compose up и у вас два боевых сервера являющихся копией друг друга с точность до бита. Начиная с версии docker'а 1.10 идентификаторы контейнеров являются их же собственной SHA256 подписью гарантирующей идентичность.


    Xcode, brew, port install, ./configure && make && sudo make install, mysql --version


    Всё, больше никаких мук с установкой серверного софта локально, никаких несовпадений версий мускуля для разных проектов, и возни с удалением всего этого добра после завершения проекта. Это еще ничего, если вы маковод, а вот если у вас виндоус… Docker позволит запускать почти всё, что угодно, лишь бы это работало на линуксе. Можно и Хром в контейнере запускать.


    SSH (sic!), VPN, Capistrano, Jenkins-slave


    Для того чтобы запустить контейнер не нужно получать root на сервере, морочиться с ключами и настраивать систему деплоя. С docker'ом деплой выглядит как сборка и настройка физического сервера дома, дальнейшего его всестороннего тестирования, а затем магического перемещения в произвольное количество датацентров одной командой. Для этого достаточно запустить docker run на своём ноутбуке и docker сам секьюрно подключится к серверу по TLS и всё запустит. Внутрь контейнера тоже попасть проще простого: docker exec -it %containername% bash и у вас в руках консоль для отладки. Можно даже rsync через docker'овский туннель гонять вот так: rsync -e 'docker exec -i' --blocking-io -rv CONTAINER_NAME:/data ., главное не забыть добавить --blocking-io.


    Git (!!!)


    Используете Git как способ выкатки приложения на сервер? Отлично! Docker это буквально новый Git, только для контейнеров. Вместо git push (и настройки кучи дополнительного софта и сопряжения с Github’ом) вы получаете docker push. Вместо запуска скрипта деплоя, docker-compose up. И все контейнеры обновятся и перезапустятся. Конечно, если вы хотите zero-downtime деплой, надо будет немного покумекать. Но даже без этого, ваши пользователи увидят MAINTENANCE.HTML не более чем на несколько секунд. Вдобавок, теперь вы можете отправлять тестру не хеш коммита гита и ждать, пока он (или дженкинс) воссоздаст окружение, а просто шлёте ему хеш контейнера и он его сразу запускает.


    Datacenter lock-in


    Всё, больше его нет. Хотите переезжайте всем приложением за пару минут на другой континент, а хотите — размазывайте своё приложение по всему земному шару. Контейнерам всё равно где крутиться, они объединены виртуальной сетью, видят и слышат друг друга отовсюду, включая девелоперкую машину в случае живой отладки.


    bundler, rvm, dotenv, /opt


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


    *.log, *.pid


    И логами, и процессами заведует docker. Есть много драйверов сборки логов (kudos ➞ Fesor) и отправки их на анализ. Можно грабить корованы.


    useradd www


    Можно забыть детские кошмары о том, что веб-сервер кто-то взломает и получит доступ ко всей системе, если его запустить от рута. А еще не нужно больше искать следы взлома в страхе, что теперь надо всё переустанавливать. Просто обновите софт в образе, убейте контейнер (или всю машину целиком, только базу забекапьте, пожалуйста) и перезапустите сервис.


    chroot, CGroups, LXC


    Docker объединяет и абстрагирует сложные и разрозненные технологии в своих библиотеках libcontainer, runC, libnetwork. Если вы пробовали настроить LXC, то уже любите docker. Пока эти библиотеки как отдельные проекты еще свежи, но уже используется в самом docker'е.


    Вкусности docker'а


    Dockerfile


    Может показаться, что Dockerfile это старый добрый Chef-конфиг, только на новый лад. А вот и нет: от конфигурации сервера в нем осталась только одна строка — имя базового образа операционной системы. Остальное же — часть архитектуры приложения. И это стоит воспринимать, как декларацию API и зависимостей именно сервиса, а не сервера. Эта часть пишется проектирующим приложение программистом по ходу дела естественным путём прямо в процессе разработки. Такой подход дает не только поразительную гибкость конфигурации, но и позволяет избежать испорченного телефона между разработчиком и админом. Больше про это ждите в статье про микросервисы.


    Слоёные имаджи


    Имаджи в docker не монолитны, а состоят из copy-on-write слоев. Это позволяет переиспользовать файлы базового readonly имаджа во всех контейнерах бесплатно, запускать контейнер, не копируя файловую систему имаджа, делать контейнеры readonly, а также кешировать разные этапы сборки имаджа. Сильно похоже на коммиты гита, если вы знакомы с его архитектурой.


    Плагины и драйверы


    Fesor:


    Для него есть и драйвера логгеров, и плагины для волумов и сетей… словом… и это все еще будет развиваться но и уже немало.

    Самое приятное, что никакой магии в плагинах нет. Простые, как выражаются разработчики докера, «водопроводные работы».


    docker-daemon — это асинхронный HTTP-сервер


    Да, ребята решили не играть в параллельность, а замутить Single Actor архитектуру через асинхронность, как в nginx. Только нам на радость выбрали язык попроще и запилили docker на Go, так что не нужно становиться Игорем Сысоевым, чтобы читать исходники docker'а.


    docker in docker


    Можно разрешать одним контейнерам управлять другими контейнерами. Таким образом получается, что на хост машине не будет установлено ничего, кроме docker'а. Делается это так:


    docker run -v /var/run/docker.sock:/var/run/docker.sock \
           -v $(which docker):/bin/docker \
           -ti ubuntu

    Но это не настоящий иерархичный docker-in-docker, а плоский зато стабильный вариант.


    VXLAN


    В последних версиях docker'а появилась поддержка распределенной сети. В статье это не раз упоминается, и не зря. С самого начала у docker'а была проблема с объединением нескольких машин в единый кластер, или даже нескольких контейнеров в группу. Предлагались кривые решения с проксированием, настройкой хост машины, и прочие некошерные вещи. Теперь же docker умеет сам настраивать на хост машине VXLAN, который объединяет несколько физических машин и docker'ов на них в единую виртуальную IP сеть. В такой сети контейнеры будут видеть друг друга как если бы они работали в одной сети. Само собой, такой кластер упирается в ширину сети между машинами, но и это уже прорыв для рядового девопса. А если еще и NAS запилить, то уже взрослый многофункциональный кластер получается.


    Куда дальше?


    На передовом крае запуск распределенных кластеров, docker как операционная система, docker-in-docker-in-docker. И, как любая открытая платформа, docker разделяется на составляющие части развиваемые отдельными группами, что очень ободряет коллектив.


    Swarm? Machine! Compose!!!


    Кроме самого docker'а, есть еще несколько интереснейших проектов внутри сообщества docker'а, которые отлично дополняют контейнеры: Machine, Compose и Swarm. О них — в следующих статьях.


    Робота над ашипками


    Благодарю покорно за холивар в комментах. Чтобы такое добро не пропадало, постараюсь раскрывать тему глубжее, отвечая прямо в статье.


    VasilioRuzanni:


    А аргументы Phusion в пользу использования baseimage-docker еще актуальны?

    Вот проблемы, которые описаны в статье по ссылке:


    1. Ubuntu не спроектирована для работы в контейнере.


      Базовый образ убунты в docker'е это ее облачный вариант с правильно выключенным init и затюненным dpkg. Получается, что таки допроектировали. Для старых добрых OpenVZ контейнеров убунту тоже приходилось допиливать, и ничего, жили и живем годами в продакшне.


    2. Нет init — будут зомби.


      Да, зомби всё еще копятся. Если запустить fork-бомбу, то через 10 секунд на хост-машину с docker'ом уже не папость по SSH: can't fork. К чести docker'а, запуск docker ps покажет все запущенные контейнеры, а docker kill погасит бомбу и порипает всех зомби.


      Однако, как часто бывает, если хотеть что-то сломать, то что-то таки сломается. Если в вашем приложении воркеры действительно часто внезапно мрут, ожидая завершения дочернего процесса, то у меня для вас плохие новости. Если же вы в таком поведении воркеров не видите ничего плохого, то дались вам эти зомби? Если же частые разрывы в иерархии процессов у вас by design, то да, стоит посмотреть в сторону, например, tini.


    3. Syslog?


      Так как docker предполагает, что микросервис шлет свои логи в STDOUT и STDERR, syslog не нужен. Docker сам управляет логами, и позволяет их сразу слать на анализ без сохранения. Если хотите хранить, то, во-первых, это не по облачному феншую, а во-вторых, логи таки могут занять весь диск.


    4. Cron?


      Что простите? А дженкинс нам на что? Как можно юзать крон в 2016 году? Однако, иногда очень-очень хочется, и, стоит надеяться, что docker инкапсулирует запуск сервисов по времени в самого себя. Но и сейчас никто не мешает запустить контейнер с произвольной реализацией крона и запускать контейнеры из него.


    5. SSH?


      По сути, консольная утилита docker уже и есть SSH. Она связывается с демоном по зашифрованному соединению, аутентифицируется по ключу, запускает шел и эмулирует терминал. Есть даже аналог scp.


    6. Неправда, что docker рассчитан на запуск только одного процесса на контейнер!


      Неправда, что неправда!


    7. А давайте сделаем из непривычного docker'а привычный OpenVZ.


      А давайте без давайте.



    powerman:


    Безопасность подразумевает необходимость ежедневных обновлений пакетов ОС…

    Приличный тред получился.


    Во-первых, если у вас живое приложение, то не будет никаких проблем с обновлением любого софта, и не только «пакетов ОС», а еще и версий фреймворков, баз данных, хитрожёлтых самопальных зависимостей, и еще чего угодно. Взяли — и пересобрали.


    А во-вторых, работу с «пакетами ОС», если они на самом деле используются в каком-то вашем микросервисе, надо при обновлении тестировать. А готовить новый релиз к тестированию в мире docker'а принято с помощью — подожди-подожди — пересборки.


    И главное, спросите любого владельца маломальски прибыльного сайта, что ему важнее: hardened gcc (с PIE и SSP) и потенцально невзламываемая до следующего shellshock интернет-шаурмятня или мгновенный выкат новой версии приложения без «этого тупого бага с оплатой», уносящего по 100500 денег в час?


    Можно взглянуть на безопасность из будущей статьи про микросервисы. Современный сервер состоит из приложения и системы. Обе части надо защищать и обновлять. В предельном случае, к которому стремится сообщество docker'а, в контейнере не будет системы, а только приложение. И это приложение должно делать только одну функцию, например CQRS из базы данных. Тогда паника админов по поводу плохого базового образа убунты бесследно проходит, так как убунты в контейнере больше нет.


    grossws:


    Оверлейный vxlan, про который пишет автор публикации в предпоследнем абзаце, — без шифрования. Т. е. если использовать --link между контейнерами, то весь трафик внутри должен быть шифрованным и подписанным. Много ли людей будут это делать, а не воспринимать --link, как секьюрный оверлей? Я, например, сейчас использую tinc (p2p vpn), как паллиативное решение.

    Прошу всех читателей не воспринимать --link, как секьюрный оверлей, и сам не буду. Если ваше приложение перезрело приватное облако в одном датацентре и дозрело до распределенного по глобусу монстра, пожалуйста, настройте шифрование.


    @админы:


    Docker админам не нужен, ведь уже же есть «правильная инфраструктура». Пусть всё остается как есть, а кодеры учатся кодить под «правильную инфраструктуру».

    Рекомендую почитать «Механическое пианино» Воннегута. За известным исключением, все профессии, однажды, теряют свою маржу.


    Scf:


    Если вам нужны логи в кибане не в виде текста, а в виде структурированных данных, если у вас ненадежная сеть (привет, амазон), если вас волнуют потенциальные даунтаймы и узкие места в системе, если вы не можете себе позволить потерю логов из-за сетевых проблем, то…
    Мы долго думали об этом, но варианта лучше и гибче, чем писать логи в каталог, смапленный наружу, где они подхватываются логсташем, который парсит их в зависимости от их типа и шлет в кибану json-документы, не нашли.

    Да, с логами надо быть осторожными. Если лог напрямую слать по сети, то можно залочить процесс, пишущий лог. Полностью поддерживаю описанное решение, особенно в том случае, если логсташ тоже крутится в контейнере ;)


    Fesor:


    …есть множество кейсов когда это неудобно (shared memory например надо организовать между процессами)

    Shared memory подразумевает выполнение процессов на одной машине. Если эти два процесса запущены на одном ядре, как в случае docker'а, то им достаточно иметь доступ к одному и тому же файлу (один inode в файловой системе), чтобы расшарить память. Рецепт для docker'а очень прост: делаете mmap файлу из общего volume'а и всё.


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


    JPEG:


    Да, последний шаг осталось сделать докеру до гита: мердж имаджей с резолвом --theirs. Я серьёзно :)

    Мержа нет потому, что рисковано мержить бинари, зависящие друг от друга. А ребейза нет потому, что нельзя проверить, не зависят ли верхние слои от нижних. В общем, полного гита не получится.

    Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

    Что для вас докер?
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 241
      +1
      Докер работает только в Линуксе (и уже в винде, не?)

      С оговорками, через клиентскую прослойку к виртуальной машине в VirtualBox.
      Кстати, nginx нормально из коробки не заработал, какой-то баг с sendfile и виртуальной машиной.
        +2
        Как раз в Линуксе он работает без прослоек.

        У меня nginx заработал из коробки, и даже с sendfile on;. У вас какая операционка/виртуалка? Радует то, что деньки фразочки «а на моей машине всё работает» уже сочтены ;)
          +2
          Радует то, что деньки фразочки «а на моей машине всё работает» уже сочтены ;)

          С учетом, что докер это всего лишь изоляция процессов, а не виртуализация, то явно не сочтены.
            +2
            Скажем так, фраза "это работает в моем контейнере" явно надежнее чем "это работает на моем лэптопе".

            Суть то в том что мы можем снэпшет "рабочий" перенести без необходимости внесения изменений каких-либо.
            +1
            Автор комментария скорее всего комментировал ваше "и уже в винде, не?". В общем, повторю — docker-daemon для Windows нет и не уверен будет ли вообще (хотя какая-то партнёрская программа у них с Microsoft наладилась уже давненько, может и пилят что-то под капотом), вот что сделали для Windows, так это собрали клиент docker-cli (aka docker), так что просто из Windows можно управлять удалёнными docker-daemon'ами (ну и docker-swarm'ами).
              +1
              Я себе слабо представляю ситуацию с контейнерами в виндоусе. Если есть здесь кто-то, кто ждет докер-демон под виндоус, как я ждал его под линукс, расскажите, пожалуйста, зачем он вам?
                +1
                Ждал я их, чтобы разворачивать обычные линуксовые образы под виндой. Но, судя по всему то, что "пилят что-то под капотом", будет, как и в линуксе, оберткой над ядром, а значит разворачивать на виндовых серверах линуксовые образы не получится, только контейнеры чисто под винду либо платформонезависимые (дата волумы, например)
                  +1
                  То есть вы ожидали появления возможности запуска ELF исполняемых файлов на винде без виртуалок да ещё и сразу в контейнерах с контролем ресурсов? Line (по аналогии с Wine)? Грандиозная идея :)
                    +1
                    Типа того :) Мысль такая не самому в голову пришла, меня убеждали что в вин2016 нативная поддержка докера.
                      +2
                      ну дык она там и есть, уже доступна в превью, только вся суть контейнеров в том, что процессы в нем на ядре хоста исполняются, а тут само собой понятно, какие это дает ограничения
                        +1
                        Ну, я примерно из этих соображений говорил "не может быть, что контейнер от убынты на винде нативно запустится", а меня убеждали в обратном.
                          +1
                          Ну вообще, линукс на венде запускают.
                            +1
                            Вообще, я в курсе. И даже, как это сейчас называется, пуш-реквестил куда-то куда-то откуда-то.

                            Вот думал что МС что-то из подобных проектов развила, когда меня убедили наши админы, что, как минимум, официальные образы нашего основного стека поднимутся. По сути не соврали почти — условный "LAMP" можно уже нативно поднять в докере под виндой… Но как-то осадочек остался — если "вдруг" у нас примут решение, что девелоперы должны будут поддерживать винду, то придётся искать варианты...
                              +1
                              colinux, к сожалению, мертв.
                    +1
                    Там давно есть свой App-V, а контейнеры с управлением через docker включат в Windows Server 2016.
                      +3
                      Пока кто-то ждёт, кто-то уже пользуется)
                      1) https://ru.wikipedia.org/wiki/VMware_ThinApp
                      2) http://www.cameyo.com/
                      Хотя с nix конечно рядом не стояло...
                      +1
                      Все верно, коммент был о Windows-хосте.
                    +1
                    И кстати, на локальной машине запускать докер не вижу смысла для себя, так как для пущей изоляции и приближенности к продакшену использую docker-machine всегда.
                      0
                      Расскажите, пожалуйста, где всё-таки Вами хранятся сгенерированные образы: к примеру, Вы поднимаете какой-то микросервис на рубине, делаете образ на основе образа из Docker Hub.
                      Что дальше, куда складывать? Туда же идут обновлённые каждый день в процессе разработки новые версии?
                        +4
                        либо пушить в тот же docker hub (за денежку есть приватные репозитории) либо поднять свой docker-distribution. Помимо docker hub есть еще сервисы.

                        Грубо говоря docker build && docker push
                          0
                          Добавлю, что во время разработки запуск образов происходит локально, их не нужно никуда заливать, всё происходит внутри машины с докером.
                            0
                            Ну собственно прямая аналогия с git/hg. Пушим только если хотим поделиться с другими.
                              0
                              Я про docker-distribution, который объединяет машины разработчиков и сервера.
                              Спасибо, теперь чуть понятнее.
                                0
                                Персонально я не использовал еще docker-distribution ни для чего.
                                  0
                                  который объединяет машины разработчиков и сервера.

                                  Это просто репозиторий образов. Я использую его для своих проектов (потому что docker hub немного дорогова-то для меня выходит, у меня только 6 проектов на докере а количество репозиториев уже подходит к полусотне, что же будет через пару месяцев).
                            +1
                            Как мне рассказали после презентации МС, Докер работает нативно на Винде уже, но со своими образами. То есть ставим в Докерфайле что-то вроде FROM Windows7, и далее виндовой консолью рулим.
                            +5
                            Понравилась статья, хотелось бы что-то более приближенное к разработке увидеть в следующих статьях.
                            Пробовал работать в нем, но как-то забросил, написал .sh установочный файл, который устанавливает все программы, прописывает нужное в конфигах и запускает.

                            Можно задать несколько вопросов:
                            Один контейнер — одна задача?
                            Т.е. есть контейнер с БД (mongoDB, MySQL, etc.), контейнер с Nginx, контейнер с данными (PureFTPd, ProFTPd, etc.)?
                            Каким образом я смогу соединяться с БД из контейнера с данными? В конфигах Nginx, какой будет root папка (получается она из другого контейнера)?
                            Когда я отправлю на Docker Hub проект, то получается если был контейнер с БД, то данные тоже отправится и при запуске на другой машине уже всё будет готово и БД и все файлы?
                              +1
                              Создаете дата контейнер и линкуете его со всеми контейнерами и у всех этих контейнеров будут одинаковые директории, еще прелесть в том, что в содержимое директорий в каждом контейнере может быть под совершенно разными путями. Аналог ярлыков линукса (ln -s ..)
                                +4
                                Это не "аналог ярлыков", это обычный bind mount.
                                +2
                                Один контейнер — одна задача?

                                Да. Но это лучше будет рассмотреть в отдельной статье про микросервисы. Докер, как платформа позволяет запускать несколько задач в контейнере, но лучше пересесть на микросервисы.

                                Т.е. есть контейнер с БД, контейнер с Nginx, контейнер с данными?

                                Да. Но для данных желательно использовать именованный volume, который подключается к двум контейнерам для расшаривания данных между ними.

                                Каким образом я смогу соединяться с БД из контейнера с данными?

                                Лучше никаким не связываться. Пусть пускает в себя по FTP и больше ничего не умеет. А данные кладет в volume.

                                В конфигах Nginx, какой будет root папка (получается она из другого контейнера)?

                                Да, папка будет из другого контейнера, или, лучше, из именованного volume.

                                Когда я отправлю на Docker Hub проект, то получается если был контейнер с БД, то данные тоже отправится и при запуске на другой машине уже всё будет готово и БД и все файлы?

                                Данные не принято хранить в контейнерах. Они должны храниться за пределами контейнеров. И мы опять говорим о микросервисах. Это прекрасно, значит быть второй статье.

                                Но можно и запихнуть файлы базы данных в контейнер, например, для быстрого разворачивания тестового окружения и спроса изменений простым перезапуском.
                                  +4
                                  Да. Но это лучше будет рассмотреть в отдельной статье про микросервисы. Докер, как платформа позволяет запускать несколько задач в контейнере, но лучше пересесть на микросервисы.

                                  А аргументы Phusion в пользу использования baseimage-docker еще актуальны в последних версиях Docker? Вообще, целесообразно ли его использовать? В сообществе Docker, на первый взгляд, никто его не использует.

                                  Данные не принято хранить в контейнерах. Они должны храниться за пределами контейнеров.

                                  А в чем проблема использовать Data Volume Containers? Реально интересно, так как на этот счет какие-то полярные мнения в сообществе Docker'а.

                                  P.S. Статью про микросервисы было бы очень интересно почитать
                                    +2
                                    А в чем проблема использовать Data Volume Containers?

                                    Да, собственно, ни в чём. Главное, данные не в них хранить, а использовать их лишь как единый интерфейс к данным, хранящимся на хосте, на сетевой шаре, где угодно ещё.
                                      +1
                                      Ну так вся суть Data Volume Container'а же в том, что данные храним именно в нем (главное, не удалять этот контейнер). Если мы используем папку на хосте, то какой тогда вообще смысл в отдельном контейнере для этого? Плюс, в случае папки на хосте, мы привязываем сервис работы с данными к определенному хосту Swarm-кластера и вынуждены настраивать этот хост особым образом.
                                        +1
                                        с версии 1.9 data-only контейнеры не нужны. Все фиксится named volumes. Там же добавили драйвера для волумов, так что можно в качестве оного подключить распределенную файловую систему например.
                                          +1
                                          Ну в документации Докера как раз написано про Data-Only Containers как один из вариантов. Я читал про --volume-driver, который позволяет использовать, например, Flocker. А что именно поменялось с 1.9 в этом плане? Реально интересно, ибо сам еще новичок в Docker (и DevOps вообще), и хотя активно отслеживаю эту тему — не всегда понятно, какой из доступных опций лучше воспользоваться.
                                            +3
                                            Документация чуть отстала от реальности, потому я обычно отслеживаю изменения через github ишусы.

                                            Поменялось то что теперь можно создать волум отдельно от контейнера, и мэпить его. Это невилирует необходимость держать контейнер-пустышку как промежуточное звено. Там же вся соль была в том, что волумы закрепляются за конкретными инстансами контейнеров, по хэшу. А сами волумы имен не имели. Вот это и поправили.
                                              +1
                                              Ага, я тоже смотрю CHANGELOG, но как-то пропустил этот момент. В документации об этом прямо совсем вскользь крупица информации и дальше большой кусок про "Data Volume Containers".

                                              А в чем получается практическое отличие named volume (с local-драйвером) от, собственно, от bind-mount папки хоста напрямую?
                                                +1
                                                тем что нам не нужно создавать эту папку руками, и мы таким образом упрощаем процесс провиженинга хоста. По сути достаточно поставить докер на удаленной машине через docker-machine и далее дергать docker-compose обычный. Но механика та же, да.
                                          +3
                                          Если мы используем папку на хосте, то какой тогда вообще смысл в отдельном контейнере для этого?

                                          Чтобы обычные ("кодовые") контейнеры запускались чисто, без привязки к хосту, а править конкретное место хранения можно было только в одном месте, что особенно полезно, когда данные шарятся между несколькими контейнерами.
                                        +2
                                        Дописал про baseimage-docker в конец статьи. Спасибо за хороший вопрос, совсем забыл, что сам начинал изучать докер с их критической статьи :)
                                      +2
                                      +20
                                      Предположим на секунду, что нас немного волнует безопасность… в том смысле, что злоумышленник не должен получить доступ ко всем этим микросервисам и их базам данных. Сейчас у нас пяток серверов с Hardened Gentoo, на каждом, скажем, пара десятков микросервисов. И примерно раз в сутки эти сервера обновляются (а когда случается какой-нить shellshock или heartbleed — то и несколько раз в сутки).

                                      Теперь мы решили перенести все эти микросервисы в докер. Они все разные, написаны на разных языках, используют разные библиотеки, etc. — так что получаем мы по отдельному образу на каждый микросервис, т.е., скажем, десятков пять образов. Выкатываем их на сервера и радуемся жизни… примерно часов 10.

                                      А потом наступает новый день и возникает необходимость обновить базовый образ Hardened Gentoo лежащий в основе всех образов микросервисов. Плюс обновить те дополнительные библиотеки и приложения, которые были доустановлены поверх базового образа в образах разных микросервисов — причём в разных образах они, естественно, будут немного отличаться, так что в /etc разных образов придётся обновлять разные конфиги, и делать это немного по-разному. И вместо обновления 5-ти примерно одинаковых (вынужденно одинаковых, разумеется) серверов внезапно нужно пересобрать 50 разных (ведь в этом суть докера — каждому приложению дать уникальную для него среду выполнения!) образов. Кому-то только что конкретно прибавилось работы.

                                      И, в качестве вишенки на торте, после того как пересобрали все образы — перезапустить все контейнеры, ведь это единственный способ "доставить" сегодняшнее обновление системы. При этом надо отметить, что когда обновляется, например, openssl, то мы, конечно, перезапускаем все процессы куда она подгружена… но, как правило, после ежедневного обновления системы перезапускать вообще ничего не требуется, или достаточно перезапустить один сервис. И далеко не все микросервисы безболезненно можно перезапускать — кто-то долго стартует, кто-то теряет разогретые кеши, кто-то закрывает сокеты миллиона подключенных юзеров и все эти юзеры начинают судорожно переподключаться создавая этим всплеск нагрузки на пустом месте…

                                      А приложение продолжает развиваться, и вот у нас уже не 7 серверов вместо 5-ти, а 100 образов вместо 50-ти… Хотя, вру. У нас уже давно обратно 7 серверов, а докер используется только для разработки и тестирования, где безопасность никого не волнует.

                                      И это я ещё оставил за кадром вопрос небезопасности самого докера — а ведь это сервис, который работает под root, активно меняет настройки всей системы (так что бессмысленно даже пытаться SeLinux-ом или другой RBAC обрезать его права до необходимого минимума как принято делать для всех остальных рутовых сервисов), доступен по сети и из контейнеров, и при этом очень активно допиливается (в отличие от большинства других рутовых сервисов).
                                        +3
                                        Что-то у вас тёплое с мягким сравнивается и делается вывод об упругости...

                                        Давайте начнём с развёртывания (почему-то вы начали за безопасность, но я вообще не понял как вы её там подразумевали). Docker образы состояти из слоёв, если у вас есть 25 приложений на Python и 25 приложений на Java, то вам нужен 1 образ базовой системы (лично я предпочитаю Alpine Linux — 5Мб), поверх этого образа будут установлены слои для Python, общие для 25 приложений на Python, и отдельная ветка будет идти с Java окружением, а дальше будут создаваться уже слои с приложениями. Таким образом, если обновилось только 1 приложение, и его образ обновится, то серверу при обновлении нужно будет скачать всего-навсего слои с самим приложением. Подведём итог в цифрах, пусть базовая система будет Alpine Linux — 5Мб, Python слои — 50Мб, Java слои — 160Мб, а каждое приложение будет занимать по 20Мб. При обновлении одного приложения вам нужно будет пересобрать слои самого приложения и серверу нужно будет скачать 20Мб (даже меньше из-за того что слои хранятся архивами), при обновлении Python нужно пересобирать 25 образов — 50Мб + 20Мб * 25, при обновлении Java — 160Мб + 20Мб * 25, а при обновлении базового образа, да все обзразы нужно пересобрать — 5Мб + (50Мб + 20Мб * 25) + (160Мб + 20Мб * 25), но если хотите заморочиться и вы хотите сделать отдельный случай "обновления системы" без полной пересборки, когда вы знаете, что пересборка не нужна (ну, например, обновилась только динамическая библиотека), то можно такие патчи наклвадывать сверху приложений, тогда при обновлении libopenssl.so серверам нужно будет скачать слой с новой openssl.so, добавленной последним слоем в каждый образ, 50 раз.

                                        И это я ещё оставил за кадром вопрос небезопасности самого докера — а ведь это сервис, который работает под root, активно меняет настройки всей системы (так что бессмысленно даже пытаться SeLinux-ом или другой RBAC обрезать его права до необходимого минимума как принято делать для всех остальных рутовых сервисов), доступен по сети и из контейнеров, и при этом очень активно допиливается (в отличие от большинства других рутовых сервисов).

                                        Да, сама идея root-демона, который занимается неизвестно чем — не самая приятная для осознания. Однако, стоит отметить, что вы лукавите здесь, говоря, что он доступен по сети и из контейнеров. По умолчанию, docker-daemon использует UNIX-сокеты, так что доступен он только локальным пользователям у которых есть права на доступ к сокету (обычно нужно находиться в группе docker).
                                          +6
                                          Мне кажется, что powerman говорил о проблемах безопасности базовой ОС. Как вот в glibc недавно обнаружилась. И чтобы закрыть эту уязвимость нужно обновить каждый контейнер, вместо обновления одной базовой ОС на сервере.
                                            –1
                                            не нужно, нужно только обновить один базовый слой, который тут же подхватят все контейнеры, унаследованные от этого слоя
                                              +8
                                              Что-то в докере за последний месяц изменилось и контейнеры подхватывают изменения базового образа на лету? Или вы неудачно выразились, имея в виду, что нужно ручками (или коммит-хуком) пересобрать все образы и рестартовать все контейнеры?
                                                0
                                                Конечно нужно пересобирать все контейнеры, но это проще, чем все делать вручную при каждом обновлении
                                                  +11
                                                  Дело не в том, возможно это или нет, а в том что во всех хвалебных статьях о простоте установки говорят, а о обновлениях — нет.

                                                  При этом, я так в манах и не нашел, как запустить рекурсивную пересборку всех установленных контейнеров.

                                                  Короче, для развертывания среды разработки, для всяких тулчейнов докер хорош, но для серьезного энтерпрайза с требованиями к безопасности — нет.

                                                  Пруфы: http://www.securitylab.ru/news/473082.php. И это было через много месяцев после шеллшока.

                                                  Конечно нужно пересобирать все контейнеры, но это проще, чем все делать вручную при каждом обновлении

                                                  Что делать вручную? Запускать обновление системы одной командой?
                                                    –1
                                                    Чуть ниже отлично расписано, что ваши требования не нужны так как в контейнере только конкретные либы под конкретную технологию, для питона только питон, для джавы — джава и доступа к другим процессам нету. Вам не нужно генту ставить и следить, чтобы баш был неуязвим, так как разницы нету, для основной системы, в которой бежат контейнеры. Также и для других контейнеров разницы не будет
                                                      +2
                                                      Это вовсе не так, ответил там же чуть ниже.
                                                        +5
                                                        Чуть выше написано, что уязвимости не в одном баше, а и в glibс и прочих системных библиотеках. И питон, и джава — всё glibс использует, и все от этой уязвимости становится дырявым
                                                          0
                                                          Давайте тогда рассмотрим случай, что у вас 10 одинаковых серверов. и каждый день вам нужно обновлять их всех вручную. не проще ли запилить себе образ, повырезать оттуда баши или другие неиспользуеммые утилиты, обновлять его одного, а на всех серверах все что нужно — это остановить контейнеры и пересоздать их с обновленным базовым образом, используя скрипт? в случае с гентой, если собирать каждый раз либы с исходников, то все 10 серверов будут простаивать какое-то не очень маленькое время, тогда как с докером просто качаеш базовый образ и обновляеш контейнеры. сервера простаивают меньше, вам не нужно заходить на все 10 серверов, так как всюду одинаковый контейнер
                                                            +6
                                                            Мы говорим не о простоте, а о безопасности. Самый простой путь — это вообще забить на безопасность, да.
                                                              0
                                                              И где же по-вашему не продумана безопасность?
                                                                +2
                                                                Да везде! Я хотел ttrss в docker. Что нужно? LEMP. Отлично. Берем:

                                                                • nginx
                                                                • mysql
                                                                • php-fpm
                                                                • php-cli (для крона/демона обновлений)
                                                                • app (ro-вольюм — собственно, сам ttrss с конфигами ко всему этому счастью)
                                                                • storage (бд+нагенеренное приложением)
                                                                  ничего не потерял?
                                                                  Расчехляем docker-compose… И офигеваем!
                                                                • nginx — худо-бедно настроил, завёл… Э, а где мой привычный пользователь www-data?
                                                                • mysql — mysql от root'а? Окей.. .
                                                                • php-fpm
                                                                • php-cli
                                                                • app — КТО СЛОМАЛ chown?!
                                                                  Вобщем, нафиг. После такого я пошел расчехлять свой любимый LXC.

                                                                Согласен, docker hub — классная тема. Но пока в docker'е не допилят разграничения прав — это будет ад.
                                                                  +3
                                                                  вы же понимаете что root в контейнере это не тот же рут что и на хосте? Да и контейнеры можно поднимать от имени пользователя.
                                                                    +1
                                                                    Какая разница? У меня не сервер компрометируют, а приложение. Я и без того уже перехожу на LXC, но Docker мне пока жутко неудобен, как с точки зрения устоявшихся процессов и правил так и с точки зрения сборки.
                                                                    Я 2 недели пытался завернуть ttrss в Docker так как это положено делать, обломился. На LXC я получил всё за полтора часа.
                                                                      –1
                                                                      вместо того что бы 2 недели что-то эдакое делать, можно было бы глянуть, может кто-то за нас уже все сделал.

                                                                      пока жутко неудобен, как с точки зрения устоявшихся процессов и правил так и с точки зрения сборки.

                                                                      Ну так инструмент тут непричем. Просто вы пока не увидели преимуществ лично для вас. И если кроме вас никого больше нет — то может и не надо ничего выдумывать.
                                                                        0
                                                                        … запилив всё в один контейнер с supervisor'ом, да, что идет в разрез с идеей "один контейнер = один процесс".
                                                                        В таком виде как это сделано там, лучше уж взять любой другой способ виртуализации.
                                                                          0
                                                                          другой способ виртуализации.

                                                                          docker — не способ виртуализации. Ну и если вам хочется именно тру вэй — то вот. Опять же не понимаю что там надо было делать 2 недели.

                                                                          один контейнер = один процесс

                                                                          Не так. Один контейнер = одна обязанность. Далеко не всегда это означает один процесс, есть множество кейсов когда это неудобно (shared memory например надо организовать между процессами).
                                                                            0
                                                                            Еще раз: механизмы, предлагаемые Docker'ом не предусматривают запуск более чем одного приложения в контейнере. Если у вас в контейнере, например, php-fpm, то Docker управляет только master'ом. Docker+supervisor = костыль.

                                                                            В концепции

                                                                            контейнер = одна обязанность

                                                                            гораздо лучше себя показывает LXC. Да, он дороже по ресурсам, немного сложнее и так далее, но! Он тоже позволяет без проблем выстроить нужное окружение и деплоить только приложение, монтируя хранилище с данными.
                                                                              0
                                                                              Хочу заметить, что Docker + supervisor = LXC. Если уж засовывать всё в один контейнер, то почему бы не использовать докеровскую инфраструктуру, но уже без микросервисного фанатизма?
                                                                              0
                                                                              shared memory например надо организовать между процессами

                                                                              Пожалуйста, mmap'ите файл из общего volume'а и получаете shared memory между контейнерами (сори за засилие англицизмов).
                                                                                0
                                                                                собственно так и делают, но иногда это очень близкие по обязанностям штуки, и делать два почти одинаковых контейнера просто потому что так идеологически верно — не самый удобный способ. В целом же я предпочитаю все же дробить систему на отдельные контейнеры.
                                                                          0
                                                                          LXC это немного не то. Докер же нас хочет приучить к микросервисам со всеми вытекающими удобствами и неудобствами.
                                                                        +2
                                                                        Я ещё относительно недавно тоже думал "Э, а где мой привычный пользователь www-data". А потом понял, что это просто дело привычки. Которая, кстати, часто заставляла идти на нарушение безопасности, когда админы говорили, что мои желания иметь для тупого nginx-fpm-приложения минимум три пользователя — ничем не обоснованный гемморой, а достаточного только www-data...
                                                                          0
                                                                          Я вообще иду к тому чтобы всё разделять. Не Docker-way, но что-то близкое.
                                                                        +1
                                                                        Да признайте уже что человек прав и Докер — не серебряная пуля )
                                                                +3
                                                                Пруфы: http://www.securitylab.ru/news/473082.php. И это было через много месяцев после шеллшока.

                                                                Не забывайте, что там исследуются ВСЕ образы. Вообще все. Следовательно и старые в которых нет обновлений.

                                                                Посмотрите на это с другой стороны. Благодаря докеру можно проверить на известные уязвимости все (или только свои) образы разом.
                                                                  +1
                                                                  Отличная статья, спасибо.
                                                          +4
                                                          вы начали за безопасность, но я вообще не понял как вы её там подразумевали
                                                          Безопасность подразумевает необходимость ежедневных обновлений пакетов ОС, из-за чего почти каждый день необходимо будет пересобирать как базовый образ, так и часть образов с приложениями (если они содержат какие-то дополнительные пакеты ОС помимо самого микросервиса).

                                                          Ну и ещё она подразумевает использование hardened gcc (с PIE, SSP, …) для сборки пакетов ОС, что прямого отношения к докеру не имеет, но необходимость при обновлениях компилировать пакеты из исходников может сильно замедлить пересборку всех образов по сравнению с такой же компиляцией для упоминавшихся мной обычных серверов (потому что, как я опять же упоминал выше, сервера вынужденно стараются держать одинаковыми, поэтому на них одинаковый набор USE-флагов — в Gentoo они определяют настройки опциональных фич/зависимостей пакетов, как правило это задаёт параметры передаваемые в `./configure` — т.е. можно скомпилировать пакет один раз на build-сервере и быстро установить на все сервера как бинарный пакет, а в докере продвигается идея специализированных окружений для каждого приложения, так что набор USE-флагов может и как-бы даже должен отличаться, что приведёт к необходимости компилировать один пакет несколько раз в разных конфигурациях. (Кстати, может кто-то знает, уже появились не source-based дистрибутивы в которых все пакеты собраны hardened gcc? Когда я последний раз этим интересовался в некоторых дистрибутивах так собирали 20-30% пакетов, не больше.)
                                                          Да, сама идея root-демона, который занимается неизвестно чем — не самая приятная для осознания.
                                                          Беда не столько в том, что он занимается неизвестно чем, сколько в том, что он делает слишком много всего. Обычно ту часть кода, которая работает с полными root-правами стараются вынести отдельно и держать там самый минимум кода. А докер это бинарник на 25+ MB в котором с root-правами работает всё, включая Go runtime.
                                                          Однако, стоит отметить, что вы лукавите здесь, говоря, что он доступен по сети и из контейнеров. По умолчанию, docker-daemon использует UNIX-сокеты, так что доступен он только локальным пользователям
                                                          Лукавите здесь Вы. Да, по умолчанию всё именно так. Но я в своём комментарии отвечал на конкретную статью, где автор рассказывал как докер радостно создаёт сети между датацентрами так, что контейнеры этого даже не замечают, и управляет всем этим хозяйством с одной машины — через какие конкретно UNIX-сокеты, по-вашему, всё это может работать?
                                                            +3
                                                            Безопасность подразумевает необходимость ежедневных обновлений пакетов ОС, из-за чего почти каждый день необходимо будет пересобирать как базовый образ, так и часть образов с приложениями (если они содержат какие-то дополнительные пакеты ОС помимо самого микросервиса).
                                                            Поэтому я и выступаю за использование Alpine образа в качестве базового — там всего 4 пакета, которые обновляются достаточно редко (уж никак не каждый день). Однако, musl libc приносит как свои плюсы, так и свои грабли… Я не вникал в hardened gcc, но пакеты в Alpine Linux собраны с stack-smashing protection.

                                                            В общем, если у вас уже есть отлаженная схема, то я не вижу смысла её ломать просто для того чтобы ввернуть где-нибудь Docker. Однако, я уже год гоняю в продакшене 15 образов основанных на Alpine Linux, суммарным объёмом в 4ГБ и как-то вопрос пересборки меня вообще никогда не напрягал (да, Rust и Haskell из исходников пересобираются долго, но этим занятием занимается машина и не больше одного раза в неделю, так что для меня это не является критичным процессом, да и то, когда появятся пакеты в Alpine Linux — жизнь станет веселее). Ну и использую я возможности ограничений ресурсов Docker контейнеров на полную, так что без Docker я бы даже, наверно, не приступил бы ещё к написанию этого проекта, а застрял бы в дебрях LXC.

                                                            Лукавите здесь Вы. Да, по умолчанию всё именно так. Но я в своём комментарии отвечал на конкретную статью, где автор рассказывал как докер радостно создаёт сети между датацентрами так, что контейнеры этого даже не замечают, и управляет всем этим хозяйством с одной машины — через какие конкретно UNIX-сокеты, по-вашему, всё это может работать?
                                                            Да, можно открыть доступ к Docker демону по сети, да, там можно настроить псевдобезопасность, и, наконец, ДА, мне это совершенно не нравится! Тут действительно можно долго познавать глубину дыры. Однако, есть другой подход — агенты, крутящиеся на сервере с Docker-daemon'ами, которые поднимают свою VPN до мастер ноды и общаются с локальными Docker-daemon'ами через UNIX-socket. Так делает как минимум Rancher и есть у меня подозрения, что так же (ну может без VPN) делают и Kubernetes, и Fleet, ну и остальные здравые люди.
                                                              +1
                                                              Ну и использую я возможности ограничений ресурсов Docker контейнеров на полную, так что без Docker я бы даже, наверно, не приступил бы ещё к написанию этого проекта, а застрял бы в дебрях LXC.
                                                              Возможно, вас заинтересуют механизмы systemd для ограничений всего.
                                                                +2
                                                                Это конечно прикольно, но у докера плюшек побольше будет, и изоляция окружения это далеко не самая главная как по мне. И не стоит забывать про docker-swarm и т.д. То что все это можно сделать и без докера — это факт. Просто с ним проще, и небольшая команда сможет намного быстрее скейлиться и удобнее поддерживать инфраструктуру.
                                                                  +1
                                                                  Да, я читал, пожалуй, все ваши статьи. В моём случае я использую всего 1 сервис, который можно было бы действительно в systemd запихнуть, но основной функционал заключается в запуске потенциально опасного кода в песочнице, для чего я и искользую Docker для запуска процессов без доступа к сети, с read-only FS, с ограничениями памяти и ресурсов ядра, а также CPU shares.
                                                            +1
                                                            1) С версии 1.10 можно докер в юзерспейсе запустить…
                                                            http://162.242.237.67/docker-blog/2016/02/docker-engine-1-10-security/
                                                            2) Я не уверен что правильно понята идея Контейнеров+микросервисов
                                                            «Hardened Gentoo лежащий в основе всех образов микросервисов.» зачем?
                                                            Реально если ваше приложение распилино нормально на сервисы которые предоставляют наружу четко ограниченое АПИ (например порт 80) то какай вам разница бежит ваш сервис внутри контейнера на Hardened Gentoo или альпине? Какая потенциальная угроза?
                                                            Какраз докер минимизирует угрозу, так как изолирует как минимум логически вашу апликуху на сервисы которые специфичны…
                                                            Например в моем случае вообще побарабану что за версия openssl.
                                                            Её там просто нет… она там не нужна… Она нужна один раз на уровни виртуалки… также там нет обычно ничего друго-го критического молжноидаже баш убрать
                                                            Тоесь и обновлять постоянно ничего не надо, достаточно нормального цикла разработки совершенно, все критическое в основном на самой виртуалке.
                                                            Наверно найдутся конечно контейнеры которые должны быть особо защиещены но тогда дайти им правильный базовый имидж, отелите их от остльного дерева…

                                                            Помоему надуманная проблемность… И да докер не панацея… Докер отлицно подходит под архитектуры основаны на микросервисах, и отлично подходит в динамическую инфраструктуру.
                                                            Но потенциал докера не реализуется если не подумать обо всем, например о среде в которй будут запускаться контейнры…
                                                              +1
                                                              Реально если ваше приложение распилино нормально на сервисы которые предоставляют наружу четко ограниченое АПИ (например порт 80) то какай вам разница бежит ваш сервис внутри контейнера на Hardened Gentoo или альпине? Какая потенциальная угроза?
                                                              А в чём, по-вашему, разница между обычным сервером где стоит один такой сервис и контейнером докера? В том, что на сервере есть ещё и SSH? Так конкретно SSH никогда не была большой проблемой в плане безопасности, и всё, что делается в Hardened Gentoo — делается вовсе не ради защиты sshd. Или Вы считаете что сервера, на которых только SSH и один сервис с сетевым API, не имеют проблем с безопасностью и не нуждаются в регулярных обновлениях?

                                                              Любой сервис, который смотрит в сеть и принимает пользовательский ввод — можно пытаться ломать подсовывая ему не тот ввод, который он ожидает. А сломав его и оказавшись «всего лишь» внутри контейнера — злоумышленник внезапно получает доступ ко всему, к чему есть доступ у взломанного сервиса: базам данных, виртуальной сети связывающей его с другими контейнерами, и возможно даже к управлению самим докером (если им управлять из обычного контейнера, как упоминалось в статье).

                                                              Да, в контейнерах может не быть openssl и bash — но, скажите честно, много Вы видели базовых контейнеров без bash? И любой микросервис на питоне может, внезапно, часть своих фич реализовывать запуская конвейеры внешних утилит, т.е. тот же bash и shellshock для него будут актуальны на все 100%. А что касается openssl, то в неё напихали слишком много всего помимо самого SSL, поэтому любой микросервис который пользуется, например, хеш-функциями или AES для реализации каких-нибудь JSON Web Token или миллиона других мелких вспомогательных задач не связанных с его основной функциональностью — внезапно обычно оказывается слинкован с libcrypto.so из openssl.
                                                                +1
                                                                С версии 1.10 можно докер в юзерспейсе запустить
                                                                Поясняю — рут больше не нужен
                                                                ссылка
                                                                  +1
                                                                  Это отличная новость, но никак не решение всех упомянутых проблем с безопасностью. На самом деле основная проблема с регулярными обновлениями — скорее концептуальная, а docker daemon работающий под root — техническая, причём из серии "выведи козу".
                                                                    +2
                                                                    Если у вас один сервер, то понятно, что докер вам не нужен(и то лучше чтобы было одно окружение и на локалхосте, для разработки, и на тестовом и на стейдже и на продакшене), но если 10 тогда без него будет намного сложнее. Но люди склонны придумывать себе проблемы и героически их побеждать. Посему спорить с вами не буду, используйте что считаете нужным
                                                                    +4
                                                                    CONFIG_USER_NS (aka User Namespaces) на данный момент представляет собой одну большую дыру. В Debian/Ubuntu эту дыру решили тестировать на пользователях и каждый месяц теперь у нас CVE благоаря этой чудной штуке. В Arch Linux, например, отложили включение этой опции ядра пока дебианщики не закончат тестирование в боевых условиях.
                                                                    0
                                                                    Ну да… все эти риски понятны.
                                                                    1) хакнуть баговый сервис смотрящий в сеть конечно возможно. Это не проблема докера в принципе и не достоинство это ортогональная проблема… И в 99% случает криворукие программеры вашей конторы…
                                                                    Тоесть чинится релизом и деплоэмнеотм одного контейнера.
                                                                    2) Вы только что описали приимущества дополнительной изоляци между контенерами.
                                                                    Да проникнув в контейнер (да еще по вине сторонней библиотеки, не преспроисив себя зачем она там и точно нужна..) теоритически можно получить доступ ко всему что видит контейнер.
                                                                    Но это все еще меньше чем сценарий проникновения в монилит, в которм злоумышленик увидит все.

                                                                    Технологий контейнеров не избавит конечно от проблем и то что вы говорите валидно… Контейнеры без микросервисной архитектуры ИМХО достаточно бесполезны…
                                                                    Но если её использовать, то можна даже увеличить безопасноть. Локализировать наиболле уязвимые сервисы или те что занимаются наиболее трепетными данными… И занятся в плотнуе их бзопасностью…
                                                                    Что даже не зависимо ото контейнеров хороший паттерн и даст безопасноти больше, чем параноидальная слежка за последней версией баш на всех компах… — это.
                                                                    Безопасность это комплексная проблема а не прсто пару паттернов… привычек или евристик. Она начинается с заказа, проходит через архитектуру и заканчивается конечно админами с их актуальными версиями…

                                                                    По поводу имиджей, если параноить, вполне видел где-то в сети как чуваки терли все из базового имиджа… Я лично этим не занимаюсь, в моем юскейсе это лишние усилия, мои сервисы изолированы друг от друга очень основательно…
                                                                    Да риск есть что в яве найдут такие баги, что кто-то то через http rest получит доступ в контейнере… (сложно представимо) но теоритически, я срочно кинусь апдейтить яву… ок.
                                                                    Дыра в bash? Ок, через недельку буду развивать свой сервис пропатчу и bash а пока она никак не касается моего сервиса ибо bash не задействован.
                                                                    Именно так, взвешивать и понимать риски… Разделение сситемы на сервисы помогает какраз выделить те блоки которые в опасности и не трогать остальные
                                                                  +4
                                                                  Пересборка контейнера — это запуск docker build. Обновление тысяч контейнеров по всему парку машин можно сделать одной командой, если использовать систему для оркестрации типа Kubernetes. Вы не делаете перезапуск вручную — вместо этого система автоматически в нужной последовательности: 1. запустит новый контейнер, 2. убедится, что он успешно поднялся, 3. добавит его в кластер, т.е. направит на него трафик, 4. снимет трафик с старого контейнера, 5. убьёт его. Перезапуск машин (для обновления ядра, например) делается совершенно аналогично — запускаются новые копии всех контейнеров, которые работают на машине, где-нибудь в другом месте; трафик направляется на новую машину, снимается со старой, машина перезапускается и возвращается в строй обратно.

                                                                  Насколько я знаю, сейчас в коде ядра сам по себе рут практически не даёт никаких привилегий — всё настраивается через capabilities. Рут, который в докере, именно что урезанный, без capabilities. Т.е. UID 0 даёт возможность любой файл читать (из доступных в контейнере), открывать любые порты (но только на виртуальном интерфейсе, который в контейнере есть), но ни обратиться к устройствам, ни сделать ещё какую пакость, он не может.
                                                                    0
                                                                    Пересборка контейнера — это запуск docker build.
                                                                    Формально — да. Но в контексте ответа на мой комментарий пересборка контейнера подразумевает обновление установленного в нём софта, правку конфигов, разрешение конфликтов — в общем, всё то, что обычно делается при обновлении сервера. Простым запуском docker build тут обычно не обойдёшься.
                                                                    Вы не делаете перезапуск вручную
                                                                    Я тоже этим восхищён, но описанная мной проблема перезапуска не в том, что его нужно делать вручную, а в том, что многие сервисы достаточно нетривиальны, и их перезапуск — штука достаточно дорогостоящая (в плане ресурсов, производительности, etc.) чтобы делать его без веской причины каждый день.
                                                                    Рут, который в докере, …
                                                                    … меня никогда особо и не волновал, так что не совсем понятно, к чему Вы это описали. Проблема попадания злоумышленника внутрь контейнера не в том, что он там будет root, а в том, что он получит доступ к тому (базы/сети), к чему есть доступ у работающего в контейнере сервиса.
                                                                      +3
                                                                      пересборка контейнера подразумевает обновление установленного в нём софта, правку конфигов, разрешение конфликтов

                                                                      Так точно. У вас базовый образ может быть ваша безопасная ОС, в Dockerfile пишется ADD /ваш/уникальный/конфиг, и запуск docker build на основе свежей версии ОС добавит тот же самый конфиг и соберёт новый образ. Понятно, что при обновлении ОС может формат конфига поменяться, но вы это легко заметите на стейджинге, если у вас что-то не поднимется. По-любому та же самая проблема есть при любом способе развёртывания.

                                                                      их перезапуск — штука достаточно дорогостоящая (в плане ресурсов, производительности, etc.)

                                                                      Ну а если вы обновляете libssl или ещё какую библиотеку (и тем более ядро), всё равно же перезапускать надо программу, вне зависимости от того, докер это или не докер.

                                                                      он получит доступ к тому (базы/сети), к чему есть доступ у работающего в контейнере сервиса.

                                                                      Угу. Кстати, если приложению они не нужны, в контейнер совсем не обязательно складывать bash, ps, ssh, scp и прочие полезные для злоумышленника штуки. У меня большая часть приложений в контейнерах написана на компилируемых языках. В контейнере лежит несколько so-шников от libc и бинарник с программой, а то и вообще один бинарник, слинкованный статически. Даже если хакер найдёт способ исполнить произвольный код, ему нужно будет огромных размеров payload закачивать, чтобы что-то вредное сделать.
                                                                    +7
                                                                    Ну если уж совсем по торе, то с докером желательно менять жизненный цикл софта. И в этом-то на самом деле вся прелесть. Вы релизите не jar/war/dll и кучку конфигов, а как раз целиком образ. Т.е. не важно что вы там поменяли — пропатчили что-то в системе, добавили фичу, починили баг в коде или поменяли конфигурацию. Все равно это новый билд, новая версия образа, тестирование этого образа в стейдже и вывод этого образа в прод (как правило параллельным деплойментом с переключением на уровне балансера, например). Почему так? Потому что для конечного потребителя не важна суть изменений, которые вы внесли на конкретной итерации. Важно чтобы все работало не хуже чем до обновления. И контейнеризация как раз помогает это обеспечить. И откатываться надо уметь не только после кривого кода, но и после кривых обновлений сторонных зависимостей (т.е. и ОС). А после последних, пожалуй, даже чаще.

                                                                    Более конкретно, в mvn, например, есть плагин для сборки и публикации образов в докере, Т.е. ваша история будет выглядеть так: вы пропатчили базовый имидж (или в Dockerfile прописали, или ручками закоммитили изменения, или тем же паппетом накатили), запустили обычный билд, билд нагенерил вам образов для контейнеров (он это делает довольно шустро за счет кеширования, так что собрать сотню образов может быть сравнимо с копированием файлов по сетке). Дальше ваш QA позапускал контейнеры (фактически 1 к 1 конфигурация вашего продакшена, может быть с меньшей избыточностью), прогнал автотесты, подтвердил что все работает. После этого те, кто у вас занимается релизами, взяли те же образы, подменили в продакшене одни контейнеры другими и все побежало дальше.

                                                                    Менеджмент конфигурации тоже становится малость другим. У четких пацанов уже давно конфиг = код. А значит очень хочется чтобы конфиги на продакшене = конфиги в стейджинге = конфиги у девелопера (здесь = бинарное). Все вариации в топологии за счет DNS, вся авторизация между сервисами — по сертификатам. Если уж совсем никак — то через параметры у контейнера или разделяемые тома. Чтобы различий между средами не было вообще.

                                                                    У нас тоже долго путались с концепциями, надо сказать у докера не очень удачная терминология, и от того много недопониманий. Не думайте про контейнеры как про виртуалки. Контейнеры ни кто никогда не патчит, не перезапускает, и даже ssh-ем в них не лазает. Это как "суперпроцесс", который крутится со своим изолированным окружением. Остановился — умер. Можно унести труп в лабу и там поковыряться, если уж очень нужно поискать причины сбоя, но оживлять его и возвращать в строй его уже ни кто не будет.

                                                                    А вот про безопасность самого докера — это справедливо. Технология молодая, и грабли будут. Но те же разговоры были и про виртуализацию, если память мне не врет.
                                                                      +1
                                                                      Нууу, не все так печально. Обновлять нужно только те контейнеры, которые хостят сервисы, которые затронуты этой угрозой. Учитывая, что:

                                                                      • SSH в контейнеры не ставят.
                                                                      • эскалация привилегий в контейнере не является большой проблемой — там порезаны kernel capabilities, подробнее: https://docs.docker.com/engine/security/security/
                                                                      • список запущенных процессов в контейнере известен заранее и контролируется

                                                                      в большинстве случаев достаточно обновить хосты и то небольшое число контейнеров, которые затронуты этой уязвимостью.
                                                                        0
                                                                        Товарищи минусующие, вы бы изложили свои аргументы, чтоли.
                                                                        +5
                                                                        Сразу честно признаюсь, что вопрос безопасности я поднял не для того, чтобы продемонстрировать недостатки докера, а наоборот, чтобы мне рассказали как его правильно готовить. По результатам обсуждения пока складывается следующая картина:

                                                                        • Работа очень большого и сложного процесса `docker daemon` под root. shuron и Crandel сказали, что с 1.10 это не так, но они ошиблись: в 1.10 появилась поддержка User Namespaces чтобы root внутри контейнеров не был UID=0 в хост-системе — что не имеет отношения к работе `docker daemon` под root. Фича хорошая, но, как упомянул frol в данный момент она создаёт новые угрозы безопасности.
                                                                        • aml разумно заметил, что при использовании компилируемых языков и статической линковки в контейнере кроме одного бинарника других приложений и библиотек просто не будет. В этом случае, действительно, нет необходимости ежедневно обновлять образ дистрибутива. Но возникает другая проблема: когда обнаруживается проблема безопасности в библиотеке (что, мягко говоря, не редкость), то обычно это решается штатным обновлением дистрибутива и перезапуском процессов куда подгружена старая версия библиотеки (которые легко найти, например, через `lsof`). Кто и как будет отслеживать необходимость перекомпиляции статических бинарников в этой ситуации — не понятно. Т.е. опять проблема прикапывается чтобы не пахла, а не решается, как метко описал amarao. (Кроме того, если у нас один статический бинарник — а так ли нам на самом деле нужен докер?)
                                                                        • Visphord описал процесс автоматической регулярной пересборки всех контейнеров на базе так же регулярно обновляемого базового образа. Плюс, разумеется, админы должны контролировать содержимое Dockerfile-ов образов с приложениями — чтобы там тоже все необходимые пакеты доустанавливались штатными средствами дистрибутива и были последних версий — а исключения брались на заметку и мониторились админами на предмет проблем с безопасностью вручную. Это приводит к более редким обновлениям, раз в неделю-две вместо каждые день-два, но, на мой взгляд, это вполне допустимо — учитывая что при необходимости срочно закрыть дыру всегда можно инициировать пересборку вручную. Так же увеличенный период обновлений по большей части снимает мой вопрос о возможно высокой стоимости беспричинных частых перезапусков большинства сервисов. Но у этого подхода есть своя цена: стабильных образов зафиксировавших необходимое для приложения окружение (а это одна из основных фишек докера описанных на главной странице сайта) больше не существует — образ собранный сегодня может работать, а собранный из того же Dockerfile завтра — уже нет. На мой взгляд, в общем и целом этот подход эквивалентен традиционному: админ регулярно обновляет пакеты дистрибутива на сервере (образе runtime:latest) и перезапускает задетые обновлением (все) сервисы; сначала это делается на тестовой площадке (CI), а после прохождения тестов и на продакшне.

                                                                        Последний вариант выглядит вполне рабочим.

                                                                        Для него нужен автоматизированный процесс деплоя образов докера через CI, что может оказаться слишком дорого/сложно для мелких проектов (вроде "интернет-шаурмятни" упомянутой JPEG в дополнении к статье). В то же время админа периодически обновляющего сервер такие проекты себе обычно могут позволить, так что для них переход на докер ухудшит общую безопасность проекта.

                                                                        Так же это скажется на цене поддержки системы: вместо обычного обновления серверов админом каждое обновление потребует сборки кучи образов и перекомпиляции всех приложений. На это потребуется больше времени, больше CPU, если что-то не соберётся может потребоваться привлекать разработчиков для решения проблемы, etc.

                                                                        Осталось понять, перевешивают ли (оставшиеся :)) плюсы докера эти дополнительные затраты.
                                                                          0
                                                                          стабильных образов зафиксировавших необходимое для приложения окружение (а это одна из основных фишек докера описанных на главной странице сайта) больше не существует — образ собранный сегодня может работать, а собранный из того же Dockerfile завтра — уже нет

                                                                          Вы можете оставить за программистами разработку образов:

                                                                          # hipster-programmer/ourhompage/Dockerfile
                                                                          FROM ubuntu:14.04
                                                                          COPY buggy-libssl.so /usr/lib/libssl.so

                                                                          docker build -t hipster-programmer/ourhompage:6.6.6 .

                                                                          Но вам не обязательно сразу бросаться выкатывать их в продакшен.
                                                                          Создавайте на базе образов приложений отдельные образы с любыми фиксами поверх:

                                                                          # paranoid-devops/ourhompage/Dockerfile
                                                                          FROM hipster-programmer/ourhompage:6.6.6
                                                                          # RUN apt-get update && apt-get upgrade
                                                                          COPY hardened-libssl.so /usr/lib/libssl.so

                                                                          docker build -t production/homepage:6.6.6.

                                                                          И запускайте их в продакшен:

                                                                          docker run production/homepage:6.6.6

                                                                          В этой схеме образ с приложением, собранный сегодня, завтра пересобирать не нужно.
                                                                        +13
                                                                        Почему в статье даже мельком не упомянуто, как работать с персистентными данными (например, СУБД) в идеологии докера? Ведь про то, что stateless "Hello world" замечательно ложится на концепцию, это и без статьи понятно...

                                                                        Вот есть, например, система, и в качестве СУБД используется Постгрес. Что дальше? Все рассуждения про "легкость перезапуска" оказываются вдруг неприменимы?
                                                                          +3
                                                                          С данными пока не всё так красиво, как со stateless контейнерами, но шаги в этом направлении делаются. Если с не большими и не сильно требовательными к скорости чтения/записи данными, можно обойтись сетевыми решениями вроде своей NFS или готовых облачных решений, то с базами данных сложнее. Тут либо локальное хранение на том же сервере, либо дорогие высокопроизводительные решения СХД. Недавно появилась возможность именовать и создавать volume отдельно от контейнеров, это немного улучшило управляемость. До этого для данных создавался отдельный контейнер с volume, которые подключались к другим контейнерам (которые этими данными управляют) через volumes_from. Что тоже вполне нормально работало. Перенос больших данных пока не очень удобен, есть ручные действия, хотя есть сторонние решения, типа flocker, которые эту задачу пробуют решить. Но сам пока не пробовал его в бою. На небольших тестовых данных всё хорошо, но не понятно, будет ли всё так же хорошо при копировании 500Гб БД. В любом случае, проблема больших данных лежит немного за рамками Docker, т.к. такие объёмы пока упираются в проблемы, которые Docker решать не предназначен. Бекапить работающую БД путём копирования файлов всё равно не получится. Нужен либо дамп, либо репликация, а вот это уже делается средствами Docker без проблем.
                                                                            +1
                                                                            раньше вы либо монтировали хостовое блочное устройство (каталог хоста)
                                                                            либо хитрили с единым NFS на все докер хосты — когда работаешь с CoreOS в качестве хост системы это основная проблема: как сделать единое блочное устройство

                                                                            сейчас уже по другому можно

                                                                              +2
                                                                              Дальше — каталог с данными остаётся на хосте, контейнер с postgres подключает этот каталог как volume. Зачем тут нужен докер? Чтобы иметь железобетонные гарантии точного соответствия окружения в dev и production средах. Если надо мигрировать базу данных на другой хост, всё становится сложнее — докер чудес не добавляет. Можно сделать сетевое распределённое хранилище, можно при развёртывании контейнера реплицировать данные на локальную машину, тут много вариантов.
                                                                              +1
                                                                              Почему в статье даже мельком не упомянуто, как работать с персистентными данными

                                                                              Это оттого, что невозможно объять необъятное. Статья сконцентрирована на админской части докера, на том, как он упрощает управление серверами: ставишь докер и погнали деплоить.
                                                                                +3
                                                                                Это сарказм?
                                                                                +1
                                                                                named volumes. Вот примерчик (правда он не совершенен и я планирую его в ближайшие недели улучшить, дико не нравится как стартуют контейнеры). Там 3 контейнера, nginx, php и postgresql.
                                                                                  +3
                                                                                  Я не думаю, что СУБД в одном контейнере с приложением — это хорошая идея. Если СУБД работает независимо, можно запускать несколько экземпляров приложения на разных серверах и без проблем их тушить, поднимать и обновлять. Думаю, что zero downtime deploy без этого наврядли получится сделать, например. Тут уже скорее вопрос, запускать ли СУБД вообще в контейнере, какие преимущества это дает?
                                                                                    0
                                                                                    Я думаю, что если СУБД не Вашей разработки, то разница небольшая.
                                                                                    Идеологически контейнеризовать свой код и не контейнеризовать «не свой» мне не нравится, впрочем
                                                                                      +1
                                                                                      то разница небольшая.

                                                                                      Тогда вы не поняли сути контейнеризации и принципа "один контейнер на одну роль". Суть в том, что бы все лежало максимально независимо, что бы завтра можно было тупо один контейнер задеплоить на одном серваке, а приложение на другом. Ну и т.д. Вопрос масштабирования.

                                                                                      Контейнеризуют не "код" а "окружение". То есть если у нас есть postgresql и нам надо поменять настройки — мы наследуемся от дефолтного образа и подменяем нужные конфиги, пушим и деплоим.
                                                                                  +11
                                                                                  Полгода используем Docker в production. Более 20 серверов, более 300 тысяч уникальных посетителей в сутки. Около 30 различных контейнеров. Экономит время и нервы колоссально, но нужно хорошо разобраться, чтобы начать получать профит. Технологии ешё есть куда расти: бывают небольшие сбои, кое-где некоторые вещи кажутся не логичными, но дело движется. В любом случае, Docker это лучшее, что случалось с управлением серверами за последние годы (по моему мнению). Сейчас у нас вся конфигурация и код в хранится в git, деплой через git (push в prodcution ветку). Уже давно нет никаких конфигов nginx написанных (или подправленных) кем-то в редакторе прямо на сервере. Даже при полном крахе, вся система может быть развернута за минуты на голых серверах. Пока используем машины вне кластера, переключаясь через docker-machine env внутри специального контейнера для управления. Очень хочется перейти на swarm, но пока есть факторы, которые останавливают.
                                                                                    +11
                                                                                    Расскажите как у вас все сделано. Очень интересно. А то сисадмины, которые познали дзен докера прячутся и молчат как это все завести и поддерживать
                                                                                      +2
                                                                                      Особо сложного ничего не делали. Есть набор машин, они создаются через docker-machine create, а всё окружение докера (папка .docker) хранится в гите. Само окружение управления так же запускается внутри контейнера, чтобы всем было проще его у себя запустить и работать с машинами. Проект разбит на микросервисы: 1 контейнер — 1 процесс. node.js, php, mysql, nginx. Код в контейнеры подгружается из git с заданным интервалом из продакшн ветки. Как только всё готово, мы мерджим текущую ветку в продакшн ветку и она вытягивается на сервера. node.js контейнеры при этом дополнительно пинаются, чтобы изменения подхватились. Поднят свой registry, в него собираем свои образы, заточенные под удобство конкретного проекта. Из глюков ничего особо серьёзного не было. Пару раз было что докер-демон переставал отвечать на какие-либо команды и даже его рестарт не помогал, приходилось перезагружать весь сервер. Зато, развернуть новый сервер при увеличении нагрузки можно за 15 минут из них 10 уйдёт на оплату сервера и установку ОС.
                                                                                        +1
                                                                                        Всё понятно, кроме «код подгружается в контейнеры» и «контейнеры пинаются, чтобы изменения вступили в силу». Предполагается, что фундаментальная идея докера — это деплоить контейнеры с кодом и зависимостями, как артефакт. А у вас код (даже не данные) меняется в течении жизни контейнера. Очень интересно узнать, почему вы решили так делать, учитывая то, что остальные части вполне соответствуют по технологии?
                                                                                          +2
                                                                                          Код, конфиги и данные у нас вынесены в volume. Сами контейнеры содержат только окружение. Например, если мы хотим обновить php или node.js, мы собираем образ с его новой версией и деплоим через docker-compose. Он пересоберёт образ и стартует его, подцепив volume с кодом и конфигами (которые при необходимости уже подготовлены для работы с новой версией окружения). Это удобно — мы везде быстро получаем одинаковое окружение. Но если слепо идти дальше и, например, мы немного подправили баланс в игре и для этого нужно собрать контейнер и пушнуть его на все сервера и перезапустить — это уже не удобно. Вместо этого мы просто пушим нужные коммиты в продакшн ветку и она вытягивается на все сервера через git. Это на много быстрее и не смешивает всё в кучу — наше приложение и его окружение. Если бы речь шла о каком-то бинарном приложении, которое бы нужно было предварительно скомпилировать и оно имело жесткие релизные интервалы, вариант с контейнером мог бы подойти, но в нашем случае, это будет только мешать.
                                                                                            +2
                                                                                            А как вы синхронизируете исходники и окружение?

                                                                                            Если бы речь шла о каком-то бинарном приложении, которое бы нужно было предварительно скомпилировать и оно имело жесткие релизные интервалы

                                                                                            Расширения? Модули для того же node.js?
                                                                                              +1
                                                                                              Если git pull на сервере привёл к тому, что файлы обновились, после него выполнится npm install для node.js и composer update для php.
                                                                                                0
                                                                                                А я просто делаю docker-compose pull, docker-compose up (или баш скрипт который в нужном порядке подменяет контейнеры).

                                                                                                А что вы будете делать если github во время деплоймента упадет?
                                                                                            +1
                                                                                            собрать контейнер и пушнуть его на все сервера и перезапустить — это уже не удобно

                                                                                            Как раз таки удобно: docker-compose up и последний слой переклеили с новым кодом, этот слой один улетел в репозиторий, этот же слой пулей прилетел на все сервера и зупустился там. С гитом ситуация до буквы такая же, только старые коммиты еще и копятся.

                                                                                            и не смешивает всё в кучу — наше приложение и его окружение

                                                                                            А докер как раз для этого и проектировался: смешивать в кучу приложение и окружение. Это как использовать гит для хранения не самих исходников, а zip-файлов с ними — одно название от гита остаётся.

                                                                                            Либо вы не сообщили какую-то очевидную для вас делать, меняющую всё дело, либо….
                                                                                              +2
                                                                                              В случае если я пушу один php файл в git, он просто зальётся во все нужные контейнеры и сервер продолжит работу без даунтайма. Если же пушить контейнер с кодом, придётся как минимум перезапустить php-fpm что приведёт к потере некоторых запросов, если по простому, а если по тяжёлому — приведёт к необходимости настройки умных балансировщиков, которые для нас сейчас избыточны. Пуш в продакшн ветку могут сделать несколько разработчиков, для этого либо каждому из них придётся в запускать сборку контейнера с кодом, либо поднимать CI-сервер, который будет это делать для каждого пуша. Я просто не вижу смысла делать ещё одну прослойку между git и сервером, только для того, чтобы соответствовать чьим-то убеждениям, причём без видимого профита от неё и с видимым замедлением и усложнением процесса. Я никого делать так не призываю, мы просто нашли для себя удобное решение и я им поделился.
                                                                                                0
                                                                                                И спасибо, что поделились, большое. Без дураков.

                                                                                                Теперь, когда активно деплоящая команда спросит, нужен ли им докер, я скажу, что пока может быть и не нужен. Особенно, пока не вызовется кто-то делать упор на девопс и/или QA.
                                                                                                  +1
                                                                                                  Ну так деплой через git у нас не отменяет преимущества докера. Вот пример яркий: в выходные игра попала в фичеринг и онлайн вырос на 30-40%, мощностей стало не хватать. Мы купили новый сервер, поставили ОС, а дальше docker-machine, docker-compose и готово — сервер обрабатывает запросы. 25 минут на всё, из них 20 на покупку сервера и установку ОС. Без докера бы тут было дел на много дольше. Можно конечно всякие там ansible, но мне докер тут удобнее.
                                                                                                  +1
                                                                                                  приведёт к необходимости настройки умных балансировщиков, которые для нас сейчас избыточны

                                                                                                  На самом деле можно даже через redis + confd сделать zero-downtime деплоймент (это из разряда изи). Если интересно, могу сделать примерчик.
                                                                                                    +1
                                                                                                    Вы еще спрашиваете!
                                                                                                      0
                                                                                                      Вы еще спрашиваете?
                                                                                                        0
                                                                                                        Совсем времени небыло. Вот сегодня сделаю.
                                                                                                          0
                                                                                                          Вобщем, не совсем zero-downtime, а скорее "минимально-возможный" downtime.

                                                                                                          https://github.com/intellectsoft-uk/docker-examples/tree/master/swap

                                                                                                          Если коротко — тут просто подмена контейнеров, которая полагается на docker dns. То есть пока мы не потушили старый контейнер, на новый запросы не пойдут. А это означает что у нас все еще есть минимальный downtime в размере времени погашения контейнера (очень быстро) и reload nginx-а (тоже быстро). В принципе даунтайм в этом случае составляет порядка пары сотен милисекунд, что можно компенсировать настройками nginx для апстримов.

                                                                                                          Что бы было совсем уж zero-downtime, надо уже поднимать redis и обновлять внутри nginx контейнера конфиги динамически, через какой-нибудь confd, который умеет отслеживать изменения в key-value хранилищах для актуализации конфигов.
                                                                                                      0
                                                                                                      Встречный вопрос. Если мы отталкиваемся от того, что окружение разработки похоже на окружение боевое (у нас так), то каким образом доставлять в это окружение код во время разработки? Если для боевого окружения собрать новый образ с кодом и либами с нуля и выкатить его — не проблема, то для окружения разработки это очень долго. Если представить, что закоммитили php файл и ждём, пока CI клонирует проект, установит все зависимости, соберёт образ и запустит его — так можно состариться во время разработки.
                                                                                                        +2
                                                                                                        Если представить, что закоммитили php файл и ждём, пока CI клонирует проект

                                                                                                        Клонирование проекта — необязательно, у меня обычно редко слэйвы меняются, потому повторное клонирование не происходит. По поводу сборки образов — у докера очень даже все хорошо с кешированием. По поводу копирования файлов — тут можно сделать в Dockerfile несколько копирований, отсортиврованных в порядке вероятности изменений, так мы можем сильно ускорить процесс сборки образа.

                                                                                                        У меня сейчас сборка образа без учета тестов, с пушем на docker distribution занимает где-то 30 секунд. Деплойменты с пулом новых образов — еще секунд 15-20 (отдельная джоба). Далее уже в зависимости от проекта тесты гонятся от 30 секунд до 10 минут.

                                                                                                        Хотя конечно если для вас это настолько критично, можно деплоить код через rsync и пробрасывать в контейнеры через волумы, в этом случае если окружение не менялось, будет только пару секунд на сборку контейнеров (оно просто проверит не менялось ли чего и реюзает слои образов из кэша), а если образы не менялись то и пуш в регистри займет ровным счетом ничего. Но вот тесты всеравно говнять придется, и мне как бы лишние 30 секунд на фоне прогона тестов погоды не делают.
                                                                                                          +1
                                                                                                          Сначала я должен согласиться с Fesor в том, что даже продакшн сборка может занимать секунды.

                                                                                                          Есть и другой путь: не пересобирать контейнеры для девелопмента, а прорасывать код вовнутрь с хост машины с помощью того же volume. Да, в таком случае, надо будет настроить ваш проект на перечитывание исходников на лету. Но ведь и другие мелкие настройки должны меняться для девелопмента, например стоит отключить кеширование в nginx, попросить рельсы вываливать stack trace и данные в базе тоже, скорее всего, девелоперские.

                                                                                                          Однако, в случае docker-compose можно переключать режим девелоперской тачки за те самые 10 секунд на сборку продакш версии и крутить продакшн код как угодно, а потом прыгать обратно в дев.
                                                                                                            +1
                                                                                                            Но ведь и другие мелкие настройки должны меняться для девелопмента

                                                                                                            Образ от этого не меняется, всякие мелочи можно разруливать через переменные окружения. То есть у меня алгоритм какой, мне надо подебажить — я беру продакшен образ где обнаружилась проблема, включаю его с нужными переменными окружения, и могу уже подключать удаленный отладчик.

                                                                                                            Расхождения между окружениями сводятся к минимому, но они есть, для удобства разработки.
                                                                                                              0
                                                                                                              Да, у меня точно так же. За исключением конфига nginx, его приходится немножечко сдабривать шаблонизатором.

                                                                                                              Вы этой статье и мне прямо бальзам на душу льёте, спасибо :)
                                                                                                                0
                                                                                                                За исключением конфига nginx, его приходится немножечко сдабривать шаблонизатором.

                                                                                                                Вы пользуетесь стандартным envsubst или что-то типа confd?
                                                                                                                  +1
                                                                                                                  Нет, простой подстановки мне мало, а до confd я не дорос.

                                                                                                                  Всё что мне нужно, это в паре мест добавить строчки типа expires -1;, proxy_intercept_errors и всё. Поэтому пользуюсь скриптом-шаблонизатором на (сюрприз!) перле. Перл по умолчанию установлен в контейнере nginx, так что доставлять его не приходится.
                                                                                              +4
                                                                                              Не хватает двух моментов


                                                                                              Что касается безопасности — то 2 дня назад был небольшой meetup на эту тему https://blog.docker.com/2016/02/docker-online-meetup-33-security/
                                                                                                +1
                                                                                                Начали за здравие (чётко объяснили суть докера), кончили за упокой (опять пытаются запихать его везде, где не надо).
                                                                                                  +5
                                                                                                  а у фанатов докера пока не наступило отрезвление технологией, вполне нормальное состояние, когда ее пихают везде — докер сейчас там-же, где были биткоины когда за штуку баксов перевалили,
                                                                                                  остынут, останется в тестировании, в куче микросервисов, но продакшен базы в докер пихать перестанут
                                                                                                    +2
                                                                                                    Да, "продакшен-база" в докере — это отлично. Недавно видел такое — база почти в 100 гигабайт с mysql в продакшене — и my.cnf вообще никак не настроен — как шёл в пакете дефолтный, так в продакшен и ушел.
                                                                                                    И этого "гуру" девопса очень сильно интересовал вопрос "а как же это бекапить и как ему реплику настроить, если при рестарте контейнера меняется IP?".
                                                                                                    На вопрос этому "гуре" — "Собственно, зачем было использовать абсолютно не нужную тут прослойку из docker?" я был зачем-то забанен с примерным reason "Я лучше знаю как мне делать, поналезли тут всякие г-ноадмины-советчики".

                                                                                                    Так что нам еще будет, за что масло на хлебушек покупать.

                                                                                                    Я вот на идеологии Docker построил вполне годную модель работы shared hosting'а не только для сайтов, но и приложений (мне в контейнере без разницы, в общем, что пускать, хоть java, абы памяти хватало), нечто вроде своего варианта Heroku, осталось только веб панель управления к этому всему допилить, а то меня, если честно, за несколько лет работы хостмастером все эти php панельки, мягко говоря, разочаровали
                                                                                                      +1
                                                                                                      Использование динамических ip и не использование своих конфигураций — это проблема не Docker, а человека его настраивающего. ip вообще нет необходимости использовать, т.к. всё работает через локальный DNS для контейнеров на одной машине и через DNS внешнего сервиса типа Consul, при работе на нескольких машинах. А конфиги, у нас например, подгружаются из git и чтобы их поменять, нужно только запушить новый конфиг в нужную ветку и перезагрузить контейнер. В образ конфиги мы не зашиваем, чтобы каждый раз не пересобирать.
                                                                                                        0
                                                                                                        У мсеня контейнеры стартуют в обвязке, потом обновляется мой днс и на него натравливается нгинкс
                                                                                                  +1
                                                                                                  С матчастью впринцыпе все понятно. Я думаю у многих проблема в другом — в недостатке best practice или туториалов на русском. Как деплоить докер? Как изменять код? Как составить правильно архитектуру? https://toster.ru/q/294757 помогите разобраться
                                                                                                    0
                                                                                                    Я деплою через дев контейнер экспорт => прод импорт => апдейт compose.yml => docker-compose up, все это за хапрокси, который на время рестарта контейнера перенаправляет запросы на живой клон.

                                                                                                    Все настройки только в compose.yml, ибо после экспорта метаданные стираются что есть хорошо. Айпишники руками через pipeworks. Как-то так. Пока полет нормальный. Накидать поверх этого баш скрипт и вообще песня
                                                                                                      0
                                                                                                      туториалов на русском

                                                                                                      Доки к докеру вполне себе написаны одновременно и общё, и в деталях, что сложно совместить. И там вполне школьный английский.

                                                                                                      Отвечу и по существу. Деплоить докер можно по-разному. Если проект большой, то переезжать, как описано в Докер в банке. Если маленький, то docker-machine create … и docker-compose up.

                                                                                                      Архитектуру правильно делать на микросервисах независимо от использования докера. Мои друзья рельсисты спроектировали большую систему сразу как набор слабосвязанных сервисов. И их перед этим не кусал никто докернутый. Рады, что можно хорошо и быстро тестировать изолированные части, выкатывать апдейты для части системы, делить зоны ответственности и т.д. Однако, пришлось поднапрячься при анализе системы.
                                                                                                      +21
                                                                                                      Докер — это отличная возможность переложить проблемы поддержания актуальных версий системных библиотек (того же самого libssl) с поставщиков ОС и сисадминов на никого. После того, как проблемы безопасности окружения переложены на никого, скорость внедрения и эксплуатации заметно возрастает, ведь производительность никого ограничена только супремумом пофигизма, а он, в свою очередь, верхней границы не имеет.
                                                                                                        +2
                                                                                                        Вот именно. Я не понимаю только одного: почему людям хайп вокруг новых технологий настолько сильно забивает голову, что они забывают то, что вообще-то отлично знают (ну, не забывают, но на некоторое время перестают об этом задумываться и применять)? Обычно здравый смысл и опыт могут временно отключаться из-за сильных эмоций, но докеру уже сколько лет — как эмоции могут держаться так долго?
                                                                                                          –1
                                                                                                          Кто вам мешает собрать собственный образ на базе любого дистрибутива и поддерживать его и все либы в актульном состоянии?
                                                                                                            +3
                                                                                                            Мешает пересборка контейнеров. Ради примера, рассмотрите приложение на node.js, которое упаковали в докер образ. Оно при сборке выкачивает некоторые зависимости через npm. Уверены ли вы, что приложение соберётся через, скажем, 2 месяца? Мои коллеги, которые занимаются как раз написанием приложений на ноде, говорят, что пересобирать приложение — это боль, т.к. в npm нету никакого общего релизного цикла, не говоря уж о LTS. С pypi попроще, т.к. движухи существенно меньше.

                                                                                                            Похоже, единственный способ поддержания базового слоя в собранных контейнерах в актуальном состоянии — это накладывания патча последним слоем каждый раз перед запуском контейнера.
                                                                                                              0
                                                                                                                0
                                                                                                                И что он будет делать, когда в репе кто-то сделает пакету unpublish? У нас на работе есть зеркало npm, так что я точно знаю, что пакеты удаляются.
                                                                                                                  +2
                                                                                                                  Это проблема не докера, у вас и обычный проект так не соберется.
                                                                                                                    0
                                                                                                                    Не соберётся, конечно. Соль в том, что его и не нужно пересобирать для обновления условного glibc. Представьте себе, что у вас какой нибудь лендинг, который сделали один раз, и потом год трогать не нужно.
                                                                                                                +1
                                                                                                                Мне кажется этот спор про то, за кем последнее слово: разработчиками или девопасами.

                                                                                                                Если считаете, что последние слово про безопасность должно быть за девопсами, накатывайте свои патчи поверх разработческих контейнеров:

                                                                                                                FROM ourpersonal/homepage:6.6.6
                                                                                                                RUN apt-get update; apt-get upgrade
                                                                                                                RUN rm -rf /
                                                                                                                RUN wtf

                                                                                                                Собственно, что-то подобное и происходит на "коммунальных" серверах. В качестве бонуса у вас будет возможность протестить последствия содеянного, ведь ваши обновления не всегда встают без последствий для приложений.
                                                                                                                  0
                                                                                                                  Беспорядок в npm конечно существует, но все крупные библиотеки уже давно обновляются очень культурно. Ну и они сами по себе не обновятся при сборке образа. Если конечно не указывать в зависимостях что-то типа версия 2 и больше. Мы всегда указываем все версии зависимостей чётко, это гарантирует, что каждый раз будет установлена одна и та же библиотека. Когда нужно обновится — поднимаем версию руками, обновляем, тестируем и уже после этого она попадает в сборку. Обычная практика, это касается любого пакетного менеджера, не только npm.
                                                                                                                    0
                                                                                                                    Да, последний шаг осталось сделать докеру до гита: мердж имаджей с резолвом --theirs. Я серьёзно :)
                                                                                                                    +7
                                                                                                                    То, что в докере нет никаких механизмов для "поддержания актуальности образов". Они есть у операционных систем — и мы возвращемся в наше уютное мирное болотце dependence hell.

                                                                                                                    В foobar 1.0b2 найдена уязвимость, требуется апдейт до foobar 1.0b3, однако у libpiupiu в депенденсах написано libmyaumyau == 13.44.43, а libmyaumyau breaks libaffaff 3.21.11, при этом libaffaff 3.21.10 хочет foobar ==1.0b2.

                                                                                                                    Если же депенденсы выковырять из менеджера пакетов, они вырастут в режиме unable to link при запуске бинарника, или даже TypeError: foofofo() takes 3 arguments (2 given), или даже NoneType has no method call.
                                                                                                                      –1
                                                                                                                      Никто вместо вас не будет поддерживать актуальность софта, хватит уже ожидать манны небесной, вместо вас никто не будет заниматься безопасностью. Сделайть безопасный image вам никто не мешает
                                                                                                                        +10
                                                                                                                        Вот тут вы не правы.

                                                                                                                        Использование дистрибутивов (well-estabilished, с хорошей политикой безопасности) как раз и позволяет снять с разработчкиков и сисадминов головную боль по отслеживанию CVE для всех нижележащих библиотек. В самом софте — это головная боль компании. В каждой нестандартной библиотеке (или версии), которую притащили в продакшен — это головная боль компании. Её сотрудников, точнее.

                                                                                                                        Но вот гигантские завалы библиотек, которые приходят в режиме "battery included" с языками программирования и фреймворками, или даже просто устанавливаются из основного репозитория для использования в своём софте — они снимают головную боль помнить и думать об этом.

                                                                                                                        Очередной зияющий heartbleed? apt-get update && apt-get upgrade. Poodle? apt-get update && apt-get upgrade. shellshock? О, а фикс уже раскатался в предыдущем апдейте. remote code execution in libc? Уже раскатан.

                                                                                                                        Проблема же даже не в самих "следить за уязвимостями", а в "выкатывать фиксы так, чтобы ничего не сломать". Мейнтенеры тратят значительные усилия на сопровождение дистрибутива так, чтобы "ничего не ломать". А перенос этого "in house" в режиме "секрьюрити апдейтами в контейнерах докера у нас занимается..." быстро приводит к тому, что занимается этим никто, потому что ресурсов на security team нет, и выделять их никто не будет — надо продукт делать, а не камлать на CVE'шками.
                                                                                                                          +1
                                                                                                                          у вас внутри контейнера тот же самый apt-get update && apt-get upgrade доступен, обновили один контейнер, сделали с него образ, разослали всем серверам, подняли и готово. Я не понимаю, к чему вы цепляетесь
                                                                                                                            +3
                                                                                                                            Тогда я не понимаю смысла микросерверной stateless архитектуры. Внезапно, apt-get upgrade создаёт state у системы. Более того, если разработчик хочет так, чтобы после upgrade у него не уползла версия похапе или ещё что-то, эти версии надо припинивать, то есть прописывать зависимости, то есть выкатывать софт через сборку пакетов (или городить свои костыли, что ещё веселее). То есть надо делать всё то же самое, что и делали, только "в контейнерах".

                                                                                                                            Процесс же определения какой контейнер на какой версии какой из них надо обновлять/перезапускать — нерешённая задача (да, срочно пишем оверлейный пакетный менеджер для управления контейнерами, чтобы потом очередное поколение хипстеров решило, что можно забить на зависимости и версии и выкатывать "всё это" единым блобом, не думая).
                                                                                                                              –1
                                                                                                                              Смысл в том, что у вас есть один базовый имидж, который вы обновляете, а от него наследуются остальные, хватит все усложнять
                                                                                                                                +5
                                                                                                                                И каким образом известно, кто от кого унаследовался? Каким образом базовый образ покрывает новые пакеты, установленные в "производных" образах (в одном образе питон есть, в другом php — у каждого свои багфиксы)? Кто следит в каком образе в цепочке образуется пакет и почему?

                                                                                                                                Попытки закидать ссаными тряпками людей, задающие усложнённые вопросы отлично работают, потому что никто отлично умеет справляться с несущественными вопросами безопасности с фантастической скоростью.
                                                                                                                                  +2
                                                                                                                                  Например FROM debian:8.2 в начале каждого Dockerfile. Перед тем как поливать грязью и выдумывать проблемы, поинтересовались бы для начала, как все работает
                                                                                                                                    –1
                                                                                                                                    Итак, у вас есть 50 образов, которые собираются через npm/pip/composer, и вам нужно обновить базовый слой. Внимание, вопрос: у скольких образов из 50 пересобраться сходу не получится?
                                                                                                                                      +3
                                                                                                                                      Если проекты не могут корректно собраться через месяц или полгода или на другом дистрибутиве, то это не проблемы докера, вам не кажется?
                                                                                                                                        +1
                                                                                                                                        Не кажется. Потому что сначала заявляется, что ты один раз собери больше не мучайся с постоянной поддержкой правильных зависимостей, а потом оказывается, что всё равно нужно продолжать этим заниматься. Поэтому придумать, как обновлять базовый слой без пересборки всего, правда важно.
                                                                                                                                      +3
                                                                                                                                      Э… Простите, а в каком из этих образов (в цепочке) появилась python-gi с уязвимостью? Как это узнать не разглядывая каждый образ по-очереди?

                                                                                                                                      Цепочка очень простая:

                                                                                                                                      debian-minimal -> typical python container -> typical production container -> standard deployment configuration -> proj-33-22.

                                                                                                                                      В каком из образов надо накатывать апдейт, если известно, что proj-33-22 только что позорно завалил PCI-DSS?
                                                                                                                                  +3
                                                                                                                                  apt-get upgrade не создаёт state, он делается на этапе создания контейнера, а не в рантайме. У вас просто получается новая версия контейнера — она у вас потом автоматически тестируется на CI, и если что-то не взлетает, то проблема уже решается по мере поступления.

                                                                                                                                  Без докера у вас будут ровно те же самые проблемы — сделали apt-get upgrade на боевом сервере и внезапно сломалось приложение (у меня такое было — perl 5.20 поставился — и всё рухнуло — оказалось, что код, скопмилированный и предкешированный на диске от Inline::C стал несовместим с новой версией). Были бы контейнеры, это бы всё поймалось на тестовых серверах.
                                                                                                                                    0
                                                                                                                                    Были бы контейнеры, это бы всё поймалось на тестовых серверах.

                                                                                                                                    Правильнее сказать — "были бы тестовые сервера". Контейнеры не помогут, если каку пушат сразу в продакшн без проверки.

                                                                                                                                    А всё остальное верно написано.
                                                                                                                                      0
                                                                                                                                      Правильнее сказать: "тестировались бы на тестовых серверах и код, и среда его исполнения одновременно перед обновлением продакшена". Увы, но без технологий, связывающих, хотя бы процентов на 99, ситуация "но у меня же всё работает" практически неизбежна несколько раз в году при ежедневных деплоях продакшена.
                                                                                                                                        +1
                                                                                                                                        Ну если быть совсем педантом, то и отдельные тестовые серверы не нужны. Можно развернуть тестовую копию сервиса на тех же серверах, но в отдельных контейнерах. Если поменьше реплик сделать, то можно всё протестировать без ущерба продакшну :)
                                                                                                                                    +1
                                                                                                                                    Ога, вот только банально обновить нижестоящий слой нельзя: нужно пересобирать контейнер. И рекурсивной пересборки тоже нет. Так что "обновили один контейнер" превращается в огород из костылей, который никто не будет городить: достаточно посмотреть на плачевное состояние docker hub.

                                                                                                                                    И это с учетом того, что при пересборке контейнера данные приложения в нём нужно как-то сохранять и восстанавливать.
                                                                                                                                      +7
                                                                                                                                      В обычном контейнере не должно быть данных, которые нужно сохранять и восстанавливать.
                                                                                                                                        +1
                                                                                                                                        Огород из костылей — это примитивный шелл-скрипт из нескольких вызовов docker build, чтобы собрать все приложения. А если есть continuous integration, то и вообще ничего делать не надо — коммитите новую версию базовой ОС в docker-репозитарий и откидываетесь на кресле.
                                                                                                                                0
                                                                                                                                Кто вам мешает собрать собственный образ на базе любого дистрибутива и поддерживать его и все либы в актульном состоянии?

                                                                                                                                это дополнительное время, которое обходится в дополнительные расходы. Вот честно, у меня нет никакого желания это делать как у разработчика. У меня есть для этого команда админов, или команда других чуваков, которые опубликовали образ в docker hub. Docker в этом плане предоставляет замечательную возможность разделить обязанности и синхронизировать окружение.
                                                                                                                                0
                                                                                                                                Такая возможность была всегда. Ставим MS-DOS c дискеты неизвестного происхождения, ставим винду с какого-нить ZverCD, ставим BlackCat линукс, с диска выданного на какой-то конфе и забиваем, "работает — не трогай".

                                                                                                                                Откуда вообще мысль, что проблема поддержания актуальных версий перекладывается на никого?
                                                                                                                                  +3
                                                                                                                                  Оттуда, что при использовании докера подготовкой образов начинают обычно заниматься разработчики микросервисов, а их волнует только работоспособность их сервиса, а не общая безопасность образа. Поэтому обновляют они эти образы только тогда, когда нужно обновить их сервис, а не когда вышло обновление пакетов для дистрибутива используемого в качестве базового образа — и обновляют только свой сервис, разумеется, если только ему для работы не понадобятся свежие версии каких-то пакетов дистрибутива.
                                                                                                                                    0
                                                                                                                                    у меня куча проектов была, которые были на древних бубунтах и сервера не обновлялись по 5 лет. Почему вы проблемы людей приписываете стороннему софту?
                                                                                                                                      +1
                                                                                                                                      Три варианта решения проблемы актуальности:

                                                                                                                                      • разработчикам вменяется обязанность следить за актуальностью своих образов
                                                                                                                                      • администраторам вменяется обязанность следить за актуальностью своих образов (собственно при переходе на контейнеризацию с, например, витруализации, никто сних эту обязанность и не снимает)
                                                                                                                                      • обязанность следить за актуальностью образов вменяется специально обученным людям (часто их называют девопсы)
                                                                                                                                        +2
                                                                                                                                        …и мы получаем, по сути, вместо 5-ти разных серверов за которыми следит профессиональный админ — 50 разных образов, которые по сложности поддержки почти ничем не отличаются от полноценных серверов, но следить за которыми должны разработчики, причём от них ожидается, что после "вменения обязанности" они будут делать это не хуже профессионального админа.

                                                                                                                                        В общем, теоретически и формально то, что Вы предлагаете можно назвать решением проблемы, но практически оно им никак не является.
                                                                                                                                          0
                                                                                                                                          я конечно не знаю как в других конторах — но у нас приложения в продакшене обновляются раз в 2 недели (спринт), при этом собирается новый контейнер с приложением, который наследуется от образа runtime:latest (его можно хоть каждый день в автоматическом режиме пересобирать и пушить в приватный registry), который базируется на ubuntu:latest. Соответственно в течении 2-х недель до нас гарантированно дойдут секьюрити фиксы, если они вышли в базовом образе убунты. Если же проблема глобальная (кто-то хертблид выявил) — то все, что требуется сделать — это нажать кнопочку Run в тимсити и запустить билд (да, для каждого приложения — если лень руками то можно скриптик написать).
                                                                                                                                      +5
                                                                                                                                      Для well-established операционных систем (RHEL, CentOS, Debian, Ubuntu) существует

                                                                                                                                      а) security team для дистрибутива, которая латает дырки в похапе и его либах так, чтобы не сломать всё остальное.
                                                                                                                                      б) Предъявляются требования к создателям пакетов использовать версии библиотек, которые предоставляются ОС, и правильно прописывать депенденсы.

                                                                                                                                      Вот второе требование страшно бесит программистов, у которых на ноутбуках в лучшем случае "какой-то арч", а обычно — макось. И дальше синдром "у меня всё работает почему оно в вашем говнопродакшене сыпется из-за каких-то протухших версий библиотек? О, у нас есть докер, куда я могу наспыпать всё, на чём оно у меня умудрилось заработать и это будет наш новый продашкен, как круто — оно работает у меня на ноуте, оно работает у меня на сервере".

                                                                                                                                      А дальше см начальный коммент про безопасность и "никто".
                                                                                                                                        +1
                                                                                                                                        Бить по рукам разработчиков, которые выкладывают образы на "каком-то арче", а не на корпстандарте из well-established
                                                                                                                                          0
                                                                                                                                          Осталось каким-то образом изнасиловать разработчиков использовать корпстандарт, который им не нравится.

                                                                                                                                          Да, бывают компании с диктатурой операторов, бывают с диктатурой программистов. Там, где диктатура операторов — никаких докеров не требуется, потому что есть отлаженная инфраструктура, под которую программисты приспосабливаются.
                                                                                                                                            +1
                                                                                                                                            Я бы сказал, что там, где диктатура операторов, как раз докер может отлично полететь, т.к. будет использоваться по-назначению.
                                                                                                                                              0
                                                                                                                                              Если диктатура операторов, то зачем докер? Программисты пишут код, в составе кода есть debian/rules, где описана среда для сборки пакета, тесты, процесс сборки и автоматического заполнения зависимостей. Этот репозиторий автоматически запускается на сборку в CI'е, откуда попадает в локальный apt-репозиторий, откуда запускаются интеграционные тесты по всем вариантам "копий продакшенов", после чего происходит фиксация снапшота apt-репозитория (спасибо, aplty) и бампается версия опубликованного для продакшена репозитория. Хук на CI'е бампает припиненную версию пакета в конфигурации chef'а, который автоматически его раскатывает на всех заинтересованных серверах во время следующего прогона. Это если смелости хватает. Если не хватает — финальный "в продакшен" делает человек.

                                                                                                                                              Где тут докер-то? Пакеты собираются и проходят юнит-тесты в контролируемом окружении (build-dependences), интеграционные тесты запускаются в контролируемых окружениях, эквивалентных продакшенам, раскатываются в продакшены с известными версиями критических (по версии) библиотек и самыми свежими непротиворечивыми версиями из состава дистрибутивов для всех остальных.

                                                                                                                                              Где тут место для докера-то? Какую он проблему решает? Зависимостей? Диктатура операторов заставила программистов пристально отнестись к заполнению полей в debian/control и языко-специфичных dependenc'ах в самих языках (setup.py, например). Обновлений? chef & apt и стандартный дистрибутив отлично эту проблему решают. Безопасности? Лучше, чем дистрибутивной, всё равно не будет.

                                                                                                                                              Ах, да, я понял. Программистам очень не удобно писать код на макбуках в условиях, когда программы работают на debian и ожидают среду исполнения debian/ubuntu.

                                                                                                                                              Ну так на то и диктатура операторов, что программисты претерпевают и не могут локально код запускать (без специальных костылей), который прямо тут и пишут.
                                                                                                                                                +4
                                                                                                                                                Вы всё правильно написали, но только для случая с малым количеством компонентов и не очень большой кодовой базой. Когда получается сложная система, которая зависит от 5 разных компонентов, каждый из которых от разного, но пересекающегося набора библиотек, то начинается ад с зависимостями. Иногда появляется необходимость поставить 2 версии одного и того же dev пакета, например. Чем больше кодовая база, тем больше зависимостей, тем больше ада. Начинаешь писать специальные костыли для апта, чтобы он смог поставить пакет с зависимостью типа <<, затягивать релизы, чтобы успеть сделать изменения в 2 разных местах, делать дополнительные репозитории для хранения части пакетов… И это только для сборки! Разработчики уже знают, как работает Replace и Conflict, особо продвинутые даже про divert знают.

                                                                                                                                                В общем, начинаешь понимать, что нужно либо статически собираться, либо использовать контейнеры (что, по сути, почти одно и то же).