Pull to refresh

Comments 53

Спасибо за перевод.
Действительно docker-compose незаменимый инструмент, который очень естественно вписывается в концепции докер и упрощает жизнь.
Если начинаешь докеризировать приложение, то логично разнести сервисы по отдельным образам / контейнерам. И вот тут композ очень просто решает большинство задач по запуску / конфигурации всего зоопарка.
У меня от докера такие странные ощущения. С одной стороны, это инструмент, который призван упростить развертывание приложения, но по факту все оказывается совершенно не так, как пишут в статьях. Проблемы начинаются с разницы окружений(а ведь мы с Вами помним, что докер изначально вроде бы должен был ее нивелировать) windows, mac, linux запускают докер по-разному. Кому-то нужно запускать контейнеры внутри виртуальной машины, кому-то она не нужна. Потом ты сталкиваешься с несовмесимыми с прошлой версией изменениями в самом docker, либо в доп. инструментах вроде docker-compose и вынужден обновлять конфиги, снова пересобирать и тестировать свои контейнеры. Тот же самый docker-compose.yml можно описать используя разные версии синтаксиса этого файла.
И вот, собрал ты такой счастливый проект, состоящий, скажем, из 10 сервисов. И думаешь: «О! Как хорошо, что я использовал докер, ведь теперь для запуска проекта мне нужно только выполнить `docker-compose up`» Но не тут то было, я бы даже сказал ДАЛЕКО не тут! Чтобы понимать, о чем я говорю — просто пойдите и попробуйте задеплоить любой Hello, World на тот же Amazon ECS.
windows, mac, linux запускают докер по-разному. Кому-то нужно запускать контейнеры внутри виртуальной машины, кому-то она не нужна.

Работаю с docker на 3 системах сразу же, дома на маке, на работе windows и linux, и не видел проблем с запуском. Одно из условий запуска docker — это наличие linux ядра. Соответственно на не linux системах, ему требуется виртуальная машина. Однако docker-toolbox настраивает за вас все это и вы не задумываетесь о настройке.

Потом ты сталкиваешься с несовмесимыми с прошлой версией изменениями в самом docker, либо в доп. инструментах вроде docker-compose и вынужден обновлять конфиги, снова пересобирать и тестировать свои контейнеры.

Какие изменение были сделаны, которые стали несовместимы с прошлой версией? Я просто не припомню кардинальные отличия, которые требовали изменения файлов. То что продукт развивается и изменяется — это нормально. Не забывайте, он появился в 2013 году и ему «всего лишь» 4 года.

Чтобы понимать, о чем я говорю — просто пойдите и попробуйте задеплоить любой Hello, World на тот же Amazon ECS.

Не скажу за Amazon, но скажу за Azure. Вы можете взять за основу официальный скрипт установки от Docker и установить его. А потом docker run -rm helloworld.
Расскажите подробнее в чем были сложности :)
есть отличие между Amazon EC2 и Amazon ECS. По простому: Amazon EC2 ака твой VPS, ака ваш пример с Azure, где тебе надо будет ставить докер и тд для его запуска. Для Amazon ECS же достаточно указать (в теории) просто откуда взять твой Docker образ и указать условия запуска. Ето 2 разных сервиса.

hlogeon прав:
просто пойдите и попробуйте задеплоить любой Hello, World на тот же Amazon ECS

не так просто как взять установить самому докер на vps и прогнать
Ну вообще какой-то странный аргумент, в целом. Попробуйте запустить докер-контейнеры в кубернетес на GCE, можно будет тогда целые статьи писать о проблемах и нуждах, но к докеру это каким образом относится?

На обычный линукс хост деплоится за 3 команды.


docker-machine create --driver generic --generic-ip-address={ip} --generic-ssh-key ~/.ssh/id_rsa test
eval $(docker-machine env test)
docker-compose up -d

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

