简体   繁体   English

使用Docker容器化Apache,MySQL和PHP

[英]Containerizing Apache, MySQL and PHP With Docker

I've been searching the web and reading manuals and I just can't seem to get my head around what is wrong with my Docker setup. 我一直在网上搜索并阅读手册,但似乎无法理解Docker设置的问题。

The Goal 目标

To container-ize Apache, PHP and MySQL allowing them to be customized on a per-project basis. 为了对Apache,PHP和MySQL进行容器化,允许在每个项目的基础上对其进行自定义。 The only dependency to deploy the stack should be docker. 部署堆栈的唯一依赖关系应该是docker。 All other dependencies / actions should be able to be able to be built / run via Dockerfile . 所有其他依赖项/动作都应该能够通过Dockerfile构建/运行。

The Proof of Concept 概念证明

From my Apache + MySQL + PHP stack via docker-compose.yml file - I'd like to target an index.php page to successfully render Hello Docker! 从我的Apache + MySQL + PHP堆栈通过docker-compose.yml文件-我想定位一个index.php页面以成功呈现Hello Docker! along with a list of all available databases. 以及所有可用数据库的列表。

The Problem 问题

When I visit docker.dev/index.php in my browser, rather than the PHP code running, I can only view the PHP source code. 当我在浏览器中访问docker.dev/index.php而不是运行PHP代码时,只能查看PHP源代码。 This is what I see: 这是我看到的:

<?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>

My understanding (which may be mistaken) is that Apache is correctly handling the virtual host, but doesn't know to load the PHP file through an Apache PHP Module. 我的理解(可能是错误的)是Apache正确地处理了虚拟主机,但不知道如何通过Apache PHP模块加载PHP文件。

I have setup Apache to depends_on PHP and I have linked them through a network (along with MySQL) but obviously I'm missing something or else everything would be working just as I want it to). 我已经将Apache设置为depends_on PHP,并且已通过network (以及MySQL)将它们链接在一起,但是显然我缺少了某些东西,否则一切都会按我的意愿进行。

I have created an repo on github that should allow you to test my setup with a few simple commands: 我在github上创建了一个存储库,该存储库应允许您使用一些简单的命令来测试我的设置:

git clone https://github.com/dambrogia/docker-testing.git
cd docker-testing
docker-compose up -d

You will also have to edit add docker.dev to 127.0.0.1 in your hosts file on your host machine! 您还必须在主机上的hosts文件中将add docker.dev添加到127.0.0.1

How can I render the PHP rather than read the source of it when I visit docker.dev/index.php ? 访问docker.dev/index.php时如何呈现PHP而不是读取源代码?

I do not want to use a PHP and Apache combined image if at all possible. 如果有可能, 我不想使用PHP和Apache组合的映像。 I would like to have three separate containers - PHP, Apache, MySQL. 我想要三个独立的容器-PHP,Apache,MySQL。

If you're working with PHP, and you wish to have a single process per container, then I do recommend using Nginx and using PHP-FPM, as it's significantly easier to configure than Apache for this type of setup (at least that's what I've found). 如果您正在使用PHP,并且希望每个容器有一个进程,那么我建议您使用Nginx和PHP-FPM,因为对于这种类型的安装,它比Apache的配置要容易得多(至少这就是我要做的)已经找到)。

You need to ensure you have a common shared volume to both the Nginx and PHP containers. 您需要确保Nginx和PHP容器具有相同的共享卷。 In that volume you would have your index.php . 在该卷中,您将拥有index.php Here is a crude example docker-compose.yml: 这是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"

You would then run this following command in the directory where the docker-compose.yml file is: 然后,您将在docker-compose.yml文件所在的目录中运行以下命令:

$ docker-compose -p prefix

The reason for "prefix" is that you create a project grouping for your containers so as not to clash with other container names. 使用“前缀”的原因是您为容器创建了一个项目分组,以免与其他容器名称冲突。

Naturally you then need an nginx site configuration that points to /var/www/html . 当然,您自然需要一个指向/var/www/html的nginx站点配置。 You will have little to no configuration requirements for the php-fpm container. 您几乎没有对php-fpm容器的配置要求。

