Isolate containers on the jwilder/nginx-proxy network
Asked Answered
P

1

11

I'm using jwilder/nginx-proxy to host multiple (web)apps from a single server. This is working great except that all services can communicate with each other because they are all on the same network because that is required for the proxy to work.

Proxy docker-compose.yaml

version: "3"

services:

  nginx-proxy:
    image: jwilder/nginx-proxy:alpine
    container_name: nginx-proxy
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./data/certs:/etc/nginx/certs:ro
      - ./data/nginx/vhost.d:/etc/nginx/vhost.d
      - ./data/share/nginx/html:/usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro
    restart: always

  letsencrypt-proxy:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: letsencrypt-proxy
    depends_on:
      - nginx-proxy
    volumes:
      - ./data/nginx/vhost.d:/etc/nginx/vhost.d
      - ./data/share/nginx/html:/usr/share/nginx/html
      - ./data/certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: always



networks:
  default:
    external:
      name: nginx-proxy

App 1 docker-compose.yaml

version: "3"

services:

  app:
    image: nginx:latest
    depends_on:
      - db
      - cache
    expose:
      - 80
    volumes:
      - ./application:/var/www/html
    restart: always
    working_dir: /var/www/html
    environment:
      VIRTUAL_HOST: app1.example.com
      LETSENCRYPT_HOST: app1.example.com
      LETSENCRYPT_EMAIL: [email protected]

  cache:
    image: redis:alpine
    restart: always
    volumes:
      - cachedata:/data

  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpasswd
      MYSQL_DATABASE: database_name
      MYSQL_USER: database_user
      MYSQL_PASSWORD: database_passwd
    volumes:
      - dbdata:/var/lib/mysql

networks:
  default:
    external:
      name: nginx-proxy

volumes:
  dbdata:
    driver: local
  cachedata:
    driver: local

App 2 docker-compose.yaml

version: "3"

services:

  app:
    image: nginx:latest
    depends_on:
      - db
      - cache
    expose:
      - 80
    volumes:
      - ./application:/var/www/html
    restart: always
    working_dir: /var/www/html
    environment:
      VIRTUAL_HOST: app2.example.com
      LETSENCRYPT_HOST: app2.example.com
      LETSENCRYPT_EMAIL: [email protected]

  cache:
    image: redis:alpine
    restart: always
    volumes:
      - cachedata:/data

  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpasswd
      MYSQL_DATABASE: database_name
      MYSQL_USER: database_user
      MYSQL_PASSWORD: database_passwd
    volumes:
      - dbdata:/var/lib/mysql

networks:
  default:
    external:
      name: nginx-proxy

volumes:
  dbdata:
    driver: local
  cachedata:
    driver: local

With this setup both applications will use de db and cache instance of App 1. The only way to solve that is to give those services unique names like app_1_db and app_2_db. But then App 1 is still able to connect to the app_2_db which I would like to prevent.

Is there a way to isolate all services within their docker-composer.yaml file and still use the nginx proxy?

Docker version 18.09.0, build 4d60db4
docker-compose version 1.21.2, build a133471
Pot answered 2/12, 2018 at 12:13 Comment(0)
A
14

You can connect only the app(nginx) container from your apps to the nginx-proxy network. The only edit needed should be in the app's docker-compose:

version: '3'
services:
  app:
    networks:
      - default
      - nginx-proxy

networks:
  nginx-proxy:
    external: true

That way the app service will be connected to nginx-proxy and default networks at the same time. (If you omit networks key, service is always connected to the default network)

Resolving service names to containers ip's then works as expected as long as no container can see (across all networks it's connected to) two containers with same service name.


If you want even more isolation, you can create nginx-proxy network for every app. So in your nginx-proxy docker-compose you will have:

version: "3"

services:
  nginx-proxy:
    networks: 
      - default
      - nginx-proxy_app1
      - nginx-proxy_app2

# letsencrypt-proxy service doesn't have to have networks key

networks:
  nginx-proxy_app1:
    external: true
  nginx-proxy_app2:
    external: true

and in your apps:

version: '3'
services:
  app:
    networks:
      - default
      - nginx-proxy_app1

networks:
  nginx-proxy_app1:
    external: true

and

version: '3'
services:
  app:
    networks:
      - default
      - nginx-proxy_app2

networks:
  nginx-proxy_app2:
    external: true

That way in every "proxy" network there is only one (if you are not using docker-compose scaling) app container and the nginx-proxy container.


More reading:

Absolve answered 5/12, 2018 at 16:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.