Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

 

Construct a better development environment with Docker

Having the right development environment will save time and money, and a lot of headaches. In today's blog post, we'll show you how to set up a better development environment.

Read post

Introduction

Development environments are the keystone to any project. Using a good core set of development tools will improve almost every aspect of development from building through to testing and even deployments. Having the right development environment will save not only time and money, but also a lot of headaches due to environmental differences between development and production. This is where applications such as Docker can help.

Today we are going to go through setting up a development environment for SilverStripe to mimic the environments in SilverStripe Platform.

What is Docker?

Docker is “the world’s leading software container platform”. Developers use Docker to eliminate “works on my machine” problems when collaborating on code with co-workers. Operators use Docker to run and manage apps side-by-side in isolated containers to get better compute density. Enterprises use Docker to build agile software delivery pipelines to ship new features faster, more securely and with confidence for both Linux and Windows Server apps.

Key concepts:

  • A Dockerfile defines a base image (e.g. debian), and the programs that should be present on it. This is done declaratively (e.g. RUN apt-get install apache2). The main benefit here is that re-creation of this environment will give you the same system every time. Another benefit is that you can then read these declared dependencies and re-create the machine using another method, e.g. manually or with vagrant.
  • Containers can be spun up and shut down at any time. You should never make infrastructure changes to an environment while it is running, but rather shut down the machine, add the dependency to the Dockerfile, and spin it up again.
  • Data which you want to keep between docker executions must be explicitly defined, e.g. you don’t want to lose your database every time your container is restarted.
  • Docker-compose is a tool that lets you define and spin up multiple docker containers at once. For example, your production infrastructure may have separate machines for your web server and your search server.

Requirements

As this tutorial use Docker native functions and SilverStripe installation, there are a few required applications:

Running Composer on your host

To keep containers light, composer is best installed on the host, so it can utilise caching for future builds. Before you run your containers, you should ensure your project has all dependencies installed

composer install

Creating a Docker Environment for your SilverStripe Installation

Here we will take you through setting up a Docker Environment for your SilverStripe application. We will use Docker Compose, which is a native function of Docker and is used for starting multiple services at the same time (e.g. web, database, etc).

Add docker-compose.yml

Firstly we will create the docker-compose.yml file. While this file can be located anywhere, we will be putting it in the root directory of your project for this example.

E.g. ~/projects/silverstripe/docker-compose.yml

version: '3'
services:
web:
image: brettt89/silverstripe-web
   working_dir: /var/www
  volumes:
    - .:/var/www/html

 database:
 image: mysql
  volumes:
    - db-data:/var/lib/mysql
  restart: always
 environment:
  - MYSQL_ALLOW_EMPTY_PASSWORD=true

volumes:
 db-data:

This docker-compose.yml file contains definitions for 2 services, web & database.

The web service uses a custom docker image "brettt89/silverstripe-web", which has been built specifically for SilverStripe Platform environments. As this already has the basic requirements installed, it is a good starting point. The database service defines the database SilverStripe will use for storing website information (e.g. dev/build).

The database service is just a standard mysql container with empty root password enabled. This can be replaced with any type of database compatible with SilverStripe.

Add_ss_environment.php

In order for the SilverStripe application to be able to talk to the other services, we will need to define a few settings in an _ss_environment.php file located in your project root for the SilverStripe application to read.

NOTE: You will probably want to add this file to your .gitignore so that it is not committed to your repository

NOTE: You can also add any custom definitions to this _ss_environment.php file as required.

E.g. ~/projects/silverstripe/_ss_environment.php

 <?php
/* Change this from 'dev' to 'live' for a production environment. */
define('SS_ENVIRONMENT_TYPE', 'dev');

/* This defines a default database user */
define('SS_DATABASE_SERVER', 'database');
define('SS_DATABASE_NAME', 'SS_mysite');
define('SS_DATABASE_USERNAME', 'root');
define('SS_DATABASE_PASSWORD', '');

/* Configure a default username and password to access the CMS on all sites in this environment. */
define('SS_DEFAULT_ADMIN_USERNAME', 'admin');
define('SS_DEFAULT_ADMIN_PASSWORD', 'password');

// This is used by sake to know which directory points to which URL
global $_FILE_TO_URL_MAPPING;
$_FILE_TO_URL_MAPPING['/var/www/html'] = 'http://localhost';

NOTE: You will notice we have defined SS_DATABASE_SERVER as "database". Each service within the docker-compose.yml file is accessible via its service name (e.g. database, web).

