PHP is a server-side scripting language designed for web development, but which can also be used as a general-purpose programming language. You can use Docker to containerize your php application, whether it is running natively, or is using Apache for serving web content.
The goal of this short post is to show how easy it is to run a simple php application, both natively or with Apache server, in a Docker container. Nothing fancy there, but this will help to grasp the steps to dockerize a php application or any other application built in a different language, as the same approach applies for most of the steps described here.
In this post, I am assuming you have a basic knowledge on how to run common operations on containers and what is a Dockerfile, so I’ll not detail all the steps related to those commands. The Docker host used to show these example is running a CentOS Linux release 7.4.1708 (Core).
PHP App with Command Line
A PHP app does not need a web server to run, you just write your code and run it in the PHP cli. We have here a test.php script located in ~/myapp that looks like this:
$ ls ~/myapp test.php
The below php script will display a long format of today’s date.
$ cat test.php <?php echo "Hello. Today's date is: ".date('l jS \of F Y h:i:s A'); ?>
In my Docker host, php is not installed.
$ php -v bash: php: command not found...
And we will use Docker to host a php environment to run our script.
In a Single Command
To run a docker php container with our test.php, the following command will do it!
$ docker run -v ~/myapp:/myapp -w /myapp php php test.php Hello. Today's date is: Sunday 16th of September 2018 09:01:01 AM
- -v is to map a the ~/app application directory the /myapp folder in the php container.
- -w is to specify that the working directory is /myapp. This will allow to run the script without the need to specify the full path.
- php to pull the latest php image from Docker Hub. If your application is running with a specific version of php, a tag can be specified. For instance, php:7.2-cli
- php to invoke the php cli.
- test.php is the name of the script .
Our container started a php environment, and displayed today’s date then exited.
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ee9ab36e0634 php "docker-php-entrypoi…" 9 seconds ago Exited (0) 8 seconds ago lucid_hoover
More commonly, you will probably want to do it using a Dockerfile to build the image that includes your php script. Here is the syntax of the Dockerfile.
$ cat Dockerfile FROM php COPY . /myapp WORKDIR /myapp CMD ["php", "test.php"]
- The COPY directive is to copy the app directory (~/myapp) content to the /myapp folder inside the container.
- The WORKDIR is make /myapp the default working directory, where all the php files have been copied.
- The CMD directive is to run the test.php script for php cli.
If you don’t know what a Dockerfile is, it is a text document containing all the commands you might want to call from the command line to build a custom image. These commands are typically grouped within one file to assemble the image, and this text file is called Dockerfile. More on this here.
Below command will build a php image named php-app with your newly added test.php script, using your Dockerfile.
$ docker build -t php-app . Sending build context to Docker daemon 4.096kB Step 1/4 : FROM php ---> 4a05f96f44b5 Step 2/4 : COPY . /myapp ---> 5b645455e1bd Step 3/4 : WORKDIR /myapp ---> Running in 5d6e495d1573 Removing intermediate container 5d6e495d1573 ---> 5ad81652d6fd Step 4/4 : CMD ["php", "test.php"] ---> Running in 43b6ddfe7569 Removing intermediate container 43b6ddfe7569 ---> 8cecacf3c6cd Successfully built 8cecacf3c6cd Successfully tagged php-app:latest
We can check that the php-app image has been built successfully and is available in the local registry.
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE php-app latest 8cecacf3c6cd 3 minutes ago 367MB php apache a7d68dad7584 31 hours ago 378MB php 7.2-cli 656f0f210b0f 31 hours ago 368MB
We can now run a container from that image.
$ docker run php-app Hello. Today's date is: Sunday 16th of September 2018 09:16:47 AM
PHP App with with Apache
While running a PHP app natively can be run quite easily, you will want most of the time to run it with an Apache server to serve web content. For this, there’s a version of the PHP container that’s packaged with the Apache web server, and its tagged php:apache.
For this example, I have an index.php file that looks like this:
$ cat index.php <!DOCTYPE HTML> <html> <head> <title> Test Hello World PHP Script </title> </head> <body> <?php echo "<h3>Hello World!. This PHP application is containerized with Docker</h3>" ?> </body> </html>
We will use the php:apache image available in Docker Hub to pull our container that will serve this php page.
In a Single Command
The command above will run the container and makes its port 80 exposed to the external world.
$ docker run -d -p 80:80 -v ~/myapp:/var/www/html php:apache e67b35fd3a4a2a4d2fff7f0ec00446ee1f114d8e2c7c62414d5d5ef83a8c2eee
- -d to run the container in the background.
- -p to map the external port 80 to the container internal port 80.
- -v to map the ~/app application directory the /var/www/html Apache default root folder.
My container is running and listening on port 80 via the Docker host port 80.
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 39824ec8e775 php:apache "docker-php-entrypoi…" 19 minutes ago Up 19 minutes 0.0.0.0:80->80/tcp hardcore_mcclintock
$ docker port hardcore_mcclintock 80/tcp -> 0.0.0.0:80
My Docker host IP is 192.168.16.22. Let’s browse it!
This time, the docker file will be only two lines.
FROM php:apache COPY . /var/www/html
To build the image.
$ docker build -t my-php-web-app . Sending build context to Docker daemon 5.12kB Step 1/2 : FROM php:apache ---> a7d68dad7584 Step 2/2 : COPY . /var/www/html ---> 5339433f9ca6 Successfully built 5339433f9ca6 Successfully tagged my-php-web-app:latest
Image is there now on the Docker host.
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE my-php-web-app latest 5339433f9ca6 40 seconds ago 378MB php-app latest 8cecacf3c6cd About an hour ago 367MB php apache a7d68dad7584 32 hours ago 378MB php 7.2-cli 656f0f210b0f 32 hours ago 368MB
Let’s now run the container from my-php-web-app image.
$ docker run -d -p 80:80 my-php-web-app
Because you have already used port 80 for the previous running container, you’ll have either to remove it or to map to another port to be able to run this container.
And test is successful!
Admittedly, this was a very basic example. In production you would use Docker-compose to deploy a multi-tier application running in multi containers on a Docker Swarm cluster, but going through those basic steps showed how easy it is to run php applications without actually having php, thanks to containers.
Trying something more exciting?
That was a very basic example. If you want try something more interesting, try this script which is a PHP form validation example. Copy and paste the code in your php page, try to run it in a container and enjoy Docker containerization super power.