隔离jwilder / nginx-proxy网络上的容器

Chr*_*ris 5 docker docker-compose jwilder-nginx-proxy

我正在使用jwilder / nginx-proxy从单个服务器托管多个(web)应用程序。这非常有效,除了所有服务可以相互通信是因为它们都在同一网络上,这是代理正常工作所必需的。

代理 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
Run Code Online (Sandbox Code Playgroud)

应用程式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: user@example.com

  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
Run Code Online (Sandbox Code Playgroud)

应用程式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: user@example.com

  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
Run Code Online (Sandbox Code Playgroud)

通过此设置,两个应用程序都将使用应用程序1的de dbcache实例。解决该问题的唯一方法是为这些服务赋予唯一的名称,例如app_1_dbapp_2_db。但随后App 1仍然可以连接到app_2_db我要阻止的应用。

有没有办法在docker-composer.yaml文件中隔离所有服务并仍然使用Nginx代理?

Docker version 18.09.0, build 4d60db4
docker-compose version 1.21.2, build a133471
Run Code Online (Sandbox Code Playgroud)

mic*_*sna 7

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

and in your apps:

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

networks:
  nginx-proxy_app1:
    external: true
Run Code Online (Sandbox Code Playgroud)

and

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

networks:
  nginx-proxy_app2:
    external: true
Run Code Online (Sandbox Code Playgroud)

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: