How to Build a Development Environment with Docker

How to Build a Development Environment with Docker

Building a reliable and comfortable development environment is not an easy task. Running multiple versions of the same software might be a bit tricky. This post shows how to build an awesome development environment with Docker.

MySQL Docker


Docker is an open-source platform that automates the development of applications inside software containers.
What are the advantages of using an external tool to manage software on a development machine?

  • running multiple versions. Usually only a single version of the application can be found in package manager. Very often, it’s not the latest version. Example: there’s no Oracle MySQL package in the ArchLinux packages repository.
  • saving time spent on compiling an application from sources. Managing multiple versions of the same software is time-consuming.
  • avoiding dependency hell. You can use a few versions of the application without introducing any dependency compatibility issues.
  • reliability. Official Docker images are more reliable than third party repositories.

Using Docker to install multiple versions of MySQL

MySQL has been used as an example in this post, but the process is almost the same for any kind of software. You can find the details about the official MySQL Docker images at the Docker Hub page.
You’ll need the following dependencies to achieve our goal:

  • Docker
  • systemd or equivalent
  • (optional) a build tool (GNU Make would match the requirements perfectly) – this
    example uses simple shell scripts.

The first step is to create a directory where the configuration files will be stored. A home directory will be a good choice:
mkdir -p ~/.docker/mysql/{5.6,5.7} (the location of the ). Two MySQL versions will be used as an example: 5.6 & 5.7.
Every container requires a Dockerfile, so creating those is the second step: touch ~/.docker/mysql/{5.6,5.7}/Dockerfile.
You can open Dockerfiles using any text editor: emacs, vim, gedit and so on.
~/.docker/mysql/5.6/Dockerfile

FROM mysql:5.6
ENV MYSQL_ALLOW_EMPTY_PASSWORD true
VOLUME /var/lib/mysql/5.6
EXPOSE 3306
CMD ["mysqld"]

~/.docker/mysql/5.7/Dockerfile

FROM mysql:5.7
ENV MYSQL_ALLOW_EMPTY_PASSWORD true
VOLUME /var/lib/mysql/5.7
EXPOSE 3307
CMD ["mysqld"]

Some explanation of the Dockerfiles content:

  • FROM specifies the image name & image tag used in the following format: name:tag
  • ENV sets a environment variable. In this example, an empty root user password is allowed.
  • VOLUME sets the location of mounted volume as database files should be stored on the host machine.
  • EXPOSE determines the port number that will be available from the container host.
  • CMD sets up the default entry point.

As we’re using multiple versions of MySQL, the volume path and exposed port number both need to be customized. This isn’t necessary if you’re using single instance.
After the Dockerfiles are ready, an automation tool will be required to build and run the containers. This example uses simple shell scripts, but any build tool can be used: touch ~/.docker/mysql/{5.6,5.7}/build.sh.
~/.docker/mysql/5.6/build.sh

#!/bin/bash
docker stop mysql-5.6
docker rm mysql-5.6
docker build -t mysql-5.6 .
docker run -d \
	-p 3306:3306 \
	-v /srv/mysql:/var/lib/mysql \
	--name mysql-5.6 \
	mysql-5.6
docker start mysql-5.6

~/.docker/mysql/5.7/build.sh

#!/bin/bash
docker stop mysql-5.7
docker rm mysql-5.7
docker build -t mysql-5.7 .
docker run -d \
	-p 3306:3306 \
	-v /srv/mysql:/var/lib/mysql \
	--name mysql-5.7 \
	mysql-5.7
docker start mysql-5.7

Some details about the build scripts:

  • docker stop command stops any running the container named mysql-5.6 or mysql-5.7
  • docker rm removes any existing container with the specified name
  • docker build builds a new image with the specified tag – in this example mysql-5.6 or mysql-5.7
  • docker run runs a container using a previously created image
  • docker start starts the newly created container

MySQL Docker – Almost there…

At this stage, MySQL Docker containers are fully functional and accessible from the host machine. They store MySQL user home directory on the host. There’s one issue with the containers – they do not start on the system boot. To start them, an init system or a cron job might be used. In this post, I’ll use systemd.
/etc/systemd/system/mysql-5.6.service

[Unit]
Description=MySQL 5.6 Docker container
Requires=docker.service
After=docker.service
[Service]
Restart=always
ExecStart=/usr/bin/docker start -a mysql-5.6
ExecStop=/usr/bin/docker stop -t 2 mysql-5.6
[Install]
WantedBy=multi-user.target

/etc/systemd/system/mysql-5.7.service

[Unit]
Description=MySQL 5.7 Docker container
Requires=docker.service
After=docker.service
[Service]
Restart=always
ExecStart=/usr/bin/docker start -a mysql-5.7
ExecStop=/usr/bin/docker stop -t 2 mysql-5.7
[Install]
WantedBy=multi-user.target

These newly created service units depend on Docker service. The services will always start after the docker service has been started. To start on system boot, you should enable the following services:

sudo systemctl enable mysql-5.6.service
sudo systemctl enable mysql-5.7.service

Now both MySQL containers should be started after system boot.
You can use this method as a replacement for the default system packages. Personally, I use it on all my development machines to install software that isn’t available in the system package repositories. I also use it to run multiple versions of the same server (PostgreSQL, MySQL, MongoDB, etc) for all non-dockerized applications I work on.
Why don’t you also check out our Introduction to Docker presentation?

Do you like this article?
Tags
Share