Way back in the when I first started using Docker in earnest, I wrote about my web hosting stack. Recently, this has undergone an upgrade as I’m working on a new website which will be served from the same server. I took the opportunity to split the system up into multiple docker-compose
projects, which makes deployment of further sites much easier. It allows me to manage the common containers from one docker-compose
project and then each of the sites from their own project. This will be of further use in future as I move towards deploying these with Ansible.
The Approach
My basic approach here is to move my two common containers (my Traefik container and SMTP forwarder) into their own project. This project will create a couple of networks for interfacing to the containers from other projects. To create these networks I add the following to my common project docker-compose.yml
:
networks:
gateway:
name: 'gateway'
smtp:
name: 'smtp'
Here I create two networks as per normal. The key is to give them a proper name, rather than the auto generated one that would be assigned by Docker. This will enable us to address them easily from our other projects. We then assign these to our common containers:
services:
traefik:
image: traefik:2.1
command:
...
volumes:
...
ports:
- "80:80"
- "443:443"
- "127.0.0.1:8080:8080"
networks:
gateway:
aliases:
# add hostnames you might want to refer to this container by
- example.com
restart: always
postfix:
image: boky/postfix
ports:
...
environment:
...
volumes:
...
networks:
smtp:
aliases:
- postfix
restart: always
Here I simply assign the relevant network to each container. The aliases section allows other containers on these networks to find our common containers by whatever name we specify. In the case of the postfix
container this is to connect via SMTP. For the traefik
container, adding hostnames which internal apps my need to refer to can help (for example with the WordPress loopback test).
External Projects
With this in place, the other applications can be moved out into their own projects. For each one we need to access the gateway
and smtp
networks in order to have access to our common services. These are accessed as external networks via the docker-compose.yaml
file for our project:
networks:
gateway:
external: true
smtp:
external: true
We then go ahead and add our services to access these networks:
services:
varnish:
image: wodby/varnish:latest
depends_on:
- wordpress
environment:
...
labels:
- 'traefik.enable=true'
- "traefik.docker.network=gateway"
...
networks:
- gateway
- cache
restart: always
wordpress:
image: wordpress:latest
depends_on:
- mariadb
environment:
...
volumes:
...
networks:
smtp:
cache:
database:
restart: always
Here I add my varnish cache, as per my previous article. The key thing here is to specify the label traefik.docker.network=gateway
to allow Traefik to reliably discover the container. We then also make sure the container is added to the gateway
network. I’ve also added a WordPress container, which is on the smtp
network. This will allow sending of email from WordPress via the SMTP forwarder.
Conclusion
This is a pretty simple approach for better management of my increasingly complex web stack. As I mentioned earlier that the next step will be to deploy these projects via Ansible. In this case the common containers will become part of a role which can be used across my infrastructure.
The splitting out of the apps into their own projects has enabled me to duplicate my current WordPress+Varnish+Mariadb setup for the new site I’m working on. There will be more info to come about that site as soon as I am ready to share!
One response to “Quick Project: Splitting Docker Compose Projects”
[…] I split up my increasingly complex Docker web stack into multiple projects, with common and application containers separated by shared networks. Read more […]