在DigitalOcean Droplet部署双应用失败,跨应用连接遇EOF错误求助
跨Docker Compose服务通信异常排查(DigitalOcean Droplet环境)
问题背景
我有两个独立Docker Compose管理的应用,本地部署正常,但放到DigitalOcean Droplet后出现通信故障:
- Python Flask应用(Gunicorn运行):负责拉取互联网数据存入PostgreSQL,仅接受本地连接,当前运行正常
- Golang应用:拉取互联网数据后,需请求Flask接口获取数据并存入自身PostgreSQL
- 异常表现:Golang应用向
http://jobs-web:5000或http://jobs:5000发起GET请求时,返回EOF错误
现有Compose文件
Flask应用Compose
web: container_name: jobs-web build: . command: [ "gunicorn", "-b", "0.0.0.0:5000", "app:create_app()", "--log-level", "debug", "--access-logfile", "-", "--error-logfile", "-", "--timeout", "0", "--preload", ] environment: ENABLE_SCHEDULER: ${ENABLE_SCHEDULER} FLASK_ENV: production SQLALCHEMY_DATABASE_URI: ${SQLALCHEMY_DATABASE_URI} volumes: - .:/app depends_on: - db networks: - fullstack db: container_name: jobs-db image: postgres:16.4-alpine3.20 restart: always environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} volumes: - postgres_data:/var/lib/postgresql/data - ./init-db.sh:/docker-entrypoint-initdb.d/init-db.sh - ./.env:/app/.env networks: - fullstack networks: fullstack: external: true volumes: postgres_data: test_postgres_data:
Golang应用Compose
services: remoti-db: image: postgres:16.4-alpine3.20 container_name: remoti-db ports: - 5432:5432 restart: always environment: - POSTGRES_DB=${DB_NAME} - POSTGRES_USER=${DB_USERNAME} - POSTGRES_PASSWORD=${DB_PASSWORD} networks: - remoti-network volumes: - database_postgres:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, "pg_isready -U ${DB_USERNAME}"] interval: 3s timeout: 3s retries: 5 expose: - "5432" app: build: context: . dockerfile: Dockerfile container_name: remoti-app ports: - 4000:4000 depends_on: remoti-db: condition: service_healthy networks: - fullstack - remoti-network prometheus: image: prom/prometheus ports: - 9090:9090 volumes: - prometheus:/prometheus - ./prometheus/development.yml:/etc/prometheus/prometheus.yml networks: - remoti-network grafana: image: grafana/grafana ports: - 3000:3000 depends_on: - prometheus networks: - remoti-network volumes: - grafana:/var/lib/grafana - ./grafana/provisioning/datasources:/etc/grafana/provisioning/datasources - ./grafana/provisioning/dashboards:/etc/grafana/provisioning/dashboards - ./grafana/dashboards:/etc/dashboards - ./grafana/grafana.ini:/etc/grafana/grafana.ini migrations: image: migrate/migrate:latest env_file: - .env command: -path /migrations -database ${DSN} up volumes: - ./migrations:/migrations networks: - remoti-network depends_on: remoti-db: condition: service_healthy volumes: database_postgres: migrations: prometheus: grafana: networks: fullstack: external: true remoti-network: driver: bridge
排查步骤与解决方案
1. 确认外部网络一致性
两个Compose都声明了external: true的fullstack网络,需确保Droplet上该网络为同一个:
- 执行
docker network ls查看网络ID,确认两个服务连接的fullstack网络ID一致 - 若不一致,先删除旧网络:
docker network rm fullstack,重启Flask应用Compose(会创建外部网络),再启动Golang应用Compose
2. 验证Flask端口可达性
进入Golang应用容器,直接测试Flask服务:
- 进入容器:
docker exec -it remoti-app sh - 用curl调试:
curl -v http://jobs-web:5000- 连接被拒绝:检查Flask容器是否正常启动,确认Gunicorn绑定
0.0.0.0:5000(配置已正确),查看容器日志docker logs jobs-web排查启动错误 - 返回EOF:检查Flask应用日志,看请求处理时是否提前断开连接
- 连接被拒绝:检查Flask容器是否正常启动,确认Gunicorn绑定
3. 检查Droplet防火墙/安全组
DigitalOcean Droplet的防火墙规则可能拦截容器间通信:
- 放行容器内部网段流量(默认Docker网段为172.17.x.x或自定义网段)
- 无需对外暴露Flask的5000端口,只需保证内部网络互通
4. 优化服务启动顺序
Flask可能在DB未完全就绪时启动,导致后续请求异常:
- 给Flask的
web服务添加健康检查(需Flask提供健康接口):web: # ... 其他配置 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:5000/health"] interval: 5s timeout: 3s retries: 3 - Golang应用可添加对Flask服务的依赖:
app: # ... 其他配置 depends_on: remoti-db: condition: service_healthy jobs-web: condition: service_healthy
5. 验证容器DNS解析
在Golang容器内测试DNS解析:
- 执行
nslookup jobs-web,确认能解析到Flask容器IP - 若解析失败,检查Docker DNS配置,或直接用Flask容器IP测试:
curl http://<容器IP>:5000
内容的提问来源于stack exchange,提问作者noloman
相关产品推荐
相关产品推荐

