Using Docker for Local Drupal Development

Josh Fabean
|
July 8, 2017
Image
Docker whale logo riding waves created by Drupal 8 logos

Using Docker is great, it makes sure that every developer working on the project is using the same server and if it works on your machine it really should work on everyone's. It's also great because once you have it set up you can spin up aditional sites in a matter of seconds instead of trying to manage a local web server on your computer yourself. This blog should get you off the ground and get your first Drupal site spun up so you can get right into working on your site.

Prerequisites

  1. Have docker for installed for you computer. For Windows, for Mac, for Linux you know what to do.
  2. Install Docker Compose, for Mac & Windows will get it already installed with the bundles linked above, for linux you'll need to install it yourself.
  3. At Code Koalas we have a git repo for our docker compose templates, you don't need to pull in the whole thing but you can pull in the couple yaml files you need.
  4. Make sure you have no other servers running on port 80 or our docker containers won't run. If running Mac, it by default runs an Apache server sometimes, because why not. You can stop it like this: sudo apachectl stop.

Setting up local dev environment

The first thing we do is spin up a small container that's an nginx proxy. It will manage all the local network requests to docker and point them to the proper container. In the repo linked above, the yaml file we need for that is devenv.yaml The file is this:


version: '2'
services:
  nginx-proxy:
    image: codekoalas/nginx-proxy
    container_name: nginx-proxy
    ports:
    - "80:80"
    - "443:443"
    volumes:
    - /var/run/docker.sock:/tmp/docker.sock
    networks:
    - dockercompose
    restart: always
networks:
  dockercompose:
    driver: bridge

You'll want to save that file somewhere on your system where you can access it later, this is why personally I have that whole docker-compose repo in my ~/Code directory on my computer. To spin up this repo you run the following command docker-compose -f /path/to/file/devenv.yaml up -d. That's telling docker compose to up a file in daemon mode and using a file. It will output some things and the first time ran will have to download some container images.

Getting your Drupal install ready

To get your Drupal site ready to spin up, all you need is a simple Drupal 8 codebase downloaded, but you need the D8 install not in the root of your repo but in a sub-directory like docroot. We use a slight variant of the Drupal Composer - Drupal Project which lets you manage all of your contrib modules & themes and D8 itself using composer instead of clogging your own repo with other people's code. Code Koalas' version of the composer Drupal project adds a couple of extra modules and maps the drupal install to docroot instead of web but you can use either or neither. Your local directory just needs to look like the following:

drupal 8 install directory

It doesn't need everything I have in mine, but you will have your website's git repo, and inside of that will be the directory docroot which contains a full D8 install.

Setting up the docker-compose file

You'll see in my site I have a compose.yaml, that's the next step we will take one of our templates we have in our docker-compose repo and use it in our site.

Our D8 docker-compose file is drupal8blank.yaml


version: '2'
services:
  d8blank-mysql:
    container_name: d8blank-mysql
    image: mysql:5.6
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: drupal
      MYSQL_USER: mysql
      MYSQL_PASSWORD: mysql
    volumes:
      - ~/Sites/sites-databases/d8blank:/var/lib/mysql
    networks:
      - dockercompose
    command: mysqld --max_allowed_packet=64M
    restart: always
  d8blank:
    container_name: d8blank
    image: codekoalas/drupal8
    environment:
      VIRTUAL_HOST: .d8blank.dev
      GIT_REPO: https://github.com/CodeKoalas/drupal-project.git
      GIT_BRANCH: master
      MYSQL_SERVER: mysql
      MYSQL_DATABASE: drupal
      MYSQL_USER: mysql
      MYSQL_PASSWORD: mysql
      DRUPAL_BASE_URL: http://d8blank.dev
      DRUPAL_TRUSTED_HOSTS: d8blank\.dev$$
      DRUPAL_HTTPS: "off"
      APACHE_DOCROOT: /var/www/site/docroot
      PRODUCTION: "false"
      LOCAL: "true"
    volumes:
      - ~/Sites/sites-files/d8blank:/mnt/sites-files
      - ~/Sites/d8blank:/var/www/site
    networks:
      - dockercompose
    extra_hosts:
      - "xdebug:192.168.237.237"
    links:
      - d8blank-mysql:mysql
    restart: always
networks:
  dockercompose:
    external:
      name: dockercompose_dockercompose

You'll need to take all the references to d8blank and change them to the name of your repo's directory. So instead of on line 3 it saying d8blank-mysql change it to mycoolsite-mysql and do that throughout the whole file. You'll also want to change the GIT_REPO to point to the http download of your git repo, if you don't have this in a git repo you can skip this and it will be okay.

Now, if this is a brand new site you can skip to the next section, but if you have an existing database we have a simple way to get that in. You will need to export that database and save the name as starter.sql, place that in the root of your project. Our Docker container looks for a starter.sql in the root of the repo and imports it, if there is not database loaded in mysql.

Spin up the site

Now your file system is all set up and ready to go, all we need to do now is in terminal go to the directory of your project and run docker-compose -f compose.yaml up -d this will output its starting containers. Though in the command prompt it will say it's done, it does actually take the containers themselves a minute or two to work on first boot.

Access your site locally

Our setup is built for you to access your sites on nameofcontainer.dev so in our example it'd be mycoolsite.dev. You can have many sites up at once and it will work just fine. The only issue is getting your computer to match that domain to your local computer. A simple way is to edit your host file for that single domain. The cool way on Mac is using dnsmasq to point all .dev to localhost, I'm sure you can find similar things for Windows, and the same tutorial I believe mostly works on Linux. If that's too much trouble you can edit your host file by typing the following into Terminal sudo vim /etc/hosts then adding this to the bottom of that file 127.0.0.1 mycoolsite.dev.

Things to know

When using a Docker setup you now have a layer between you and your code, it's just like the code running on your remote servers, which means command line tools are a little harder. Luckily you can just log into the container and run your command. To log into the container use the following command docker exec -ti nameofcontainer /bin/bash then you're in the root of your project on that server. From there you have drupal console, drush, composer, git and other normal command line tools. If that command is too much to remember or type you can add this to your .profile locally.


dlogin() {
  docker exec -ti $1 /bin/bash
}

With that locally you type dlogin nameofcontainer and you're in, which is what most people in the office here use.

When you're done working on your site and want to turn it off, go to the root of the project and run docker-compose -f compose.yaml down and that will turn off the servers. You can always spin it right back up whenever you'd like to get your site back.

Conclusion

Working with Docker is great. Since we've switched to it exclusively for Drupal projects, we can spin new people up on projects in a matter of a minute or two instead of 15 minutes for them to figure out local servers themselves. It also has decreased the quantity of bugs due to varying versions of php or server setup. We now run the same servers local, dev, staging and production and it's easy for any team member to help another dev on their project as they're all the same setup. I hope this is useful and if you run into issues following this tutorial let me know on twitter @joshfabean.

Want to talk about how we can work together?

Ryan can help

Ryan Wyse
CEO