Как стать автором
Обновить

Комментарии 49

У меня вот какой вопрос возникает, когда периодически приходится допиливать чужие проекты на django:
Вы наверняка jquery и/или bootstrap ставите с помощью bower
Однако в задаче для gulp говорите минифицировать и склеивать весь *.js из перечисленных директорий. А вас не заботит, что в репозитории bower хранится как оригинал, так и .min.js? В итоге они ведь оба попадают в mainpage.js
Может быть стоит склеивать только те скрипты/стили, которые реально подключаются на страницу?
Можно. Это просто образец. Думаю, что у меня в этом плане определённо ошибка, поскольку наиболее правильно действительно жёстко прописывать имена файлов для слияния. А вот в папке project уже можно создать под отдельные страницы или группы страниц свои поддиректории и компилировать из них все файлы.

gulp.src(['./front/jquery/jquery-xxx.min.js', './front/bootstrap/bootstrap.min.js', './front/angularjs/angular.min.js',
'./front/angularjs/i18n/angular-locale_ru-ru.js', './front/project/pages/mainpage/**/*.js', './front/project/plugins/statistics/**/*.js'])

Вот, скажем пример того, что может получиться. На выходе имеем 1 сжатый рабочий JS файл.

Ещё добавлю, что я вообще не гарантирую правильную работу приведённого gulp сценария. Поскольку я его даже не оптимизировал и сильно не углублялся. Статья предназначена прежде-всего для бэкенд и фулл-стек разработчиков, которые могут самостоятельно настроить gulp/grunt/compass и т.д.
В таком случае вы дублируете список файлов в base.html и в gulp.js. Я ищу список подключенных в base.html javascript файлов (в простейшем случае весь js подключается там. Js, который подключается на других шаблонах, но не подключается в base.js — отсутствует), их уже сжимаем и склеиваем
В этом нет нужды. Мы знаем, что на главной странице будет скомпилированный файл mainpage.js. Его и подключаем. Для тестов можно использовать что-то вроде Jasmine. Так что в большинстве случаев отдельное подключение каждого скрипта не требуется. Другой вариант — писать отдельный JS для различных регионов одного и того же шаблона. В таком случае, опять же, отдельное подключение скриптов не нужно. Есть ещё require.js, с которым Gulp может работать. Так что мы можем обойтись вообще подключением одного файла сжатого или не сжатого — не имеет значения.
Если каждый человек в вашей команде обязан пользоваться livereload — ваша правда.
Ситуация с подключением различных скриптов в зависимости от определенных условий требует решения как в вашем, так и в моём варианте
Это решается на уровне JS. Livereload обеспечивается докером только на локальной машине. На продакшн gulp будет выполняться один раз — перед стартом сервера. Мы чётко определяем, что на этой странице или на этой группе страниц будет подключен один скрипт. Мы прописываем его генерацию в Gulp. Если отключить сжатие, склейка будет происходить меньше секунды. JS программер не меняет ничего в теге script — всё происходит в настройках Gulp. Программист вполне свободно делит приложение на отдельные модули и на выходе получает 1 файл. Это даже лучше: программер сразу видит что происходит после склейки, есть ли конфликты. А на проде уже включится сжатие, которое может занимать продолжительное время, но, в любом случае, там оно будет проходить один раз.
Не могли бы вы пояснить, какие сервисы в итоге в каких контейнерах/каком окружении будут выполняться, а то я что-то ничего не понял
База данных, Gulp и бэкенд на Django. Gulp будет служить для компиляции независимого js приложения, которое будет обмениваться с бэкендом данными через Rest. Docker упростит развёртывание проекта и задаст общий стиль разработки: в нём будет работать livereload и запускаться локальный dev сервер. Также, docker избавит разработчиков от необходимости самостоятельно ставить postgresql, python, django, node.js, gulp и запускать все серверы и демоны. Рассматриваемая архитектура выходит за рамки данной статьи, так что это может означать продолжение, в котором контейнер с проектом обзаведётся nginx, добавится контейнер с redis для кеширования, а связь между сервером и клиентом будет раскрыта. В данной статье рассмотрена возможность один раз настроить окружение так, чтобы на остальных машинах оно ставилось одной — тремя командами.
Мне все-таки хотелось бы подробнее этот вопрос разобрать. Потому что архитектура тут в стиле Дали, и свзяи между контейнерами и хост-машиной довольно необычны на мой взгляд. Мне интересно, почему решено сделать именно так? Все-таки классически контейнеры обычно независимы друг от друга и от хост-системы, а у вас все сплетено в один клубок
А что не так со связью контейнеров и хост-системы?
Очень много volumes как на мой взгляд. Плюс жесткая проброска портов контейнеров на хост машину.
Пробрасывается три нужных порта: БД, SSH, HTTP. Есть альтернативный вариант — ставить listen 0.0.0.0 на всех контейнерах. Тогда пробрасывать порты не надо вообще. Лично я предпочитаю localhost В дальнейшем, если делаем деплоймент в контейнерах (облачные сервисы позволяют такой вариант), нам остаётся оставить только один проброшенный порт — HTTP. Впрочем, вариант с одной сетью на все контейнеры выглядит красивым и логичным.

