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

Полная автоматизация среды разработки с помощью docker-compose

Время на прочтение7 мин
Количество просмотров26K
Всего голосов 29: ↑27 и ↓2+25
Комментарии38

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

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


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

Посоветуйте пожалуйста.
Я делаю сайты на nginx+php7-fpm, mariadb, sphinx. Мне docker как-то может помочь?
Как перенести список пакетов с VPS на Debian на другой такой же сервер. Ну чтобы на другом сервере поставились такие же пакеты с такой же конфигурацией, такой софт есть?
Докер для этого идеален, сделали образ и потом с него запускаете контейнер на любом сервере, где установлен докер.

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

Ну так я и есть админ, причём я «ленивый» админ, поэтому уже больше двух лет использую докер где только можно. Вот небольшой список, что у нас крутится в контейнерах:
bind
icinga2
icinga2 docker monitoring — я тут недавно писал про это статью
git
horde
keybox
mariadb
forum
backup(nodebackup) — это для бэкапа контейнеров.
postgrel
proxy
vpn

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

Для локальной разработки точно поможет, не надо будет ничего, даже пхп, устанавливать локально (кроме самого докера), любые целевые версии можно использовать одновременно дл янескольких проектов без шаманста, конфиги править без sudo и прочие плюшки.


Если на продакшене докер запускать не хочется или не можется, то крайне желательно иметь скрипты разворачивания продакшена с нуля. Это могут быть кофиги утилит систем типа ansible или puppet, а могут быть простые bash-скрипты (как у нас). Главное, держать их в синхронизации с файлами докера.

Мы похоже делаем.
У нас есть гит репозиторий, где находятся все конфигурации для контейнеров. Для каждого контейнера своя папка, в ней лежат два файла — docker-compose.yml и env. Во втором (env) написано на каком сервере должен разворачиватся контейнер. Когда делается комит, то git-runner раскладывает папки по серверам.
Также в этом репозитории лежит Vagrantfile с которого можно запустить виртуальную машину и уже в ней что-то потестировать.

А в первом что? Как контейнеры друг с другом связываете?

В смысле что? Там конфигурация контейнера/ов. Они (папки) больше логически поделены, чем на контейнеры.
К примеру docker-compose.yml для redmine.
redmine:
  image: redmine:3.2
  hostname: redmine.example.local
  links:
    - mysql:mysql
  ports:
    - "192.168.40.203:3000:3000" # http
#    - "192.168.33.10:3000:3000" # vagrant-http
  volumes:
    - /etc/localtime:/etc/localtime:ro
    - /etc/timezone:/etc/timezone:ro
    - /a/data/redmine.intern/redmine:/usr/src/redmine/files
    - ./config/configuration.yml:/usr/src/redmine/config/configuration.yml
  restart: unless-stopped
  labels:
    nextfullbackup: "1M"
    noffullbackup: "2"
    backup: "/a/data/redmine.intern"
    strategy: "off"

mysql:
  image: mysql:5.7
  ports:
    - "192.168.40.203:3306:3306" # mysql-database
#    - "192.168.33.10:3306:3306" # vagrant-mysql-database
  volumes:
    - /etc/localtime:/etc/localtime:ro
    - /etc/timezone:/etc/timezone:ro
    - /a/data/redmine.intern/db:/var/lib/mysql
  environment:
    - MYSQL_ROOT_PASSWORD=PASS
    - MYSQL_DATABASE=redmine
  command: mysqld --lower_case_table_names="1"
  restart: unless-stopped

«Labels» нужны для бэкапа, через них моя программа находит, какие контейнеры надо сохранять.
Они (папки) больше логически поделены, чем на контейнеры.

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

Можно ещё сделать сеть и к этой сети подключить два контейнера из разных docker-compose файлов.
Это будет в первом:
    networks:
      - dbnet
    external_links:
      - mariadb


А это во втором:
    networks:
      default:
        aliases:
          - mariadb

Для этого нужна вторая версия docker-compose файла
version: "2"

