Writ

Docker network, duplicating apps

2019-12-31

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.

The setup

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.

The problems

container_name

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.

names on the internal network, and nginx

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
All site content protected by CC-BY-4.0 license