Я тоже не верю в silver bullet, но, увы, выбирать приходится. У меня станные ощущения вызывает любой новый инструмент. Так и не разобрался хорошо это или плохо :) Пару лет иcпользую экслюзивно докер для развертывания приложений, в которых учавствовал. Попробую поделиться своими мыслями, но перед этим спешу поделиться несколькими фактами и наблюдениями:


  1. Первое приложение в докере задеплоил в начале 2015 (версия докера 1.5, потом обновили до 1.6). Никаких проблем по вине докера не возникало. Недавно обновили проект до последней версии — по прежнему все отлично. Сильных изменений изменений с точки зрения приложения не было.
  2. В средине 2015 довелось работать над приложением побольше. Разворачивали Mesos, Marathon, все таски в докерах. 20+ различных сервисов, 60+ контэйнеров в кластере. 1.5 года — не одной проблемы с докером, больше с мезосом возились, но это отдельная история.
  3. В команде ребята работают OSX, Ubuntu & Arch Linux — тут никаких проблем не возникало.
  4. Участвовал в гибридных проектах, где часть приложения написанна на .Net, а вторая на Node.js/Java. Для таких проектов docker-compose был просто спасением. Не было нужды писать гайды. Просто docker-compose up и спокойно продолжаем писать на любимом .NET.
  5. До появления докера, активно использовал Vagrant для тех же целей — было не так весело.

Теперь мысли:


  1. Разница окружений (window, linux, osx). Докер ипользует внутренние фишки ядра линукса (cgroups, cnames) — отсюда и нужна запускать виртуальную машинну в бэкраунде. Не так уж и страшно.
  2. Microsoft поверил в докер и два года работала с командой Docker, чтобы сделать нативную поддержку на Windows Server 2016. Они верят, должны ли мы? :)
  3. Docker-compose действительно менял свой синтаксис — ничего от вас не утаить :). Но это все во благо прогресса. Главное, что это изменение прошло фактически безболезненно. Один раз обновил — и забыл. Радикальных изменений, как, например, в Angular.JS не было :)
  4. Не имею опыта использования docker-compose для развертывания и не вижу в этом большого смысла, так как на серверах все же вещи обстоят несколько иначе. Для этого уже есть целый зоопарк хороших инструментов: Mesos, Kubernetes, Swarm, Amazon ECS. Конечно, хотелось бы "Вжух, вжух и в продакшен", но так точно не получится.
  5. Amazon, Azure, Google Cloud — все предлагают свои "container service". Docker уже стал дефакто стандартом.

Несомненно, перед выбором любого инструмента, нужно оценивать его сильные и слабые стороны и решать для себя использовать или нет. На сегодняшний день, для простого запуска сложных проектов в рамках большой, распределенной команды — docker-compose мне кажется лучшим вариантом. Но это, всего лишь мое мнение :)

Не имею опыта использования docker-compose для развертывания и не вижу в этом большого смысла, так как на серверах все же вещи обстоят несколько иначе. Для этого уже есть целый зоопарк хороших инструментов: Mesos, Kubernetes, Swarm, Amazon ECS. Конечно, хотелось бы «Вжух, вжух и в продакшен», но так точно не получится.


