Docker Compose:实现同一配置文件中容器的网络互通
解决Docker Compose中Flask容器互相通信的问题
嘿,这个问题我熟!Docker Compose 其实默认就给同个配置里的容器搭好了专属通信网络,咱们一步步把坑填上就行~
核心原理:Docker Compose默认网络
当你用docker-compose up启动服务时,它会自动创建一个以项目目录名为前缀的桥接网络(比如你的项目在my-flask-project目录,网络名就是my-flask-project_default)。所有在这个docker-compose.yaml里定义的服务,都会自动加入这个网络,并且:
- 容器之间可以直接用服务名称作为主机名访问(不用记IP)
- 通信时用容器内部暴露的端口,不需要依赖宿主机的端口映射(宿主机端口是给外部访问用的)
你可能踩的几个坑(以及解决办法)
1. Flask服务绑定了127.0.0.1,导致外部无法访问
这是最常见的问题!如果你的Flask代码里写的是app.run(port=5000),默认会绑定127.0.0.1——这意味着只有容器自己能访问这个服务,同一个网络的其他容器根本连不上。
修正代码:必须绑定0.0.0.0,允许所有IP访问:
if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) # 重点是host='0.0.0.0'
2. 用localhost或宿主机IP访问另一个容器
容器里的localhost指的是容器自己,不是宿主机也不是另一个容器!比如在service-b里访问http://localhost:5000,只会请求service-b自己的5000端口,而不是service-a的。
正确姿势:用docker-compose.yaml里定义的服务名作为主机名,比如你的service叫flask-a,就访问http://flask-a:5000。
完整示例配置
docker-compose.yaml
version: '3.8' services: flask-a: build: ./flask-a # 指向你的flask-a项目目录(含Dockerfile) ports: - "5001:5000" # 宿主机5001端口映射容器5000,给外部访问用 # 无需手动指定网络,默认加入项目专属网络 flask-b: build: ./flask-b ports: - "5002:5000" # 直接通过服务名访问flask-a:5000即可
Flask服务的Dockerfile(两个服务通用)
FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir flask requests # 根据你的依赖调整 COPY . . CMD ["python", "app.py"]
flask-a的app.py
from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "Hello from Flask Service A!" if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
flask-b的app.py(调用flask-a)
from flask import Flask import requests app = Flask(__name__) @app.route('/') def call_flask_a(): try: # 用服务名flask-a作为主机名,端口是容器内部的5000 response = requests.get('http://flask-a:5000') return f"Flask B received: {response.text}" except Exception as e: return f"Failed to connect to Flask A: {str(e)}" if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
验证步骤
- 把上述文件放到对应目录,运行
docker-compose up --build - 打开浏览器访问
http://localhost:5002,应该能看到Flask B返回的来自Flask A的内容 - 如果还是有问题,进入容器内部测试连通性:
# 进入flask-b容器 docker exec -it <你的flask-b容器ID> bash # ping flask-a,看能不能解析到IP ping flask-a # 用curl测试访问 curl http://flask-a:5000
可选:自定义网络(非必须)
如果你想更灵活地管理网络,可以手动定义一个网络,然后让服务加入:
version: '3.8' networks: flask-network: driver: bridge # 默认就是bridge,可省略 services: flask-a: build: ./flask-a ports: - "5001:5000" networks: - flask-network flask-b: build: ./flask-b ports: - "5002:5000" networks: - flask-network
效果和默认网络完全一样,只是名字更清晰而已。
内容的提问来源于stack exchange,提问作者funseiki