В volumes тоже можно сделать оптимизацию. Например, конфиги супервайзора поместить в одну папку. Остальные тома все на своём месте.
Проброс БД порта не нужен, для этого есть link. Контейнер приложения всё равно связывается с контейнером СУБД напрямую по стандартному порту независимо от того на какой порт проброшен он на хосте. Зачем SSH вообще непонятно. Конфиги супервизора, да и вообще все можно копировать в контейнеры при билде, а не шарить с хостом.
И ответы на это уже размещены в различных комментариях этой статьи. SSH используется для отладки и тестирования. Поскольку плагин для docker желает видеть docker-machine. Копирование конфигов при билде, как я писал ниже — оптимальный вариант. По поводу link вместо проброса портов хотелось бы уточнить: чем это лучше? Есть авторитетные источники, которые подтверждали бы это? Я пока вижу только одно обоснование: вам так больше нравится. А мне больше нравится проброс портов. На этапе оптимизации я бы использовал директиву net и связал бы все контейнеры в одну сеть, вывернув наружу только 80 порт.

К тому же, я не совсем понимаю как вы планируете использовать link и зачем? postgresql и так прекрасно доступен в project на одноимённом хосте. Проброс портов делается только для хоста. Вы, видимо, путаете тёплое с мягким.
По поводу link вместо проброса портов хотелось бы уточнить: чем это лучше?

Не занимаются эксклюзивно ресурсы хост-машины, а значит можно запускать множество инстансов множества приложений одновременно без конфликтов. Ваша схема позволяет одновременно поднять два инстанса из разных веток одного приложения?
Вы посмотрите для чего вообще был сделан проброс портов: я использую pgadmin, использую Remote interpreter в PyCharm. Я не использую проброс портов для доступа к БД или для ssh управления сервером. Надо же различать области применения. При этом, если от порта БД можно отказаться, то от SSH — с трудом. Он используется в IDE. Для базы данных есть альтернативный вариант — узнать на хосте IP контейнера, сделать expose и коннектиться к базе. Либо, связать контейнеры директивой net и использовать ssh туннель. Только делать мне больше нечего: на dev среде настраивать туннелирование. Всё прекрасно работает при использовании ports.
Мне вот хотелось бы узнать, на сколько на практике это разворачивать для fontend разработчика? Просто мы по началу тоже хотели использовать такую систему, но вот с разворачиваем ее на Мак'ах возникли проблемы, так как на них докер работает из-под virtualbox, то ощутимой разницы с Vagrant не заметно. Да и плюс наш фронтэндщик работает без idе.
Как-то в статье не освещено основное, видимо, требование к системе развертывания: разработчик разворачивает исходники проекта (например из гита) локально, работает с ними локально, и система должна подхватывать изменения на лету или с минимумом движений. Отсюда куча томов с привязкой к хосту — отслеживание изменений файлов хоста на лету.
Конфиги можно подключить и из Dockerfile. Но тогда для перезапуска службы с новым конфигом, надо будет заново делать build. Это не совсем удобно. Вообще, в предложенном варианте не используется Docker hub для хранения получившихся сборок. И это главная причина почему в volumes так много томов. Мы исходим из того, что заказчик не будет оплачивать приватный репозиторий на Docker hub.
docker build делается буквально за доли секунды

