热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何正确连接php-fpm和NginxDocker容器?-Howtocorrectlylinkphp-fpmandNginxDockercontainers?

Iamtryingtolink2separatecontainers:我正在尝试连接两个独立的容器:nginx:latestnginx:最新php:fpmphp

I am trying to link 2 separate containers:

我正在尝试连接两个独立的容器:

  • nginx:latest
  • nginx:最新
  • php:fpm
  • php:fpm

The problem is that php scripts do not work. Perhaps the php-fpm configuration is incorrect. Here is the source code, which is in my repository. Here is the file docker-compose.yml:

问题是php脚本不能工作。可能php-fpm配置不正确。这是源代码,在我的存储库中。这里是文档编辑器。

nginx:
    build: .
    ports:
        - "80:80"
        - "443:443"
    volumes:
        - ./:/var/www/test/
    links:
        - fpm
fpm:
    image: php:fpm
    ports:
        - "9000:9000"

and Dockerfile which I used to build a custom image based on the nginx one:

还有Dockerfile,我用它基于nginx创建了一个自定义映像:

FROM nginx

# Change Nginx config here...
RUN rm /etc/nginx/conf.d/default.conf
ADD ./default.conf /etc/nginx/conf.d/

Lastly, here is my custom Nginx virtual host config:

最后,这里是我自定义的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;
    }
}

Could anybody help me configure these containers correctly to execute php scripts?

有人能帮我正确配置这些容器来执行php脚本吗?

P.S. I run containers via docker-composer like this:

我通过docker-composer来运行容器:

docker-compose up

docker-compose起来

from the project root directory.

从项目根目录。

6 个解决方案

#1


26  

Don't hardcode ip of containers in nginx config, docker link adds the hostname of the linked machine to the hosts file of the container and you should be able to ping by hostname.

不要在nginx配置中硬编码容器的ip, docker链接将连接机器的主机名添加到容器的主机文件中,您应该能够按主机名进行ping。

EDIT: Docker 1.9 Networking no longer requires you to link containers, when multiple containers are connected to the same network, their hosts file will be updated so they can reach each other by hostname.

编辑:Docker 1.9网络不再要求您链接容器,当多个容器连接到同一个网络时,它们的主机文件将被更新,以便它们可以通过主机名相互联系。

Every time a docker container spins up from an image (even stop/start-ing an existing container) the containers get new ip's assigned by the docker host. These ip's are not in the same subnet as your actual machines.

每次docker容器从一个映像(甚至停止/启动一个现有的容器)旋转时,容器都会得到docker主机分配的新ip。这些ip与实际的计算机不在同一子网中。

see docker linking docs (this is what compose uses in the background)

参见docker链接文档(这是组合在后台使用的)

but more clearly explained in the docker-compose docs on links & expose

但是在链接和公开的docker- composer文档中有更清晰的解释

links

链接

links:
 - db
 - db:database
 - redis

An entry with the alias' name will be created in /etc/hosts inside containers for this service, e.g:

将在/etc/hosts中为该服务在容器中创建具有别名的条目,例如:

172.17.2.186  db
172.17.2.186  database
172.17.2.187  redis

expose

暴露

Expose ports without publishing them to the host machine - they'll only be accessible to linked services. Only the internal port can be specified.

在没有将它们发布到主机的情况下公开端口——它们只能被链接的服务访问。只能指定内部端口。

and if you set up your project to get the ports + other credentials through environment variables, links automatically set a bunch of system variables:

如果你建立了你的项目,通过环境变量获得端口+其他凭证,链接会自动设置一系列系统变量:

To see what environment variables are available to a service, run docker-compose run SERVICE env.

要查看服务可用的环境变量,请运行docker- composition运行服务env。

name_PORT

name_PORT

Full URL, e.g. DB_PORT=tcp://172.17.0.5:5432

完整的URL,例如DB_PORT = tcp:/ / 172.17.0.5:5432

name_PORT_num_protocol

name_PORT_num_protocol

Full URL, e.g. DB_PORT_5432_TCP=tcp://172.17.0.5:5432

完整的URL,例如DB_PORT_5432_TCP = tcp:/ / 172.17.0.5:5432

name_PORT_num_protocol_ADDR

name_PORT_num_protocol_ADDR

Container's IP address, e.g. DB_PORT_5432_TCP_ADDR=172.17.0.5

容器的IP地址,例如DB_PORT_5432_TCP_ADDR=172.17.0.5

name_PORT_num_protocol_PORT

name_PORT_num_protocol_PORT

Exposed port number, e.g. DB_PORT_5432_TCP_PORT=5432

暴露的端口号,例如DB_PORT_5432_TCP_PORT=5432

name_PORT_num_protocol_PROTO

name_PORT_num_protocol_PROTO

Protocol (tcp or udp), e.g. DB_PORT_5432_TCP_PROTO=tcp

协议(tcp或udp),例如DB_PORT_5432_TCP_PROTO=tcp

name_NAME

name_NAME

Fully qualified container name, e.g. DB_1_NAME=/myapp_web_1/myapp_db_1

完全限定容器名,例如DB_1_NAME=/myapp_web_1/myapp_db_1

#2


55  

I know it is kind an old post, but I've had the same problem and couldn't understand why your code didn't work. After a LOT of tests I've found out why.

我知道这是一个古老的帖子,但我也有同样的问题,不明白为什么你的代码不能工作。经过多次测试,我发现了原因。

docker-compose.yml

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

/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

Dockerfile

FROM nginx:latest
RUN ADD ./default.conf /etc/nginx/conf.d/

#3


