Pull to refresh

Comments 38

А зачем Вам нужен Supervisor в докер контейнере?

Например, для работы с queues в Laravel.
Можно же просто запускать докер-контейнер с командой очереди?

Использования Supervisor да и в целом других дополнительных процессов внутри основного приложения это не "docker-way". К примеру для обработки очередей я бы предложил такую схему в Вашем случае:


  1. Создать дополнительный entrypoint entrypoint-queue.sh


    #!/usr/bin/env bash
    
    trap "echo 'Shutting down'; kill \$!; exit" SIGINT SIGTERM
    
    echo "Start the queue..."
    php /var/www/project/artisan queue:work 

  2. В docker-compose.yml создать сервис обработки очередей на основе главного сервиса:


    # main application example
    &app-service app: &app-service-template
     image: some-image
     hostname: *app-service
     volumes:
       - ..:..
     restart: always
    
    # queue service
    &queue-service queue:
     <<: *app-service-template
     entrypoint: /scripts/entrypoint_queue.sh
     hostname: *queue-service
     restart: always
     ports: []


Готово. Супервайзер не нужен.
Похожим способом решается задача планирования (аля cron)

В документации докера есть даже пример по запуску супервизора: docs.docker.com/config/containers/multi-service_container
Какие тут могут быть подводные камни?
Просто если представить ситуацию, что есть условно 5 очередей, на каждую хочется 3 воркера запустить, это тогда нужно 15 контейнеров поднять?
в приведенном скрипте, если появляется временно-постоянная проблема (например отвалился какой-нибудь сервис или очередь), то один из процессов будет постоянно умирать, а с ним — и весь супервизор (читай все остальные процессы в нем принудительно перезапускаются). Либо надо придумывать какие-то свои политики для перезапуска, либо следить за проблемами вручную.

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

Просто если представить ситуацию, что есть условно 5 очередей, на каждую хочется 3 воркера запустить, это тогда нужно 15 контейнеров поднять?


локально вам обычно не нужно столько. а для прод деплоймента обычно вы просто указываете сколько реплик вы хотите. при этом опять же, если это независимые вещи, то манипулировать ими можно индивидуально. скажем если вам надо одного процесса 4 инстанса, второго 3, а третьего 2 — вам не надо править конфиг супервизора, вы просто масштабируете свои деплойменты (в т.ч. можете это делать на ходу по мере необходимости)
в приведенном скрипте, если появляется временно-постоянная проблема (например отвалился какой-нибудь сервис или очередь), то один из процессов будет постоянно умирать, а с ним — и весь супервизор

не очень понял, почему весь супервизор умирать будет, умирать будет только косячный процесс
while sleep 60; do
  ps aux |grep my_first_process |grep -q -v grep
  PROCESS_1_STATUS=$?
  ps aux |grep my_second_process |grep -q -v grep
  PROCESS_2_STATUS=$?
  # If the greps above find anything, they exit with 0 status
  # If they are not both 0, then something is wrong
  if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
    echo "One of the processes has already exited."
    exit 1
  fi
done


Вот этот кусок проверяет каждую минуту, какой процесс умер и прибивает весь супервизор. Если он не будет так делать, то какой-то процесс умрет и вы не сможете его перезапустить без перезапуска всего супервизора все равно
можно и без этого всего, просто запустить супервизор же
Use a process manager like supervisord. This is a moderately heavy-weight approach that requires you to package supervisord and its configuration in your image (or base your image on one that includes supervisord), along with the different applications it manages. Then you start supervisord, which manages your processes for you. Here is an example Dockerfile using this approach, that assumes the pre-written supervisord.conf, my_first_process, and my_second_process files all exist in the same directory as your Dockerfile.

FROM ubuntu:latest
RUN apt-get update && apt-get install -y supervisor
RUN mkdir -p /var/log/supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY my_first_process my_first_process
COPY my_second_process my_second_process
CMD ["/usr/bin/supervisord"]
в докере, полагаю, можно запустить все что угодно, вопрос зачем.

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

По этой же ссылке дословно написано следующее:

It’s ok to have multiple processes, but to get the most benefit out of Docker, avoid one container being responsible for multiple aspects of your overall application
entrypoint_scheduler.sh
#!/usr/bin/env bash

trap "echo 'Shutting down'; kill \$!; exit" SIGINT SIGTERM

SCHEDULE_COMMAND="${@:-echo 'scheduler ticked'}";
FIRST_START_DELAY="${FIRST_START_DELAY:-2}";
SCHEDULE_PERIOD="${SCHEDULE_PERIOD:-60}";

STDOUT="${STDOUT:-/proc/1/fd/1}";
STDERR="${STDERR:-/proc/1/fd/2}";

echo "[ Info ] Command to execute: \"$SCHEDULE_COMMAND\". Delay between executions: $SCHEDULE_PERIOD";
echo '[ Info ] Press [CTRL+C] to stop';

sleep "$FIRST_START_DELAY";

while :; do
  # Stop freeze on large delay
  for (( i=1; i<=$SCHEDULE_PERIOD; i+=1)); do
    sleep 1;
  done;

  # Execute command
  ${SCHEDULE_COMMAND} > ${STDOUT} 2> ${STDERR};
done;

docker-compose.yml
&scheduler-service scheduler:
  <<: *app-service-template
  entrypoint: /scripts/entrypoint_scheduler.sh
  command: /path/to/app/artisan schedule:run
  hostname: *scheduler-service
  ports: []

Отличная работа! Перед создаем не смотрели в Laradock (самый удобный, на мой взляд, способ работы с php в Docker. Для разработки)? Какие преимущества вашего контейнера?