А для хранения контейнеров можно развернуть собственную registry
Существенное замечание. Только build не всегда делается за доли секунды, и не всегда есть необходимость в специализированном репозитории. Описанный пример позволяет хранить конфигурацию для развёртывания среды непосредственно в исходниках. Кстати, при docker pull должен получиться билд без исходного кода, иначе харам и побивание камнями. Поэтому, в принципе, docker hub или registry это красиво, но не нужно. Тем более, что билд выполняется не так долго. Даже если в Dockerfile стоит несколько команд на установку определённых пакетов. А такая команда в приведённом примере, прошу обратить внимание, имеется.
Нет, вы просто разносите процессы разработки и развертывания.

При разработке вы что-то там делаете в virtualenv, тестируете, а когда все готово — генерируете артифкат — docker image, самодостаточный, который уже заливаете на удаленный сервер, и который там встает в строй из других таких же контейнеров.

Только build не всегда делается за доли секунды
Там как бы есть кеширование. После того, как вы один раз собрали базовый образ, ваши __изменения__ в него, вызванные __вашим__ кодом, накатываются __буквально__ за доли секунды
И в итоге получается система, которой на host-машине нужен git, docker-composer и сам docker. И на которую лучше не дышать. Захотели вынести БД на отдельный сервер — что может быть проще, он же в контенере! Ой, а у нас теперь конфиги недоступны, потому что репозитория там нет.

Docker build не настолько страшный зверь, чтобы вытворять такие кульбиты в попытках его избежать
Контейнер с БД идёт без специфичных конфигов. Если мы захотим перенести контейнер на другой сервер, проблем не возникнет. Напомню, что в реальных условиях данные, содержащиеся в БД в git не коммитятся. К тому же, я бы не стал в репозиторий докера коммитить свои файлы. Всё должно прекрасно подниматься с нуля, а вот мешать репозиторий среды с репозиторием проекта — не хорошо. В нашем случае, проект поставляется со всеми конфигами и описанием среды. Докер автоматизирует сборку среды с нуля. Производить овероптимизэйшн не имеет смысла. К тому же, как видно из примера, два контейнера билдятся и ничто не мешает сделать им пулл. При этом, проект в репозиторий среды не попадёт. Что вы пытаетесь критиковать — я не понимаю. Разделение среды и проекта сделано вполне осознано. Вопрос сохранения билда не поднимался.
Насколько среда готова к деплою на хотя бы стейджинг с учетом разноса отдельных сервисов на разные хосты?

Разделение среды выполнения и проекта вполне нормально. Ненормальна привязка контейнеров среды исполнения к файлам и конкретным портам на хост-машине.
Мы недавно зарелизили один проект на Python 3.4 + Django. Это был наш первый эксперимент с Docker. Для разворачивания среды разработчика решили использовать vagrant — он умеет запускать образы Docker. И команда для «запуска всего» получилась короче:
vagrant up

При этом состав компонентов схож с вашим (у нас дополнительно поднимаются контейнеры с CRON, админкой и пр.).

Хотелось немного прокомментировать ваше решение использовать supervisor внутри контейнера. В вашей ситуации не вижу смысла использовать его для запуска manage.py runserver, который при создании контейнера можно запускать напрямую, например так:
docker run --name django_app --detach --publish 8005:8000 django_image bash -c "manage.py runserver"

Supervisor в вашем случае, насколько я понял, нужен только для управления логами. Мы оставили вопрос управления логами на потом (пока не ротируем), но вроде Docker имеет свою мощную систему управления логами, умеющую интегрироваться с несколькими популярными решениями. Например, при создании контейнера вышеописанным способом логи можно смотреть так:
docker logs -f django_app