19  

As pointed out before, the problem was that the files were not visible by the fpm container. However to share data among containers the recommended pattern is using data-only containers (as explained in this article).

如前所述,问题是文件不能被fpm容器可见。然而,要在容器中共享数据,推荐的模式是使用数据容器(本文中对此进行了解释)。

Long story short: create a container that just holds your data, share it with a volume, and link this volume in your apps with volumes_from.

长话短说:创建一个只保存数据的容器,与一个卷共享数据,并将这个卷与volumes_from链接到应用程序中。

Using compose (1.6.2 in my machine), the docker-compose.yml file would read:

使用组合(在我的机器中是1.6.2),docker- composer。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

Note that data publishes a volume that is linked to the nginx and fpm services. Then the Dockerfile for the data service, that contains your source code:

注意,data发布了一个与nginx和fpm服务链接的卷。然后是数据服务的Dockerfile,其中包含您的源代码:

FROM busybox

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

And the Dockerfile for nginx, that just replaces the default config:

而nginx的Dockerfile则替换了默认配置:

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).

它只告诉nginx使用共享卷作为文档根,并为nginx设置正确的配置,以便能够与fpm容器通信(即::正确的主机:端口,它是fpm:9000,感谢由composer定义的主机名和SCRIPT_FILENAME)。

#4


14  

New Answer

Docker Compose has been updated. They now have a version 2 file format.

Docker撰写已被更新。他们现在有一个版本2的文件格式。

Version 2 files are supported by Compose 1.6.0+ and require a Docker Engine of version 1.10.0+.

撰写1.6.0+支持版本2文件,需要1.10.0+版本的Docker引擎。

They now support the networking feature of Docker which when run sets up a default network called myapp_default

它们现在支持Docker的网络特性,该特性在运行时设置一个名为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:

当这些容器被自动添加到默认的myapp_default网络时,它们将能够彼此对话。然后在Nginx配置中:

fastcgi_pass fpm:9000;

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.

在注释中提到的@treeface还记得确保PHP-FPM监听端口9000,这可以通过编辑/etc/php5/fpm/pool.d/www.conf来完成,需要监听= 9000。

Old Answer

I have kept the below here for those using older version of Docker/Docker compose and would like the information.

对于使用Docker/Docker撰写的旧版本的用户,我在这里保留了以下内容,并希望获得相关信息。

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- composer(在编写本文时,它只支持docker网络特性)。这是我对自己所学的理解。

Docker has recently deprecated its link feature in favour of its networks feature

Docker最近已经弃用了它的链接功能,而代之以它的网络功能

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.

因此,使用Docker网络特性,您可以通过以下步骤链接容器。有关选项的完整解释,请参阅之前链接的文档。

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).

下一步运行您的PHP-FPM容器,确保您打开端口9000并分配给您的新网络(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.

这里重要的一点是——在命令末尾的php-fpm名称,也就是名称,我们稍后将需要它。

Next run your Nginx container again assign to the network you created.

接下来,再次运行您的Nginx容器,将其分配给您创建的网络。

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.

对于PHP和Nginx容器,您还可以根据需要添加命令等。

Now comes the Nginx configuration. Which should look something similar to this:

现在是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;
    }
}

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.

注意到fastcgi_pass php-fpm:9000;块的位置。也就是说在9000港口联系集装箱php-fpm。当您向Docker网桥上添加容器时,它们都会自动获得一个主机文件更新,该更新将容器名与它们的IP地址对应。因此,当Nginx看到它将知道如何联系之前命名为PHP-FPM并分配给您的mynetwork Docker网络的PHP-FPM容器。

You can add that Nginx config either during the build process of your Docker container or afterwards its up to you.

您可以添加,Nginx配置你的集装箱码头工人在构建过程中或之后它取决于你。

#5


7  

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.

前面的答案已经解决了,但是应该明确地声明:php代码需要在php-fpm容器中生存,而静态文件需要住在nginx容器中。为了简单起见,大多数人都将所有代码都附加到这两种代码中,如下所示。如果将来,我可能会在我自己的项目中分离出这些代码的不同部分,以最小化哪些容器可以访问哪些部分。

Updated my example files below with this latest revelation (thank you @alkaline )

用这个最新的发现更新了我下面的示例文件(谢谢@alkali)

This seems to be the minimum setup for docker 2.0 forward (because things got a lot easier in docker 2.0)

这似乎是docker 2.0 forward的最小设置(因为在docker 2.0中,事情变得简单多了)

docker-compose.yml:

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)

(更新docker-compose。上面的yml:对于具有css、Javascript、静态文件等的站点,您将需要那些可以访问nginx容器的文件。同时,fpm容器仍然可以访问所有php代码。同样,由于我的基本代码是css、js和php的杂乱组合,本示例将所有代码都附加到两个容器中)

In the same folder:

在同一文件夹:

site.conf:

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:

/ / index . php代码:

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

试着从你最喜欢的浏览器的URL

site.local.[YOUR URL].com/index.php

#6


6  

I think we also need to give the fpm container the volume, dont we? So =>

我认为我们还需要给fpm容器体积,不?所以= >

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:

如果我不这样做,我在触发请求时遇到这个异常,因为fpm无法找到被请求的文件:

[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"

(错误)6 # 6:* 4 FastCGI stderr派:“主要脚本未知”在阅读响应头从上游客户:172.17.42.1,服务器:localhost,请求:“GET / HTTP / 1.1”,上游:“FastCGI:/ / 172.17.0.81:9000”,主持人:“localhost”


推荐阅读
author-avatar
试管婴儿
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有