In Docker Compose 1.6 or higher Networks and Volumes are now first class citizens. This means you have more control and you can use individual services in one or more networks. Sharing volumes have been improved. It was never so easy. A new docker-compose.yml
format was introduced. The Docker compose config file must start with an entry version: "2"
to use the new features. This blog post covers a typical web server stack with nginx, PHP-FPM and MariaDB with the new Docker Compose configuration format.
Docker Named Volumes
One really interesting point is to use named volumes. You can create new volumes with docker volume create my-volume
or you can use Docker Compose too. The latter one creates a default volume with the prefix of the name of the project. With this, you don't need data only containers anymore. Which is a good benefit. The command docker-compose ps
won't have extra dead entries, and docker volume ls
will have more descriptive output, because volumes have names. I guess there is also a slightl performance improvement, if you have some data only containers, because Docker Compose doesn't have to start the data only containers.
So, when should I use named volumes? Every time, especially for persistence data like Databases! One benefit is, that you have only change the volume driver and then you can use flocker for instance. This could be useful for production. For development, you can mount your PHP files directly in the container. You can read more about best practices in Docker for PHP Developers.
Docker with Multiple Networks
A DNS is embedded in the Docker engine to auto discover services by name. No link definitions needed, but you can still use it. You can access other container by their name from another container in the same network. No linking means a faster start of the application, because of the asynchronous start. You can put Docker Container on different networks to increase the security, for instance frontend and backend.
Typical web server stack
The new Docker Compose configuration format has three top level keys named services, volumes and networks. The following server stack contains a nginx, PHP-FPM and a MariaDB (MySQL) container with a named data volume for the database data. Only the nginx Docker container is in the frontend network. The others are put to the backend network.
version: '2'
services:
#
# [ server stack ]
#
# - nginx
# - php
# - mysql
#
nginx:
image: prooph/nginx:www
restart: "always"
links:
# nginx access the php-fpm container with php
- php-fpm:php
networks:
- frontend
# nginx must communicate with php-fpm from the backend network
- backend
php-fpm:
image: prooph/php:7.0-fpm
restart: "always"
# see 12factor.net why env variables are used here
environment:
- MYSQL_HOST=${MYSQL_HOST}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
networks:
- backend
mysql:
image: mariadb
restart: "always"
# named volumes come here into play
volumes:
- data-mysql:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
networks:
- backend
#
# [ volumes definition ]
#
# creates Docker volumes which can be mounted by other containers too e.g. for backup
#
volumes:
data-mysql:
driver: local
#
# [ networks definition ]
#
networks:
frontend:
driver: bridge
backend:
driver: bridge
Conclusion
The new features of Docker Compose and Docker gives you great benefits. Faster Docker container starts, increased network security and better portability of the volumes. Further Docker daemon improvement is to use the overlayfs storage driver. Remember that you can also use multiple Docker Compose configuration files and merge or extend from them. One example is to setup your production configuration and overwrite only the parts for development e.g. ports or volume definitions.