如何在docker swarm中禁用对覆盖网络的外部访问

如何在docker swarm中禁用对覆盖网络的外部访问,docker,nginx,docker-compose,reverse-proxy,Docker,Nginx,Docker Compose,Reverse Proxy,我正在尝试建立一个swarm,它具有以下服务: nginx作为反向代理(主要用于处理虚拟主机和SSL,尽管nginx.conf中没有这样做) 一个golang web应用程序 redis用于缓存 用于存储的postgresql 这将导致docker compose文件类似于: version: '3' services: proxy: image: nginx:1.13.5-alpine ports: - "80:80" deploy: p

我正在尝试建立一个swarm,它具有以下服务:

  • nginx作为反向代理(主要用于处理虚拟主机和SSL,尽管nginx.conf中没有这样做)
  • 一个golang web应用程序
  • redis用于缓存
  • 用于存储的postgresql
这将导致docker compose文件类似于:

version: '3'
services:
  proxy:
    image: nginx:1.13.5-alpine
    ports:
      - "80:80"
    deploy:
      placement:
        constraints: [node.role == manager]
    depends_on:
      - api
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    networks:
      - webnet

  api:
    image: user/webapp:latest
    deploy:
      replicas: 4
    ports:
      - "8000:8000"
    depends_on:
      - postgres
      - redis
    networks:
      - webnet

  postgres:
    image: postgres:9.6.5-alpine
    ports:
      - "5432:5432"
    deploy:
      placement:
        constraints: [node.role == manager]
    networks:
      - webnet

  redis:
    image: redis:4.0.2-alpine
    ports:
      - "6379:6379"
    deploy:
      placement:
        constraints: [node.role == manager]
    command: redis-server --appendonly yes
    networks:
      - webnet

networks:
  webnet:
我使用的nginx配置文件是:

upstream api {
    server api:8000;
}

server {
    listen 80;

    location / {
        proxy_pass http://api;
    }
}
这一切都在起作用。我可以使用curl和nginx服务代理从另一台机器连接到相应的webapp服务

问题是,我还可以从外部机器连接到redis、api和postgres服务

我想要的是只让代理服务可以从外部接口访问

我想确保redis、api和postgres服务只能通过swarm访问。(或者,只能在主机节点的本地网络上访问。在这种情况下,主机是CentOS 7,设置为swarm manager)

我没有使用webnet,而是尝试创建一个名为backend的覆盖网络,将
internal
设置为
true
。大概是这样的:

docker network create -d overlay --internal backend 
然后在docker-compose.yml文件中使用
后端
网络,而不是用于redis、postgres和api服务的webnet。这似乎不起作用。所有服务仍然可以在外部ip上使用

我可以通过以下方式解决此问题:

  • 阻止我不想公开的服务的端口
  • 执行上述操作,并将nginx作为主机上的代理(而不是容器)运行

虽然上述方法确实有效,但我还是希望所有这些逻辑都能在docker compose级别上实施,而不是依赖防火墙或外部进程。

如果您不希望端口可以从外部访问,那么就不需要发布这些端口。容器始终可以通过公共docker网络对容器进行通信,而无需发布端口

version: '3'
services:
  proxy:
    image: nginx:1.13.5-alpine
    ports:
      - "80:80"
    deploy:
      placement:
        constraints: [node.role == manager]
    depends_on:
      - api
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    networks:
      - webnet

  api:
    image: user/webapp:latest
    deploy:
      replicas: 4
    depends_on:
      - postgres
      - redis
    networks:
      - webnet

  postgres:
    image: postgres:9.6.5-alpine
    deploy:
      placement:
        constraints: [node.role == manager]
    networks:
      - webnet

  redis:
    image: redis:4.0.2-alpine
    deploy:
      placement:
        constraints: [node.role == manager]
    command: redis-server --appendonly yes
    networks:
      - webnet

networks:
  webnet:

嗨,很抱歉把这个挖出来,但我有一个相关的问题。在我的代码中,我按名称和端口调用容器,如
connectredis:6379
。如果我阻止端口访问,我是否只能使用
connect redis
调用该服务?@GustavoSilva这仍然是TCP网络,因此您需要连接到端口。另一个容器可能正在侦听多个端口,具体取决于该容器中运行的应用程序。根据您用于连接的应用程序的不同,它可能已经知道默认的redis端口,如果您不指定,则可以使用该端口,但这是特定于客户端应用程序的。