Также спорным решением, на мой взгляд, является необходимость установки SSH внутри образа Docker. Pycharm вроде умеет конектиться к контейнерам Docker напрямую, а если нужно запустить консоль внутри работающего контейнера, то это можно сделать так:
docker exec --tty --interactive django_app /bin/bash

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

Хотелось бы послушать ваш рассказ про деплой на боевую инфраструктуру.
В приведённом примере pure docker не используется. Это порождает некоторые проблемы, но избавляет от других. К примеру, перелинковка контейнеров проходит проще. Спор о том что лучше: Vagrant или Docker, на мой взгляд, не имеет смысла. Vagrant, безусловно, позволяет работать с монолитной инфраструктурой. Только для этого запускается целая виртуальная машина. docker-machine делает то же самое, но здесь он не используется. Поэтому, PyCharm и не поддерживает прямого выхода на Docker контейнер. Сам плагин для докера сделан для Win и Mac, видимо, поэтому требует запуска docker-machine.

Деплоймент может происходить разными способами. Самое первое что приходит на ум: многие облачные серверы поддерживают .yml синтаксис для развёртывания docker. Хотя, docker-machine позволяет делать деплой одной-двумя командами с локального компа. А есть еще и настраиваемая CI среда с поддержкой Docker, которая называется CIrcleCI.
С supervisor согласен полностью. Разумно использовать его, к примеру, если нужно запустить celery или, хотя бы, связку web-серверов. В прошлый раз работал с celery, поэтому, supervisor вошёл в пример статьи. Если говорить о шаблоне Docker системы, то в нём проще оставить supervisor, чем убрать, а потом при необходимости поднимать заново. Хотя, это дело личное.
вроде Docker имеет свою мощную систему управления логами

Не нужно ее использовать. Она для дебага при разработке.
Вопрос пожалуй один — почему контейнеры описсаны в одном docker-compose файле? Почему бы каждый «контейнер» не описать отдельно? Я понимаю, что поднять все целиком очень просто, но все же.
Потому, что в docker-compose файлах описывается, как-раз, несколько контейнеров. Для описания отдельных контейнеров используются Dockerfile's. Несколько docker-compose файлов необходимо, скажем, для того, чтобы отдельно описать инфраструктуру dev и production. Предположим, что у нас используется amazon для баз данных, а web сервер стоит жёстко на хосте, а не внутри контейнера. Тогда у нас будет отдельный файл для такого боевого сервера (но только в том случае, если мы используем прод с совместимым yml синтаксисом файлов для деплоймента). Другой вариант: один из участников команды использует специфические инструменты. Скажем, инструменты статистики и/или дебага. Ему не нужно запускать сервер разработки — только снимать результаты выполнения. Тогда для него будет создан отдельный файл.

К тому же, если под каждый контейнер будет свой файл, его придётся запускать отдельно. Больше команд для запуска. А значит, в использовании compose нет смысла. С тем же успехом можно запускать обычную команду docker.
Сложность проекта я понимаю так: есть код(backend часть, без JS, без статики)и вот нам надо сделать так, чтобы он подружился с уже готовой инфраструктурой и притащил еще свои сервисы(DNS, nginx). На сервере уже есть контейнеры или набор контейнеров(кластер) или Рэбита, Постгриса(вот он как раз из тех сервисов, который должен быть для всех един(не важно в каком виде, кластер или нет)).

Где подобная сложность у вас? Насколько я понял, у вас все сводится к разделению окружения. Окей. Почему тогда не использрвать Вагратн, Отто?

К тому же, если под каждый контейнер будет свой файл, его придётся запускать отдельно. Больше команд для запуска. А значит, в использовании compose нет смысла. С тем же успехом можно запускать обычную команду docker.


Глупости говорите, товарищ. Про Фабрик слышали? А про баш-скрипты?

Вопрос пока один — зачем городить такие огороды? Может есть путь проще?
Вы хотите стартовать контейнеры bash скриптом или фабриком? Ну-ну.
Я думаю, что скорее, вы ленитесь читать. Docker — не вагрант. У него свои особенности. В частности, возможность обслуживать каждый контейнер отдельно. Хорошо это или плохо — предмет холивара. Тот же вагрант может использоваться для запуска полного образа или docker контейнеров. Всё зависит от необходимости. Если вам нравится вагрант, то зачем писать здесь или пытаться сделать вагрант из докера? Docker-compose тоже отдельный инструмент, который для того и создан, чтобы разворачивать среду из одного файла, который описывает все контейнеры. Нет, конечно, можно на каждый контейнер сделать свой yml файл, написать bash скрипт, чтобы запустить всё это дело вместе и насмешить других разработчиков. Особенно, тех, которые потом будут ваш проект обслуживать. Я думаю, что они поступят проще: соберут всё в один yml файл и воспользуются docker-compose для работы. Либо, сделают отдельные Dockerfile's и обернут в вагрант для запуска. Вариантов много, на самом деле. Мне больше нравится вариант с compose. Нахожу yml файл более простым для переноса и более информативным. Фабрик и bash скрипты удобно использовать внутри контейнера, а не снаружи. Для запуска Docker контейнеров и так достаточно инструментов.
Внутри контейнера? Realy? А знаете ли вы, что если у вас код на серверной машине, и там лежит fab.py вы можете удаленно налить весь свой проект внутрь докера? Фантастика? Или вы по ssh заходите и делаете deploy?

Простите, но я вас не понимаю. Наверное, мне стоит употреблять те же вещества, что и вы употребляли перед тем, как приняли такое очень странное решение. Все что вы описали в своих проблемах: разделение версий, разграниченный доступ, бла-бла-бла путь в Вагрант. Если у вас это конечно сервер — окей докер. В таком случае — вы очень странно, а почти что никак не можете внятно объяснить где у вас сложный проект? Почему выбрана система хранить все в одном файле? Что будет если c контейнерам если надо «перезагрузить» контейнеры? Что произойдет с вашей БД, которая во-время перезагрузки будет недоступна?
Видите как много бывает вопросов, если это реально сложный проект, а не состоящий из двух контейнеров, именно это я и ожидал тут увидеть, а не конфиг их двух контейнеров.
Я не понимаю, зачем fabric нужен на этапе dev. И, тем более, не понимаю как вы хотите оправдать фабриком написание по одному yml файлу на каждый контейнер. Велосипеды какие-то изобретаете. Про вагрант я уже говорил: здесь рассматривается применение докера. Вопрос «почему не вагрант» бессмысленный. Здесь просто рассматривается docker + docker-compose. Если вам интересно применение вагранта, не занимайтесь ерундой и напишите об этом свою статью. Может, хоть из минусов вылезете.
С моей БД во время перезагрузки не произойдёт ничего страшного. Во-первых, статья не рассматривает production, где подразумевается использовать Database as Service. Во-вторых, yml файл compose прекрасно стартует контейнеры, в той очерёдности, которая предписана links. Суть ваших претензий вообще не очень понятна. Docker-compose прекрасно автоматизирует запуск N контейнеров вместе без плясок на локальном компе с баш скриптами и fab-файлом. Разумеется, для деплоймента можно использовать fab и предложенная архитектура прекрасно справится с этим. Вопрос в другом: где вы в данной статье видели попытку задеплоить проект? Здесь речь шла о том, как паковать продукт вместе с окружением. Минимум места на диске, минимум ресурсов, минимум времени на развёртывание с нуля. Пока я вижу только одну претензию. Вы так не делаете, поэтому считаете архитектуру слабой. Вопрос о разделении контейнеров по разным yml файлам вообще бессмысленный. Вопрос с fabric ещё неплохой. Можно задуматься о том, чтобы все команды compose обернуть в него. Только тогда на второй план уйдёт забота о правильном запуске контейнеров. Docker-compose и так не обладает полными возможностями Pure Docker commands, ограничивая процесс только жизненно необходимыми командами. Если это упросить ещё и до трёх fab команд, получится какой-то перегруз системы ненужным попечением о ней. Хотя, после выбора решения для CI, можно будет написать скрипт деплоймента под fab.
Товарищ, вы можете ответить на мои вопросы выше, или так и будите ходить вокруг да около?
Легенда ваша разъезжается.

