Настройка: диспетчер vhost контейнеров nginx, который использует systemd для автоматического создания контейнеров php-fpm, когда их соответствующие vhosts активированы.
Конфигурация: общий том для сокетов в / var / run. systemd-socket-proxyd, используемый для прослушивания записывающего сокета nginx, затем запускает контейнер fpm, подождите, пока контейнер fpm создаст прослушивающий сокет, затем проксирует записывающий сокет nginx на прослушивающий сокет fpm.
nginx:/etc/nginx/conf.d/default:
try_files $uri =404;
root /usr/share/nginx/html;
fastcgi_pass unix:/var/run/docker-apps/vhost.fpm-waker.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
Это указывает nginx передавать запросы php в /var/run/docker-apps/vhost.fpm-waker.sock. Сначала мы должны убедиться, что nginx и fpm имеют одинаковые разрешения:
nginx:/etc/nginx/nginx.conf:
user www-data;
Затем мы убеждаемся, что fpm откроет сокет unix, где его ожидает найти systemd:
fpm:/etc/php5/fpm/pool.d/www.conf:
listen = /var/run/docker-apps/vhost.fpm.sock
listen.owner = www-data
listen.group = www-data
Теперь конфигурация готова, запускаем (но не запускаем) наш контейнер fpm:
docker create \
--name vhost \
--ipc="container:nginx" \
-v /var/run/docker-apps:/var/run/docker-apps \
fpm
Часть импорта здесь - это сопоставление томов, которое гарантирует, что область файловой системы доступна для записи обоими сокетами, которые мы собираемся использовать.
host:/vagrant/docker/docker-compose.yml:
nginx:
image: nginx
container_name: switchboard.noflag.org.uk
ports:
- 80:80
- 443:443
volumes:
- /var/run/docker-apps:/var/run/docker-apps
Наконец, наши дескрипторы служебных модулей systemd на хосте:
[Unit]
Description=vhost fpm container
[Service]
ExecStart=/usr/bin/docker start -a vhost
ExecStartPost=/bin/sleep 2
ExecStop=/usr/bin/docker stop vhost
Этот дескриптор службы позволяет systemd управлять запуском и остановкой контейнера. Давайте протестируем это:
# systemctl start vhost.service
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cacb32d1468c fpm "/usr/sbin/php5-fpm -" 26 hours ago Up 26 minutes 9005/tcp vhost
Да, этот дескриптор службы работает нормально.
Теперь мы сообщаем systemd, когда и как создать прокси-сервер прослушивающего сокета, на который nginx будет писать:
# more vhost.fpm-waker.socket
[Socket]
ListenStream=/var/run/docker-apps/vhost.fpm-waker.sock
SocketUser=www-data
SocketGroup=www-data
[Install]
WantedBy=sockets.target
Этот дескриптор описывает сокет, который systemd откроет для записи nginx. Когда сокет активирован, так будет и vhost.fpm-waker.service.
# more vhost.fpm-waker.service
[Unit]
Requires=vhost.fpm.service
After=vhost.fpm.service
[Install]
Also=vhost.fpm-waker.socket
[Service]
ExecStart=/lib/systemd/systemd-socket-proxyd /var/run/docker-apps/vhost.fpm.sock
vhost.fpm-waker.service автоматически запускает vhost.service, который, как мы видели, успешно запускает контейнер fpm. Запросы к сокету проксируются / lib / systemd / systemd-socket-proxyd до тех пор, пока fpm не сделает доступным прослушивающий сокет /var/run/docker-apps/vhost.fpm.sock.
Что произойдет, если мы вообще пропустим systemd-socket-proxyd?
# more vhost.fpm-waker.service
ExecStart=docker start -a vhost
# systemctl start vhost.fpm-waker.service
# docker logs vhost
[24-Nov-2016 13:07:06] ERROR: An another FPM instance seems to already listen on /var/run/docker-apps/vhost.fpm-waker.sock
[24-Nov-2016 13:07:06] ERROR: FPM initialization failed
Таким образом, мы можем подтвердить, что для этого процесса необходим systemd-socket-proxyd, поскольку fpm не будет рад передать уже существующий прослушивающий сокет.
Что происходит, когда мы складываем все воедино?
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2f92b7ce5e7b nginx "nginx -g 'daemon off" 28 hours ago Up About an hour 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nginx
# systemctl enable vhost.fpm-waker.socket
Created symlink from /etc/systemd/system/sockets.target.wants/vhost.fpm-waker.socket to /etc/systemd/system/vhost.fpm-waker.socket.
# ls -la /var/run/docker-apps
. ..
# systemctl start vhost.fpm-waker.socket
# ls -la /var/run/docker-apps
srw-rw---- 1 www-data www-data 0 Nov 24 21:31 vhost.fpm-waker.sock=
Хорошо. Systemd успешно создал наш сокет, к которому будет подключаться nginx. Давайте проверим, что nginx может разговаривать с сокетом:
# docker exec -it nginx ls -la /var/run/docker-apps
srw-rw---- 1 www-data www-data 0 Nov 24 21:31 vhost.fpm.sock=
Последний шаг. При наличии файла index.php в месте, доступном как для контейнеров nginx, так и для fpm, следующее должно вывести текст «Hello, world» из php:
# curl http://localhost:80/index.php
<p>Sorry, the page you are looking for is currently unavailable.<br/> Please try again later.</p>
<p>If you are the system administrator of this resource then you should check the <a href="http://nginx.org/r/error_log">error log</a> for details.</p>
Однако это не так. Контейнер fpm не имеет записей в журнале, но он является работает, как и ожидалось:
# docker logs vhost
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cacb32d1468c fpm "/usr/sbin/php5-fpm -" 26 hours ago Up 6 minutes 9005/tcp vhost
2f92b7ce5e7b nginx "nginx -g 'daemon off" 28 hours ago Up About an hour 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nginx
Более того, записывающий сокет nginx (созданный systemd) и прослушивающий сокет fpm (созданный fpm) присутствуют и верны:
# ls -la /var/run/docker-apps/
total 0
drwxr-xr-x 2 root root 60 Nov 24 21:31 ./
drwxr-xr-x 18 root root 660 Nov 24 20:06 ../
srw-rw---- 1 www-data www-data 0 Nov 24 21:31 vhost.fpm.sock=
srw-rw---- 1 www-data www-data 0 Nov 24 21:31 vhost.fpm-waker.sock=
Единственная подсказка - в журналах nginx:
docker logs nginx
172.21.0.1 - - [24/Nov/2016:20:51:04 +0000] "GET /index.php HTTP/1.1" 502 537 "-" "curl/7.38.0" "-"
2016/11/24 20:56:53 [error] 5#5: *15 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 172.21.0.1, server: localhost, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/docker-apps/vhost.fpm-waker.sock:", host: "localhost"
К сожалению, очень мало об использовании сокетов unix для запуска контейнеров докеров с использованием systemd-socket-proxyd и еще меньше о запуске контейнеров fpm таким образом. На данный момент я совершенно не понимаю, куда идти дальше.
Чтобы увидеть полную схему проекта, вы можете скачать его здесь и, возможно, сможете воспроизвести проблему с помощью vagrant. Однако в настоящее время служебные модули systemd не копируются на хост автоматически: