Пожалуйста, начинайте читать с начала серии: habrahabr.ru/post/267441

Как не надо использовать Docker.



Чтобы понимать эту статью надо знать базовые команды Dockerfile для создания изображений и принципы объектно-ориентированного дизайна.

Открываю документацию любого официального образа сервисного ПО — например, Nginx и нахожу раздел «How to use this image». Нам предлагают создать свой образ на базе официального, скопировав в него наши файлы, настроить мапинг порта в мир, и подмонтировать свою папку с конфигами.

FROM ...
COPY  . /usr/src/myapp
WORKDIR /usr/src/myapp

Да, нам предлагают унаследовать Model от View в одном звездном классе и заплатить за хранение на Docker Hub образов наших проприетарных приложений. Business, as usual. Это же нам предлагают сделать в образах PHP, Pyhon, Ruby, и так далее. Для Python и Ruby даже сделаны версии с ONBUILD-триггерами на построение изображений-наследников, которыми приложение из папки будет скопировано в новый образ, «which should be all you need» — как 640 килобайт.

К счастью, решение известно так же давно как проблема. Банда четырех, создатель Java Джеймс Гослинг и Фаулер последние 20 лет твердят: используйте композицию вместо наследования. Поэтому я положу рядом контейнеры с разными сервисами, создам адаптер, data transfer object, и свяжу их через конфиг.

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

Продолжение можно найти здесь

