Setting up and Debugging PHP7 in Docker

Before developing applications in any new language/platform I make sure that the debugger works in the set up. I had been working on some projects in Python and PHP recently and I have already shared my notes on setting up and debugging Python (Django) application in Docker and how to debug the application.

In this post I will describe how to setup PHP7 in Docker and debug the application. You can checkout the project from this Github repo.

Here is the Docker file for this setup –

FROM php:7.0.17-apache

RUN apt-get update
RUN apt-get install -y apt-utils vim curl sqlite3
RUN pecl install xdebug
# copy test db file
ADD ./db/employee.db /employee.db
# The base image does not have php.ini. 
# Copy our own, with xdebug settings
ADD ./php.ini /usr/local/etc/php/


The container is based on php image from docker hub. The version number is 7.0.17-apache. This example uses Sqlite3 database, so the package is installed.

To debug PHP applications, you need to install xdebug. In the docker file it is installed using pecl. Then employee.db (Sqlite3 DB) is copied from the project folder to the root of docker container.

The PHP base image does not create php.ini. But we need to create one to set a few XDebug parameters. So we copy php.ini from the project folder to /usr/local/etc/php in the container.

Here is the content of php.ini –


zend_extension is set to path of file. Ad of current version, pecl installs xdebug at the path specified above. You can check if the above path is valid in your docker container by executing ‘find’ command (you need to run bash command in the container and execute ‘docker exec -it php7-apache2 bash’)

$ find / -name

If you find that path of is different in you set up, you will have to rebuild the image by executing ‘docker-compose build’.

Coming back to php.ini, you need to set value of xdebug.remote_host to IP of your host machine, from where you would remote debug the application. Set xdebug.remote_port to any port that is not already taken in the host machine. In this example, the port is set to 9000.

docker-compose.yml contains some simple settings –

version: "2"

    build: .
    container_name: php7-apache2
      - '8002:80'
      - $PWD/htdocs:/var/www/html

It maps port 80 from the container to 8002 to the host machine. So you can access Apache2 running in the container from host machine using url http://localhost:8002. Using volumes setting, it maps htdocs folder in the project to /var/www/html folder in the container. /var/www/html is the doc root for Apache2 server in the container. So any file you create in htdocs folder in the project in host machine can be served by Apache2 in the container.

To enable PHP debugging in Visual Studio Code, you need to install PHP Debug extension. In Visual Studio Code, select menu View | Command Pallet and type Install Extension in the filter text box. Select that option and then search for extension and install it.

Next step is to add lunch configuration. Click on Debug icon in the left bar and then click on the drop down list to select configuration. Initially the list only displays ‘No Configuration’ and ‘Add Configuration’. Select ‘Add  Configuration’ and select PHP configuration.

Two PHP configurations are added to launch.json file – “Listen for XDebug” and “Launch currently open script”. We are interested in the first configuration. We need to add local to remote mapping path to this configuration –

    "name": "Listen for XDebug",
    "type": "php",
    "request": "launch",
    "serverSourceRoot": "/var/www/html",
    "localSourceRoot": "${workspaceRoot}/htdocs",
    "port": 9000

Local folder in project, htdocs, is mapped to /var/www/html in the container.

Start the container by executing command –

$ docker-compose up

Then set breakpoint in index.php (say line #2) and open http://localhost:8002 in the browser. In VS Code you should see that breakpoint is hit at the same line.

Watch this video to see how all this works –

-Ram Kulkarni

6 Replies to “Setting up and Debugging PHP7 in Docker”

  1. Excellent, you help me a lot.

    Insted of this:

    “serverSourceRoot”: “/var/www/html”,
    “localSourceRoot”: “${workspaceRoot}/htdocs”,

    I had to use this:

    “pathMappings”: {
    “/mnt/d/path/to/project/app”: “${workspaceRoot}/app”

    And for this:


    I used this:



Leave a Reply