program story

php-fpm 및 Nginx Docker 컨테이너를 올바르게 연결하는 방법은 무엇입니까?

inputbox 2020. 9. 14. 20:45
반응형

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연결된 볼륨 게시 합니다. 그런 다음 소스 코드를 포함 하는 데이터 서비스의 경우 :nginxfpmDockerfile

FROM busybox

# content
ADD path/to/source /var/www/html

그리고 Dockerfilenginx의 경우 기본 구성을 대체합니다.

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/*;
}

참고URL : https://stackoverflow.com/questions/29905953/how-to-correctly-link-php-fpm-and-nginx-docker-containers

반응형