How to create an optimal Docker environment

In order to develop software, it is necessary to have a local environment with all the available services needed to run the application being developed correctly.

For example, if you are developing a web application with Symfony, you will need to have a webserver such as Apache or Nginx, a PHP interpreter and probably a database on which to save data, such as Postgre or MySql.

Docker environment

How can Docker help you?

Docker allows you to split these three parts by launching three isolated environments, with a service running in each. These isolated environments are Docker containers. So, following the example, to run our application correctly we will need to have three containers running: one for the web server, one with the PHP interpreter and one with the database.

Running these containers alone is not enough. We also need to make them communicate with each other. As we said, each container is an isolated environment and is unaware of the outside world. Because of this, the PHP container is not aware of the fact that there is a MySql container to connect to.

Docker compose

Docker compose is a tool that allows for the creation of multi-container applications. It is widely used for configuring development environments locally, because it is easy to set up and the command line api is very simple and quick to learn.

It is configured with a yaml file, which is named docker-compose.yaml by convention but not necessarily. Take care, however, as it is also possible to use a different file by specifying it when Docker compose is started.

Once the configuration file is ready, it is possible to launch the containers with the command:

docker-compose up

…and to stop all containers with the command:

docker-compose down

The docker-compose.yaml file

Let’s see what a configuration file for Docker compose looks like.

version: ‘3.4’
services:
myappdb:
image: mysql:5.7.29
container_name: myappdb
volumes:
– ./docker:/init
command: –init-file /init/db-init.sql
environment:
MYSQL_ROOT_PASSWORD: “secret”
nginx:
image: nginx:latest
container_name: myapp-nginx
ports:
– 80:80
volumes:
– ./docker/nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
– “myapp”
myapp:
build:
context: ./
container_name: myapp
volumes:
– ./:/var/www/myapp

Let’s now look at the interesting parts of this file to understand how each one works.

version: ‘3.4’

This is the version of the configuration syntax used.

myappdb:

Each service is distinguished by a name. This name is very important and must be unique. In fact it is used as a namespace to reach the container. For example, in this case the PHP application will have to try to connect to the database which has the hostname “myappdb” and port 3306.

image: mysql:5.7.29
Image from which to initialise the container.

container_name: myappdb
Name of the container.

volumes:
– ./docker:/init

With this statement, we map a local folder to one inside the container so that the files it contains can be reachable by a process running inside the container.

command: –init-file /init/db-init.sql

Add the argument to the main Dockerfile command or overrides it.

environment:
MYSQL_ROOT_PASSWORD: “secret”

It is possible to assign environment variables.

ports:
– 80:80

It is possible to map a port so that it can be reached by the host. In this case, we will be able to reach the nginx container through port 80.

build:
context: ./

For the PHP container, we don’t start from a ready image but rather we create it dynamically by looking for a Dockerfile in the specified folder.

Official resources

Docker compose Documentation and Docker compose reference reference to consult anytime, anywhere!

To conclude

We wanted to give you a rough idea of what Docker compose is and how it works. Check out the official documentation and start experimenting locally. The best way to learn is to get your hands dirty!

Read related articles