Docker Compose双网卡宿主机:配置Django容器访问外部PostgreSQL
Let's break down a clean, Docker-native approach to solve your problem without disrupting existing container communication or external network access.
Core Idea
Create a custom Docker bridge network explicitly bound to your VM_D's en1 interface (the one connected to VM_P). This lets your Django-related containers access VM_P's PostgreSQL via this custom network, while still keeping the default bridge network for communication with other services (Caddy, Redis, etc.).
Step 1: Create the Custom Network
First, create a bridge network tied to en1. Replace the subnet/gateway/IP values with ones matching your en1 network segment (run ip addr show en1 on VM_D to get these details):
docker network create \ --driver bridge \ --subnet 192.168.10.0/24 \ # Match en1's subnet --gateway 192.168.10.1 \ # Match en1's gateway -o "com.docker.network.bridge.host_binding_ipv4"="192.168.10.5" \ # en1's static IP on VM_D custom-postgres-net
Step 2: Update Your Docker Compose Config
Modify your production.yml to include the custom network and attach it to Django/Celery services:
- Add a
networkssection at the top level (undervolumes):
version: '2' volumes: caddy: {} networks: default: # Keep the default bridge network for internal service communication external: false custom-postgres-net: # Reference the custom network we created external: true
- Attach the custom network to your Django, Celery Worker, and Celery Beat services (since they all need database access):
django: &django build: context: . dockerfile: ./compose/production/django/Dockerfile depends_on: - redis env_file: .env command: /gunicorn.sh networks: - default - custom-postgres-net # Add this line celeryworker: <<: *django depends_on: - redis command: /start-celeryworker.sh networks: - default - custom-postgres-net # Add this line celerybeat: <<: *django depends_on: - redis command: /start-celerybeat.sh networks: - default - custom-postgres-net # Add this line
Leave the Caddy and Redis services as-is—they don't need access to VM_P, so staying on the default network is fine.
Step 3: Configure Django's Database Connection
Update your .env file to point to VM_P's PostgreSQL IP (the one reachable via VM_D's en1 interface):
DATABASE_URL=postgres://<db-user>:<db-password>@<vm-p-ip>:5432/<db-name>
Step 4: Verify PostgreSQL Access on VM_P
Ensure VM_P's PostgreSQL allows connections from VM_D's en1 subnet:
- Edit
pg_hba.confon VM_P and add:
host all all 192.168.10.0/24 md5 # Replace with your en1 subnet
- Restart PostgreSQL to apply changes:
sudo systemctl restart postgresql # Adjust command based on your OS
Why This Works
- No network conflicts: Your Django containers use two networks—default bridge for internal services, custom network for VM_P access. Docker supports multiple networks per container, so this avoids the "only one host network" error from your first attempt.
- Preserves external access: VM_D's
en0interface remains unaffected, so your containers can still pull images, access external APIs, etc. - Native Docker tooling: No third-party tools like Pipework needed—this uses Docker's built-in network capabilities.
Troubleshooting Tips
- Confirm the custom network is bound correctly: Run
docker network inspect custom-postgres-netand check theOptionssection for the host binding IP. - Test connectivity from the Django container:
docker exec -it <django-container-name> ping <vm-p-ip> docker exec -it <django-container-name> psql -h <vm-p-ip> -U <db-user> -d <db-name>
- Ensure
en1on VM_D has a static IP (avoid DHCP changes breaking the network binding).
内容的提问来源于stack exchange,提问作者AlEmerich

