如何实现同一主机不同网络下多Nginx容器的互联?
问题描述
同一主机上部署了13个独立容器化的微服务,每个微服务包含PHP、Nginx和MySQL组件。需要实现微服务MS1的Nginx向微服务MS2的Nginx发起HTTP请求,咨询该需求是否可实现,并提供了sale-service和product-service的docker-compose配置示例。
sale-service配置示例:
version: '3' networks: sale_network: driver: bridge services: sale_php: build: context: ${SALE_DIRECTORY} dockerfile: php8.1.Dockerfile container_name: "sale_php" restart: unless-stopped tty: true networks: - sale_network volumes: - ${SALE_DIRECTORY}:/var/www/html ports: - "${SALE_PHP_PORT}:9000" sale_nginx: build: context: ${SALE_DIRECTORY} dockerfile: nginx.Dockerfile container_name: sale_nginx restart: unless-stopped tty: true ports: - "${SALE_NGINX_PORT}:80" networks: - sale_network volumes: - ${SALE_DIRECTORY}:/var/www/html depends_on: - sale_php sale_mysql: image: mysql:8.0.0 container_name: sale_mysql restart: unless-stopped tty: true volumes: - mysqldata:/var/lib/mysql ports: - "${SALE_MYSQL_PORT}:3306" environment: MYSQL_USER: ${SALE_MYSQL_USERNAME} MYSQL_PASSWORD: ${SALE_MYSQL_PASSWORD} MYSQL_ROOT_PASSWORD: ${SALE_MYSQL_PASSWORD} SERVICE_TAGS: sale networks: - sale_network volumes: mysqldata: driver: local
product-service配置示例:
version: '3' networks: product_network: driver: bridge services: product_php: build: context: ${PRODUCT_DIRECTORY} dockerfile: php8.1.Dockerfile container_name: "product_php" restart: unless-stopped tty: true networks: - product_network volumes: - ${PRODUCT_DIRECTORY}:/var/www/html ports: - "${PRODUCT_PHP_PORT}:9000" product_nginx: build: context: ${PRODUCT_DIRECTORY} dockerfile: nginx.Dockerfile container_name: product_nginx restart: unless-stopped tty: true ports: - "${PRODUCT_NGINX_PORT}:80" networks: - product_network volumes: - ${PRODUCT_DIRECTORY}:/var/www/html depends_on: - product_php product_mysql: image: mysql:8.0.0 container_name: product_mysql restart: unless-stopped tty: true volumes: - mysqldata:/var/lib/mysql ports: - "${PRODUCT_MYSQL_PORT}:3306" environment: MYSQL_USER: ${PRODUCT_MYSQL_USERNAME} MYSQL_PASSWORD: ${PRODUCT_MYSQL_PASSWORD} MYSQL_ROOT_PASSWORD: ${PRODUCT_MYSQL_PASSWORD} SERVICE_TAGS: product networks: - product_network volumes: mysqldata: driver: local
解决方案
完全可以实现该需求,核心是让需要通信的微服务容器处于同一个Docker网络中,容器间就能通过服务名或容器名直接通信。以下是具体实现步骤:
方法1:创建公共自定义网络(推荐)
这是最安全且灵活的方式,既能保留各微服务自身的网络隔离,又能实现跨微服务通信:
- 在主机上创建一个公共Docker网络:
docker network create microservices_common_network
- 修改每个微服务的docker-compose.yml,添加公共网络配置并让服务加入该网络。以sale-service为例:
version: '3' networks: sale_network: driver: bridge # 声明公共网络为外部已存在的网络 microservices_common_network: external: true services: sale_php: # 原有配置不变 networks: - sale_network - microservices_common_network # 加入公共网络 sale_nginx: # 原有配置不变 networks: - sale_network - microservices_common_network # 加入公共网络 sale_mysql: # 原有配置不变 networks: - sale_network - microservices_common_network # 加入公共网络 # 原有volume配置不变
- 同样修改product-service的配置,让其服务加入公共网络:
version: '3' networks: product_network: driver: bridge microservices_common_network: external: true services: product_php: # 原有配置不变 networks: - product_network - microservices_common_network product_nginx: # 原有配置不变 networks: - product_network - microservices_common_network product_mysql: # 原有配置不变 networks: - product_network - microservices_common_network # 原有volume配置不变
- 重启所有微服务容器后,sale_nginx即可通过
product_nginx:80(服务名+容器内部端口)访问product_nginx的服务,无需依赖主机映射的外部端口。
方法2:使用主机网络(不推荐)
如果不需要容器网络隔离,可让所有微服务直接使用主机网络栈:
修改每个docker-compose.yml的网络配置:
networks: hostnet: external: true name: host services: sale_nginx: # 原有配置不变 networks: - hostnet
这种方式下,sale_nginx可通过localhost:${PRODUCT_NGINX_PORT}访问product_nginx,但会失去容器网络的隔离性,端口冲突风险高,不适用于多微服务场景。
注意事项
- 容器间通信优先使用内部端口(如Nginx的80端口),无需依赖主机映射的外部端口,效率更高且更安全。
- 若未指定
container_name,可直接使用docker-compose中定义的服务名作为域名访问,Docker DNS会自动解析。 - 13个微服务均可按此方式配置,实现任意微服务间的容器通信。
内容的提问来源于stack exchange,提问作者M a m a D
相关产品推荐
相关产品推荐