Хорошо быть админом :(

Можно сделать сеть, как указал выше de1m, можно назначать Докер-имена любым IP или домейнам (допустим, если ваше приложение должно обращаться к каким-то внешним API).
Есть смысл еще использовать параметр -d, для запуска в background-режиме, bash-сессия может прерваться, а с ней и запущенный docker-compose
Docker в продакшене с проброской портов «27100:27017»? Попробуйте фаерволом закрыть все порты, кроме нужных, и подключиться извне к порту 27100. Будете удивлены. Чтобы закрыть порт от посторонних глаз, я делал проброску портов так: «172.17.0.1:27017:27017», где 172.17.0.1 — интерфейс docker0.

Название поста: "Полная автоматизация среды разработки с помощью docker-compose". Ни слова о продакшене, чисто для локального запуска всё.

Вот небольшой список, что у нас крутится в контейнерах:
bind
git

а какой глубокий смысл запускать git/bind в докере? Вы их часто обновляете или вам часто приходится разворачивать соотв окружения на других серверах? Можно use-case так сказать, преимуществ использования докер конкретно в этих случаях?

Вообще заметил в последняя время плохую тенденцию — запускаем все в докере ибо это стильно/модно/молодежно. Как в свое время была тенденция — переписываем все gnu утилиты на go.
Докер — это не только способ доставки приложений до железа, но и способ документирования где и что подкручено (есть, конечно, исключения, когда это непрозрачно, например, образ выкатывается из tar-архива).

Это не отменяет того факта, что прежде чем что-то (хоть докер, хоть не докер) использовать нужно оценивать потенциальную выгоду и затраты.
Докер — это не только способ доставки приложений до железа, но и способ документирования где и что подкручено (есть, конечно, исключения, когда это непрозрачно, например, образ выкатывается из tar-архива).
для этого вроде как есть системы управления конфигурациями — chef, puppet, ansible,…

Просто стало интересно, зачем запускать тот же bind и уж тем более git в докере, какие преимущества мы получаем?
Я напишу только три плюса, но наверное их больше(это всё со стороны администратора).
1. В обоих случаях у меня получается чёткое разделение на систему и данные, то есть, когда я делаю бэкапы, то я знаю, что мне нужна только одна, ну или несколько определённых папок и всё.
Когда у меня к примеру сгорит сервер, то я просто беру новый ставлю на него линукс и докер, заливаю бэкап (один только) и всё, у меня снова всё работает, вообще всё работает что было.
2. Здесь только про гит — это обновления. Когда выходит новая версия, я просто скачиваю новый образ, запускаю с него контейнер и у меня уже актуальная версия.
3. Касается всех — это мониторинг. То есть у меня сделано так, что я вижу статус каждого контейнера, а так как каждый контейнер это один процес. То я соответственно вижу, если не работает контейнер, то это значит, что не работает какой-то сервис.
Причём каждый контейнер автоматически регестрируется в мониторинге и мне ничего не надо делать. Раньше без докера было по другому и было сложнее, в винде всё ещё приходится по старинке делать.

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

Я себе очень мало случаев могу представить, где докер что-то сделает хуже.
Мы на фирме у нас стараемся по возможности всё на докер и линукс перевести, но из-за виндовсы не очень получается, хотя его у нас мало.
Я себе очень мало случаев могу представить, где докер что-то сделает хуже.

В последнее время реже, но раньше, год-полтора назад, очень часто попадалась на глаза рекомендация не использовать докер для важных стейтфулл сервисов, в частности для операционных СУБД, особенно кластеризованных, пускай и мастер-слэйв режимах. В дев- и тест-средах поднималась в контейнере, а для прода использовался обычный инстанс. Просто болезни молодости были или всё же шансы, что что-то пойдёт не так и данные пострадают выше?

Может, потому что хардкор-СУБД стремятся сами управлять памятью, процессорами и дисковым пространством? В этом случае, в «боевом режиме» прослойка Докера будет несколько снижать производительность. Ну и, разумеется, все рабочие файлы надо размещать на томах (volumes) а не в ФС Докера.

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

1. Опять таки — для этого есть SCM. Ведь все равно вам где то надо хранить персистентные данные при использовании докера.
2. А в случае не Docker вам достаточно yum update/apt-get update или что вы там используете. Единственный плюс который я вижу — ваш дистрибутив не поддерживает нужной вам версии ПО, а собирать свой rpm/deb накладно и/или невозможно. Но это довольно таки редкий случай.
3. Что касается регистрации возможно, но в том же Zabbix отлично работает auto discovery и без всяких докеров

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

я тоже самое вижу и без докера. Если я мониторю smtp, pop3, imap4, mysql на одном сервере, то когда перестает работать определенный сервис я это вижу. Или я не понял, что вы хотели сказать.
мне не охота спорить, поэтому вы правы, а я, соответственно, нет.
Поэтому я пойду посыплю голову пеплом и верну все мои серверы на четыре года назад.
да никто не спорит, просто хотел понять в чем профит, мб я что то упускаю или чего то не знаю о докере ;)

