Docker WordPress Dev Environment

This post documents setting up local development environments with Docker using the official WordPress Docker repository as a base image. Page two includes configurations for remote PHP debugging with Xdebug and VS Code.

Docker Compose

Aside from making the container configuration easier to understand, Docker Compose coordinates the creation, start and stop of the containers used together in the environment.

The environment has multiple sites served on various ports including at least one WordPress site, a phpmyadmin site and mysql. For virtual host names, nginx-proxy is being used for containers with virtual host environment properties set in their docker compose data. Additionally, the mysql db container is accessible from the host at 127.0.0.1:8001

Create this docker compose yaml file in the projects root directory with the nginx-proxy configuration.

nginx-proxy.yml
version: "2"
services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro

Create this docker compose yaml file for the WordPress stack. This includes the linked MariaDB database and phpMyAdmin containers from their official repositories. Xdebug is not included in the official WordPress image on Docker Hub and will not be included in this configuration since it is using unmodified images. Adding xdebug and rebuilding the image is covered on page two.

wp.yml
version: "2"
services:
  db:
    image: mariadb
    volumes:
      - mysql:/var/lib/mysql
    ports:
      - "8001:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=secret
  phpmyadmin:
    image: phpmyadmin/phpmyadmin:latest
    ports:
      - "8002:80"
    links:
      - db:mysql
    environment:
      - MYSQL_ROOT_PASSWORD=secret
      - VIRTUAL_HOST=phpmyadmin.app
      - VIRTUAL_PORT=8002
  wp:
    image: wordpress
    volumes:
      - ./wordpress:/var/www/html
    ports:
      - "8003:80"
    links:
      - db:mysql
    environment:
      - WORDPRESS_DB_PASSWORD=secret
      - VIRTUAL_HOST=wordpress.dev
      - VIRTUAL_PORT=8003
volumes:
  mysql:

Update your systems hosts file.

hosts
# Docker (nginx-proxy)
127.0.0.1 phpmyadmin.app
127.0.0.1 wordpress.dev

Navigate to your project root in your CLI, such as Terminal on OS X, PowersShell or Cygwin on Windows.

Create the Containers

Create new nginx-proxy and WordPress containers using the up command with docker-compose.

docker-compose -f nginx-proxy.yml -f wp.yml up
  • The -f flags specify the compose files to use. Multiple compose files are combined into a single configuration. This multiple file solution is for demonstration purposes. Here is a single file example that can be run without a file flag.

Stop Containers

Stop the containers without removing them.

docker-compose -f wp.yml -f nginx-proxy.yml stop

Start Containers

Start the stopped containers. Include the nginx-proxy.yml first so when the WordPress containers are started the virtual hosts can be dynamically configured.

docker-compose -f nginx-proxy.yml -f wp.yml -f start
  • If you have restarted your computer and another process is using the nginx-proxy port, e.g., 80, you will need to halt that process before starting the container.

Shutdown Containers

Shutdown the environment using the down command. If your data is not stored in a volume, it will not persist since this will remove the containers.

docker-compose -f wp.yml -f nginx-proxy.yml down

The next page covers adding Xdebug and configuring VS Code for remote debugging.


Visual Studio Code

My favorite feature so far is in the form of an extension. The vscode-php-debug extension works better than any free PHP debugging solution I have tried, such as Eclipse, Netbeans or SublimeTextXdebug. In order to use the debugger, the Xdebug PHP extension will need to be installed for your version of PHP. Here are some Xdebug installation resources:

User Settings

My VS Code user preferences – I am not thrilled with the existing VS Code Git integration, I prefer the command line tools for this, so I have it disabled in my settings. Another setting I changed from the default, "workbench.editor.enablePreview": true – When this is set to true, a subsequent file open will close the previous file if it has not been double clicked or edited. I wanted to keep the files open, so I set this to false.

~\AppData\Roaming\Code\User\settings.json
// Place your settings in this file to overwrite the default settings
{
    "editor.renderWhitespace": "all",
    "editor.fontFamily": "Fira Code",
    "editor.fontLigatures": true,
    "editor.fontSize": 13,
    "editor.lineHeight": 22,
    "editor.minimap.enabled": false,

    "files.trimTrailingWhitespace": true,

    // Is git enabled
    "git.enabled": false,

    "window.zoomLevel": 0,

    "workbench.editor.enablePreview": false,
    "workbench.iconTheme": "vs-seti",
    "workbench.activityBar.visible": true,
    "workbench.sideBar.location": "left"
}

Extensions

Here is a list of my favorite VS Code extensions

PHP Debug

Remote debugging with xdebug – As noted in the Remote Host Debugging section, To make VS Code map the files on the server to the local machine, add the serverSourceRoot and localSourceRoot settings in the project .vscode/launch.json file. For example,

launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "serverSourceRoot": "/var/www/html",
            "localSourceRoot": "${workspaceRoot}"
        },
        {
            "name": "Launch currently open script",
            "type": "php",
            "request": "launch",
            "program": "${file}",
            "cwd": "${fileDirname}",
            "port": 9000
        }
    ]
}

Resources

Xdebug for XAMPP on OS X

After discovering how nice the vscode-php-debug extension works in Visual Studio Code on my Windows 10 laptop, I wanted this same setup for a PHP project on my work Mac Book Pro running OS X Yosemite (10.10). The version of XAMPP I currently have installed on the Mac is 5.6.11-0 and for this tutorial, there are a few requirements to consider:

Requirements

Use homebrew to install the autoconf utility for producing configure scripts.

# install autoconf
$ brew install autoconf

phpize

XAMPP comes with phpize which we will want to utilize to prepare the build environment for the Xdebug PHP extension. If another version of phpize is installed, it will need to be renamed. Check to see if phpize is installed in /usr/bin:

$ cd /usr/bin
$ ls -al | grep phpize
-rwxr-xr-x     1 root   wheel      4508 Sep  9  2014 phpize

If the grep search returns phpize, similar to what is shown above, then rename it to phpize_bak.

# rename / backup phpize
$ sudo mv phpize phpize_bak

Create a new symbolic link in /usr/bin to target the XAMPP version of phpize.

# navigate to the /usr/bin directory
$ cd /usr/bin

# create symbolic link to XAMPP phpize
$ sudo ln -s /Applications/XAMPP/bin/phpize-5.6.11 phpize

# check phpize version
$ cd /
$ phpize -v
Configuring for:
PHP Api Version:         20131106
Zend Module Api No:      20131226
Zend Extension Api No:   220131226

phpize -v command output should be similar to what is shown above.

Xdebug Installation

Open the XAMPP phpinfo.php file in a web browser, for example, http://localhost/dashboard/phpinfo.php. In another browser window or tab, open https://xdebug.org/wizard.php and copy the phpinfo page content in the first window or tab and paste it into the textbox on the xdebug.org page. Then submit for analysis to determine the Xdebug source to download. The response should be a Summary and Tailored Installation Instructions.

Example Summary
  • Xdebug installed: no
  • Server API: Apache 2.0 Handler
  • Windows: no
  • Zend Server: no
  • PHP Version: 5.6.11
  • Zend API nr: 220131226
  • PHP API nr: 20131226
  • Debug Build: no
  • Thread Safe Build: no
  • Configuration File Path: /Applications/XAMPP/xamppfiles/etc
  • Configuration File: /Applications/XAMPP/xamppfiles/etc/php.ini
  • Extensions directory: /Applications/XAMPP/xamppfiles/lib/php/extensions/no-debug-non-zts-20131226
Example Instructions
  1. Download xdebug-2.4.0.tgz
    continued…

You can follow the Tailored Installation Instructions from xdebug.org or you can follow the instructions here that I have found to work well.

  1. Unpack the downloaded file
    # navigate to the downloaded file
    $ cd ~/Downloads
    
    $ tar -xvzf xdebug-2.4.0.tgz
    $ cd xdebug-2.4.0
    
  2. run phpize
    $ phpize
    
    # example output
    Configuring for:
    PHP Api Version:         20131106
    Zend Module Api No:      20131226
    Zend Extension Api No:   220131226
    
  3. Configure with XAMPP php-config.
    $ ./configure --enable-xdebug --with-php-config=/Applications/XAMPP/xamppfiles/bin/php-config
    
  4. run make
    $ make
  5. In the Tailored Installation Instructions from xdebug.org, locate the step after make that contains the cp command and paths for copying the xdebug.so extension file into XAMPP, for example,
    $ cp modules/xdebug.so /Applications/XAMPP/xamppfiles/lib/php/extensions/no-debug-non-zts-20131226
    
  6. Edit /Applications/XAMPP/xamppfiles/etc/php.ini
    After “;zend_extension”
    Add the zend_extension setting from the xdebug.org instructions, for example:

    zend_extension=/Applications/XAMPP/xamppfiles/lib/php/extensions/no-debug-non-zts-20131226/xdebug.so
    
  7. Additionally, add these xdebug configuration settings in php.ini after the zend_extension setting:
    xdebug.remote_enable=1
    xdebug.remote_handler=dbgp
    xdebug.remote_host=localhost
    xdebug.remote_autostart = 1
    xdebug.remote_port=9000
    xdebug.show_local_vars=1
    xdebug.remote_log=/Applications/XAMPP/logs/xdebug.log
    
    ;---------------------------------
    ; uncomment these dev environment
    ; specific settings as needed
    ;---------------------------------
    ;xdebug.idekey = "netbeans-xdebug"
    ;xdebug.idekey = "sublime.xdebug"
    
    ;some pages in your Drupal site will not work default = 100
    ;xdebug.max_nesting_level=256
    

    Optional – for development only
    Find “max_execution_time” and set to unlimited:

    max_execution_time=0
    
  8. Restart Apache using XAMPP’s manager-osx
  9. Reload http://localhost/dashboard/phpinfo.php and verify that xdebug section exists. Another verification method is to copy and paste the phpinfo into the form at https://xdebug.org/wizard.php and resubmit it for analysis.

Virtual Machine for LAMP Development

This blog post addresses a common scenario — a local LAMP development environment on your Windows or OS X computer. You could use XAMPP on either Windows or OS X, MAMP on OS X or native Apache in OS X. Here, we will create a Linux virtual machine with Samba configured to share the Virtual Machine file system with the host computer. We will also create virtual hosts, install and configure WordPress and Xdebug.

First thing you will need is Virtual Machine software. For my Virtual Machine, I chose to install the free VMware Player. If your host operating system is OS X, you can install VirtualBox if you do not want to purchase VMware Fusion or Parallels. You could also use VirtualBox on a Windows host instead of VMware if you prefer.

Next, you will need to create a Linux virtual machine. I decided to Download Ubuntu Server 32 bit since it is compatible with the intel processor of my host computer.

Install SSH

After creating a new VM and installing Linux, time to get our dev environment setup. Install SSH so we can run commands from the host. Later we will use ssh to to tunnel the Xdebug connection from the VM back to the host.

# update the distro
$ apt-get update
$ apt-get upgrade -y

# install SSH
$ sudo apt-get -y install openssh-client openssh-server

Get the IP address of the Linux virtual machine.

# lookup inet addr ip 
$ ifconfig eth0

From the host, open a terminal and SSH into the virtual machine. In a Windows host, you can use Cygwin, PuTTY or a Git Bash.

$ ssh jim@192.168.59.129
...
jim@192.168.59.129's password:
Welcome to Ubuntu 12.04.3 LTS (GNU/Linux 3.8.0-29-generic i686)

 * Documentation:  https://help.ubuntu.com/
Last login: Sat Nov  2 12:55:45 2013
jim@ubuntu:~$

Install LAMP server

Read my blog post for more on how to install the LAMP server and phpMyAdmin: Mint LAMP Development Environment

# install LAMP server 
$ sudo apt-get install lamp-server^

Restart Apache and test the web server root URL from a host browser using the virtual machines IP address, e.g., http://192.168.59.129/.

$ sudo /etc/init.d/apache2 restart

Virtual Hosts

# edit the Apache config
$ sudo nano /etc/apache2/apache2.conf

# in apache2.conf, add these virtual host settings below the files node
NameVirtualHost *:80

<VirtualHost *:80>
   DocumentRoot /var/www
   ServerName www.ubuntu.vm
   ServerAlias ubuntu.vm
</VirtualHost>

<VirtualHost *:80>
   DocumentRoot /var/www/wordpress
   ServerName www.wordpress.vm
   ServerAlias wordpress.vm
</VirtualHost>

Edit your hosts file in your host operating system to map to the virtual hosts you specified in the Apache config of the Linux virtual machine.

192.168.59.129  ubuntu.vm
192.168.59.129  wordpress.vm

Since we have set the hosts file to map 192.168.59.129 to ubuntu.vm, once you disconnect your current ssh session (Ctrl+D), you will need to use the host alias you specified in the hosts file to reconnect.

ssh jim@ubuntu.vm

Samba Network Share

You can use Samba to share the /var folder in you virtual machine.

# install Samba 
$ sudo apt-get install samba

Linux system permissions take precedence over Samba permissions. For example if a directory does not have Linux write permission, setting samba writeable = Yes will not allow to write to shared directory / share.

# edit Samba config 
$ sudo nano /etc/samba/smb.conf

####### Authentication #######
  security = user

# bottom of smb.conf
[etc]
    path = /etc
    browsable = yes 
    read only = no 
    create mask = 0755 
    admin users = jim

[home]
    path = /home
    browsable = yes 
    read only = no 
    create mask = 0755 
    admin users = jim

[var]
    path = /var
    browsable = yes 
    read only = no 
    create mask = 0755 
    admin users = jim 

Ctrl+C to exit nano, press Y to save and return to write your changes to the file.

Install the PAM authentication module for Samba which will sync the system users to the Samba user database.

# Install libpam-smbpass package
$ sudo apt-get install libpam-smbpass

# restart Samba for the new settings to take effect
$ sudo restart smbd
$ sudo restart nmbd

# set user jim as the owner of share directory
$ sudo chown -R jim /var/www

For OS X, open Finder, select Go > Connect to Server (command + K). Enter the server address: smb://ubuntu.vm and select Connect

OS X - Connect to Server Dialog
OS X – Connect to Server Dialog

For Windows, select Run from the Start menu or open Windows Explorer and enter:

\\ubuntu.vm\www
Windows Run Dialog
Windows Run Dialog

Server Time Synchronisation

Server time is likely to become inaccurate in our development scenario. We can use Ubuntu’s NTP server and NTP’s server pool to keep the server datetime accurate.

# install ntp
$ sudo apt-get install ntp

# edit /etc/ntp.conf
$ sudo nano /etc/ntp.conf
# add these two lines
server ntp.ubuntu.com
server pool.ntp.org

# change server time zone
$ sudo dpkg-reconfigure tzdata

Enabling Module Rewrite

The mod_rewrite Apache module is a rule-based rewriting engine to rewrite requested URLs. It is very useful for genarating SEO friendly URLs.

# enable the module 
$ sudo a2enmod rewrite

# restart apache to activate the configuration change
$ sudo service apache2 restart

Install WordPress

# download the latest WordPress to a downloads directory
$ mkdir ~/downloads
$ cd ~/downloads

$ wget http://wordpress.org/latest.tar.gz

# -z : Uncompress the resulting archive with gzip command.
# -x : Extract to disk from the archive.
# -v : Produce verbose output i.e. show progress and file names while extracting files.
# -f latest.tar.gz : Read the archive from the specified file.
# -C : To change the directory (current directory is default)

# this will create /var/www/wordpress since the archive root directory is wordpress 
$ sudo tar -zxvf latest.tar.gz -C /var/www

# make yourself the owner
sudo chown jim /var/www/wordpress

Create Database

Create MySql database, user and grant permissions in one line.
base_user is typically root
base_user_pass is password for base_user (no space between -p and base_user_pass is important)

mysql -u base_user -pbase_user_pass -e "create database new_db; GRANT ALL PRIVILEGES ON new_db.* TO new_db_user@localhost IDENTIFIED BY 'new_db_user_pass'"

phpMyAdmin

If phpMyAdmin is installed, you can use it to create the wordpress database as described in this next section. Read my earlier blog post if you need help doing this,
Mint LAMP Development Environment

In the browser, goto http://ubuntu.vm/phpmyadmin/. Select the Databases tab and under “Create new database”, enter in a database name such as “wordpress”, and select Create. Collation will automatically be assigned by MySQL when the database tables are created, during the WordPress installation.

# copy WordPress sample config
$ cd /var/www/wordpress
$ cp wp-config-sample.php wp-config.php

In the browser, goto http://wordpress.vm and start the installation. If you need to manually edit the wp-config.php file, you can do so with nano.

$ nano wp-config.php 

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'database_name_here');

/** MySQL database username */
define('DB_USER', 'username_here');

/** MySQL database password */
define('DB_PASSWORD', 'password_here');

/** MySQL hostname */
define('DB_HOST', 'localhost');

After saving wp-config, complete the WordPress installation at http://wordpress.vm

You can backup the MySql database using mysqldump within your ssh session. For example, replace mysql_username with your username and mysql_password with your password:

$ mysqldump -h localhost -u mysql_username -pmysql_password wordpress > /home/wordpress-$(date +"%Y-%m-%d").sql

WordPress Revisions Cleanup

Run this sql query in phpMyAdmin to delete all revisions from each post, including all of its meta data.

DELETE a,b,c
FROM wp_posts a
LEFT JOIN wp_term_relationships b ON (a.ID = b.object_id)
LEFT JOIN wp_postmeta c ON (a.ID = c.post_id)
WHERE a.post_type = 'revision'

Xdebug

$ sudo apt-get install php5-xdebug

Check Xdebug

$ php --version

PHP 5.3.10-1ubuntu3.8 with Suhosin-Patch (cli) (built: Sep  4 2013 20:05:42)
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies
    with Xdebug v2.1.0, Copyright (c) 2002-2010, by Derick Rethans

Configure Xdebug

$ sudo nano /etc/php5/conf.d/xdebug.ini