Комментарии (48)


  1. Glueon
    22.09.2015 17:08
    +2

    Погодите. Т.е. вы считаете, что исходный код внутри контейнера — это трэш и угар?
    Поэтому нужно его выделять в отдельный data container, или что контейнеры-контейнерами, а исходный код на целевой сервер должен поставляться каким-то боком и монтироваться в контейнер через volume с хостовой машины?


    1. iborzenkov
      22.09.2015 17:21
      +5

      ага и потом 20 контейнеров и своя система развертывания этих контейнеров, по сложности превышающая настройку сервера без докера, к половине приложений костыли и десяток супервизоров (если что — я так не считаю, это они так считают)


      1. Grikdotnet
        22.09.2015 19:32
        -2

        Конечно, это нужно немногим. Может быть, кому-нибудь мои статьи будут полезны.


    1. Grikdotnet
      22.09.2015 19:29

      Glueon, про Data Volume container и распространении приложения в нем есть отдельная статья.


      1. Glueon
        23.09.2015 13:21

        Вы про свою? понял, что про свою.


    1. alexac
      22.09.2015 20:28

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


  1. js605451
    22.09.2015 20:42
    +2

    ИМХО, на статью не тянет. Философия Docker:

    1. Артефакт работы программиста — не исходный код, не дистрибутив приложения, а контейнер, который включается на любой физической машине одной кнопкой «вкл» (при условии, что на машине установлен Docker).
    2. Образ Docker типа Nginx — это не веб-сервер, запакованный в контейнер, а веб-фреймворк, который работает поверх голой ОС. Ваше решение — это не «программа, которая хостится внутри Nginx», а просто «очень сильно кастомизированный Nginx» (иногда настолько кастомизированный, что конфигов не хватило и «пришлось написать плагин»)


    1. Grikdotnet
      23.09.2015 00:02

      Каждое слово, вроде бы, понятно, но текст в целом не понимаю, простите :)
      Nginx — это веб-серевер, а не фреймворк, и ничем из него фреймворк не сделать. Удобно хранить вместе приложение и runtime — ради бога, эти статьи для тех, кому надо разделять.


      1. js605451
        23.09.2015 17:58

        docker.com:

        Package your application, dependencies and configurations together to ensure that your application will work seamlessly in any environment on any infrastructure just like it did on your machine.

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

        Это официальная точка зрения команды Docker на то, что они делают и как это использовать.

        По поводу:
        Nginx — это веб-серевер, а не фреймворк

        Вики:
        A web application framework (WAF) is a software framework that is designed to support the development of dynamic websites, web applications, web services and web resources.

        Вики:
        In computer programming, a software framework is an abstraction in which software providing generic functionality can be selectively changed by additional user-written code, thus providing application-specific software.

        Укажите пожалуйста по каким причинам Nginx нельзя относить к веб-фреймворкам.


        1. VolCh
          24.09.2015 07:08

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


          1. js605451
            24.09.2015 11:59

            Смотрите:
            Port 80 -> Docker -> Nginx -> uWSGI -> Django -> My Code

            1. Общепринятое мнение, что веб-фреймворк — это Django.
            2. Мнение в духе Docker: веб-фреймворк — это всё что от Docker и до Django.

            В первом случае мы говорим о том, что есть какой-то сайт, сделанный на фреймворке Django, и его нужно запускать на каком-то веб-сервере. Во втором случае мы говорим о том, что есть какой-то сайт, сделанный на фреймворке «Docker/Nginx/uWSGI/Django» и его можно запускать на любой «голой» ОС.



            1. VolCh
              24.09.2015 15:42

              Скорее так: Port 80 -> Docker -> Nginx -> uWSGI -> Django -> My Code -> Django -> uWSGI -> Nginx -> Docker -> Port 80

              То есть c моим кодом взаимодействует (вызывает его и обрабатывает результаты вызовов) только Django, а остальные звенья лишь транслируют запросы и ответы. Мне как разработчику нужно только API Django изучить, если в мои задачи не входит подготовка готового к выкладке на продакшен образа/пакета, а она, как правило, не входит — администрирование связки этих продуктов сама по себе нетривиальная задача, достаточная для выделение под неё «специально обученного человека».


              1. Grikdotnet
                29.09.2015 09:48

                В цепочке еще СУБД, i/o и memcached/redis/etc. Junior-у, который клепает формочки Django хватит, а senior и архитектор обязаны учитывать детали всего стека.


    1. VolCh
      23.09.2015 11:43

      1. То есть никаких внешних ресурсов типа собственно кода приложения и его баз данных? Контейнер (или набор типа веб-сервер, апп-сервер, БД-сервер) самодостаточен и обеспечивает персистентность? Или в философии Докера персистентность данных приложения не нужна и если контейнер упал или его удалили, то приложение начинает жизнь с ноля?

      2. Разве веб-фреймворк, а не основа для контейнера, который представляет собой (для админа) «чёрный ящик» с несколькими входами и выходами?


      1. Grikdotnet
        23.09.2015 12:14
        -1

        1. Персистентность реализуется через Data Volume container.
        2. Простите, не понимаю, разве веб-фреймворк что? Уточните, пожалуйста.

        В целом, Docker размывает границы между админами и разработчиками — разработчики начинают заботиться о настройках системных служб и включают их конфигурацию в контейнер.


        1. VolCh
          23.09.2015 14:39

          1. Я так понимаю работу с помощью докер с типичным веб-приложением: готовим (или берём готовыми) три универсальных образа для веб-, апп- и бд-сервера. Готовим конфиги, исполняемый код (бинарники или скрипты) и данные для них. Готовим сценарий выкладки (с помощью compose, bash, ...) по которому поднимается контейнеры бд с прилинкованными (или скопированными) конфигами и данными, аппа с прилинкованными (или скопированными) конфигами и исполняемым кодом, веба с прилинкованными (или скопированными) конфигами и статикой. Результат работы разработчика — образы или их докерфайлы, исполняемый код, начальные конфиги, данные или ссылки на них и сценарий подъёма всего этого добра. Админы запускают сценарии, при необходимости правя конфиги, пути и т. п., чтобы они соответствовали хосту и окружению в котором поднимаются контейнеры.

          2. Я засомневался в утверждении «это не веб-сервер, запакованный в контейнер, а веб-фреймворк». Разве фреймворк, а не чёрный ящик?

          Хм, то есть я как разработчик должен решать, например, сколько воркеров создавать тому же nginx, не зная даже сколько процессоров на хосте, на который решит выложить мой проект админ? Как по мне в конфиги nginx я должен вписать пути и прочие зависимости от проекта, а админ уже должен регулировать параметы, которые зависят от среды, хоста, доступного железа и т. п.


          1. js605451
            23.09.2015 15:44

            1. Всё верно: программист делает «детский конструктор из кубиков», а «админ из этих кубиков в своей песочнице строит какую-нибудь крепость».
            2. Вы не должны принимать решения, которые зависят от среды исполнения. Количество воркеров — это такой же конфигурационный параметр, как коннекшн стринг к базе. Совершенно точно будут параметры, которые вы захотите железно захардкодить и запретить админам их изменять, но будут и параметры, которые вы захотите сделать частью интерфейса. Например внутренний параметр «количество воркеров Nginx» вы можете пробросить как внешний параметр «количество ядер для использования». Типа абстракция такая.


            1. VolCh
              23.09.2015 17:05

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


              1. js605451
                23.09.2015 17:34

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


                1. Grikdotnet
                  23.09.2015 17:47

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


      1. js605451
        23.09.2015 15:39

        1. Внешние ресурсы подключаются через «позднее связывание». У типичного веб-приложения, завёрнутого в Dockerfile будет несколько параметров типа коннекшн стринга для БД. Значения для этих параметров указываются при запуске контейнера.
        2. Всё верно: для админа это действительно чёрный ящик с понятным интерфейсом, у которого с одной стороны, например, открытый серверный сокет, а с другой — несколько конфигурационных параметров типа того же коннекшн стринга. Запускаешь и работает. Но это для админа. А программист отвечает за реализацию того, что внутри этого ящика — за детали реализации. Вот с точки зрения «решения» Nginx — это веб-фреймворк.


        1. Grikdotnet
          23.09.2015 17:52

          В моем случае параметры можно просто указать в файле конфигурации. Конфиг субд и дамп базы распространяются в одном архиве с приложением, все установится и запустится само, без участия админа одной командой, причем, не только на production, но и локально. Админ может поправить параметры на production — все конфиги «торчат» из контейнера.


          1. VolCh
            24.09.2015 07:12
            +1

            все установится и запустится само, без участия админа

            Очень смелое утверждение, причём особенно касательно production. Без участия админа пробросятся 80 и 443 порт? Без участия админа установится сам докер?


        1. Glueon
          23.09.2015 23:04

          Дополню, что админу ничто не мешает изменить настройки чего-либо у уже работающего контейнера и сделать commit.


          1. Grikdotnet
            23.09.2015 23:50

            commit и push изменят эти настройки у всех в команды разработчиков, а мне совсем не нужно значение innodb_buffer_pool_size=32Gb на локальной виртуалке


          1. Grikdotnet
            23.09.2015 23:52

            commit без push… а зачем? там они потеряются при выкладке новой версии. пусть они лежат все вместе в отдельной папке прямо под рукой у админа и монтируются в контейнер, не надо открывать shell в контейнере чтобы отредактировать конфиг, а в контейнере пусть лежат дефолтные значения,


  1. novoxudonoser
    23.09.2015 00:02
    +5

    Статья ужасна (вернее её нет).

    Выстрел в ногу это то как использую доскер я:

    cd /tmp/шото
    make
    make install
    


    1. Grikdotnet
      23.09.2015 00:15
      -2

      в огороде бузина, в городе дядька :)


      1. novoxudonoser
        23.09.2015 02:34

        Что вы пытаетесь этим сказать?


        1. Grikdotnet
          23.09.2015 04:14
          -1

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


          1. VolCh
            23.09.2015 14:10

            Вот, например:

            Открываю документацию любого официального образа сервисного ПО — например, Nginx и нахожу раздел «How to use this image». Нам предлагают создать свой образ на базе официального, скопировав в него наши файлы, настроить мапинг порта в мир, и подмонтировать свою папку с конфигами.

            FROM…
            COPY. /usr/src/myapp
            WORKDIR /usr/src/myapp

            Да, нам предлагают унаследовать Model от View в одном звездном классе и заплатить за хранение на Docker Hub образов наших проприетарных приложений.


            1. Пример приведён из доков по php, хотя по тексту об nginx речь идёт.

            2. Предлагают, первым делом, не унаследовать «звёздный класс» типа
            class DockerNginx extends DockerDebian
            {
                public function __construct()
                {
                    $this->install('nginx');
                    /// some other init...
                }
            
                public function run()
                {
                    $this->cmd('nginx')
                }
            }
            
            , а инстанцировать и запустить его, предварительно установив свойство /usr/share/nginx/html. Типа
            $some_nginx = new DockerNginx();
            $some_nginx->fs->root->share->nginx->html = $host->fs->pwd->static-html-directory;
            $some_nginx->run();
            

            Во вторую очередь предлагают унаследовать «звёздный класс», переопределив это свойство (относящееся в рамках nginx исключительно к Model, если рассматривать его как MVC приложение) в конструкторе, типа:
            class SomeContentNginx extends DockerNginx
            {
                public finction __construct()
                {
                    $this->fs->root->share->nginx->html = clone ($host->fs->pwd->static_html_directory);
                }
            }
            
            $some_nginx = new SomeContentNginx();
            $some_nginx->run();
            

            То есть продемонстрированы две основные возможности изменения функциональности объекта: инъекция желаемой зависимости в объект вместо дефолтной после инстанцирования объекта перед началом его использования и унаследование класса в котором желаемая зависимость устанавливается при его инстанцировании перед началом использования. За рамками документации класса DockerNginx остаются как другие способы инжектирования Docker, так и свойства, которые можно инжектировать в Nginx, поскольку предполагается, что пользователь, которому они нужны достаточно знаком с обеими системами или хотя бы способен почитать документацию по ним, чтобы максимум за пару часов собрать свой универсальный образ согласно своим практикам использования nginx и Docker, например использования его во всех своих проектах с помощью docker-composer, подключая тома или линки.

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


            1. Grikdotnet
              23.09.2015 14:27

              SomeContentNginx extends DockerNginx вносит зависимость от DockerNginx.
              классический вопрос проектирования, лучше обратиться к Фаулеру www.martinfowler.com/articles/injection.html


              1. VolCh
                23.09.2015 16:47

                А без этой зависимости никак не обойтись тут. Ваши скрипты точно так же зависят от DockerNginx в docker pull nginx, просто вы используете не наследование. Но и не композицию, а патчите инстанс $some_nginx класса DockerNginx после его инстанцирования.


                1. Grikdotnet
                  23.09.2015 17:13

                  В моем случае это не зависимость вида «DockerNginx», а реализация интерфейса iNginx. Я могу прозрачно подменить MariaDB на Oracle MySQL в команде запуска, а контейнер с приложением не изменится.


                  1. VolCh
                    24.09.2015 07:19

                    Вот что не хватает вашей серии статей — картинки (или хотя бы списка) с описанием конечного результата. Что вы имеете в виду под контейнером с приложением? У вас 4 контейнера в приложении всего? nginx, php, mysql и приложение?


                    1. Grikdotnet
                      24.09.2015 12:43

                      Да, я это уже понял.

                      Конечный результат — образ в виде .tar.xz размером 2-5 мегабайт с приложением и конфигами. На его основе которого я парой команд где угодно поднимаю весь стек целиком: база, nginx/tomcat, php/python/java, mysql/postgres, и мое приложение.
                      Количество контейнеров не имеет значения. Важно, что один или два маленьких файла автоматизируют создание любого полного стека, не ограничивая в конфигурировании.

                      Дело в том, что я не планировал писать подробную книгу и объяснять основы построений модульной архитектуры. Я написал это для своих, а хабр неудобен для публикации связанных развернутых материалов, это новостная лента.


                      1. VolCh
                        24.09.2015 15:52

                        Стандартный образ Docker? Или просто заархивированный каталог, в котором скрипты сборки и запуска (compose или bash — не суть) веб, апп и бд контейнеров + линковка/копирование к ним конфигов и собственно исполняемого кода (php, python или sql — тоже не суть)?

                        Я просто не пойму до конца вашу идею: функциональность compose (жонглирование контейнерами и внешними ресурсами после скачивания образов и сздания контейнеров, но до их запуска) через bash или какой-то абсолютно другой подход? Кстати, как в вашем подходе решается задача поднятия веб-, апп- и бд-серверов на разных хостах?


          1. novoxudonoser
            23.09.2015 15:26

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


            1. Grikdotnet
              23.09.2015 17:16
              -3

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


              1. drwatson32
                24.09.2015 12:38

                Тогда зачем эта статья здесь?


                1. Grikdotnet
                  24.09.2015 12:45
                  -2

                  для тех, кто в теме


  1. drwatson32
    23.09.2015 14:11

    А почему нельзя использовать docker compose для таких целей?


    1. Grikdotnet
      23.09.2015 14:21

      можно использовать, а можно и обойтись без него — по правилу Бритвы Оккама


      1. drwatson32
        23.09.2015 14:51

        Мне сие непонятно, видимо потому что я приверженец правила KISS.


        1. Grikdotnet
          24.09.2015 12:45

          значит, symphony, hybernate и микросервисная архитектура не для вас :)


          1. VolCh
            24.09.2015 15:54

            symphony и doctrine (вроде как клон hybernate на php) как раз исповедуют принцип «напишите простой конфиг, а всю чёрную работу мы сделаем за вас»


          1. Glueon
            25.09.2015 16:05

            Какая связь?