docker:将结构拆分为有用的网络

docker: split structure into usefull networks

我不太确定 docker 网络的正确用法。

我是 运行 一个(单一托管的)反向代理和应用程序本身的容器,但我想设置 proxyfrontendbackend。 project1 的最后一个,假设最后可能有多个项目。 但我什至不确定,如果这种结构是它应该做的方式。我认为后端应该只供前端访问,前端应该可供代理访问。

所以这是我目前只有一个网络(网桥)的工作结构 - 这没有意义:

  1. 反向代理(网络:反向代理):
    • jwilder/nginx-proxy
    • jrcs/letsencrypt-nginx-proxy-companion
  2. 数据库
    • mongo:3.6.2
  3. 项目 1
    • one/frontend
    • one/backend
    • two/frontend
    • two/backend

所以我的第一个 docker-compose 看起来像这样:

version: '3.5'

services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    networks:
      - reverse-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/docker/nginx-proxy/vhost.d:/etc/nginx/vhost.d:rw
      - html:/usr/share/nginx/html
      - /opt/nginx/certs:/etc/nginx/certs:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro

  nginx-letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: nginx-letsencrypt
    networks:
      - reverse-proxy
    depends_on:
      - nginx-proxy
    volumes:
      - /var/docker/nginx-proxy/vhost.d:/etc/nginx/vhost.d:rw
      - html:/usr/share/nginx/html
      - /opt/nginx/certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock:rw
    environment:
      NGINX_PROXY_CONTAINER: "nginx-proxy"

  mongodb:
    container_name: mongodb
    image: mongo:3.6.2
    networks:
      - reverse-proxy

volumes:
  html:

networks:
  reverse-proxy:
    external:
      name: reverse-proxy

这意味着我之前必须创建 reverse-proxy。到目前为止,我不确定这是否正确。

项目应用程序——前端容器和后端容器——是由我的CI使用docker命令创建的(不是docker组合):

docker run
  --name project1-one-frontend
  --network reverse-proxy
  --detach
  -e VIRTUAL_HOST=project1.my-server.com
  -e LETSENCRYPT_HOST=project1.my-server.com
  -e LETSENCRYPT_EMAIL=mail@my-server.com
  project1-one-frontend:latest

我应该如何将其分成有用的网络?

TL;DR;您可以将多个网络附加到给定的容器,这让您可以在很大程度上隔离流量。

useful networks

从上下文来看,我从问题中推断 "useful" 意味着服务之间存在某种程度的隔离。

I think the backend should only be accessable for the frontend and the frontend should be accessable for the proxy.

docker-compose 这很简单。只需在顶层指定您想要的网络,就像您为 reverse-proxy:

所做的一样
networks:
  reverse-proxy:
    external:
      name: reverse-proxy
  frontend:
  backend:

然后是这样的:

version: '3.5'

services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    networks:
      - reverse-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      ...

  frontend1:
    image: some/image
    networks:
      - reverse-proxy
      - backend

  backend1:
    image: some/otherimage
    networks:
      - backend

  backend2:
    image: some/otherimage
    networks:
      - backend

  ...

这样设置,只有frontend1可以到达backend1backend2我知道这不是一个选项,因为您说过您要通过 docker run 运行安装应用程序容器(前端和后端)。但我认为它很好地说明了如何在 Docker 的网络中大致实现您所追求的目标。

那么,您如何才能做到上面 docker-compose.yml 中说明的内容呢?我发现了这个:https://success.docker.com/article/multiple-docker-networks

总而言之,您只能使用 docker run 连接一个网络,但您可以使用 docker network connect <container> <network> 将 运行ning 容器启动后连接到更多网络。

创建网络的顺序,运行 docker-compose up 或 运行 管道中的各种容器由您决定。如果愿意,您可以在 docker-compose.yml 中创建网络,或者使用 docker network create 并将它们导入到您的 docker-compose 堆栈中。这取决于您如何使用此堆栈,这将决定此处的操作顺序。

可能显而易见的指导原则是,在您尝试将网络附加到容器之前,网络需要存在。最直接的管道可能看起来像..

  1. docker-compose up 以及 docker-compose.yml
  2. 中定义的所有网络
  3. 每个应用程序容器:

    docker run容器

    docker network attach 正确的网络

... would like to set up networks like proxy, frontend and backend. ... I think the backend should only be accessable for the frontend and the frontend should be accessable for the proxy.

docker 中的网络不与其他 docker 网络通信,因此我不确定以上内容是否指的是这些网络上的网络或容器。您可以拥有的是多个 docker 网络上的容器,它可以与任一网络上的服务通信。

使用 docker 设计网络布局的重要部分是同一网络上的任何两个容器都可以相互通信,并且可以使用 DNS 找到彼此。人们经常搞砸的地方是为反向代理创建代理网络之类的东西,将多个微服务附加到代理网络,然后突然发现该代理网络上的所有内容都可以找到彼此。所以如果你有多个项目需要相互隔离,它们不能存在于同一个网络中。

换句话说,如果 app-a 和 app-b 不能相互通信,但确实需要与共享代理通信,那么共享代理需要在多个应用特定网络上,而不是每个应用都在在同一个共享代理网络上。

根据您的体系结构,这可能会变得更加复杂。例如。我一直想使用的一种设计是让每个堆栈都有自己的反向代理,该反向代理连接到应用程序专用网络和共享代理网络,而不发布任何端口。然后全局反向代理发布端口并与每个堆栈特定的反向代理对话。这样做的好处是全局反向代理不需要提前知道所有潜在的应用网络,同时仍然允许你只暴露一个端口,而不是让微服务通过共享代理网络相互连接。