4

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.

The Goal

To container-ize Apache, PHP and MySQL allowing them to be customized on a per-project basis. The only dependency to deploy the stack should be docker. All other dependencies / actions should be able to be able to be built / run via 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! 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. 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.

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).

I have created an repo on github that should allow you to test my setup with a few simple commands:

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!

How can I render the PHP rather than read the source of it when I visit docker.dev/index.php?

I do not want to use a PHP and Apache combined image if at all possible. I would like to have three separate containers - PHP, Apache, MySQL.

5
  • Is there any particular reason for not wanting Apache and PHP bundled together? Commented Oct 29, 2017 at 8:01
  • I'm not sure it's possible at all. But for sure it's possible for Nginx, PHP to have separate containers Commented Oct 29, 2017 at 11:32
  • 1
    @NigelRen - Because I use different versions of PHP for different projects sometimes depending on what needs to be done. I don't want to be pigeonholed into one static setup. I'd like my setup to be dynamic in that aspect, which IMO is the entire point of docker. Thanks for your replies! It's much appreciated! Commented Oct 29, 2017 at 16:56
  • 1
    @AlexKapustin What leads you to believe it's not possible? Can you provide documentation, a link or just elaborate on either of your statements? Thanks for your replies! It's much appreciated! Commented Oct 29, 2017 at 16:56
  • The reason why I ask is that if you install one of the many versions of the standard PHP containers - they have Apache already installed. All you need to do is start which ever PHP container you need. BUT as this has Apache, which your saying you wanted as a different container - hence the question. Commented Oct 29, 2017 at 16:58

3 Answers 3

4

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).

You need to ensure you have a common shared volume to both the Nginx and PHP containers. In that volume you would have your index.php. Here is a crude example 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 -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. You will have little to no configuration requirements for the php-fpm container.

A side note regarding the nginx configuration. The above docker-compose.yml is incomplete without the referencing of the php container within the nginx configuration. 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.

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.

Hopefully this at least gives you ideas to help solve your setup.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for your detailed answer, @AlexKapustin had recommended nginx earlier as well so I dove into the nginx world for a bit. I got that working with the same type of setup you have recommended here, so what you supplied is definitely a viable and promising solution. I took what I learned from nginx (along with proxying to :9000 for fpm) and I'm currently applying it to an Apache setup with some more luck. I'll have an updated solution soon. Thanks for the response, it can definitely help someone else down the road as well!
@domdambrogia: as an aside, it's worth noting that if you accept someone else's answer, they get +15 reputation, and if you accept your own, you get +0. So, while you are free to accept your own answer, would you consider accepting Dave's in preference? It seems to be in agreement with the solution you actually went with.
@halfer I upvoted dave which should give him +10. And while he did get me in the right direction with nginx - 1. My original question was for apache and 2. The key was PHP FPM and proxying apache requests for PHP files to the PHP FPM container. His answer was very constructive and helped my debugging process (I likely wouldn't have found a solution without it, hence the upvote) but I confidently think my answer is the correct answer. My intentions are not to help / hurt anyone's rep, but to contribute to making the info more widely available to anyone else who is looking.
@halfer I just edited my answer to include a small nginx site config example, which demonstrates the use of the php container, by name. Because of the links: config, the nginx container "knows" about the php container. An /etc/hosts record is added and managed by docker so that the linked containers can communicate. As a note for those reading. The answer contained "version 2" docker-compose, "version 3" however recommends using networks: instead of links:.
@domdambrogia nps, glad to have helped. I understand that it wasn't the answer you were looking for and agree that yours is the correct answer.
|
2

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

TL; DR

The approach I used to solve this was proxying all apache requests to any .php files to PHP-FPM via fcgi://php:9000. Port 9000 is the default

You can see this Apache setting in action here.

The /var/www/html/$1 portion of the setting is where the files are mapped within the PHP container.

Comments

-2

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.

As you say, you wish to be able to run different PHP versions. That's absolutely fine, and you should customise that in your 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 Dockerfiles.

I run a set of microservices, which use a mix of 5.6 and 7.0. They all inherit from a very plain alpine (of varying versions: 3.5, 3.6 and latest, which will become 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. 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. 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.

1 Comment

Oh dear, this post doesn't seem to be very popular. Would anyone like to offer some feedback?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.