I released a Docker image suitable for PHP development with the latest supported PHP versions installled plus latest 5.3 release. The image is aimed to help developers which need to develop and test their projects in different PHP versions (specially free or open source software developers).

Docker is a tool built on top of Linux’s operating system-level virtualization features. It allows applications to be build and shipped as containers, which can mean that you can hook it in your deployment pipeline to generate a Docker container as your shippable binary (if adopting Docker for both development and production) or just use it for development purposes as a replacement to Vagrant, for example. I won’t extend on this, read the Docker user guide and this paragraph will be a lot clearer, believe me!

Using the Docker image

Now that you’re used to Docker and installed it, using the PHP Development image will be straightforward. At the time of writing, it comes with the following PHP versions:

  • 5.6.3
  • 5.5.19
  • 5.4.35
  • 5.3.29

Each PHP version comes with the Zend OPCache and Xdebug extensions installed and some PHP QA tools are installed globally with Composer. The image also ships with Nginx and PHP-FPM. Check the image’s page for a full list of the extensions and libraries installed.

Let’s start a new container. First, pull the image from the Docker Hub:

$ docker pull eriksencosta/php-dev

Now, let’s create a very simple “Hello World” application:

$ mkdir ~/hello-world; echo '<?php echo "Hello world!";' > ~/hello-world/index.php

Start up the container:

$ docker run -p 80:80 -v ~/hello-world:/var/www/hello-world -d "eriksencosta/php-dev:latest"

Open http://localhost/hello-world/ (if you’re using Boot2Docker, replace localhost with the IP address returned from the command boot2docker ip) in your browser and be delighted by your awesome application greeting the whole world. Better than the UN, they say.

If you go to http://localhost/info.php, you’ll see the full information from the running PHP version.

Switching between the PHP versions

To get the real value of the image, you need to switch between the PHP versions. Stop the current running container:

$ docker stop $(docker ps -l | tail -1 | awk '{print $1}')

And start a new container in interactive mode:

$ docker run -t -i -p 80:80 -v ~/hello-world:/var/www/hello-world "eriksencosta/php-dev:latest" /bin/bash

You’ll be assigned with a terminal inside the container. To switch between the different PHP versions, use the phpenv command:

# phpenv versions
* 5.6.3 (set by /opt/phpenv/version)

5.6, 5.5, 5.4 and 5.3 are just shortcuts. phpenv let you define the global (system-wide) and local PHP version. To set it globally:

# phpenv global 5.4
# php -v
PHP 5.4.35 (cli) (built: Dec 14 2014 00:35:12)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend Technologies
    with Xdebug v2.2.6, Copyright (c) 2002-2014, by Derick Rethans

To set a local version, run:

# cd /var/www/hello-world
# phpenv local 5.3
# php -v
PHP 5.3.29 (cli) (built: Dec 14 2014 00:24:19)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend Technologies
    with Xdebug v2.2.6, Copyright (c) 2002-2014, by Derick Rethans

To start Nginx and PHP-FPM, run:

# webserver start
Starting PHP-FPM (PHP version 5.3) server.
Starting Nginx server.

To disable the Zend OPCache (which is enabled by default):

# opcache disable
The Zend OPCache (PHP version 5.3) was disabled.

You need to restart the webserver for the changes to take effect.
Execute: webserver restart

A real life example

There is nothing wrong with the “Hello World” application but… it does nothing! So let’s move to a better example using a simple Silex application. This example application is an issue tracker that only list issues (that are stored in a MySQL database). Clone the application’s repository:

$ cd ~
$ git clone git://github.com/eriksencosta/silex-docker-example.git

Our application needs a MySQL database. But our PHP container don’t comes with a MySQL server. The power of Docker lies in using lightweight images as building blocks. So instead of creating an image with all application dependencies, you start different Docker containers and consume then as attached network resources. With this in mind, pull the MySQL Docker image:

$ docker pull mysql

Start the MySQL container:

$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=root -d mysql

Start the PHP container:

$ docker run -t -i --link some-mysql:mysql -p 80:80 -v ~/silex-docker-example:/var/www/example -P "eriksencosta/php-dev:latest" /bin/bash

Run the needed set up commands:

# cd /var/www/example
# composer install
# php app/console example:configure:environment --variable="EXAMPLE_DEBUG=true"
# php app/console example:database:create
# php app/console example:schema:create

To check everything is working, run the test suite:

# behat

Load the fixtures data to the database:

# php app/console example:fixtures:load --truncate

Configure the Nginx virtual host and start the servers:

# cp dockerfiles/php-dev/default.vhost /etc/nginx/sites-available/default
# webserver start

In your browser, go to http://localhost. That’s all!

Wrapping up

I limited the scope of this post to present the Docker image and not to explain fully what is Docker and how to use it but I hope I’ve raised some interest about it on you.

This Docker image is intended only for development purposes (it is not meant to be used in production!). The image is built using the PHP Development Ansible playbook. The Dockerfile is on GitHub too. The Silex example application README have an extra usage example.