使用Docker将Apache、MySQL和PHP容器化

4
我一直在搜索网络和阅读手册,但似乎无法理解我的Docker设置出了什么问题。
目标是将Apache、PHP和MySQL容器化,使它们能够根据每个项目进行自定义。部署堆栈的唯一依赖应该是docker。所有其他依赖项/操作都应该能够通过Dockerfile构建/运行。
从我的Apache + MySQL + PHP堆栈通过docker-compose.yml文件 - 我想要将一个index.php页面定位到成功呈现Hello Docker!以及所有可用数据库列表。
问题在于,当我在浏览器中访问docker.dev/index.php时,除了查看PHP源代码外,无法运行PHP代码。这是我看到的内容:
<?php

/**
 * This file:
 *     Has not been tested
 *     Does not use prepared statements
 *     Is for Proof of Concept only!
 */

$host = '127.0.0.1';
$user = 'root';
$pass = 'docker';

$conn = new mysqli($host, $user, $pass);

$sql = 'show databases';
$results = $conn->query($sql);

?>

<h1>Hello Docker!</h1>

<ul>
    <?php while ($row = $results->fetch_assoc()) : ?>
        <li><?= $row['Database'] ?></li>
    <?php endwhile ?>
</ul>

我的理解(可能有误)是Apache正确处理虚拟主机,但不知道如何通过Apache PHP模块加载PHP文件。
我已经设置了Apache依赖于PHP,并通过网络将它们连接起来(还有MySQL),但显然我漏掉了某些东西,否则一切都应该按照我的意愿工作。
我在github上创建了一个仓库,可以通过几个简单的命令测试我的设置。
git clone https://github.com/dambrogia/docker-testing.git
cd docker-testing
docker-compose up -d

你还需要在你的主机上的hosts文件中添加docker.dev到127.0.0.1。
当我访问docker.dev/index.php时,如何呈现PHP而不是查看源代码?
如果可能的话,我不想使用PHP和Apache组合镜像。 我想要三个单独的容器 - PHP,Apache,MySQL。

不想让Apache和PHP捆绑在一起有什么特别的原因吗? - Nigel Ren
我不确定这是否完全可能。但是对于Nginx、PHP来说,它们可以有单独的容器。 - Alex Kapustin
1
@NigelRen - 因为我有时会为不同的项目使用不同版本的PHP,这取决于需要完成什么任务。我不想被限制在一个静态的设置中。我希望我的设置在这方面是动态的,这在我看来就是Docker的全部意义。感谢您的回复!非常感激! - domdambrogia
1
@AlexKapustin 你是什么让你相信这是不可能的?你能提供文档、链接或详细说明你的任何一个观点吗?感谢您的回复!非常感谢! - domdambrogia
我问的原因是,如果您安装了许多标准PHP容器中的任何一个版本,它们都已经安装了Apache。您只需要启动所需的任何PHP容器即可。但是,由于这个容器已经包含了您想要作为不同容器的Apache,因此我才会提出这个问题。 - Nigel Ren
3个回答

4

如果您使用PHP,并且希望每个容器只有一个进程,则我建议使用Nginx并使用PHP-FPM,因为相对于Apache来说,这种设置方式的配置要容易得多(至少这是我的经验)。

您需要确保在Nginx和PHP容器之间有一个共享卷。在该卷中,将拥有您的index.php文件。以下是一个粗略的docker-compose.yml示例:

services:
  php7:
    image: "php:7.1.10-fpm"
    container_name: "prefix-php"
    volumes:
      - "./your/local/dir:/var/www/html"
  nginx:
    image: "nginx:1.13.6"
    container_name: "prefix-nginx"
    ports:
      - "80:80"
      - "443:443"
    links:
      - "php7"
    volumes:
      - "./your/local/dir:/var/www/html"

在存放docker-compose.yml文件的目录下,执行以下命令:

$ docker-compose -p prefix

"prefix"的原因是为了为您的容器创建项目分组,以避免与其他容器名称冲突。
自然而然,您需要一个指向 /var/www/html 的 nginx 站点配置。对于 php-fpm 容器的配置要求很少或几乎没有。
关于 nginx 配置的一个侧面说明。上述 docker-compose.yml 没有在 nginx 配置中引用 php 容器是不完整的。这将看起来像是这样(大致如此): "
server {
    listen 80 default_server;

    # ...more config, like root, index, server_name, etc

    location ~* \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass prefix-php:9000; # Note the container name here.
        fastcgi_index index.php;
        fastcgi_hide_header X-Powered-By;
        fastcgi_read_timeout 300s;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # ...more rules
}