Laradock — интересный проект, разработчики, которые его поддерживают достойны уважения. Я внимательно его изучал. Но Laradock содержит в себе намного больше сервисов, чем может потребоваться. Там есть почти всё. И из-за этого он становиться чем-то похожим на Homestead, 90% того что там есть, скорее всего не пригодится. Моя цель заключалась в том, чтобы создать лёгкую среду, которую можно быстро модифицировать.
Ларадок содержит возможность развернуть множество сервисов. Их вовсе не обязательно все разворачивать. Скачиваются и запускаются только нужные контейнеры. При необходимости расширяется своими контейнерами в лёт. Например, я недавно настраивал окружение в докер контейнерах для разработчиков — склонировал ларадок, прокинул внутрь нужные конфиги, добавил два контейнера которых не было в комплекте, и в результате у меня есть репозиторий с sh скриптом, который по одной команде разворачивает: nginx, mariadb, php, redis, clickhouse, couchbase, клонирует кодовую базу, прокидывает альясы в hosts, поднимает контейнеры, накатывает миграции и дамп базы. На всё минут 15 — запустить скрипт, пойти попить кофе, вернуться, и можно работать.

Ларадок очень хорошо использовать именно в качестве базы для своей сборки. Если вам мозолят глаза лишние папки\разделы в docker-compose — можно их выпилить. По опыту(раньше у меня был самописный комплект контейнеров) скажу, что там из коробки предусмотрено многое, и чтобы потом не допиливать напильником своё решение, лучше взять готовое.

З.Ы. Хотя документация у ларадока так себе.

+1
Читал статью и не мог понять почему не Ларадок
Автор не разобрался с Ларадоком и сделал свой аналог.

Как по мне докер все же лучше для каждого проекта свой, а не одна свалка для всех проектов

Не сравнивали скорость mysql в докере и на голом железе? Я не могу понять или собрано для докера с какими то параметрами или что, но все докеровские образы просадку в бд дают около 30-40%, и это не сеть и не разрешение имен. Когда у приложения свои обработки тяжелые то можно не заметить, а когда пхп код очень быстрый то слабым звеном бд становится.

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


P.S. Не раз были проблемы с MySQL при запуске разных контейнеров с разными версиями Docker.

Если я правильно помню, то Docker по умолчанию пробрасывает порты на все доступные сетевые интерфейсы. Таким образом:

nginx:
image: nginx:stable-alpine
container_name: nginx
ports:
- "${NGINX_PORT}:80"


выставит в локалку 80 порт (и ваше веб-приложение) на общий доступ, и в случае использования Linux в качестве хоста, радостно пропишет все в iptables так, чтобы порт действительно открылся в локалку, даже если у вас стоит что-то в духе «deny all incoming from all». Для меня это в свое время стало весьма неприятным открытием.
с докером есть много сюрпризов — он сложнее и разнообразней чем хочет казаться: )

для проблемы описанной вами есть решение для docker-compose.yml:
services:
your_service:
ports:
- ${NETWORK_INTERFACE:-127.0.0.1}:${YOUR_SERVICE_PORT:-8000}:80

.env может содержать
NETWORK_INTERFACE=0.0.0.0
или
NETWORK_INTERFACE=127.0.0.1
Класс, спасибо — не знал про такое. Не могу найти это в документации (искал вот тут и вокруг)… не подскажете, начиная с какой версии Docker Compose доступны такие рюшечки?
Чьорт, надо же. Полезно, но не меняет того факта, что большинство забивает на привязку к IP и выставляет порты наружу (сам этим болел когда-то по незнанию). Есть также вариант вписать «ip»: «127.0.0.1» в /etc/docker/daemon.json, и тогда все контейнеры будут по дефолту только на локалхосте — КМК так надёжнее.
у меня была задача делать докер композ чтоб разработчики могли стартовать работу на проекте с нулевой ручной настройкой. внешний доступ к сервисам был даже удобен для совместной работы, но корпоративный сканер безопасности постоянно шлёт дурацкие запросы так что пришлось по умолчанию доступ ограничивать.

Делал в свое время видео на эту тему — https://youtu.be/QHXiQI7APcE
Без очередей, кронов и прочего. Просто чтобы начать писать. Обе базы: mysql и psql

UFO just landed and posted this here
Интересный проект)

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

Возможно вам будет интересно — github.com/rhamdeew/docker-compose-php
Если рабочая машина windows, получиться поднять?
Если pro или выше, то докер там работает относительо хорошо через hyper-v (есть еще экспериментальные с wsl2, но не пробовал). Если хомяк, то привет виртуалбокс и гемор с шаренными папками (оч. тормозные по умолчанию)
wsl2 пользуюсь с момента появления, полёт отличный. Стартует мгновенно, к работе никаких нареканий. Субъективно всё быстрее стало.
+ в сторону WSL2, экспериментальным он был пока из Insider Preview не вылез (у меня вешал хост по 3 и более раз на дню).

Но с выходом Win10 v2004 уже почти пол года полет нормальный.

У меня вопрос по этим двум командам:
docker exec -i postgres psql --username user_name database_name < /path/to/dump/pgsql-backup.sql
Или зайдите в контейнер postgres и выполните:


psql --username user_name database_name < /path/to/dump/pgsql-backup.sql


  1. В первом случае чтобы задуть дамп в базу указываем путь к дампу на хост-машине, да?(кстати как это технически происходит, через пайп?)
  2. А как во втором случае изнутри контейнера виден тот же самый путь? Пробрасывать внутрь папку с дампом не нужно?
В первом случае да, путь на хост машине.
Во втором — путь внутри контейнера.
Могу также посоветовать удобный сервис phpdocker.io — конструктор контейнеров
А под Windows можно всё это развернуть?
Sign up to leave a comment.

Articles