【Docker实战】分离nginx容器以及php容器
这是一次分离php容器环境,以及nginx容器环境的试验,结果稍稍令人满意。为什么要分离php,nginx环境我的开发环境,一直以来都是php,nginx一起安装的。那么既然使用容器,就希望着将各个服务独立出来。而且本着一切从简的原则,服务是有必要拆分出来的,因为不拆分的话,即将面对每一个新项目部署,都必须新配置一个default.conf。而如果nginx独立出来的话,有新项目了,我只需要修..
这是一次分离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;
}
更多推荐
所有评论(0)