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 하나에 따라 사용자 정의 이미지를 구축하는 데 사용되는 :
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 스크립트를 실행하기 위해 이러한 컨테이너를 올바르게 구성하는 데 도움을 줄 수 있습니까?
추신 : 다음과 같이 docker-composer를 통해 컨테이너를 실행합니다.
docker-compose up
프로젝트 루트 디렉토리에서.
nginx 구성에서 컨테이너의 IP를 하드 코딩하지 마십시오. docker 링크는 연결된 컴퓨터의 호스트 이름을 컨테이너의 호스트 파일에 추가하므로 호스트 이름으로 핑할 수 있습니다.
편집 : Docker 1.9 네트워킹은 더 이상 컨테이너를 연결할 필요가 없으며 여러 컨테이너가 동일한 네트워크에 연결되면 호스트 파일이 업데이트되어 호스트 이름으로 서로 연결할 수 있습니다.
Docker 컨테이너가 이미지에서 회전 할 때마다 (기존 컨테이너를 중지 / 시작할 수도 있음) 컨테이너는 Docker 호스트에 의해 할당 된 새 IP를 가져옵니다. 이 IP는 실제 머신과 동일한 서브넷에 있지 않습니다.
docker linking docs 참조 (이것은 compose가 백그라운드에서 사용하는 것입니다)
그러나 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
name_PORT_num_protocol_PROTO
프로토콜 (tcp 또는 udp), 예 :
DB_PORT_5432_TCP_PROTO=tcp
name_NAME
완전한 컨테이너 이름 (예 :
DB_1_NAME=/myapp_web_1/myapp_db_1
나는 그것이 오래된 게시물이라는 것을 알고 있지만 동일한 문제가 있었고 왜 코드가 작동하지 않았는지 이해할 수 없었습니다. 많은 테스트 후 나는 그 이유를 알아 냈습니다.
docker-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/
이전에 지적했듯이 문제는 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
For the sake of completion, here's the config file required for the example to work:
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;
}
}
which just tells nginx to use the shared volume as document root, and sets the right config for nginx to be able to communicate with the fpm container (i.e.: the right HOST:PORT
, which is fpm:9000
thanks to the hostnames defined by compose, and the SCRIPT_FILENAME
).
New Answer
Docker Compose has been updated. They now have a version 2 file format.
Version 2 files are supported by Compose 1.6.0+ and require a Docker Engine of version 1.10.0+.
They now support the networking feature of Docker which when run sets up a default network called myapp_default
From their documentation your file would look something like the below:
version: '2'
services:
web:
build: .
ports:
- "8000:8000"
fpm:
image: phpfpm
nginx
image: nginx
As these containers are automatically added to the default myapp_default network they would be able to talk to each other. You would then have in the Nginx config:
fastcgi_pass fpm:9000;
Also as mentioned by @treeface in the comments remember to ensure PHP-FPM is listening on port 9000, this can be done by editing /etc/php5/fpm/pool.d/www.conf
where you will need listen = 9000
.
Old Answer
I have kept the below here for those using older version of Docker/Docker compose and would like the information.
I kept stumbling upon this question on google when trying to find an answer to this question but it was not quite what I was looking for due to the Q/A emphasis on docker-compose (which at the time of writing only has experimental support for docker networking features). So here is my take on what I have learnt.
Docker has recently deprecated its link feature in favour of its networks feature
Therefore using the Docker Networks feature you can link containers by following these steps. For full explanations on options read up on the docs linked previously.
First create your network
docker network create --driver bridge mynetwork
Next run your PHP-FPM container ensuring you open up port 9000 and assign to your new network (mynetwork
).
docker run -d -p 9000 --net mynetwork --name php-fpm php:fpm
The important bit here is the --name php-fpm
at the end of the command which is the name, we will need this later.
Next run your Nginx container again assign to the network you created.
docker run --net mynetwork --name nginx -d -p 80:80 nginx:latest
For the PHP and Nginx containers you can also add in --volumes-from
commands etc as required.
Now comes the Nginx configuration. Which should look something similar to this:
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;
}
}
Notice the fastcgi_pass php-fpm:9000;
in the location block. Thats saying contact container php-fpm
on port 9000
. When you add containers to a Docker bridge network they all automatically get a hosts file update which puts in their container name against their IP address. So when Nginx sees that it will know to contact the PHP-FPM container you named php-fpm
earlier and assigned to your mynetwork
Docker network.
You can add that Nginx config either during the build process of your Docker container or afterwards its up to you.
As previous answers have solved for, but should be stated very explicitly: the php code needs to live in the php-fpm container, while the static files need to live in the nginx container. For simplicity, most people have just attached all the code to both, as I have also done below. If the future, I will likely separate out these different parts of the code in my own projects as to minimize which containers have access to which parts.
Updated my example files below with this latest revelation (thank you @alkaline )
This seems to be the minimum setup for docker 2.0 forward (because things got a lot easier in docker 2.0)
docker-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
(UPDATED the docker-compose.yml above: For sites that have css, javascript, static files, etc, you will need those files accessible to the nginx container. While still having all the php code accessible to the fpm container. Again, because my base code is a messy mix of css, js, and php, this example just attaches all the code to both containers)
In the same folder:
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;
}
}
In folder code:
./code/index.php:
<?php
phpinfo();
and don't forget to update your hosts file:
127.0.0.1 site.local.[YOUR URL].com
and run your docker-compose up
$docker-compose up -d
and try the URL from your favorite browser
site.local.[YOUR URL].com/index.php
I think we also need to give the fpm container the volume, dont we? So =>
fpm:
image: php:fpm
volumes:
- ./:/var/www/test/
If i dont do this, i run into this exception when firing a request, as fpm cannot find requested file:
[error] 6#6: *4 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 172.17.42.1, server: localhost, request: "GET / HTTP/1.1", upstream: "fastcgi://172.17.0.81:9000", host: "localhost"
For anyone else getting
Nginx 403 error: directory index of [folder] is forbidden
when using index.php
while index.html
works perfectly and having included index.php
in the index in the server block of their site config in sites-enabled
server {
listen 80;
# this path MUST be exactly as docker-compose php volumes
root /usr/share/nginx/html;
index index.php
...
}
Make sure your nginx.conf file at /etc/nginx/nginx.conf
actually loads your site config in the http
block...
http {
...
include /etc/nginx/conf.d/*.conf;
# Load our websites config
include /etc/nginx/sites-enabled/*;
}
'program story' 카테고리의 다른 글
"Workspace 버전과 비교"와 "최신 버전과 비교"의 차이점은 무엇입니까? (0) | 2020.09.14 |
---|---|
ASP.NET MVC 5 대 AngularJS / ASP.NET WebAPI (0) | 2020.09.14 |
VB.NET 코드를 C #으로 마이그레이션 할 때 for 루프가 다르게 작동하는 이유는 무엇입니까? (0) | 2020.09.14 |
파이썬 3에서 바이너리 데이터를 stdout에 쓰는 방법은 무엇입니까? (0) | 2020.09.14 |
재귀 하위 폴더 검색 및 목록 파이썬에서 파일 반환 (0) | 2020.09.13 |