Docker Laravel Dev Environment

This post documents building a local Laravel development environment with Docker. Included are examples for debugging Laravel’s PHP with Xdebug using the Visual Studio Code editor. Source Code available on GitHub.

Install Laravel

In this example, we will be using the Composer Dependency Manager for PHP to install Laravel. To check if Composer is installed globally and in your PATH, enter composer --version in the CLI, for example,

composer --version
Composer version 1.4.1 2017-03-10 09:29:45

Get Composer if you need to install it.

With Composer, use the create-project command and the laravel/laravel package name followed by the directory to create the project in. The optional third argument is for a version number. For example, to install Laravel version 5.5 into a local directory such as home/laravel/mysite on the host computer, open a CLI then execute the composer create-project command from the directory where you want to create your project. For example:

cd ~/laravel

composer create-project laravel/laravel mysite "5.5.*"

Docker

Once composer is finished creating the Laravel project, we are ready to create the docker containers to host it. The following examples require both Docker and Docker Compose. Head on over to Docker, select Get Docker and the platform of your choice to install Docker on your computer. This should install both Docker and Docker Compose. The examples in this post were written while using Docker Community Edition, Version 17.09.0-ce.

Start Docker as needed and test the installation. Open a CLI and issue these commands.

docker --version

docker-compose --version

For the Windows platform with IIS installed, port 80 is likely in use. To eliminate conflicts, shut down the IIS web server. Open an admin command prompt and enter net stop was

PHP Container

This dockerfile builds from the official Docker Hub PHP image. At the time of this writing, php 7.1.10 was the latest non RC version available in the library. If you want to use a different version, change the php version as needed, such as FROM php:5.6.31-fpm.

Create the app.dockerfile in the root of the laravel project. For example, home/laravel/mysite/app.dockerfile

app.dockerfile
FROM php:7.1.10-fpm

# php-fpm default WORKDIR is /var/www/html
# change it to /var/www
WORKDIR /var/www

RUN apt-get update && apt-get install -y \
    libmcrypt-dev \
    mysql-client --no-install-recommends \
    && docker-php-ext-install mcrypt pdo_mysql \
    && pecl install xdebug \
    && echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)\n" >> /usr/local/etc/php/conf.d/xdebug.ini \
    && echo "xdebug.remote_enable=1\n" >> /usr/local/etc/php/conf.d/xdebug.ini \
    && echo "xdebug.remote_autostart=1\n" >> /usr/local/etc/php/conf.d/xdebug.ini \
    && echo "xdebug.remote_connect_back=0\n" >> /usr/local/etc/php/conf.d/xdebug.ini \
    && echo "xdebug.remote_host=10.0.75.1\n" >> /usr/local/etc/php/conf.d/xdebug.ini \
    && echo "xdebug.remote_port=9001\n" >> /usr/local/etc/php/conf.d/xdebug.ini \
    && echo "xdebug.idekey=REMOTE\n" >> /usr/local/etc/php/conf.d/xdebug.ini

For Mac platforms, change the app.dockerfile xdebug remote host IP, e.g., xdebug.remote_host=10.254.254.254

Then create an alias for IP 10.254.254.254 to your existing subnet mask as follows:

sudo ifconfig en0 alias 10.254.254.254 255.255.255.0

If you want to remove the alias, use sudo ifconfig en0 -alias 10.254.254.254

Nginx Container

Create a nginx server block configuration file for php and the Laravel project root.

nginx.conf
server {
    listen 80;
    index index.php index.html;
    root /var/www/public;

    location / {
        try_files $uri /index.php?$args;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

This dockerfile builds from the official Docker Hub nginx image adding the nginx.conf Nginx server block configuration file to /etc/nginx/conf.d on the container.

web.dockerfile
FROM nginx:1.12

ADD nginx.conf /etc/nginx/conf.d/default.conf

The next page covers creating the docker-compose file, container build, create, start and stop. Xdebug and launch config for VS Code PHP debugging.


Docker Drupal Dev Environment

This post documents mounting a new Drupal Composer
project as a volume in a Docker container. Features include Drush, Drupal Console, mailhog and phpMyAdmin. A Docker-sync configuration is available for OS X.

Composer

With the release of Drupal 8.3, using Composer to manage Drupal projects has vastly improved and is becoming a best practice. See Getting Started at getcomposer.org to install Composer.

Drupal Composer Template

Using Composer and the Composer template for Drupal projects to create a new Drupal site.

Open a CLI and execute the composer create-project command from the directory where you want to create your project. For example,

composer create-project drupal-composer/drupal-project:8.x-dev mysitefolder --stability dev --no-interaction

Docker

The docker-compose.yml file from Docker4Drupal image stack is optimized for local development. Use curl to download the file into the root of your Drupal project. For example,

PowerShell

curl https://raw.githubusercontent.com/wodby/docker4drupal/master/docker-compose.yml -Outfile mysitefolder\docker-compose.yml

Bash

curl -o mysitefolder/docker-compose.yml  https://raw.githubusercontent.com/wodby/docker4drupal/master/docker-compose.yml

Update the docker-compose.yml file. Create a named volume for data persistence in the mariadb node.

docker-compose.yml
...
services:
  mariadb:
    ...
    volumes:
      - mysql:/var/lib/mysql

  • Note that an ellipsis … in the code snippets are not a part of the code and are there only to denote code that is being skipped and not applicable to the example. View all of the docker-compose.yml updates on GitHub.

In the php node, comment out the vanilla Drupal image node and uncomment the image without Drupal. Additionally, change the volume to mount the relative local directory ./ to /var/www/html in the container.

...

  php:
    image: wodby/drupal-php:7.1-2.1.0
    ...
    volumes:
      - ./:/var/www/html

In the nginx node, change the volume to mount the relative local directory ./ to /var/www/html in the container.

...

  nginx:
    ...
    volumes:
      - ./:/var/www/html

For data persistence, in the volumes node at the bottom of the docker-compose.yml file, replace the unused codebase volume with mysql.

...

  volumes:
    mysql:

Run containers

From the site folder, e.g., mysitefolder, execute docker-compose

docker-compose up -d

Drupal Console

Test drive Drupal Console by connecting to the php container.

docker-compose exec --user=82 php sh

List all of the Drupal Console commands.
Disconnect from the session with Ctrl+D

drupal list

Source Code

Resources

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.


Docker

This page is a collection of various Docker commands and resources. For more info, read the Docker Documentation. To learn what Docker is, the official Docker Overview is an excellent resource.

Containers

# list
docker ps -a
 
# stop all
docker stop $(docker ps -a -q)

# remove all
docker rm $(docker ps -a -q)

# connect to any container
docker-compose exec [SERVICE] sh

# use user www-data (82) for Nginx and PHP containers
docker-compose exec --user=82 php sh

Images

# list
docker images -a

# remove image
docker rmi [IMAGE ID]

# remove dangling images
docker rmi $(docker images -q -f dangling=true)

# remove all images
docker rmi $(docker images -a -q)

Volumes

# list
docker volume ls

# remove volume
docker volume rm [VOLUME NAME]

# remove all volumes
docker volume rm $(docker volume ls -q)

# remove dangling volumes (1.13+)
docker volume prune

Drupal Dev Environment

Drupal Composer project mounted as a volume in a Docker container. Features include Drush, Drupal Console, mailhog and phpMyAdmin. A Docker-sync configuration is available for OS X.

Docker Drupal Dev Environment – Drupal Composer

WordPress Dev Environment

This example documents a local development environment for WordPress using Docker and 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 this environment.

Docker WordPress Dev Environment – Xdebug with VS Code