使用 Docker 容器隔离 PHP

2025-06-07

使用 Docker 容器隔离 PHP

Docker 是一项很棒的技术。它能让你很好地搭建开发环境或测试新软件,而且不会阻塞你的系统。

我正在尝试使用 Docker、Apache 和 PHP 来运行一些网页。如何才能轻松地切换 PHP 版本,而不会阻塞本地计算机或创建多个 Docker 镜像/Vagrant 容器?我相信很多开发人员都能轻松找到解决方案,但我必须承认,我在概念化容器解决方案方面确实遇到了困难。层层抽象会造成思维障碍,我相信我并非唯一遇到这种情况的人。

我突然想到,Apache/PHP 并不符合 Docker 的“每个容器一个进程”原则。PHP 和 Apache 紧密结合,以至于在关注点分离方面,根本行不通。

我非常希望我的 Web 服务器容器与编程语言能够完全隔离。切换到 NGINX 和 PHP-FPM 后,隔离更加清晰,让我们能够轻松切换语言版本。如果您的旧网站需要不同的版本,或者您想在升级之前试用一下网站,那么这将会非常方便。

设置

因此计划是,当请求发送到test5.com/index.php url 时,Nginx 容器将传递请求以将index.php处理到运行 PHP 5 的容器中,显然对于test7.com/index.php和 PHP 7 也是如此。

首先,向/etc/hosts文件添加 2 个条目:

127.0.0.1 test5.com
127.0.0.1 test7.com 
Enter fullscreen mode Exit fullscreen mode

这些将是我们用来访问 Nginx 容器的地址。

从 GitHub 下载或克隆docker-php-isolation-example仓库到系统上合适的位置。所有命令都将在此文件夹中通过 CLI 运行。

文件夹结构比较简单:

  • webroot - 不言自明的文件夹,其中包含一个名为的文件index.php,其中包含phpinfo()命令。

  • site.conf ——Nginx 站点配置文件。

  • docker-compose.yml -docker 设置配置文件。

docker -compose.yml文件设置了 3 个容器,全部基于 Alpine Linux 镜像,因此容器的总大小只有 120Mb。

version: '2'
services:
    web:
        image: nginx:alpine
        ports:
            - "8080:80"
        volumes:
            - ./webroot:/var/www/html
            - ./site.conf:/etc/nginx/conf.d/site.conf
        links:
            - php7
            - php5
    php7:
        image: php:7-fpm-alpine
        volumes:
            - ./webroot:/var/www/html
    php5:
        image: php:5-fpm-alpine
        volumes:
            - ./webroot:/var/www/html
Enter fullscreen mode Exit fullscreen mode

主容器是 Nginx 代理,它是唯一一个拥有外部端口(8080)的容器。该容器将所有有效请求代理到另外两个容器,一个运行 php 7 php-fpm,另一个运行 php 5 php-fpm,端口号为 9000。

php隔离图

webroot文件夹在所有 3 个容器之间共享,Nginx 需要它来提供任何非 PHP 文件,而 PHP 容器需要访问 PHP 文件。

site.conf文件包含定义 Nginx 如何处理请求:

server {
    listen 80;
    index index.php;
    server_name test7.com;
    root /var/www/html/;

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php7:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

server {
    listen 80;
    index index.php;
    server_name test5.com;
    root /var/www/html/;

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php5:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}
Enter fullscreen mode Exit fullscreen mode

我确信有办法将这两个地址合并为一个并使用正则表达式,但生命太短暂了。

运行它

从 CLI 导航到下载存储库的文件夹并输入docker-compose up -d

如果镜像尚未保存在本地,这将下载镜像并启动容器。完成后,输入以下命令docker ps以确保 3 个容器正在运行。

因此打开您选择的浏览器并输入 test5.com:8080,您应该会看到 PHP 5 的 phpinfo()。

屏幕截图-2017-10-07-08.04.07

接下来,输入 test7.com:8080,您应该会看到 phpinfo(),您猜对了,就是 PHP 7!

屏幕截图-2017-10-07-08.03.49

就这样,我们可以定义使用哪个版本的 PHP 来处理相同的 index.php 文件,享受数小时的乐趣……

整理

够刺激了吗?要关闭正在运行的容器,请输入docker-compose down,这将关闭并删除容器。

如果要删除已下载的图像,请输入docker images然后docker rmi IMAGE ID,例如将删除 ID 为4fe1b7f08eb1、8b057b9de5801b95155d2daf 的3docker rmi 4fe1b7f08eb1 8b057b9de580 1b95155d2daf幅图像

最后

将 PHP 作为一种“软件即服务”来提供,这个想法可能有点不起眼,但我觉得它真的很酷。能够隔离编程语言的不同版本让我非常感兴趣,我可能会尝试在未来的项目中融入这一点。

使用 Docker 容器隔离 PHP 于 2017 年 7 月 10 日首次出现在我的博客网站上。

文章来源:https://dev.to/johnmccuk/isolated-php-with-docker-containers-4epn
PREV
面向新手程序员的 Visual Studio Code 设置 VS Code 面向新手程序员的设置
NEXT
在 Ubuntu 24.04 上安装 PostgreSQL 17