Да, вы правы, конечно, но что меня удивило, никто из этих провайдеров не представляет действительно легкого и интуитивного способа это сделать. Заходишь в ECS, там тебя нагружают лапшой из EC2, ECR, Clusters, EC2 instances, Services, task definitions и еще просто тонной информации, которую предстоит переварить даже для минимальной конфигурации. Я находил решение в виде CodeShip, они помогают автоматизировать все эти трудности и сделали прекрасную консольную утилиту jet. Потом написал свои скрипты, которые делают почти тоже самое, потратил целую неделю, развернул, а потом подумал: «Да ну его нах», купил простой instance на linode и там в пару команд все завелось. Но осадочек всё-таки остался. В общем, я считаю, что пока что очень нехватает бесплатных и интуитивнопонятных интсрументов для управления более сложными системами. За рекомендации буду очень признателен)
Тут налетело много «защитников» докера, судя по комментариям которых, я немного сомневаюсь, что им нужен докер. Лично для меня главным его преимуществом, из-за которого я его выбрал была именно возможность создавать микросервисы и поставлять их не только как самодостаточные независимые решения, но и целыми «кластерами», инкапсулирующими решение каких-то конкретных бизнес-задач. И если с первым пунктом практически никаких проблем не возникает, то со вторым они начинаются. И это можно заметить даже по комментам. Кто-то предложил swarm-mode, кто-то тулзы наподобие code ship, я имел дело с docker-compose и Amazon task-definitions и они показали мне себя ой как недружелюбно. Входе попытки задеплоить я постоянно узнавал, что например «Фича Х из docker-compose v2 не поддерживается Amazon». Или что ты не можешь нормально использовать volume-контейнеры. Реально проблем было столько, что приложение, которое я с другим разработчиком нормально разворачивали локально на множестве различных машин(windows, mac, linux) мы деплоили целую неделю. И в итоге так и не удовлетворившись результатом и числом действий, которые необходимо проделать, что бы это задеплоить в том виде, в котором мы этого хотели просто подняли обычную linux-машину на которой выполнили docker-compose up и отложили нормальный деплой до времени появления dev.ops.
Я очень люблю докер, но хочу предостеречь новичков, что все не так просто и радужно, каким это может казаться в начале. В общем, не серебряная пуля.

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


  • передача ключей и прочих секретов в процесс сборки контейнеров (текущее решение — base64 кодирование содержимого файлов типа .ssh/id_rsa в одну строку .env, ARG в докерфайле, декодирование в RUN типа
    ARG ID_RSA
    RUN mkdir ~/.ssh \
    && ssh-keyscan -H -t rsa github.com >> ~/.ssh/known_hosts \
    && echo "$ID_RSA" | base64 --decode > ~/.ssh/id_rsa \
    && unset ID_RSA \
    && chmod 600 ~/.ssh/id_rsa \
    && git clone git://someuser.github.com/simerepo.git \
    && rm -r ~/.ssh
    ``` - довольно большая обвязка для одной целевой строчки, а вопросы по секурности остаются
  • то же с собственно выполняющимися контейнерами, но там немного полегче, можно шаринг файлов с хостом volume использовать
  • при шаринге активно изменяющихся файлов с хостом куча проблем с правами, никогда не угадаешь от какого пользователя коллега будет разворачивать систему, и если читать файлы из контейнера обычно проблем не составляет, то вот записанные в нём переписать или удалить на хосте обычно требует sudo
  • попытки следовать лучшим практикам типа запуска программ в контейнере не от рута ещё больше проблем доставляют
  • связывание с внешними системами (как и относительно внешними типа баз данных, так и и полностью типа платежных систем) по DNS-именам

Это только навскидку о самом наболевшем. Как решаете эти проблемы?


И в чём плюсы монолитного репозитория? Что делаете если один сервис нужен в нескольких проектах?


Кстати, использование разных конфигов очень удобно делать с каскадированием, один общий docker-compose.yml и "диффы" с ним для разных окружений, для разработки стандартный docker-compose.override.yml чтобы вообще без файлов запускать, а для тестов, например docker-compose --file docker.compose.yml --file docker-compose.test.yml


В общем соглашусь с hlogeon — странные ощущения

передача ключей и прочих секретов в процесс сборки контейнеров (текущее решение — base64 кодирование содержимого файлов типа .ssh/id_rsa в одну строку .env, ARG в докерфайле, декодирование в RUN типа


Обычно dockerfile находится в том репозиторий, с которым вы работаете и собираете, поэтому зачастую проблема по передаче ключей для git clone решается не на уровне контейнера, и она не возникает на процессе сборки. Однако проблема с передачей всяких секретов также решается на уровне docker-entrypoint.sh, в котором уже задаются все специфичные настройки.

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


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

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


Можно по подробнее в чем была проблема?

связывание с внешними системами (как и относительно внешними типа баз данных, так и и полностью типа платежных систем) по DNS-именам


А здесь в чем проблема? По умолчанию в контейнер пробрасывается адрес DNS сервера хост системы. Можно самому задать DNS сервер.

Обычно dockerfile находится в том репозиторий, с которым вы работаете и собираете, поэтому зачастую проблема по передаче ключей для git clone решается не на уровне контейнера, и она не возникает на процессе сборки. Однако проблема с передачей всяких секретов также решается на уровне docker-entrypoint.sh, в котором уже задаются все специфичные настройки.

Речь именно о фазе сборке, о внешних приватных зависимостях. git clone как самый простой пример, обычно это npm/yarn/composer или иной пакетный менеджер.


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

Проблема в том, что на фазе билда (читай на фазе разработки Dockerfile) я не знаю под каким uid будет выполняться docker run, более того я не знаю под каким uid работают докер-демоны.


Можно по подробнее в чем была проблема?

С правами вестимо. Когда entrypoint требует root прав для подготовки данных для "демона", а потом должна запустить демон с правами обычного юзера. ну и плюс сама entrypoint висит с pid 1


А здесь в чем проблема? По умолчанию в контейнер пробрасывается адрес DNS сервера хост системы. Можно самому задать DNS сервер.

Не всё так просто. Во-первых, очень легко может установиться 8.8.8.8, если хост с NetworkManager с DNS 127.0.0.1. Во-вторых, я немного не о том, а о links — можно задать, например, что имя some-link соотвествует в контейнере 10.0.12.45, но нельзя что test-db.local

Речь именно о фазе сборке, о внешних приватных зависимостях. git clone как самый простой пример, обычно это npm/yarn/composer или иной пакетный менеджер.

А с пакетными менеджерами вам не хватает функционала ARG?

Проблема в том, что на фазе билда (читай на фазе разработки Dockerfile) я не знаю под каким uid будет выполняться docker run, более того я не знаю под каким uid работают докер-демоны.

Если вам важно какой uid используется в контейнере при сборке и при запуске после сборки используйте команду USER.
Под каким uid работают docker daemon на хост системе? А зачем вам это знать при работе с файлами?

С правами вестимо. Когда entrypoint требует root прав для подготовки данных для «демона», а потом должна запустить демон с правами обычного юзера. ну и плюс сама entrypoint висит с pid 1

Вы можете разбить на 2 файла entrypoint, в первом вы выполните работу которая требует root, потом смену uid с помощью USER, а потом запуск entrypoint. А зачем вам требуется pid?

Не всё так просто. Во-первых, очень легко может установиться 8.8.8.8, если хост с NetworkManager с DNS 127.0.0.1. Во-вторых, я немного не о том, а о links — можно задать, например, что имя some-link соотвествует в контейнере 10.0.12.45, но нельзя что test-db.local

Или я не понял ваш кейс или я не понимаю зачем смешивать эти разные вещи. links — это же связка конкретного контейнера с другим конкретным контейнером, зачем вам задавать url данного контейнера, если вы и так знаете его прямой IP адрес?
А с пакетными менеджерами вам не хватает функционала ARG?

Одна команда выливается в почти десяток строчек в докерфайле, плюс требует ручного заполнения .env файла.


Если вам важно какой uid используется в контейнере при сборке и при запуске после сборки используйте команду USER.
Под каким uid работают docker daemon на хост системе? А зачем вам это знать при работе с файлами?

Мне не важен uid, мне важно:


  • минимум действий от рута в контейнере при запуске
  • отсутствие конфликта прав при монтировании каталога с исходниками приложения на контейнер в процессе разработки.

И в общем случае я не знаю под каким uid на хост-системе работает и демон докера, и пользователь отдающий команду на запуск контейнера. На своей локальной знаю — 0 и 1000, но это мало помогает, если контейнер работает от 0 или не 1000


Вы можете разбить на 2 файла entrypoint, в первом вы выполните работу которая требует root, потом смену uid с помощью USER, а потом запуск entrypoint. А зачем вам требуется pid?

Это как? entrypoint выполняется уже в контейнере, там нет команд типа USER, максимум sudo/su


Или я не понял ваш кейс или я не понимаю зачем смешивать эти разные вещи. links — это же связка конкретного контейнера с другим конкретным контейнером, зачем вам задавать url данного контейнера, если вы и так знаете его прямой IP адрес?

Есть в docker-compose секция тип external для link, для ссылки из контейнеров на внешние по отношению к этой системе контейнерам или физхосты. Но только по IP. Полезно, например, для подключения кучи стэков к одной базе или для мокания совсем внешних сервисов.

UFO just landed and posted this here

Вот эту опцию имел в виду: https://docs.docker.com/compose/compose-file/#/extrahosts


Есть еще вариант шаринга томов между контейнерами, типа volumes_from когда надо дать одному контейнеру права на чтения тома, в который пишет другой.


Концепция мне тоже нравится, но на практике для php/node приложений реализовать её не смог за разумное время, не теряя прелестей docker-compose по сборке. Как-то не нашел нормального способа билдить и запускать всю систему с билд-контейнерами без многочисленных баш-скриптов на хосте для подготовки образов на хосте, чтобы при запуске докер-композ он брал готовые, а не пытался билдить.


С секретами начали что-то делать, но только в swarm-mode и только в рантайме, вряд ли будут на обычный демон в билд-тайм переносить. Да, отдельный билд-контейнер решит проблему билд-секретов в сварм-моде.


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

UFO just landed and posted this here

Установка зависимостей типа npm_modules, vendor и т. п. из приватных репозиториев.


Проблема в том, что нельзя контейнеру задать link с cсылкой на внешнее DNS-имя, только на IP-адрес.

UFO just landed and posted this here
И в чём плюсы монолитного репозитория? Что делаете если один сервис нужен в нескольких проектах?

Это решается через реестр образов.

Раз мы заговорили о «девелопмент» среде на основе докера. Как решить вопрос запуска разных приложений хотя бы на разных IP минимальными телодвижениями для программиста и автоматически прописывать DNS запись на новый IP?

Очень просто ports: ip:80:80. Но я сейчас использую nginx-proxy как описано здесь, только на Win пришлось поставить локально nginx, для проксирования на Docker Api. На linux машине прописал в DNS домен, для локальной разработки

Если вы говорите о локальной среде, мне не совсем понятно, зачем запускать сервисы на разных ip. При развертывании проблемы DNS (service discovery) уже решены за счет других сторонних инструментов: Mesos/Marathon, Kubernetes, Consul, Swarm. Осталось выбрать :)

UFO just landed and posted this here
Я на совоей Ubuntu использую tonistiigi/dnsdock.

Настраивается в два шага:
  1. прописываю в resolv.conf строку nameserver 172.17.42.1
  2. колдую docker run --name 'ddns' --restart=unless-stopped -d -v '/var/run/docker.sock:/run/docker.sock' -p '172.17.42.1:53:53/udp' tonistiigi/dnsdock -domain='docker'


где,
--restart=unless-stopped — авто перезапуск dnsdock контейнера после перезагрузки компьютера или возникновении ошибки в контейнере
-p '172.17.42.1:53:53/udp' — проброс DNS сервиса на ip docker0 интерфейса
-domain='docker' — домен наших контейнеров.

Адрес контейнера формируется из переменных окружения DNSDOCK_NAME, DNSDOCK_IMAGE и домена который был указан при запуске dnsdock

Например в docker-compose контейнеру nginx я добавляю переменные окружения DNSDOCK_NAME и DNSDOCK_IMAGE

project_nginx:
image: nginx

environment:
DNSDOCK_NAME: site
DNSDOCK_IMAGE: project

и после запуска контейнера, сразу могу стучаться по адресу http://site.project.docker
UFO just landed and posted this here
Честно говоря не знаю. Я это дело как настроил себе год назад, с тех пор для нового проекта только копирую структуру директорий и docker-compose.yaml. Потом bash скриптом массово переименовываю project на другой префикс.

Есть контейнер который DNS на запущенные контейнеры держит.

А вы запускаете докер на физических или виртуальных серверах?

Использую OSX, т.е. локально Docker запускается в виртуальной машине, но это происходит "за ширмой" и не доставляется проблем. Когда использовал Linux, докер запускался непосредственно на физической машине.


Если Вы имели ввиду, как мы запускаем докер в "production" окружениях — то там да, виртуальные машины (Amazon, Google Cloud, Digital Ocean).

Немного не в тему, то я плохо представляю как можно проект на Amazon, Google Cloud, Digital Ocean держать с их ценами… Имхо, лишь если крутой инвестор вложился в проект, то это позволительно… Или я ошибаюсь?

Самый дешевый вариант, который достаточно долго использовал для разных, в том числе и своих проектов — это Digital Ocean дроплет за $5 в месяц. Вполне достаточно для старта большинства приложений. Можно увеличивать размер сервера по необходимости. Amazon, Google Cloud — предлагают хорошую интергацию с их сервисами. Позволяют сместить фокус с работы над инфраструктурой на работу над приложением путем больших затрат. Тут все индивидуально.


Мне кажется, что все же крутой инвестор не самая большая проблема :)

UFO just landed and posted this here
А как вы поступаете в продакше с обшими папками, ну, например, загруженные юзерами файлы и т.п. Просто шарите папку, чтобы файлы на хосте хранились?

Чтобы избежать мучений с закончившимся местом на диске — используем, в основном, Amazon S3. Для разного рода временных файлов — используем volumes и храним на хосте.

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

Постоянно делать docker-compose up --build не обязательно, если уверен что конфигурация не изменялась. На крайний случай можно git хук повесить, который будет пересобирать образы при изменении Dockerfile, но это лишнее на мой взгляд.

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

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

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

Да, абсолютно. Можно жить и без --build, но у нас это часто приводило к станностям в работе приложения. Обновил проект, забыл запустить с --build. Мы измеряли, у нас разница с --build и без --build всего несколько секунд, что не существенно, особенно с учетом того, что проект рестартуется максимум два раза в день. Проект в целом запускается с --build за секунд 5-10 (2 базы данных, 6 сервисов), не более того. Если запускается дольше, есть вероятность, что Dockerfile не совсем корректно построен. Несколько самых популярных ошибки из нашей практики:


  1. Сторонние зависимости должны идти в начале докера. Они меняются редко и не будут перестраиваться каждый раз, при изменении кода приложения.
  2. Копирование файлов, в которых описаны сторонние зависимости должно идти отдельным шагом, что бы при каждом запуске они не ставились заново. В примере ниже, сразу происходит копирование package.json (зависимости для Node.js приложения), а лишь потом происходит установка зависимостей. Если package.json не меняется — то и зависимости не будут ставиться заново.
  3. На рабочих окружениях, код не копируется в Docker, а добавляется как volume.

FROM node:6.3
EXPOSE 8082
COPY package.json /app/
RUN cd /app && \
    npm install --quiet
WORKDIR /app

По поводу сборки у нас подход похожий, но немного на стероидах. Поделюсь этим в отдельной статье.


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

У вас весь проект умещается на одном сервере или развертываете на нескольких через swarm mode? Получилось ли со swarm mode автоматизировать build и deploy?
Сторонние зависимости должны идти в начале докера. Они меняются редко и не будут перестраиваться каждый раз, при изменении кода приложения.

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

Данную проблему решил с помощью запуска докера с параметром --userns-remap=user.
В контейнере процессы запускают из под рута, но файлы созданные в volume имеют права вашего локального пользователя и группы, указанного в ремапинге.
Может кому поможет, но внезапно наткнулся в reddit на ссылочку
https://nanobox.io/app-deployment-tool/
Как поступить, если код приложения должен быть доступен в нескольких контейнерах — nginx, php, cron-php (для крона у меня отдельный).
Стоит ли его включать внутрь (как делаете вы) всех контейнеров или же лучше маунтить внешнюю папку?

Я пока остановился на volume_from, то есть один контейнер делаем базовым (я обычно php-fpm том делаю, cli внутри него использую при необходимости), выставляющий нужные для других тома. Но вообще считаю костылём, контейнеры должны быть независимыми, но пока не нашел красивого удобного способа собрать, например, nginx контейнер со статикой отдельно от php-fpm контейнера.

Может стоит тогда в nginx контейнер запихивать тоже вообще весь код приложения, а не только статику?

Не имеет значения особого в плане штатной сборки, в nginx контейнер нужно будет установить php со всеми нужными расширениями, собрать, удалить php. Удалять только php или ещё и основной код — особой разницы нет. Мне не нравится сама идея при сборке nginx-контейнера использовать php. Ну и всякие каталоги /uploads всё равно нужно будет шарить между nginx и php контейнерами.

Я имел ввиду, что код приложения целиком запихивать как в nginx, так и в php контейнеры. При этом не комбинировать их. Как вам это решение?

Мне не нравится, что при этом придется думать о синхронизации(чтобы в обеих контейнерах был одинаковый код) и пересоздавать также nginx контейнер при обновлении кода.

Иначе получается, что нельзя код включать внутрь контейнера и надо хранить его в отдельном volume. Но как тогда делать деплой чере докер? Ведь не получится просто обновить php-контейнеры, ибо код в volume.

Я это понял. Но чтобы его запихнуть нужно, как правило, хотя бы composer install запустить, а это значит установить php и composer в nginx контейнер, если следовать классическому подходу. А поскольку ни php, ни php-код для nginx-контейнера не нужны, то логично их удалить.


В принципе есть много разных вариантов сборки контейнеров только с тем, что им нужно и без шаринга между собой, но вот не нашёл ни одного, который бы работал нормально с docker-compose — он рассчитан только на сборку образов с помощью docker build, который рассчитан только на копирование файлов из контекста :(

Может тогда правильно было бы так:
1. На сервере, на котором происходит сборка (или же в CI) установить php, composer
2. clone из репозитори
3. composer install. В итоге мы имеем проект целиком, но еще не в контейнерах
4. Строим контейнеры через build. Индивидуально включая в каждый из них лишь те файлы, которые нужны контейнеру.
5. Делаем ролаут контейнеров nginx(со статикой проекта), php и т.п.

P.S. Единственная проблема, что при ролауде nginx оборвутся соединения из-за перезапуска. Как её решить?

Ну совсем правильно тогда так:


  1. Делаем билд-контейнер с php, composer,… Пользователь и прочее строго синхронизировано с целевыми контейнерами, чтобы не возникло проблем с правами.

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

Лично я начинал с volumes_from подхода, но в итоге отказался от него из-за сопутствующих трудностей деплоя в пользу включения внутрь контейнера в качестве volume

Не очень понял. Можно пример?

Докерский деплой ведь не получится? Как обновляешь код?
Sign up to leave a comment.

Articles