你会注意到我将容器命名为 "php7",实际上你可以在这个docker-compose.yml文件中添加另一个 "php5" 容器,这样就可以定义使用不同版本PHP的nginx站点,所有运行在相同docker-compose设置中。
我知道这并没有直接回答你的问题,因为它没有使用apache解决问题,但这是一个值得考虑的替代方案。
希望这至少能给你提供一些想法来帮助解决你的设置。

2
感谢您详细的回答,@AlexKapustin 之前也推荐过 nginx,所以我深入了解了一下 nginx。我使用了您在这里推荐的相同设置,并成功地使其工作,因此您提供的方案绝对是可行且有前途的解决方案。我从 nginx 中学到的知识(以及代理到 :9000 的 fpm),目前正在将其应用于 Apache 设置,并取得了更多的成功。我很快就会有一个更新的解决方案。感谢您的回复,它肯定也可以帮助其他人! - domdambrogia
有趣的是,Dave,nginx容器如何从您的配置中知道要将PHP请求转发到哪个容器?我看到有一个“链接”条目,但据我所知,这只是让Docker Compose知道启动服务的顺序。 - halfer
4
@halfer 我给dave点了赞,应该可以让他得到+10的评分。他确实指导了我正确使用nginx-1,但我的原始问题是关于apache的。重点是使用PHP FPM并将Apache请求代理到PHP FPM容器中的PHP文件。他的回答很有建设性,帮助了我的调试过程(如果没有他,我可能找不到解决方案,因此点了赞)。但我自信地认为我的答案才是正确的答案。我的意图不是为了帮助/伤害任何人的声誉,而是为了让这些信息对其他正在寻找解决方案的人更加广泛地可用。 - domdambrogia
1
@halfer 我刚刚编辑了我的答案,包括一个小的nginx站点配置示例,演示了通过名称使用php容器。由于links:配置,nginx容器“知道”php容器的存在。Docker会添加和管理/etc/hosts记录,以便链接的容器可以进行通信。对于阅读此答案的人来说,请注意。答案中包含了“version 2”的docker-compose,但是“version 3”建议使用networks:而不是links: - Dave Goodchild
1
@domdambrogia 不用客气,很高兴能帮到你。我明白这不是你想要的答案,也同意你的答案是正确的。 - Dave Goodchild
显示剩余2条评论

2
我已经解决了这个问题,并创建了一个仓库,供对更深入的解释或概念证明感兴趣的任何人使用。
请查看我的仓库:https://github.com/dambrogia/docker-testing TL; DR
我使用的方法是将所有Apache请求代理到任何.php文件通过fcgi://php:9000连接到PHP-FPM。端口9000是默认值。
您可以在此处查看Apache设置的操作过程。 设置中的/var/www/html/$1部分是文件在PHP容器内映射的位置。

-2

你可能遇到了“容器应该只做一件事”的梗,这没问题,但这并不意味着你必须将其拆分到这个程度。在Docker中,LAMP容器是非常正常的,我不知道是否有人尝试过拆分Apache和PHP - 我认为这是浪费工程力量。

正如你所说,你希望能够运行不同版本的PHP。这完全没有问题,你应该在Dockerfile中进行自定义。如果你的目的是构建一组服务可以继承的容器,那么你可以简单地拥有一个基本的Apache容器,在其中添加PHP以继承Dockerfile

我运行一组微服务,它们使用5.6和7.0的混合版本。它们都继承自一个非常简单的alpine(不同版本:3.5、3.6和最新版本,即将成为3.7)。将我的Dockerfile要求复制粘贴到顶部大约需要15分钟,再加上一些我可能会做的容器调整。因此,如果你的目标是一个可直接运行的容器集合,我不确定你实际上会节省多少时间。

话虽如此,如果你真的想追求这个,你可以研究一下Piwik使用的机制。我不太熟悉它,但PHP容器提供了FastCGI服务,需要由另一个容器中的Web服务器代理。


哦,亲爱的,这篇帖子似乎不太受欢迎。有人愿意提供一些反馈吗? - halfer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接