Networking

Docker:在網路級別隔離組合堆棧,同時允許 Traefik 反向代理單個服務

  • December 14, 2021

我正在嘗試保護我的家庭實驗室中的容器。

主要目標是:

  • 隔離nginxAnginxB,因此它們無法通過彼此交談172.17.0.1(例如,阻止nginxA通過到達nginxB172.17.0.1:5001
  • 將nginxAnginxB與 localhost隔離,使它們可以通過 traefik 獨占訪問
  • 允許nginxA與位於同一堆棧中的nginxA_DB對話,但不允許其他容器或 traefik 與nginxA_DB 對話

每個 docker 堆棧都有一個 nginx/apache 服務,它的埠以下列方式暴露在 docker-compose 中:

docker-compose-nginxA.yml:

networks:
 internal:
   ipam:
     config:
       - subnet: 10.0.0.0/29

...SNIP...

nginxA:
 networks:
   internal:
     ipv4_address: 10.0.0.2
 ports:
   - "172.17.0.1:5000:80"

docker-compose-nginxB.yml:

networks:
 internal:
   ipam:
     config:
       - subnet: 10.0.0.8/29

...SNIP...

nginxB:
 networks:
   internal:
     ipv4_address: 10.0.0.10
 ports:
   - "172.17.0.1:5001:80"

使這些服務只能通過localhost (172.17.0.1) 或traefik 訪問

Traefik 也在同一台機器上,配置如下:

http:

 routers:

   nginxA:
    entryPoints:
      - web
    service: nginxA

   nginxB:
    entryPoints:
      - web
    service: nginxB


...SNIP...

 services:

   nginxA:
     loadBalancer:
       servers:
         - url: http://172.17.0.1:5000

   nginxB:
     loadBalancer:
       servers:
         - url: http://172.17.0.1:5001

一個想法是/24用 traefik 連接同一網路中的所有容器,而不通過 compose 暴露任何埠,但是單個 traefik 網路不會將容器彼此隔離,只會與外部隔離。

另一個想法是為每個容器創建一個/31網路並合併所有網路 traefik,但我不確定這是否會按預期進行隔離。例如。

nginxA:
 networks:
   internal:
     ipv4_address: 10.0.0.2 # /29
   nginxA-traefik:
     ipv4_address: 10.50.0.1 # /31

traefik:
 networks:
   nginxA-traefik:
   nginxB-traefik:
 ...

感謝您閱讀到這裡!你有什麼想法可以做到這一點嗎?

你在正確的軌道上。與上一個範例一樣,您希望為兩個容器之間的每個通信路徑創建一個單獨的網路。只要子網不同,這些都可以是/31’s 或s 或任何您想要的。/29

例子:

  • nginxA-traefik連接nginxAtraefik
  • nginxB-traefik連接nginxBtraefik
  • nginxA-nginxA_DB連接nginxAnginxA_DB

您不應該對nginx容器進行任何埠映射,因為traefik它將直接通過 docker 網路與它們通信。這將允許每個nginx容器相互通信traefik(反之亦然),但它們不能相互通信。


然而!這不能很好地擴展,因為您必須為連接到 traefik 的每個服務創建/管理一個網路,這將很快變得笨拙。更好的方法是為所有與 traefik 連結的服務(例如 )創建一個網路traefik_public,將所有服務容器(即nginx_Anginx_B以及其他任何東西)連接到該網路,並添加一些規則iptables以僅允許進出traefik.

我編寫了一個非常簡單的容器防火牆,它會iptables自動為您處理規則:https ://github.com/kaysond/trafficjam 您只需指定要保護的網路(traefik_public)和允許與/來自通信的容器(例如ancestor=traefik:latest),它會照顧其餘的!

引用自:https://serverfault.com/questions/1082384