11

We can deploy apache and php in separate docker containers and then link them.

But is there any way to install apache locally (using apt-get install apache2) and php-fpm in docker container and then link them?

Thanks

3 Answers 3

21

Yes. Since you are using php-fpm with Apache as you should (instead of mod_php), you will have something similar to this in your Docker-based Apache site configurations:

  <FilesMatch \.php$>
    SetHandler "proxy:fcgi://php-fpm-container:9000"
  </FilesMatch>

The above works when both php-fpm and apache are running in separate docker containers; php-fpm-container refers to the php-fpm container.

To run Apache on the host, and php-fpm in Docker:

So long as your Docker php-fpm container exposes port 9000 to the host, Apache won't know or care whether that is served from the host or from inside docker.

Your apache site configs will need to be modified to point at localhost:

  <FilesMatch \.php$>
    SetHandler "proxy:fcgi://localhost:9000"
  </FilesMatch>

Incidentally this is a pretty neat way to run multiple different PHP versions on one host and one Apache server. Just expose each php-fpm container on a different port (perhaps 9001, 9002 etc).

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

10 Comments

I should add, if your PHP code needs to write to the filesystem (as any PHP framework almost certainly will), your PHP containers will need mounts for those directories from your host.
I am trying to do Apache on host with PHP-fpm docker, it is giving 404 for me, I can see 404 error on docker logs (on windows UI) but I correct mount /var/ww/html to my windows folder as well. not sure why it is not working. where should I look for problem ?
Thank you so much!! I've been trying to resolve the same issue for 3 days in a row, my mind almost melted!
@SumitGupta start with the simplest possible scenarios eg start with a test.html file and prove that works; then make a one-line simple test.php file and see if that works. What framework are you using (or none)? Are you specifying the php file in the URL or relying on a .htaccess to find it?
@jeff-h test file doesn't work either. I think it has somethign to do with different folder path in Docker image and windows, in windows host it is E:\Project .. but in docker it is /var/www/html. Do you knwo where can I see the php-fpm "DOCUMENT ROOT" path > maybe it is need customization .. my individual question is here : stackoverflow.com/questions/71089127/…
|
7

Here is a guide on how to set up php-fpm in a docker container, while the host system runs Apache (and optionally: mysql, memcached, etc).

This guide is specifically tailored around setting up a development environment as opposed to for production. If running in production, you may want to investigate a method for keeping the container updated (ie: in an automated build pipeline) and configure PHP settings to be production-appropriate (ie: hiding error messages and other production configuration)

1) Create a custom Docker image

Create a new folder for your custom php-fpm image (ex: sitename-php74-fpm). Replace sitename and the php version as appropriate.

Inside, create a Dockerfile:

FROM php:7.4-fpm

# These pages may be helpful for customizing the below run lines:
# https://github.com/docker-library/docs/tree/master/php
# https://github.com/mlocati/docker-php-extension-installer

# Easy installer allows for easier dependency installation
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/

RUN                                                           \
    apt-get update &&                                         \ 
    apt-get install -y telnet &&                              \
                                                              \
    printf "                                                \n\
            [www]                                           \n\
            listen = 127.0.0.1:7474                         \n\
            php_flag[log_errors] = on                       \n\
                                                            \n\
            [global]                                        \n\
            error_log = /var/log/php74-sitename/error.log   \n\
            " >> /usr/local/etc/php-fpm.conf &&               \
                                                              \
    chmod +x /usr/local/bin/install-php-extensions &&         \
    install-php-extensions gd xdebug mysqli pdo pdo_mysql     \
        memcache bz2 zip

Customize the file as appropriate for your desired PHP version and extensions needed. Some notes:

  • I pull the telnet client because it is useful for troubleshooting connection problems, however, you could remove this.
  • As this instance is for PHP 7.4, I use port 7474 to allow multiple php fpm versions to run simultaneously
  • We log to /var/log/php74-sitename/error.log, which we will set up in the subsequent steps
  • Reminder that if you are doing this in production, you should definitely customize this as otherwise it will show errors to the browser, also.
  • I listen on 127.0.0.1 only to prevent other devices on the network/internet from connecting to php-fpm (if you only specify a port, it will listen on all interfaces).

Now build the docker image with docker build -t sitename-php74-fpm .

2) Host system configuration

Prerequisite: I will assume you already have Apache set up and serving some static paths. If not, please do that first before continuing.

Install and enable fcgi for apache:

apt-get install libapache2-mod-fcgid
a2enmod proxy_fcgi

Update Apache configuration

Update the configuration for the site that should use php-fpm (ex: /etc/apache2/sites-enabled/default-ssl.conf:

<VirtualHost _default_:443>
    ServerAdmin webmaster@localhost

    DocumentRoot /path/to/website
    
    ...

    <FilesMatch \.php$>
        SetHandler "proxy:fcgi://127.0.0.1:7474"
    </FilesMatch>

</VirtualHost>

This will allow Apache to forward the request to Docker. Restart Apache /etc/init.d/apache2 restart

Make log folder

mkdir /var/log/php74-sitename
chown www-data:www-data /var/log/php74-sitename

3) Run Docker

Start the php-fpm server:

docker run \
  --user 33:33 \
  --network host \
  --restart always \
  --detach \
  --name sitename-php74-fpm \
  --volume=/path/to/web:/path/to/web \
  --volume=/var/log/php74-sitename:/var/log/php74-sitename \
  sitename-php74-fpm

Notes:

  • I have php-fpm run as www-data (user/group 33 on my system). This matches Ubuntu's default configuration, however, you could run it as another user if you prefer. Make sure it has proper access to your web folder.
  • I use host networking so php-fpm can easily access mysql and memcache. An alternate method would be -p 127.0.0.1:7474:7474 to share the php-fpm port, and --add-host=host.docker.internal:host-gateway to share the host's ports. In that case, you'd need to have your app connect to host.docker.internal instead of localhost, and update user permissions in mysql for the docker IP.
  • The first volume is the path to your website -- it's necessary to share it with the container so it can read your site files.
  • The second volume is the log path.

You should now be able to access your PHP website, though you might get some MySQL errors (see below MySQL section).

Appendix: Troubleshooting

It can be challenging to pinpoint where problems arise inside or outside the container, so here are some general troubleshooting tips and tools.

Docker output -- php-fpm's access log

Checking the docker instance can give some hints, especially for Apache connecting to php-fpm. Run this in a window while trying to access your site:

docker logs --follow sitename-php74-fpm

It should output access log information as you refresh the page.

php-fpm's error Log

You can check logs where you specified them earlier (ie: /var/log/php74-sitename/error.log)

Verifying php-fpm's file access

Enter the container as follows and check it has appropriate permissions:

docker exec -it sitename-php74-fpm /bin/bash
ls -lth /path/to/web
cat /path/to/web/index.php

MySQL connection path adjustment

If you've previously been connecting to localhost, you will likely find you are now getting a 'File Not Found' error. This is because the PHP MySQL client actually aliases that to a socket connection. To work around this, simply update your app config to connect to 127.0.0.1 instead of localhost.

Verifying php-fpm's network access

This simple test ensures php-fpm can connect to MySQL (or some other service running on the host). A more advanced version could install the mysql client, though it is not included in Debian's repos so a custom install would be needed.

Enter the container as follows and check basic port access to mysql:

docker exec -it sitename-php74-fpm /bin/bash
telnet 127.0.0.1 3306

Comments

3

you can build your own image and in the Dockerfile you can apt install ...

but there is also an official image with apache + php-fpm here: https://hub.docker.com/_/php

so you dont have to. its ready to go.


but i believe it could work by exposing your php-fpm port and configuring your apache FastCgiExternalServer to this port instead of a unix socket.

3 Comments

I don't think there is an official php-fpm+apache image, you'll have to brew it yourself I'm afraid
@FilidorWiese Of course there are. They're right there in the repository; see e.g. hub.docker.com/_/php?tab=tags&page=1&name=apache
@larsks there are either apache (with built-in php) or php-fpm, but not two in one

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.