Ubuntu环境下Docker容器间通信故障排查:Django与Flask服务互访失败问题求助
Let's break down why your Flask container can't reach your Django service and fix it step by step:
Root Cause
Your two docker-compose projects are creating separate default networks by default, which means the Flask container can't resolve or reach the Django container. Using the host's Docker bridge IP (172.17.0.1) or tools like docker-host won't solve this because the containers aren't in the same network space.
Step 1: Create a Shared Docker Network
First, create a single external network that both projects will use. Run this command in your terminal:
docker network create ecommerce-shared-network
Step 2: Update Django's docker-compose.yml
Modify your Django docker-compose.yml to use the shared network instead of its isolated one:
version: '3.8' services: backend: build: context: . dockerfile: Dockerfile command: "python manage.py runserver 0.0.0.0:8000" ports: - 8000:8000 volumes: - .:/app depends_on: - db networks: - shared-network queue: build: context: . dockerfile: Dockerfile command: "python consumer.py" depends_on: - db networks: - shared-network db: image: mysql:5.7.22 restart: always environment: MYSQL_DATABASE: admin MYSQL_USER: root MYSQL_PASSWORD: root MYSQL_ROOT_PASSWORD: root volumes: - .dbdata:/var/lib/mysql ports: - 33066:3306 networks: - shared-network # Remove dockerhost and tcp_message_emitter - they're not needed for cross-container communication # Replace the old backend network with the shared external network networks: shared-network: external: true name: ecommerce-shared-network
Step 3: Update Flask's docker-compose.yml
Add the shared network to your Flask project's docker-compose.yml too:
version: '3.8' services: backend: build: context: . dockerfile: Dockerfile command: "python main.py" ports: - 8001:5000 volumes: - .:/app depends_on: - db networks: - shared-network queue: build: context: . dockerfile: Dockerfile command: "python consumer.py" depends_on: - db networks: - shared-network db: image: mysql:5.7.22 restart: always environment: MYSQL_DATABASE: main MYSQL_USER: root MYSQL_PASSWORD: root MYSQL_ROOT_PASSWORD: root volumes: - .dbdata:/var/lib/mysql ports: - 33067:3306 networks: - shared-network # Add the shared network definition networks: shared-network: external: true name: ecommerce-shared-network
Step 4: Update Flask Code to Use Django's Service Name
Instead of using the host IP (172.17.0.1), use the service name from Django's docker-compose (backend) as the hostname. Docker's built-in DNS will automatically resolve this to the Django container's IP within the shared network:
@app.route("/api/products/<int:id>/like", methods=["POST"]) def like(id): # Replace the hardcoded IP with the Django service name req = requests.get("http://backend:8000/api/user") json = req.json() try: product_user = ProductUser(user_id=json["id"], product=id) db.session.add(product_user) db.session.commit() publish("product_liked", id) except: abort(400, "You already liked this product") return jsonify({ "message": "success" })
Why This Works
- By putting both containers in the same network, they can communicate directly using their service names (no need for host IPs or port forwarding between containers).
- Docker's internal DNS handles resolving service names to container IPs, so you don't have to hardcode dynamic IP addresses.
- The
dockerhosttool is designed for containers to reach services running on the host machine, not for container-to-container communication—so we can safely remove it here.
Additional Checks
- Verify your Django
/api/userendpoint is working correctly by testing it directly viahttp://localhost:8000/api/userfirst. - Add healthchecks to your Django service to ensure it's fully ready before Flask tries to connect:
backend: # ... existing config ... healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/api/user"] interval: 10s timeout: 5s retries: 5
内容的提问来源于stack exchange,提问作者Luis Batista