Необходимо полностью эмулировать пространство Production, а ещё лучше — поставлять код участникам процесса разработки вместе со средой.


А потом у вас:
Во-первых, статья не рассматривает production, где подразумевается использовать Database as Service


Так полностью или частично?

С моей БД во время перезагрузки не произойдёт ничего страшного.


Вы в этом уверены? Логи смотрели?

Вопрос в другом: где вы в данной статье видели попытку задеплоить проект?


Ваше же?

Необходимо автоматизировать развёртывание проекта, ....
Что вас смущает в эмуляции Production? Эмулируется среда, а не инструмент CI. Давайте ещё тесты тестами покроем и дебаг отдебажим, чтобы вы были счастливы.

Да и автоматизация, если вы внимательно почитаете, относилась к развёртыванию на машине разработчика.
Потому что тут смешались в кучу кони люди

— Есть контейнеры — см. Dockerfile
— Есть система управления контейенрами (ну чтоб не bash-скриптами все запускать, а по-модному — напрмиер, docker-composer).

По идее, они служат для разных целей, а то, что тут наверчено — просто пример плохой архитектуры и ничего более.
Запустил почти похожую схему, с той лишь разницей, что докер крутится не локально, а на удаленной машине.
При попытке запустить Python console получаю такое:

ssh://root@172.16.12.6:2222/usr/local/bin/python /root/.pycharm_helpers/pydev/pydevconsole.py 0 0
PyDev console: using IPython 4.1.2
Couldn't connect to console process.
Process finished with exit code -1

Не сталкивались с похожей проблемой ?
Начинали с этого примера: docker-compose для Django + Nginx + Postgre + Radis. Что интересно, после переходя на compose, стало проще детектировать проблемы межкомпонентного взаимодействия.

После вызова docker-compose up сразу видны все логи в одном месте (а значит и все существующие проблемы)
Я уже перешёл на вариант с vagrant + ansible. Для меня docker-compose, прежде-всего, был решением с удобным декларативным синтаксисом (в отличии от Dockerfile API). Ansible оказался более мощным решением, которое закрыло множество других фронтов. Например, позволило работать с сервером, на котором не производилась дополнительная подготовка среды (достаточно иметь ssh доступ и стандартную версию ОС).
ansible использовать для подготовки сервера (читай — установки докера), а docker-compose — для запуска контейнера, нет?
Эм… Т.е. предлагаешь написать yml файл ansible, который поставит docker, чтобы выполнить yml файл docker-compose'ра?
Ага. Грубо говоря, чем-то подобным прямо сейчас занимаюсь.
У меня нет таких кейсов. Я использую вагрант. Скрипты провижена и деплоймента выходят почти идентичными. Разница только в том, что на локалке я вручную управляю GIT, и не ставлю пулл в скрипты. А так, в докере смысла особо нет. Вагрант мне раньше не нравился по причине запуска полной версии виртуалки, необходимости писать ugly bash provision scripts, постоянного выполнения этого провижена на каждом reload. Ансибл, в принципе, две проблемы решил. В итоге, имеем с одной стороны недостаток в виде тяжеловесной виртуалки, а с другой — кучу недостатков докера. От невнятного синтаксиса конфигурации, до необходимости заводить контейнеры на проде. Особенно раздражают проблемы установки докера у участников процесса. К тому же, докер жёстко привязывает сценарий деплоймента к своему синтаксису (почему и надо на сервак ставить докер, чтобы избежать лишней работы), а ансибл, в принципе, лишь создаёт абстракцию над системным shell и может быть легко заменён bash скриптами при необходимости.
На продакшене вагрант?

А какие проблемы с установкой?

Докер не привязывает сценарии деплоя к своему синтаксису, докер — сервис, предоставляющий API, для которого есть клиенты такие как сам docker, docker-compose, модули docker того же ansible.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории