Running the Apache HTTP Server with PHP inside Docker
Running the Apache HTTP Server (“httpd”) with PHP inside Docker is easy. So easy that, in case you’re using httpd and PHP, you actually have no reasons not to do it. Here’s a short guide about how to do that.
1 A Vanilla Prototype
To run the Apache HTTP Server with PHP in Docker on your, say, htdocs/
directory, on port 8082, you can run the following command:
That’s it! If you try this, and it works for you, you’re done!
The command does the following:
- If the Docker image
php:apache
is not present in your machine’s local Docker registry, it will be downloaded from Docker hub. - It creates a new container based on the image
php:apache
. - It maps port
80
from the container to port8082
on your host machine. - It mounts the directory
htdocs/
from your host machine to/var/www/html
in the container.
If you’re lucky, you can now access http://localhost:8082/ and see your web pages hosted from an Apache HTTP Server with PHP in a Docker container.
1.1 Things that didn’t work for me
For me, this didn’t work, for the following reasons:
- I override a lot of configuration in
.htaccess
. - I need a modified PHP configuration.
- I use Apache HTTP Server modules which are not enabled by default.
So I created my own Dockerfile
to cope with the changes that I need.
2 The Dockerfile
The standard image does not serve all purposes. Things you might want to change are:
- Enable additional Apache HTTP Server modules.
- Allow overriding specific directives in
.htaccess
. - Add a PHP configuration.
2.1 Explanation
- The
FROM php:apache
selects the latest version of PHP with the latest version of the Apache HTTP Server. I do not use this image in production, otherwise I would pin down the version. - The
SHELL
line changes the shell command for the subsequentRUN
commands to be/bin/bash -c
instead of/bin/sh -c
. I do this to get brace expansion. - The
RUN ln
command enables the Apache HTTP Server modules. I could’ve usedRUN a2enmod
instead, but since I know what I’m doing,ln
is simpler and faster for me thana2enmod
. There’s a caveat: If the way how Debian handles Apache HTTP Server modules changes, myDockerfile
might fail. If I would usea2enmod
, myDockerfile
would still work. Refer to [man:a2enmod] for more information abouta2enmod
. - The
RUN sed
command replacesAllowOverride None
withAllowOverride All
for the directory/var/www/
. I have a lot of configuration in my.htaccess
file which needs this. - The
COPY
command copies myphp.ini
file to the desired location in the docker image. My PHP configuration has a lot of modifications.
For more information what these Dockerfile
commands mean and how they work, refer to [Dockerfile].
3 The docker
commands
To use and run this image, you need a few docker
commands.
docker build -t my/apache-php .
- This command builds your Apache PHP Docker image from the
Dockerfile
and stores it in your local registry under the namemy/apache-php
. docker run --name apache -d 8082:80 --mount type=bind,source="$(pwd)"/htdocs,target=/var/www/html my/apache-php
- This command runs your docker image
my/apache-php
in a docker container. The Docker container is namedapache
for further reference. Port80
inside the container, which is where the Apache HTTP Server is running, is mapped to port8082
on the host. So you can access this with http://localhost:8082/. The option--mount type=bind,source="$(pwd)"/htdocs,target=/var/www/html
creates a bind mount of thehtdocs
directory of the host to/var/www/html
in the container. If your web pages are in a different directory, adjust thesource
path accordingly. docker stop apache
- Stops your docker container.
docker rm apache
- Removes your docker container.
docker container logs apache
- Prints the logs of the Apache HTTP Server inside the container.
docker exec -it apache bash
- Logs into the Apache PHP container using a bash shell.
docker ps -f name=apache
- Shows the status of the Apache PHP container.
4 The Makefile
The Makefile
serves as a more convenient way to wrap the docker commands needed to deal with the container. The things you want to do:
- (Create and) start the container.
- Stop (and remove) the container.
- Print the logs of the container.
- Login to the container.
So, the Makefile
offers the following commands:
make start
- Builds and starts the container. Docker is incremental. In case the
Dockerfile
was not changed, the container image will actually not be rebuilt. The Apache HTTP Server will be bound to port8082
. If you want a different port, for example, port9000
, you can run it like this:make start PORT=9000
. make stop
- Stops and removes the container. Because the container does not store any data, it can safely be removed.
make logs
- Prints the logs of the container, in case you want to inspect the logs.
make login
- Login to the container with a root bash, in case you want to inspect something inside the container.