这是一次分离php容器环境,以及nginx容器环境的试验,结果稍稍令人满意。

为什么要分离php,nginx环境

我的开发环境,一直以来都是php,nginx一起安装的。那么既然使用容器,就希望着将各个服务独立出来。而且本着一切从简的原则,服务是有必要拆分出来的,因为不拆分的话,即将面对每一个新项目部署,都必须新配置一个default.conf。而如果nginx独立出来的话,有新项目了,我只需要修改default.conf,然后重启nginx即可完成部署,减少了创建、配置nginx配置文件的工作,何乐而不为?

在我的博客系统中,就已经使用了nginx + golang的架构,nginx是一套独立的容器,用来转发请求到我的博客中。相对于golang这些,可以自起web服务的语言来说,采用nginx转发机制会比较简单,直接将请求转发到对应的端口即可得到服务器的响应。但是类似于php-fpm(而不是php-cli)等动态解析的web服务来说,因为不是自起的服务,而是通过php-fpm来解析php文件,所以单独的nginx转发就不可用了,而是需要特殊的配置。

如何配置

  • 构建php镜像

这里使用alpine作为基础镜像,是因为这个它只有5.5M,很迷你,没有其他冗余的工具。

FROM alpine

RUN apk update && apk add -U php php-fpm tzdata php-json php-curl

# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN sed -i '/listen = 127.0.0.1:9000/c\\listen = 0.0.0.0:9000' /etc/php7/php-fpm.d/www.conf

WORKDIR /opt
# to run php-fpm foreground by force and allow-to-run-as-root
CMD ["/usr/sbin/php-fpm7","-F", "-R"]

执行构建镜像命令,构建alpine-php:dev开发版镜像

docker build -t alpine-php:dev .
  • 拉取nginx镜像
docker pull nginx

新建或者使用 docker cp 命令复制 nginx 容器中的默认配置文件 /etc/nginx/conf.d/default.conf,内容如下


server {
    listen       80;
    server_name  api.test.com;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
        root           /opt/backend/web/;
        fastcgi_pass   alpine-prs:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

注意:

因为绑定了域名 api.test.com, 所以需要将 api.test.com 添加到本地 hosts 中。

root /opt/backend/web/ 这项配置很重要,代表是php容器中项目的入口文件。有一些博文都有提到过,nginx容器,以及php容器都需要将项目挂载到相同的目录下才能正常访问。但是经过我这次实践测试,得出的结论是,只要php容器中有项目文件就能正常访问。

fastcgi_pass alpine-prs:9000; 这项配置,代表php容器是 alpine-prs,nginx 将所有的 php 文件的解析,都转发到了 alpine-prs:9000 上解析,9000 是 alpine-prs 中 php-fpm 监听的端口。因此,在运行 nginx 容器之前,需要创建 alpine-prs 容器,并用 --link 命令参数,使 nginx 容器与 php 容器关联起来。

  • 运行容器

首先运行 alpine-prs 容器,并将项目挂载到容器中的 /opt 目录下,

docker run -t -i -d --rm --name alpine-prs -p 5010:80  -v /yunfei/project:/opt -v /yunfei/alpine/7.3/php.ini:/etc/php7/php.ini  alpine-php:dev

然后运行 nginx 容器,需要挂载我们修改过的 default.conf 到容器中,并且用 --link 参数,关联 alpine-prs 容器

docker run -t -i --rm --name nginx -p 80:80 --link alpine-prs:alpine-prs -v $PWD/default.conf:/etc/nginx/conf.d/default.conf nginx

这样就能通过 api.test.com 来请求站点了,可以在项目入口处创建 phpinfo.php 文件来做测试。

测试结果如下:

在这里插入图片描述

nginx 访问日志:

在这里插入图片描述

  • 遗留问题

从 ningx 访问日志来看,它记录的是容器自身的IP,这显然不是我们日志中想要的客户端IP。而当我加入一些代理设置后,问题仍是解决不了。希望了解这块的大牛,能提供一个好的解决方案。设置的代理如下:

location / {

    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    root   /opt/backend/web/;
    index  index.php index.html index.htm;
}
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