【问题标题】:Multi Docker container with PHP7 fpm and nginx带有 PHP7 fpm 和 nginx 的多 Docker 容器
【发布时间】:2017-03-31 19:45:31
【问题描述】:

我在设置多 docker 容器环境时遇到问题。 这个想法很标准:

  • 一个容器运行 php-fpm
  • 另一个是 nginx 代理

我的 phpfpm Docker 文件很简单:

FROM php:7.0-fpm

# install the PHP extensions we need
RUN apt-get update && apt-get install -y libpng12-dev libjpeg-dev && rm -rf /var/lib/apt/lists/* \
    && docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \
    && docker-php-ext-install gd mysqli opcache

# set recommended PHP.ini settings
# see https://secure.php.net/manual/en/opcache.installation.php
RUN { \
        echo 'opcache.memory_consumption=128'; \
        echo 'opcache.interned_strings_buffer=8'; \
        echo 'opcache.max_accelerated_files=4000'; \
        echo 'opcache.revalidate_freq=2'; \
        echo 'opcache.fast_shutdown=1'; \
        echo 'opcache.enable_cli=1'; \
    } > /usr/local/etc/php/conf.d/opcache-recommended.ini

VOLUME /var/www/html

CMD ["php-fpm"]

Nginx 更是如此:

FROM nginx

COPY conf.d/* /etc/nginx/conf.d/

conf.d 文件夹内的位置是单个文件 default.conf

server {
    listen 80;
    server_name priz-local.com;
    root /var/www/html;

    index index.php;

    location / {
        proxy_pass  http://website:9000;
        proxy_set_header   Connection "";
        proxy_http_version 1.1;
        proxy_set_header        Host            $host;
        proxy_set_header        X-Real-IP       $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

还有 docker-compose.yml

website:
  build: ./website/
  ports:
   - "9000:9000"
  container_name: website
  external_links:
     - mysql:mysql
nginx-proxy:
  build: ./proxy/
  ports:
    - "8000:80"
  container_name: proxy
  links:
       - website:website

这种精确的设置在 AWS Elastic Beanstalk 上完美运行。但是,在我的本地 docker 上,我遇到了以下错误:

2016/11/17 09:55:36 [错误] 6#6: *1 connect() failed (111: Connection 拒绝)同时连接到上游,客户端:172.17.0.1,服务器: priz-local.com,请求:“GET / HTTP/1.1”,上游: “http://127.0.0.1:9000/”,主持人:“priz-local.com:8888” 172.17.0.1 - - [17/Nov/2016:09:55:36 +0000] "GET / HTTP/1.1" 502 575 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36(KHTML,如 Gecko)Chrome/54.0.2840.71 Safari/537.36" "-"

更新 如果我登录代理容器并尝试 curl 到另一个容器,我会得到这个:

root@4fb46a4713a8:/# curl http://website
curl: (7) Failed to connect to website port 80: Connection refused
root@4fb46a4713a8:/# curl http://website:9000
curl: (56) Recv failure: Connection reset by peer

我尝试的另一件事是:

server {
    listen 80;
    server_name priz-local.com;
    root /var/www/html;

    #index index.php;
    #charset UTF-8;

    #gzip on;
    #gzip_http_version 1.1;
    #gzip_vary on;
    #gzip_comp_level 6;
    #gzip_proxied any;
    #gzip_types text/plain text/xml text/css application/x-javascript;

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location /nginx_status {
        stub_status on;
        access_log off;
    }

    location / {
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }

    location ~ \.php$ {

        set $nocache "";
        if ($http_cookie ~ (comment_author_.*|wordpress_logged_in.*|wp-postpass_.*)) {
           set $nocache "Y";
        }

        fastcgi_pass  website:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_intercept_errors on;
        include fastcgi_params;

        #fastcgi_cache_use_stale error timeout invalid_header http_500;
        #fastcgi_cache_key $host$request_uri;
        #fastcgi_cache example;
        #fastcgi_cache_valid 200 1m;
        #fastcgi_cache_bypass $nocache;
        #fastcgi_no_cache $nocache;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        allow all;
        expires max;
        log_not_found off;

        fastcgi_pass  wordpress:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_intercept_errors on;
        include fastcgi_params;
    }
}

网站开始工作,但所有资源 (js|css|png|jpg|jpeg|gif|ico) 现在都返回403。

我错过了什么?

【问题讨论】:

  • 让我猜猜。你的本地环境是 mac?
  • 是的,不确定您是否将其称为一般问题...
  • Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) 猜测不多:p
  • 这是客户端,而不是服务器环境,兄弟……所以这仍然是一个猜测。无论如何,我知道 Windows docker 遭受容器 dns 无法像在 linux 上那样工作的问题,因为它在 vm 上运行。您必须将带有 vm ip 的容器名称添加到主机系统的 hosts 文件中。不知道,可能是mac的问题?
  • 我在 hosts 文件中有一个条目。不仅如此,从主机到 nginx 的 url 可以正确解析。是容器之间的通信有问题。

标签: php amazon-web-services nginx docker


【解决方案1】:

在与R0MANARMY 聊了很长时间并得到他的很多帮助后,我想我终于明白了问题的根源。

这里的主要问题是我没有使用 docker,因为它本来可以工作。

另一个原因是 fpm 不是网络服务器,代理到它的唯一方法是通过 fastcgi(或者可能不是唯一的,但简单的 proxy_pass 在这种情况下不起作用)。

所以,正确的设置方法是:

  1. 将代码卷安装到两个容器中。
  2. 为php脚本通过nginx配置fastcgi到php容器中
  3. 配置虚拟主机直接通过 nginx 服务静态资产。

这里有几个例子说明如何做到这一点:

http://geekyplatypus.com/dockerise-your-php-application-with-nginx-and-php7-fpm/

https://ejosh.co/de/2015/08/wordpress-and-docker-the-correct-way/

更新 添加对我有用的实际解决方案:

为了更快的周转,我决定使用 docker-compose 和 docker-compose.yml 看起来像这样:

website:
  build: ./website/
  container_name: website
  external_links:
    - mysql:mysql
  volumes:
    - ~/Dev/priz/website:/var/www/html
  environment:
    WORDPRESS_DB_USER: **
    WORDPRESS_DB_PASSWORD: ***
    WORDPRESS_DB_NAME: ***
    WORDPRESS_DB_HOST: ***
proxy:
  image: nginx
  container_name: proxy
  links:
    - website:website
  ports:
    - "9080:80"
  volumes:
    - ~/Dev/priz/website:/var/www/html
    - ./deployment/proxy/conf.d/default.conf:/etc/nginx/conf.d/default.conf

现在,这里最重要的信息是我将完全相同的代码安装到两个容器中。这样做的原因是因为 fastcgi 不能提供静态文件(至少据我所知),所以想法是直接通过 nginx 提供服务。

我的default.conf 文件如下所示:

server {
    listen 80;
    server_name localhost;
    root /var/www/html;

    index index.php;

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location /nginx_status {
        stub_status on;
        access_log off;
    }

    location / {
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass website:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        #fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_intercept_errors on;
        include fastcgi_params;
    }
}

所以,这个配置通过 php 请求代理,由 fpm 容器处理,而其他一切都取自本地安装的卷。

就是这样。我希望它会对某人有所帮助。

唯一的几个问题:

  1. 仅有时http://localhost:9080 下载 index.php 文件而不是执行它
  2. 从 php 脚本到外部世界的 cURL'ing 需要很长时间,现在甚至不知道如何调试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-08
    • 1970-01-01
    • 2018-12-13
    • 2018-01-25
    • 2021-02-23
    • 2018-07-17
    相关资源
    最近更新 更多