Комментарии 38
Из похожего — давно использую devilbox.readthedocs.io/en/latest
А зачем Вам нужен Supervisor в докер контейнере?
Использования Supervisor да и в целом других дополнительных процессов внутри основного приложения это не "docker-way". К примеру для обработки очередей я бы предложил такую схему в Вашем случае:
Создать дополнительный 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
В 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)
Какие тут могут быть подводные камни?
Просто если представить ситуацию, что есть условно 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
#!/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;
&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. Для разработки)? Какие преимущества вашего контейнера?
Ларадок очень хорошо использовать именно в качестве базы для своей сборки. Если вам мозолят глаза лишние папки\разделы в docker-compose — можно их выпилить. По опыту(раньше у меня был самописный комплект контейнеров) скажу, что там из коробки предусмотрено многое, и чтобы потом не допиливать напильником своё решение, лучше взять готовое.
З.Ы. Хотя документация у ларадока так себе.
Как по мне докер все же лучше для каждого проекта свой, а не одна свалка для всех проектов
Не сравнивали скорость mysql в докере и на голом железе? Я не могу понять или собрано для докера с какими то параметрами или что, но все докеровские образы просадку в бд дают около 30-40%, и это не сеть и не разрешение имен. Когда у приложения свои обработки тяжелые то можно не заметить, а когда пхп код очень быстрый то слабым звеном бд становится.
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
docs.docker.com/compose/compose-file/compose-file-v1/#ports
Делал в свое время видео на эту тему — https://youtu.be/QHXiQI7APcE
Без очередей, кронов и прочего. Просто чтобы начать писать. Обе базы: mysql и psql
Сталкивался с тем что большинство подобных проектов перегружены функционалом. Поэтому собрал свое решение с минимальным количеством используемых контейнеров ориентированное на максимально быструю настройку и запуск проекта.
Возможно вам будет интересно — github.com/rhamdeew/docker-compose-php
У меня вопрос по этим двум командам:
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
- В первом случае чтобы задуть дамп в базу указываем путь к дампу на хост-машине, да?(кстати как это технически происходит, через пайп?)
- А как во втором случае изнутри контейнера виден тот же самый путь? Пробрасывать внутрь папку с дампом не нужно?
Среда разработки PHP на базе Docker