Add the following xdebug config values after the zend_extension path value so it looks like this.

zend_extension=/usr/lib/php5/20090626+lfs/xdebug.so
xdebug.remote_enable=1
xdebug.remote_handler=dbgp
xdebug.remote_mode=req
xdebug.remote_host=127.0.0.1
xdebug.remote_port=9000

When debugging from the host computer, use ssh to tunnel the debug-connection back to it.

# ssh remote port forwarding
ssh -R 9000:localhost:9000 jim@ubuntu.vm

Using the “-R” argument tells ssh to listen on TCP port 9000 on the ubuntu server and forward it back through the ssh connection to the TCP port specified (localhost:9000). So from Xdebug’s perspective on the Ubuntu server, it is talking to localhost on the local computer.

More info: Mint LAMP Development Environment – Part Two | Xdebug

Other PHP debugging options

You could use the FirePHP Extension for Firefox to log to your Firebug Console using a simple PHP method call. There is also a SublimeTextXdebug package for Sublime Text.

If all you have is ssh and nano

<?php var_dump(__FILE__, __LINE__, $_REQUEST); ?>

or

<?php
echo '<pre>';
print_r( $somevariable );
echo '</pre>';
?>

Resources

Mint LAMP Development Environment – Part Two

Linux Mint 15 ‘Olivia’

I decided it was time to ditch my Linux 13 KDE setup and try the improved MATE 1.6 desktop now that Linux Mint 15 released. I find it pretty slick and fast, a nice change from Windows when I decide to do some development in a true LAMP environment. Speaking of which, we need to get that installed. Before doing that, the first thing I like to do is open up a terminal and run:

sudo apt-get update

This will download the package lists from the repositories and update them with information on the latest package versions. If you have not installed LAMP (Linux, Apache, MySQL & PHP) please read my earlier blog post, Mint LAMP Development Environment. Then you can return to this post to add an IDE with debugging capabilities along with some other nice tools.

Xdebug

sudo apt-get install php5-xdebug

Check Xdebug

php --version
PHP 5.4.9-4ubuntu2 (cli) (built: Mar 11 2013 16:09:26) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies
    with Xdebug v2.2.1, Copyright (c) 2002-2012, by Derick Rethans

Configure Xdebug

sudo pluma /etc/php5/mods-available/xdebug.ini

Add the following xdebug config values after the zend_extension path value so it looks like this.

zend_extension=/usr/lib/php5/20100525/xdebug.so
xdebug.remote_enable=1
xdebug.remote_handler=dbgp
xdebug.remote_mode=req
xdebug.remote_host=127.0.0.1
xdebug.remote_port=9000

NetBeans

The IDE I prefer for Drupal development as of this writing is NetBeans. I found this post, Configuring NetBeans for Drupal development to be very helpful. In the Usage section of the post, the author suggests using the sites folder of your Drupal installation when creating the New Project > PHP Application with Existing Sources. This did not work for me, instead, I selected the root folder of my Drupal install as the Sources Folder for the NetBeans IDE project import. By including the entire Drupal installation in my NetBeans project, I could step through and debug any of the Drupal code including modules in the sites folder.

NetBeans IDE Resources

Eclipse

Download

As of this writing, the latest stable version of Eclipse was Eclipse Juno (4.2). I downloaded the Eclipse Classic 4.2.2 64 bit Linux version from http://www.eclipse.org/downloads/. Make sure you download the appropriate 32 or 64 bit version of Eclipse to match your Linux Mint operating system. To check which version of Linux Mint you are running, in a terminal, enter

uname -m

i686 = 32-bit; x86_64 = 64 bit

Install

Open up a terminal, change to the Downloads directory and and extract the archive.

cd ~/Downloads
tar xzf eclipse-SDK-4.2.2-linux-gtk-x86_64.tar.gz

With superuser permissions, move the extracted eclipse directory and its contents into the /opt/ folder.

sudo mv eclipse /opt/

Create a symbolic link so you can start Eclipse from a terminal

sudo ln -s /opt/eclipse/eclipse /usr/bin/eclipse

Launch eclipse

eclipse

or if working on files directly in /var/www/

sudo eclipse

PHP Development Tools (PDT)

To install latest stable PDT build in Eclipse, select Help > Install New Software and enter following URL in the work with input:
http://download.eclipse.org/tools/pdt/updates/release

Recoll

You could use the terminal to search for files with commands such as find, grep, and awk. However, I like the the Recoll desktop search tool.

Filezilla

When you are ready to deploy your development work to a remote server via FTP or SFTP, this cross-platform FTP client is my goto tool for the job.

sudo apt-get install filezilla

Resources