Докер из коробки показывает состояние запущенных процессов. Если какой-то процесс даже сегфолтится, то он не пропадает из списка, а переходит в состояние exited (по памяти). То есть грубый мониторинг можно сделать по простой формуле "все процессы должны быть в состоянии running" ничего не зная о том, что это за процессы.

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

У нас мониторинг для дев-сервера на баше с грепом написан и крону запускается, тупо если больше минуты один и тот же контейнер не Up… то письмо шлется. Даже нет списка мониторинга

Позвольте вопрос. Какие данные и как вы бэкапите? Ведь простое копирование файлов в сторону, как правило, плохая идея из-за различных кешей-буферов и прочего.
Я использую для этого nodebackup, специально писал для удобного сохранения данных из контейнеров, а также нормальных серверов. Есть также готовый докер образ, которому надо только подсунуть конфигурацию, crontab файл и ssh key. Там под капотом используется duplicity.

Пример (посмотрите выше, там где пример для redmine):
У меня для redmine есть один docker-compose.yml файл в нем описаны два контейнера, причём один из них это СУБД, то есть когда это всё работает, сохранять не желательно. Надо выключить контейнер, также контейнеры связаны между собой.
Вот эта часть в docker-compose.yaml говорит, что нужет бэкап
  labels:
    nextfullbackup: "1M"
    noffullbackup: "2"
    backup: "/a/data/redmine.intern"
    strategy: "off"

Nodebackup может через docker.sock посмотреть какой контейнер надо сохранять. Если в «strategy:off», то это означает, что перед тем, как начать делать бэкап, то нужно выключить контейнеры, также тот, который слинкован. После этого он смотрет на путь в «backup» и тут уже включается duplicity. После этого контейнер снова стартует.
Если посмотрите выше, то видно, что эта папка примонтирована в оба контейнера.

Есть варианты, где контейнер не надо выключать, к примеру bind. Тогда соответственно «strategy: on». Там на самом деле ещё много можно опций писать.

Есть ещё один вариант, когда к примеру большая СУБД, но на долго контейнер нельзя выключать. Тогда используются возможности файловой системы (btrfs или сephfs) и делается снапшот.
То есть nodebackup выключает контейнер, потом снапшот, потом контейнер снова включается, а дальше nodebackup спокойно делает бекап со снапшота, после чего его стирает.

PS Извеняюсь, что так растёкся мыслью, просто я вроде как написал хорошую програму для докер контейнеров, а никто не знает. ))
Спасибо за развернутый ответ. Я интересовался, потому что сам не смог найти ответ на достаточно простой вопрос: как сложить данные в архив, чтоб при этом целостность данных не была нарушена. В итоге, для файлов, написал свой велосипед, который делает снапшот и запаковывает данные в tar-архив. Плюсом к этому logrotate, который занимается ротацией архивов.

duplocity — вещь хорошая, но сама делать снапшоты не умеет.

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

Например за условный bind отвечает одна команда.
За железо — другая.
За сбор логов — третья.
У каждой свои инструменты — docker, chef, etc. У каждой — свои репозитарии (vcs). Взаимодействие осуществляется по декларативно прописанным интерфейсам: файлы, порты, и т.д.
Докер позволяет ставить любые версии софта, не ломая голову над управлением общими зависимостями.
Можно одной-двумя командами перейти на другую версию/конфигурацию — а потом вернуться, что-то пойдет не так. При этом ничто другое в системе не поломается.

Предположим есть builder контейнер, который строится и потом запускается через run, а результат его работы надо положить в другой pro контейнер. Ведь не будешь же класть весь NodeJS со всеми модулями из билдера в продакшен образ, где только Nginx нужен. Что то типа этого тикета и схожий кейс там же.


Может ли compose помочь с этим как-то?

Да, выходит, что так.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий