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

时间:2015-04-27 21:08:34

标签: php nginx docker dockerfile docker-compose

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

问题是php脚本不起作用。也许php-fpm配置不正确。 这是源代码,位于我的repository中。这是文件function dummy(next) { err = True; if(err) return next(new Error('No handler error')); return next(null, data); }

docker-compose.yml

nginx: build: . ports: - "80:80" - "443:443" volumes: - ./:/var/www/test/ links: - fpm fpm: image: php:fpm ports: - "9000:9000" 我用它来构建基于nginx的自定义图像:

Dockerfile

最后,这是我自定义的Nginx虚拟主机配置:

FROM nginx

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

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

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

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

来自项目根目录。

7 个答案:

答案 0 :(得分:71)

我知道这是一个老帖子,但我遇到了同样的问题,无法理解为什么你的代码不起作用。 经过大量的测试后,我发现了原因。

搬运工-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/

答案 1 :(得分:29)

不要在nginx配置中硬编码容器的ip,docker链接会将链接机器的主机名添加到容器的hosts文件中,你应该能够通过主机名ping。

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

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

see docker linking docs(这就是后台使用的内容)

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

  

<强>链接   

links:
 - db
 - db:database
 - redis
     

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

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

     

完整网址,例如DB_PORT = TCP://172.17.0.5:5432

     

name_PORT_num_protocol

     

完整网址,例如DB_PORT_5432_TCP=tcp://172.17.0.5:5432

     

name_PORT_num_protocol_ADDR

     

Container的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

答案 2 :(得分:21)

如前所述,问题是fpm容器无法看到这些文件。但是,要在容器之间共享数据,建议的模式是使用仅数据容器(如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服务相关联的卷。然后是数据服务的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,即fpm:9000感谢compose定义的主机名和SCRIPT_FILENAME)。

答案 3 :(得分:14)

新答案

Docker Compose已更新。他们现在有一个version 2 file format

  

Compose 1.6.0+支持版本2文件,并且需要版本为1.10.0 +的Docker Engine。

他们现在支持Docker的网络功能,在运行时设置一个名为 myapp_default的默认网络

their documentation,您的文件将如下所示:

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撰写并希望获得相关信息的用户,我保留了以下内容。

当我试图找到这个问题的答案时,我一直在谷歌上绊倒这个问题,但由于Q / A强调docker-compose(在撰写本文时只有对docker网络功能的实验支持)。所以这是我对所学知识的看法。

Docker最近有deprecated its link功能支持其networks feature

因此,使用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;。多数民众赞成在端口php-fpm上联系容器9000。将容器添加到Docker桥接网络时,它们都会自动获得主机文件更新,并根据其IP地址放入容器名称。因此,当Nginx发现它会知道要联系之前命名为php-fpm并分配给mynetwork Docker网络的PHP-FPM容器时。

您可以在Docker容器的构建过程中或之后添加该Nginx配置。

答案 4 :(得分:7)

正如之前的答案已经解决了,但应该非常明确地说明:php代码需要存在于php-fpm容器中,而静态文件需要存在于nginx容器中。为简单起见,大多数人都将所有代码都附加到两者上,正如我在下面所做的那样。如果未来,我可能会在我自己的项目中分离出代码的这些不同部分,以尽量减少哪些容器可以访问哪些部分。

使用此最新启示更新了我的示例文件(谢谢@alkaline)

这似乎是docker 2.0转发的最低设置 (因为在docker 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容器可以访问的那些文件。虽然仍然拥有所有的php 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();

并且不要忘记更新您的主机文件:

127.0.0.1 site.local.[YOUR URL].com

并运行你的docker-compose up

$docker-compose up -d

并尝试使用您喜爱的浏览器中的网址

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

答案 5 :(得分:6)

我认为我们还需要给fpm容器提供音量,不是吗?所以=&gt;

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

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

  

[错误] 6#6:* 4 stderr发送的FastCGI:&#34;主要脚本未知&#34;从上游读取响应头时,客户端:172.17.42.1,服务器:localhost,请求:&#34; GET / HTTP / 1.1&#34;,上游:&#34; fastcgi://172.17.0.81:90​​00&#34 ;,主持人:&#34; localhost&#34;

答案 6 :(得分:0)

对于其他获得

的人
  

Nginx 403错误:[文件夹]的目录索引被禁止

"use strict"; angular.module('myApp',[]); angular.module('myApp').controller('MainController', function($scope) { var vm = this; vm.selectCategory=selectCategory; vm.options = { imageList:[ { name: 'Fluffy', images: 'images/Fluffy.jpeg', caption: 'cuddly', category: 'lake' }, { name: 'Blacky', images: 'images/blacky.jpeg', caption: 'cuddly', category: 'lake' }, { name: 'Tabby', images: 'images/tabby.jpeg', caption: 'sleepy', category: 'family' }, { name: 'Cleo', images: 'images/Cleo.jpeg', caption: 'sleepy', category: 'family', }, { name: 'Fluffy', images: 'images/Fluffy.jpeg', caption: 'cuddly', category: 'family' }, { name: 'Blacky', images: 'images/blacky.jpeg', caption: 'cuddly', category: 'lake' }, { name: 'Tabby', images: 'images/tabby.jpeg', caption: 'sleepy', category: 'lake' }, { name: 'Cleo', images: 'images/Cleo.jpeg', caption: 'sleepy', category: 'lake' } ], }; function selectCategory(pos) { vm.selectedCategory = pos; }; });正常工作时使用<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <!DOCTYPE html> <html ng-app = "myApp"> <head> <meta charset="UTF-8"> <title>AngularJS Picture Gallery</title> <div ng-controller = "MainController as vm"> <div class = "container"> <div class = "row"> <div class = "col-md-12" id ="myBtnContainer"> <button class = "btn active" ng-click = "vm.selectCategory('all')"> Show all </button> <button class = "btn active" ng-click = "vm.selectCategory('lake')"> Lake Pics </button> <button class = "btn active" ng-click = "vm.selectCategory('family')"> Family Pics </button> <button class = "btn active" ng-click = "vm.selectCategory('kids')"> Kid Pics </button> </div> <div class = "row"> <div class = "col-md-12"> <div class = "thumbnail"> </div> </div> <div ng-repeat = "image in vm.options.imageList | filter: { category: vm.selectedCategory }"> <img ng-src="{{image.images}}" hspace ="15" vspace ="10"> </div> </div> </div> </div> </body> </html>并且在index.php的站点配置服务器块的索引中包含index.html时,

index.php

确保位于sites-enabled的nginx.conf文件实际上将您的站点配置加载到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