Running your environment

Once you have these basic steps completed, the next step is to create your development environment and start using it.

$ docker-compose up -d

The command above will download the relevant images (if they don't already exist locally in your cache), build any additional parameters, and then run them within your docker host.

Once this has completed, you will be able to use docker-compose commands to control your containers.

E.g. SSH into your Web Server

# Run a bash console on your web box
$ docker-compose exec web /bin/bash
root@fab57fa497e7:/var/www#

NOTE: You will find your project root at `/var/www/html` and can run CLI commands as required

FAQ 

  • How can I access my environment from my browser?

The brettt89/silverstripe-web docker image is based on a light PHP & Apache build. As such, your container will listen on all requests to port 80 by default. In order to access this port from your host, you will need to map this port in your docker-compose.yml file.

E.g. Adding ports to docker-compose.yml

web:
  image: brettt89/silverstripe-web
  working_dir: /var/www
  ports:
     - 8080:80
   volumes:
    - .:/var/www/html

This will map port localhost:8080 of your docker host to port 80 on the web service. After running docker-compose up -d to rebuild your web-box, you should be able to access your website via http://localhost:8080/         

  • Can I use nginx-proxy for multiple development environments?

Absolutely! We recommend using a variant of jwilder/nginx-proxy as SilverStripe requires a few additional configurations to run correctly. brettt89/nginx-proxy should be used instead.

NOTE: We recommend creating a unique docker network for your environments and running brettt89/nginx-proxy globally in this network. Defining brettt89/nginx-proxy in your docker-compose.yml file is not recommended for multiple development environments.

E.g. Using custom docker network

# Create docker network
$ docker network create my-network

# Add nginx-proxy to this network.
$ docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro --net
my-network --name nginx-proxy brettt89/nginx-proxy

Add your network to your docker-compose.yml files

networks:
 default:
   external:
     name: my-network

Add the VIRTUAL_HOST environment variable to your service

   environment:
    - VIRTUAL_HOST=project1.docker

NOTE: You will need to point this domain at nginx-proxy for it to be handled correctly.

As brettt89/silverstripe-web is an image on hub.docker.com, you can easily extend the installed applications by using a custom Dockerfile in your project.

 E.g. Update ~/projects/silverstripe/docker-compose.yml to use build instead of image.

web:
   build: ./Dockerfile
   working_dir: /var/www
   ports:
     - 8080:80
   volumes:
     - .:/var/www/html

In your Dockerfile, you can use FROM to specify using brettt89/silverstripe-web as your base image and add additional commands as required.

E.g. Custom Dockerfile ~/projects/silverstripe/Dockerfile

FROM brettt89/silverstripe-web
# Install additional Apt components
RUN apt-get update -y && apt-get install -y \
   wget

 # Install additional PHP extensions
RUN docker-php-ext-install -j$(nproc) \
   iconv

NOTE: brettt89/silverstripe-web is based off php:5.6-apache, as such the docker-php-ext-* tools should be used for PHP extensions.

Useful Links

About the author
Brett Tasker

Brett began his career in development at a young age, working around New Zealand & Australia in the IT industry. He quickly developed a passion for Web Development and joined SilverStripe as an Operational Developer.

Working in a wide range of industries from a Heavy Diesel Engineer to Parts Departments and Security, Brett found a passion for Engineering and Electronics. Ever since then, you can always find him at his desk, or in the garage.

Post your comment

Comments

  • Hi Thomas,
    Performance issues on Docker are usually related to their setup / OS / configuration. We suggest taking a look at performance guides by docker to see if it would help improve performance :)
    e.g. https://docs.docker.com/docker-for-mac/osxfs-caching/
    Cheers

    Posted by SilverStripe, 26/04/2018 10:04am (7 years ago)

  • Hi Brett,

    I am experiencing slow page loads when developing with docker (a page takes 5-10s)
    Have you come across this.
    Would kind enough to share how you resolved this issue.

    Thanks

    Posted by Thomas, 20/04/2018 8:16pm (7 years ago)

  • running composer update command in local machine can provide different results than running same command in container... Some modules depend on specific php versions and if php versions differ (local vs. container), you can be in trouble.

    Posted by Pali, 02/06/2017 9:50am (8 years ago)

  • Nice writeup; With Silverstripe 3.6 supporting PHP 7 do you have images based on PHP 7 also?

    Posted by Matthew Hailwood, 18/05/2017 4:37pm (8 years ago)

RSS feed for comments on this page | RSS feed for all comments