Debugging PHP Web Apps in a Docker Container

Debugging is an essential task of software development in any programming language. Unfortunately, the out-of-the-box experience with debugging in PHP is not always great. The “stock” PHP binaries available at php.net do not come configured with either of the two popular debug servers Xdebug and Zend Debugger. Developers are required to do additional configuration to make debugging possible with their PHP stack. This can be a significant hurdle for developers who are new to PHP.

Alternatively, developers can use a professional PHP stack like Zend Server, which comes configured with both Xdebug and Zend Debugger.

Docker, a technology that’s all the rage these days, provides another possible solution – debug your PHP web app in a Docker container, created from a predefined image of a PHP stack with a debug server. These predefined images are available in the Docker Hub. Developers with basic understanding of Docker can use the technology to debug their PHP web apps without the need to know how to install and configure a debug server in their PHP stack.

Below is a comprehensive walkthrough of pulling an appropriate image from Docker Hub, running a container and then debugging PHP code on it. The walkthough uses the Zend Studio 13 Early Access, which introduces the new Docker Tooling.

Note. The scenario described is still possible with earlier versions of Zend Studio, but any Docker management operations would need to be executed in a command terminal.

1. Install the Docker Engine on the Operating System

The first prerequisite is to install and configure the Docker Engine. We need it to be able to pull images from Docker Hub and to run the container. The Docker web site provides a comprehensive installation guide for each operating system.

2. Install the Docker Support in Zend Studio

Once we have the Docker Engine installed, we need to have the Docker Tooling installed in Zend Studio. It is available as a an extra feature and can be found under the Enhancements category on the Welcome screen.

Zend Studio Docker Support Installation

After restarting Zend Studio, we can switch to the Docker Tooling perspective. This new perspective has several views for managing Docker images and containers:

  • Docker Explorer – view for creating/managing connections to Docker daemons
  • Docker Images – view for managing Docker images
  • Docker Containers – view for managing Docker containers

Zend Studio Docker Support Perspective

3. Connect the Docker Tooling to the Docker Daemon

Clicking on the link inside the Docker Explorer view launches the wizard for creating new Docker connection. The default settings may work in some cases, especially on Linux. So, it is worth clicking first on the Test Connection button. If the test fails then custom configuration must be provided.

On Windows and Mac OS X where boot2docker is used the TCP connection configuration must be provided. The Docker host and certificates path can be found in the boot2docker console.

Zend Studio Docker Support Connection Windows

On Linux the Unix socket configuration must be provided. The location of the socket is usually unix:///var/run/docker.sock.

Clicking again on the Test Connection button should result in a “Success” message. Clicking on the Finish button will establish the connection to the Docker daemon and will display it in the Docker Explorer view.

Zend Studio Docker Support Connection

4. Pull an Image from Docker Hub

Now we need to pull an image from Docker Hub. We will use the tommylau/xdebug image, which has Apache HTTP Server, PHP and Xdebug inside. This can be done using the Pull Image tool button in the Docker Images view. It will display the Pull Image dialog where we need to enter “tommylau/xdebug” in the Name field. Clicking the Finish button will pull the image to the local machine. The image is quite large, so this operation can take a while. When done, the new image will be displayed in the Docker Explorer and Docker Images views.

Zend Studio Docker Support Images View

5. Run a Docker Container from the Image

We have the Docker image on our local system. Now we need to launch a Docker container out of it and map the HTTP port of the container’s Apache server to a port on our local system. We also need to map the document root of the container’s Apache server to a folder on the local system. These mappings are essential for debugging PHP code on the Docker container.

Creating a container is done by selecting the tommylau/xdebug image in the Docker Image view and then clicking on the Run Image tool button. There are a couple of important settings we need to do in the wizard that will pop up:

  • Map the HTTP port of the container’s Apache server to a port on our local system:
    1. Deselect the “Publish all exposed ports to random ports on the host interfaces” checkbox.
    2. (Don’t miss this one!) Select the checkbox of the first row in the table below (Container Port 80).
    3. Click on the Edit… button
    4. Set the Host Port to some free port on the local machine, e.g. 8080.
    5. Click the OK button to close the Exposing a Container Port dialog.

Zend Studio Docker Support Port Mapping

  • Map the document root of the container’s Apache server to a folder on the local system:
    1. Click on the Next button to advance to the second wizard page.
    2. Click on the Add button of the Data Volumes group.
    3. Enter “/var/www/html” as Container Path.
    4. Select the “Mount a host directory or host file” radio box.
    5. Click on the Directory button and browse some empty directory on the local file system, e.g. /home/raev/www
    6. Click on the OK button to close Data Volume dialog.
    7. (Don’t miss this one!) Select the checkbox of the newly added data volume in the table.

Zend Studio Docker Support Volume Mapping
Clicking on the Finish button will start the Docker container. It will appear in the Docker Explorer and Docker Containers views. Startup logs can be seen in the Console view.

Zend Studio Docker Support Containers View

We can test if the container is working by requesting the HTTP port of the container we mapped to the local system, i.e. requesting http://localhost:8080 in a web browser. The browser should display a “Forbidden” page. This is OK because this is how the Apache server is configured in the Docker image we used. This error is actually a proof that the web browser requested the Apache server running in our Docker container. Additional access logs are printed in the Console view.

Zend Studio Docker Support Console View

6. Configure a PHP Server to Represent the Docker Container

Now we need to configure the PHP tooling in Zend Studio to run and debug PHP code in the our Docker container. The PHP tooling uses the abstraction of PHP Servers as the environment of deploying, running and debugging PHP code. Therefore, we need to create a new PHP Server entity in Zend Studio that represents our Docker container. So, we need to switch to the PHP perspective and click the Add tool button on the PHP Servers view. In the PHP Server Creation wizard we have to select the Generic PHP Server view and make the following settings on the next wizard page:

  1. Give some name in the Server Name field, e.g. “Docker Xdebug”.
  2. Set the Base URL to “http://<host>:<port>” where:
    • <host> is the host where the Docker Engine is running. On Linux it is localhost. On Windows and Mac OS X where boot2docker is used it is the IP displayed in the DOCKER_HOST environment variable, usually 192.168.59.103.
    • <port> is the port we used to map the container’s HTTP port to the local system, e.g. we use 8080 in this tutorial.
  3. Set the Document Root to the folder we used to map the container’s document root to the local file system.

Zend Studio Docker Support PHP Server Configuration

On the next wizard page, we must configure the debugger settings of the server. Select “XDebug” in the Debugger drop-down list. We choose this option because the Docker image we pulled from Docker Hub has Xdebug preconfigured. If we use another image where Zend Debugger is preconfigured then we should choose the “Zend Debugger” option, or “<none>” in case the image has no PHP debug server preconfigured. Clicking on the Finish button creates the new PHP server and displays it in the PHP Servers view.

7. Create a PHP Project with Some Code

Now, let’s create some PHP code! We need a new project. It can be created by calling New > File > Local PHP Project from the main menu. In the displayed wizard we must make sure that the project is targeted on the PHP server we’ve just created and the project’s location points to the PHP server’s document root.

Zend Studio Docker Support PHP Project Configuration

After creating the project we can place some code in the index.php file. Even a simple printing of “Hello World!” would be enough.

8. Debug It!

Now let’s debug it. Right-clicking on the index.php file and choosing Debug As > PHP Web Application will request the web application in the Zend Studio internal browser and will connect the Zend Studio debug client to the Xdebug server running in the Docker container. You can see the execution breaks on the first line of index.php and a dialog pops up to propose switching to the Debug perspective.

Zend Studio Docker Support Debugging

We can call this a success!

Conclusion

In this article we have seen how we can use predefined Docker images to setup complex PHP stack environments and use Zend Studio and its new Docker support to develop, run and debug PHP code on them.

Note. You can also use the zend/php-zendserver Docker image that comes with a completely installed and configured Zend Server.