Как правильно связать контейнеры php-fpm и Nginx Docker?
Я пытаюсь связать 2 отдельных контейнера:
Проблема заключается в том, что скрипты php не работают. Возможно, неправильная конфигурация php-fpm.
Вот исходный код, который находится в моем репозитории . Вот файл docker-compose.yml
:
nginx:
build: .
ports:
- "80:80"
- "443:443"
volumes:
- ./:/var/www/test/
links:
- fpm
fpm:
image: php:fpm
ports:
- "9000:9000"
и Dockerfile
, которые я использовал для создания пользовательского изображения на основе nginx one:
FROM nginx
# Change Nginx config here...
RUN rm /etc/nginx/conf.d/default.conf
ADD ./default.conf /etc/nginx/conf.d/
Наконец, вот моя настраиваемая конфигурация виртуального хоста Nginx:
server {
listen 80;
server_name localhost;
root /var/www/test;
error_log /var/log/nginx/localhost.error.log;
access_log /var/log/nginx/localhost.access.log;
location / {
# try to serve file directly, fallback to app.php
try_files $uri /index.php$is_args$args;
}
location ~ ^/.+\.php(/|$) {
fastcgi_pass 192.168.59.103:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
}
}
Может ли кто-нибудь помочь мне правильно настроить эти контейнеры для выполнения сценариев php?
P.S.
Я запускаю контейнеры через докер-композитор следующим образом:
docker-compose up
из корневого каталога проекта.
Ответы
Ответ 1
Не печатайте ip-адрес контейнеров в конфигурации nginx, ссылка docker добавляет имя хоста связанного компьютера в файл hosts контейнера, и вы должны иметь возможность ping по имени хоста.
EDIT: Docker 1.9 Networking больше не требует связывания контейнеров, когда несколько контейнеров подключены к одной и той же сети, их файл hosts будет обновлен, чтобы они могли достигать друг друга по имени хоста.
Каждый раз, когда контейнер-докер вращается от изображения (даже останавливая/запуская существующий контейнер), контейнеры получают новый ip, назначенный хостом докера. Эти ip не находятся в той же подсети, что и ваши фактические машины.
см. docker linking docs (это то, что составляют использование в фоновом режиме)
но более четко объяснено в docker-compose
документы по ссылкам и разоблачать
связи
links:
- db
- db:database
- redis
Запись с именем псевдонима будет создана в /etc/hosts внутри контейнеров для этой службы, например:
172.17.2.186 db
172.17.2.186 database
172.17.2.187 redis
разоблачать
Экспортировать порты без их публикации на хост-машине - они будут доступны только для связанных служб. Можно указать только внутренний порт.
и если вы настроите свой проект на получение портов + другие учетные данные через переменные среды, ссылки автоматически устанавливают набор системных переменных:
Чтобы узнать, какие переменные среды доступны для службы, запустите docker-compose run SERVICE env
.
name_PORT
Полный URL-адрес, например DB_PORT = tcp://172.17.0.5: 5432
name_PORT_num_protocol
Полный URL, например DB_PORT_5432_TCP=tcp://172.17.0.5:5432
name_PORT_num_protocol_ADDR
IP-адрес контейнера, например DB_PORT_5432_TCP_ADDR=172.17.0.5
name_PORT_num_protocol_PORT
Номер DB_PORT_5432_TCP_PORT=5432
порта, например DB_PORT_5432_TCP_PORT=5432
name_PORT_num_protocol_PROTO
Протокол (tcp или udp), например DB_PORT_5432_TCP_PROTO=tcp
name_NAME
DB_1_NAME=/myapp_web_1/myapp_db_1
имя контейнера, например DB_1_NAME=/myapp_web_1/myapp_db_1
Ответ 2
Я знаю, что это добрый старый пост, но у меня была такая же проблема, и я не мог понять, почему ваш код не работает. Почему?
докер-compose.yml
nginx:
build: .
ports:
- "80:80"
links:
- fpm
fpm:
image: php:fpm
ports:
- ":9000"
# seems like fpm receives the full path from nginx
# and tries to find the files in this dock, so it must
# be the same as nginx.root
volumes:
- ./:/complex/path/to/files/
/etc/nginx/conf.d/default.conf
server {
listen 80;
# this path MUST be exactly as docker-compose.fpm.volumes,
# even if it doesn't exist in this dock.
root /complex/path/to/files;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ ^/.+\.php(/|$) {
fastcgi_pass fpm:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Dockerfile
FROM nginx:latest
COPY ./default.conf /etc/nginx/conf.d/
Ответ 3
Как указывалось ранее, проблема заключалась в том, что файлы не были видны контейнером fpm. Однако для обмена данными между контейнерами рекомендуемый шаблон использует контейнеры только для данных (как описано в в этой статье).
Короче говоря: создайте контейнер, который просто держит ваши данные, делится им с томом и связывает этот том в ваших приложениях с помощью volumes_from
.
Используя compose (1.6.2 на моей машине), файл docker-compose.yml
будет читать:
version: "2"
services:
nginx:
build:
context: .
dockerfile: nginx/Dockerfile
ports:
- "80:80"
links:
- fpm
volumes_from:
- data
fpm:
image: php:fpm
volumes_from:
- data
data:
build:
context: .
dockerfile: data/Dockerfile
volumes:
- /var/www/html
Обратите внимание, что data
публикует том, связанный с службами nginx
и fpm
. Затем Dockerfile
для службы данных, которая содержит исходный код:
FROM busybox
# content
ADD path/to/source /var/www/html
И Dockerfile
для nginx, который просто заменяет конфигурацию по умолчанию:
FROM nginx
# config
ADD config/default.conf /etc/nginx/conf.d
Для завершения здесь нужен конфигурационный файл, необходимый для работы примера:
server {
listen 0.0.0.0:80;
root /var/www/html;
location / {
index index.php index.html;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
}
}
который просто говорит nginx использовать общий том в качестве корня документа и устанавливает правильную конфигурацию для nginx для связи с контейнером fpm (то есть: right HOST:PORT
, который является fpm:9000
, благодаря именам хостов определяемый составом, и SCRIPT_FILENAME
).
Ответ 4
Новый ответ
Docker Compose обновлен. Теперь они имеют формат версии 2.
Файлы версии 2 поддерживаются Compose 1.6.0+ и требуют Docker Engine версии 1.10.0 +.
Теперь они поддерживают сетевую функцию Docker, которая при запуске устанавливает сеть по умолчанию, называемую myapp_default
Из их документации ваш файл будет выглядеть примерно так:
version: '2'
services:
web:
build: .
ports:
- "8000:8000"
fpm:
image: phpfpm
nginx
image: nginx
Поскольку эти контейнеры автоматически добавляются в сеть myapp_default по умолчанию, они смогут разговаривать друг с другом. Тогда у вас в конфигурации Nginx:
fastcgi_pass fpm:9000;
Также, как упоминалось в комментариях @treeface в комментариях, убедитесь, что PHP-FPM прослушивает порт 9000, это можно сделать, отредактировав /etc/php5/fpm/pool.d/www.conf
, где вам понадобится listen = 9000
.
Старый ответ
Я сохранил ниже для тех, кто использует устаревшую версию Docker/Docker, и хотел бы получить информацию.
Я продолжал споткнуться на этот вопрос в Google, пытаясь найти ответ на этот вопрос, но это было не совсем то, что я искал из-за акцента Q/A на docker-compose (который на момент написания экспериментальная поддержка сетевых функций докеров). Итак, вот мой взгляд на то, что я узнал.
Недавно Docker отказался от своей функции в пользу своей функции
Поэтому, используя функцию Docker Networks, вы можете связать контейнеры, выполнив следующие шаги. Для полного объяснения параметров, прочитанных в документах, связанных ранее.
Сначала создайте свою сеть
docker network create --driver bridge mynetwork
Затем запустите свой контейнер PHP-FPM, чтобы открыть порт 9000 и назначить новую сеть (mynetwork
).
docker run -d -p 9000 --net mynetwork --name php-fpm php:fpm
Важным здесь является --name php-fpm
в конце команды, которая является именем, это нам понадобится позже.
Затем запустите свой контейнер Nginx снова назначить созданной сети.
docker run --net mynetwork --name nginx -d -p 80:80 nginx:latest
Для контейнеров PHP и Nginx вы также можете добавить команды --volumes-from
и т.д. по мере необходимости.
Теперь идет конфигурация Nginx. Что должно выглядеть примерно так:
server {
listen 80;
server_name localhost;
root /path/to/my/webroot;
index index.html index.htm index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
include fastcgi_params;
}
}
Обратите внимание на fastcgi_pass php-fpm:9000;
в блоке местоположения. Thats говорит контактный контейнер php-fpm
на порту 9000
. Когда вы добавляете контейнеры в сеть моста Docker, все они автоматически получают обновление файла hosts, которое помещает их имя контейнера в соответствие с их IP-адресом. Поэтому, когда Nginx видит, что он будет знать, что он свяжется с контейнером PHP-FPM, вы назвали php-fpm
ранее и назначены вашей сети mynetwork
Docker.
Вы можете добавить эту конфигурацию Nginx либо во время процесса сборки вашего контейнера Docker, либо после этого до вас.
Ответ 5
Как уже обсуждались предыдущие ответы, но следует сказать очень четко: PHP-код должен жить в контейнере php-fpm, в то время как статические файлы должны жить в контейнере nginx. Для простоты большинство людей просто привязали весь код к обоим, как я также сделал ниже. Если будущее, я, вероятно, выделил эти разные части кода в моих собственных проектах, чтобы свести к минимуму, какие контейнеры имеют доступ к тем частям.
Обновлены мои примеры файлов ниже с этим последним откровением (спасибо @alkaline)
Это, по-видимому, минимальная настройка для docker 2.0 forward
(потому что в докере 2.0 стало намного проще)
докер-compose.yml:
version: '2'
services:
php:
container_name: test-php
image: php:fpm
volumes:
- ./code:/var/www/html/site
nginx:
container_name: test-nginx
image: nginx:latest
volumes:
- ./code:/var/www/html/site
- ./site.conf:/etc/nginx/conf.d/site.conf:ro
ports:
- 80:80
( ОБНОВЛЕНО docker-compose.yml выше. Для сайтов, на которых есть css, javascript, статические файлы и т.д., вам понадобятся эти файлы, доступные для контейнера nginx. код, доступный для контейнера fpm. Опять же, поскольку мой базовый код является беспорядочным соединением css, js и php, этот пример просто привязывает весь код к обоим контейнерам)
В той же папке:
site.conf:
server
{
listen 80;
server_name site.local.[YOUR URL].com;
root /var/www/html/site;
index index.php;
location /
{
try_files $uri =404;
}
location ~ \.php$ {
fastcgi_pass test-php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
В коде папки:
./код/index.php:
<?php
phpinfo();
и не забудьте обновить файл hosts:
127.0.0.1 site.local.[YOUR URL].com
и запустите компоновку вашей докеры
$docker-compose up -d
и попробуйте URL из вашего любимого браузера
site.local.[YOUR URL].com/index.php
Ответ 6
Думаю, нам также нужно предоставить объем fpm контейнеру, не так ли? So = >
fpm:
image: php:fpm
volumes:
- ./:/var/www/test/
Если я этого не сделаю, я запускаю это исключение при запуске запроса, так как fpm не может найти запрошенный файл:
[ошибка] 6 # 6: * 4 FastCGI, отправленный в stderr: "Первичный script неизвестный" при чтении заголовка ответа вверх, клиент: 172.17.42.1, server: localhost, request: "GET/HTTP/1.1", upstream: "fastcgi://172.17.0.81: 9000", хост: "localhost"
Ответ 7
Для кого-то другого
Ошибка Nginx 403: указатель каталога в [папке] запрещен
при использовании index.php
то время как index.html
отлично работает и включил index.php
в индекс в блоке сервера их конфигурации сайта в sites-enabled
server {
listen 80;
# this path MUST be exactly as docker-compose php volumes
root /usr/share/nginx/html;
index index.php
...
}
Убедитесь, что ваш файл nginx.conf на /etc/nginx/nginx.conf
загружает конфигурацию вашего сайта в блоке http
...
http {
...
include /etc/nginx/conf.d/*.conf;
# Load our websites config
include /etc/nginx/sites-enabled/*;
}