如何正确链接php-fpm和Nginx Docker容器?

slsn1g29  于 2023-02-28  发布在  PHP
关注(0)|答案(8)|浏览(199)

我正在尝试链接2个单独的容器:

问题是php脚本不起作用。可能php-fpm配置不正确。下面是源代码,在我的repository中。下面是文件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脚本吗?

**P.S.**我通过docker-composer运行容器,如下所示:

docker-compose up
从项目根目录。

bfnvny8b

bfnvny8b1#

我知道这是一个老职位,但我有同样的问题,不明白为什么你的代码不工作。经过大量的测试,我已经找到了原因。
fpm似乎从nginx接收完整路径,并试图在fpm容器中查找文件,因此它必须与nginx配置中的server.root完全相同,即使它不存在于nginx容器中。
为了证明:

    • 停靠-编写. 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/配置文件d/默认配置文件*
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;
    }
}
    • 停靠文件**
FROM nginx:latest
COPY ./default.conf /etc/nginx/conf.d/
bvjxkvbb

bvjxkvbb2#

不要在nginx config中硬编码容器的ip,docker link会将链接机器的主机名添加到容器的hosts文件中,您应该能够通过主机名ping。
编辑:Docker 1.9 Networking不再要求你链接容器,当多个容器连接到同一个网络时,它们的主机文件将被更新,这样它们就可以通过主机名相互连接。
每次一个docker container从一个镜像中旋转出来(甚至停止/启动一个已经存在的container),container就会得到docker主机分配的新的ip,这些ip和你的实际机器不在同一个子网中。
请参阅docker链接文档(这是compose在后台使用的)
but more clearly explained in the docker-compose docs on links & expose

链接

links:
 - db
 - db:database
 - redis

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

172.17.2.186  db
172.17.2.186  database
172.17.2.187  redis

曝光

公开端口而不将其发布到主机-它们将仅可由链接服务访问。只能指定内部端口。
如果您将项目设置为通过环境变量links automatically set a bunch of system variables获取端口和其他凭据:
要查看服务可以使用哪些环境变量,请运行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
x1米11米1x
完全限定的容器名称,例如DB_1_NAME=/myapp_web_1/myapp_db_1

uyhoqukh

uyhoqukh3#

如前所述,问题在于文件对于fpm容器是不可见的,但是要在容器之间共享数据,推荐的模式是使用data-only containers(如this article中所述)。
长话短说:创建一个容器来保存您的数据,将其与卷共享,并使用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发布了一个链接到nginxfpm服务的卷,然后是 * data * 服务的Dockerfile,其中包含您的源代码:

FROM busybox

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

对于nginx,Dockerfile只是替换默认配置:

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容器通信(即:右侧的HOST:PORT(由于compose定义了主机名,因此为fpm:9000)和SCRIPT_FILENAME)。

vfwfrxfs

vfwfrxfs4#

新答案

Docker编写已更新。他们现在有一个版本2的文件格式。
Compose 1.6.0+支持版本2文件,需要版本1.10.0+的Docker引擎。
它们现在支持Docker的网络功能,运行时会设置一个名为 myapp_default 的默认网络
their documentation中,您的文件看起来如下所示:

version: '2'

services:
  web:
    build: .
    ports:
      - "8000:8000"
  fpm:
    image: phpfpm
  nginx
    image: nginx

由于这些容器会自动添加到默认的 myapp_default 网络中,它们将能够相互通信。
fastcgi_pass fpm:9000;
另外,正如@treeface在评论中提到的,请记住确保PHP-FPM正在侦听端口9000,这可以通过编辑/etc/php5/fpm/pool.d/www.conf来完成,您将需要listen = 9000

旧答案

我一直在这里为那些使用旧版本的Docker/Docker组成,并希望信息如下。
当我试图在谷歌上找到这个问题的答案时,我一直在无意中发现这个问题,但由于问答中强调了docker-compose(在撰写本文时,它只对docker网络功能提供实验性支持),它并不是我所寻找的答案。
Docker最近推出了deprecated its link功能,以支持其networks feature
因此,使用Docker网络功能,您可以通过以下步骤链接容器。有关选项的完整解释,请阅读前面链接的文档。
首先创建您的网络

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

请注意location块中的fastcgi_pass php-fpm:9000;。这意味着在端口9000上联系容器php-fpm。当您将容器添加到Docker网桥网络时,它们都将自动获得主机文件更新,该更新将根据它们的IP地址放入它们的容器名称。因此,当Nginx看到时,它将知道联系PHP-您之前命名为php-fpm并分配给mynetwork Docker网络的FPM容器。
您可以在Docker容器的构建过程中添加Nginx配置,也可以在构建之后添加。

ubof19bj

ubof19bj5#

如前面的答案所示,但应非常明确地说明:php代码需要保存在php-fpm容器中,而静态文件需要保存在nginx容器中。为了简单起见,大多数人只是将所有代码附加到这两个容器中,就像我在下面所做的那样。如果将来,我可能会在我自己的项目中分离出这些不同的代码部分,以最小化哪些容器可以访问哪些部分。
更新了我的示例文件下面这个最新的启示(谢谢你@碱性)

这似乎是Docker 2.0的最低设置(因为在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

更新了上面的docker-compose.yml:对于有css,javascript,静态文件等的网站,你需要nginx容器可以访问这些文件,同时fpm容器可以访问所有php代码,同样,因为我的基本代码是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;
    }
}

文件夹代码:
./代码/索引.php:

<?php
phpinfo();

别忘了更新主机文件:

127.0.0.1 site.local.[YOUR URL].com

然后运行你的docker合成程序

$docker-compose up -d

并从您喜爱的浏览器尝试该URL

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

uxh89sit6#

我想我们还需要给fpm容器一个容量,不是吗?So =〉

fpm:
    image: php:fpm
    volumes:
        - ./:/var/www/test/

如果我不这样做,我会在触发请求时遇到这个异常,因为fpm找不到请求的文件:
[错误] 6#6:* 4 FastCGI在标准错误中发送:从上游读取响应标头时出现"主脚本未知",客户端:www.example.com,服务器:本地主机,请求:172.17.42.1"快速目录名称://172. 17. 0. 81:9000",主机:"本地主机" "fastcgi://172.17.0.81:9000", host: "localhost"

niknxzdl

niknxzdl7#

对于其他人来说
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

    ...
}

确保/etc/nginx/nginx.conf中的nginx. conf文件实际上加载了http块中的站点配置...

http {

    ...

    include /etc/nginx/conf.d/*.conf;

    # Load our websites config 
    include /etc/nginx/sites-enabled/*;
}
ccgok5k5

ccgok5k58#

使用官方图片和nginxconfig
nginx-php.yaml(您需要添加一个端口或网络方法来访问nginx服务)

services:
  nginx:
    image: nginx
    volumes:
      - /root/nginx/root:/usr/share/nginx/html:ro
      - /root/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - /root/nginx/templates:/etc/nginx/templates:ro
      - /root/nginx/log:/var/log/nginx

  php:
    image: php:fpm
    volumes:
      - /root/nginx/root:/usr/share/nginx/html:ro

example.com.conf.template

server {
    listen      80;
    listen      [::]:80;
    server_name example.com;
    set         $base /usr/share/nginx/html/example.com;
    root        $base/;

    # logging
    access_log  /var/log/nginx/access.log combined buffer=512k flush=1m;
    error_log   /var/log/nginx/error.log warn;

    # index.php
    index       index.php;

    # index.php fallback
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # handle .php
    location ~ \.php$ {
        fastcgi_pass                  php:9000;

        # 404
        try_files                     $fastcgi_script_name =404;

        # default fastcgi_params
        include                       fastcgi_params;

        # fastcgi settings
        fastcgi_index                 index.php;
        fastcgi_buffers               8 16k;
        fastcgi_buffer_size           32k;

        # fastcgi params
        fastcgi_param DOCUMENT_ROOT   $realpath_root;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param PHP_ADMIN_VALUE "open_basedir=$base/:/usr/lib/php/:/tmp/";
    }
}

相关问题