A side note regarding the nginx configuration. 关于nginx配置的附带说明。 The above docker-compose.yml is incomplete without the referencing of the php container within the nginx configuration. 在nginx配置中未引用php容器的情况下,上述docker-compose.yml是不完整的。 This would look like so (roughly speaking): 看起来像这样(大致而言):

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
}

You'll notice I named the container "php7", you could actually add another "php5" container to this docker-compose.yml and then that allows you to define nginx sites that use different versions of PHP all running on the same docker-compose setup. 您会注意到我将容器命名为“ php7”,实际上您可以docker-compose.yml添加另一个“ php5”容器,然后允许您定义使用不同版本PHP的nginx站点,这些站点均在同一docker-上运行撰写设置。

I appreciate that this doesn't directly answer your question as it doesn't solve it using apache, but it's an alternative to consider. 我很高兴这不能直接回答您的问题,因为它不能使用apache来解决,但是可以考虑。

Hopefully this at least gives you ideas to help solve your setup. 希望这至少可以为您提供一些想法,以帮助您解决设置问题。

I solved this question and created a repo for anyone who is interested a more in depth explanation or proof of concept. 我解决了这个问题,并为对进一步解释或概念验证感兴趣的任何人创建了一个回购协议。

Please see my repo: https://github.com/dambrogia/docker-testing 请参阅我的仓库: https : //github.com/dambrogia/docker-testing

TL; TL; DR DR

The approach I used to solve this was proxying all apache requests to any .php files to PHP-FPM via fcgi://php:9000 . 我用来解决此问题的方法是通过fcgi://php:9000所有.php文件的所有apache请求代理到PHP-FPM。 Port 9000 is the default 默认端口9000

You can see this Apache setting in action here . 您可以在此处查看此Apache设置的实际操作。

The /var/www/html/$1 portion of the setting is where the files are mapped within the PHP container. 设置的/var/www/html/$1部分是在PHP容器内映射文件的位置。

You've encountered the meme of "containers should do one thing", which is fine, but it does not mean that you ought to split it down this far. 您曾经遇到过“容器应该做一件事”的模因,这很好,但这并不意味着您应该将其分解为如此。 A LAMP container is perfectly normal in Docker-land, and I don't know what efforts have been made to split up Apache and PHP - I suspect it is waste of engineering effort. LAMP容器在Docker-land上是完全正常的,而且我不知道为拆分Apache和PHP付出了什么努力-我怀疑这是浪费工程精力。

As you say, you wish to be able to run different PHP versions. 如您所说,您希望能够运行不同的PHP版本。 That's absolutely fine, and you should customise that in your Dockerfile . 没关系,您应该在Dockerfile自定义。 If your intention is to build a set of containers that your services can inherit from, then you could simply have a base Apache container, upon which you add PHP in inheriting Dockerfile s. 如果您打算构建一组可以从中继承服务的容器,那么您可以简单地拥有一个基本的Apache容器,在该容器上您可以在继承Dockerfile的过程中添加PHP。

I run a set of microservices, which use a mix of 5.6 and 7.0. 我运行了一组微服务,它们混合使用5.6和7.0。 They all inherit from a very plain alpine (of varying versions: 3.5, 3.6 and latest, which will become 3.7). 它们都继承自非常普通的alpine (版本不同:3.5、3.6和最新版本,将成为3.7)。 It takes about 15 minutes to copy-and-paste my Dockerfile requirements on top, plus a bit of container tweaking that I'd probably do anyway. 复制和粘贴我的Dockerfile需求大约需要15分钟,再加上我可能会做的一些容器调整。 So, if a ready-to-run set of containers is your aim, I am not sure how much time you'd be saving in practice. 因此,如果您的目标是准备运行的一组容器,那么我不确定您将在实践中节省多少时间。

That all said, if you really want to pursue this, you could look into the mechanism that Piwik uses. 综上所述,如果您真的想追求这一点,则可以研究Piwik使用的机制。 I am not familiar with it, but the PHP container serves FastCGI, and that needs to be proxied by a web server, in another container. 我不熟悉它,但是PHP容器提供FastCGI,而这需要由Web服务器在另一个容器中进行代理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM