I ran across the case where i wanted to run the same application (a pair of containers in a docker-compose manifest) twice on the same server. The exact use case was to have each set have different mounts, and env vars (in my case, so that they’d serve different content on different subdomains). It’s not always immediately obvious how to do this, and nobody seemed to have a post on it, so here we are.
Here’s what i had:
version: '2'
services:
writstatic:
image: writstatic:latest
container_name: writstatic
links:
- writ
environment:
VIRTUAL_HOST: writ.glester.com
VIRTUAL_PORT: 80
writ:
image: writ:latest
container_name: writ
expose:
- 8080
volumes:
- /var/lib/writ:/usr/share/writ:ro
I wanted to copy that, and have the second one look like;
version: '2'
services:
writstatic-blog:
image: writstatic:latest
container_name: writstatic-blog
links:
- writ
environment:
VIRTUAL_HOST: thoughts.glester.com
VIRTUAL_PORT: 80
writ-blog:
image: writ:latest
container_name: writ-blog
expose:
- 8080
volumes:
- /var/lib/writ-blog:/usr/share/writ:ro
Not all that different - one container has a different mount path, the other has a different env var.
An important note (it’ll come up later) - the "static" site is using nginx to do reverse proxying for some paths back to the other server. It’s just an nginx.conf with some static files included.
You’ll note that there’s a static container_name set on each. That conflicts. docker-compose normally generates container names that won’t conflict, but i tend to like setting my own. You might too. Just getting rid of the container_name fixes all this.
If you didn’t touch the first container, and just ran this second one, you’ll probably find that your new setup is actually serving content from the first one - because the nginx.conf from the static site says to hit writ - which is already on the subdomains network. The one you just made for the second site is something like writblog_writ_1, and is totally unused.
Now, your first thought is probably to simply change your nginx.conf to use an env var to determine which hostname to hit, that way everything can stay on the same network. However, you’ll quickly be reminded that nginx can’t use env vars in conf. The best suggested solution is pretty reasonable - building a wrapper script which invokes envsubst to generate the conf file at startup. I’ve done it for other projects. But for some reason, I really didn’t want to rebuild my application container.
Instead, you can put the writ container in its own network, then have two networks on the static host - one to accept requests, another to proxy through to writ.
Before actually showing it, I ought to note that this is cool, but also pretty sysadmin-ey. It’s fragile, and duct-tapey, and is probably harder to grok than just saying "if you use this application, set this env var". I’m posting all this in the first place in the hopes that someone who doesn’t have the option to rebuild the application container can do so.
version: '2'
services:
writstatic-blog:
image: writstatic:latest
restart: unless-stopped
links:
- writ
environment:
VIRTUAL_HOST: thoughts.glester.com
VIRTUAL_PORT: 80
expose:
- 80
networks:
- writ-blog
- subdomains
writ:
image: writ:latest
restart: unless-stopped
expose:
- 80
volumes:
- /var/lib/boji/data/writBlog:/usr/share/writ:ro
networks:
- writ-blog
networks:
subdomains:
external:
name: subdomains_subdomains
writ-blog:
driver: bridge