使用docker的多个nginx/php应用程序的体系结构


architecture for multiple nginx/php apps using docker

我一直在vps上直接在单个nginx/php-fpm安装上运行我的大多数应用程序。我决定试试docker,已经玩了一个星期了。我读过所有可能的东西,相信我理解它的概念。

但我无法想象有这么多nginx、php和db的实例。

我接受了一件事,那就是我想要1 db,所以这很容易:

mariadb:
  image: mariadb:latest
  container_name: mariadb
  ports:
    - "127.0.0.1:3306:3306"
  restart: always
  environment:
    MYSQL_ROOT_PASSWORD: xxxxx
  volumes:
    - /srv/mysql:/var/lib/mysql

我还发现nginx代理和nginx证书的工作方式类似于魅力:

nginx-proxy:
  image: jwilder/nginx-proxy
  container_name: nginx-proxy
  ports:
    - "80:80"
    - "443:443"
  restart: always
  volumes:
    - /srv/certs:/etc/nginx/certs:ro
    - /var/run/docker.sock:/tmp/docker.sock:ro
    - ./vhost.d:/etc/nginx/vhost.d
    - /usr/share/nginx/html

nginx-certs:
  image: jrcs/letsencrypt-nginx-proxy-companion
  container_name: nginx-certs
  volumes:
    - /srv/certs:/etc/nginx/certs:rw
    - /var/run/docker.sock:/var/run/docker.sock:ro
  volumes_from:
    - nginx-proxy

这真是太棒了。但是我该如何处理实际的应用程序容器呢?

我想把内存使用率保持在最低限度,所以建议使用

  1. 1个php-fpm容器,内部有多个卷和多个nginx服务器
  2. 1个nginx服务器和多个php-fpm容器
  3. 每个项目有一个容器,并将nginx/php-fpm保存在该容器中
  4. X个nginx容器+X个php-fpm容器。X数量的应用程序

有什么想法吗?

每个主机只需要一个nginx容器,并使用它来平衡php容器之间的负载。如果你在nginx容器上正确设置了重启策略,它应该一直在运行,nginx可以处理很多负载,所以只有一个应该是好的。

当你有多个nginx时,管理起来也会变得更困难,因为一次只有一个容器可以绑定到端口80和443,在这种情况下,你需要在两个nginx容器前面有一些东西来平衡它们之间的负载。如果你想要冗余,你可以添加另一个具有相同设置的主机,即主机之间的负载平衡。

1个数据库容器,其中包含用于数据的卷是很好的。

至少有一个php容器,最好是多个,但取决于您的负载。如果您计划在运行时更改容器中的数据(php文件)(不推荐),请确保使用卷,并在所有php容器之间共享。

在php容器之间保持nginx负载平衡,并确保php容器的重启策略设置正确。

如果你需要更新php容器映像,如果你有多个,这会让你更容易,然后你可以在没有停机的情况下进行滚动升级。

  1. 下拉新图像
  2. 停止php1容器,从新映像开始
  3. 停止php2容器,从新映像开始

完成了无停机的滚动升级。

此设置适用于一个或多个站点。唯一的区别是nginx将根据主机名处理到正确php容器的代理。

因此,您总是有1个nginx,但php容器会根据您托管的站点数量而增长。

我从未使用过php-fpm,但我认为这里的文档会对您有所帮助:https://hub.docker.com/r/bitnami/php-fpm/他们解释了如何在一个单独的容器中设置一个nginx,以服务器来自"裸"php fpm容器的内容,您只需要对每个php fpm集装箱重复该步骤,但保持相同的nginx容器。解决方案2似乎是可行的,nginx代理既可以是代理,也可以是前端(将conf放在一个地方),所以nginx proxy+nginx certs+N php fpm

顺便说一句,你应该使用基于高山的图像,它们小得离谱,而且只提供你需要的东西,比如:https://hub.docker.com/r/yavin/alpine-php-fpm/

编辑

我做了一些测试。您可以为nginx代理为每个虚拟主机定义一个自定义conf。php容器收到了请求,但随后我得到了一个502错误。自定义conf位于/etc/nginx/vhost.d文件夹中,并命名为myphp.local(myphp.local是php容器的虚拟主机),它只包含一个位置指令:

location ~ '.php$ {
   fastcgi_pass myphp.local:9000;
   fastcgi_index index.php;
}

自动生成的nginx代理的default.conf看起来像:

upstream myphp.local {
   server 172.17.0.2:9000;
}
server {
    server_name myphp.local;
    listen 80;
    include /etc/nginx/vhost.d/myphp.local;
    location / {
        proxy_pass http://myphp.local;
    }
}

对我来说,php容器应该在端口9000上接收请求。但我不熟悉php,所以我不知道问题出在哪里。我的index.php是一个简单的<?php echo "hello world!" ?>