GCE实例中Docker-Compose部署的Django无法连接Cloud SQL PostgreSQL
问题:GCE上Docker Compose部署的Django无法连接Cloud SQL
环境配置
docker-compose.yml
version: "3" services: app: restart: always command: ./startup.sh image: region-docker.pkg.dev/project_id/repo/image:tag container_name: backend expose: - "8000" volumes: - static_volume:/code/static hostname: app nginx: restart: always image: region-docker.pkg.dev/project_id/repo/image:tag volumes: - static_volume:/code/static ports: - "80:80" depends_on: - app volumes: static_volume:
Django settings.py 数据库配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'Instance': 'project_id:region:instance_name', 'NAME': 'database_name', 'USER': 'username', 'PASSWORD': 'password', 'HOST': 'database_internal_IP', 'PORT': '5432', } }
报错信息
django.db.utils.OperationalError: could not connect to server: Connection timed out backend | Is the server running on host "instance-private-IP" and accepting backend | TCP/IP connections on port 5432?
已知条件
- GCE实例本地执行
psql -h instance-private-IP -U username可成功连接数据库 - 本地电脑使用相同容器配置(替换私有IP为公有IP)运行正常
- GCE实例绑定的服务账号已启用Cloud SQL访问权限
解决方案
方案1:使用Cloud SQL Auth Proxy(推荐,符合GCP安全最佳实践)
通过Cloud SQL Auth Proxy处理数据库连接,无需让Django容器直接访问Cloud SQL私有IP,依赖GCE服务账号权限即可工作。
修改docker-compose.yml,添加cloudsql-proxy服务:
version: "3" services: cloudsql-proxy: image: gcr.io/cloudsql-docker/gce-proxy:1.33.1 command: /cloud_sql_proxy -instances=project_id:region:instance_name=tcp:5432 restart: always volumes: - /var/run/cloudsql:/var/run/cloudsql app: restart: always command: ./startup.sh image: region-docker.pkg.dev/project_id/repo/image:tag container_name: backend expose: - "8000" volumes: - static_volume:/code/static hostname: app depends_on: - cloudsql-proxy environment: - DB_HOST=cloudsql-proxy nginx: restart: always image: region-docker.pkg.dev/project_id/repo/image:tag volumes: - static_volume:/code/static ports: - "80:80" depends_on: - app volumes: static_volume:
修改Django settings.py 的数据库配置,通过环境变量读取代理地址:
import os DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'database_name', 'USER': 'username', 'PASSWORD': 'password', 'HOST': os.getenv('DB_HOST', 'cloudsql-proxy'), 'PORT': '5432', } }
方案2:让Django容器使用主机网络模式
让容器共享GCE实例的网络栈,这样容器就能像实例本身一样访问Cloud SQL私有IP。
修改docker-compose.yml中app服务的配置:
app: restart: always command: ./startup.sh image: region-docker.pkg.dev/project_id/repo/image:tag container_name: backend expose: - "8000" volumes: - static_volume:/code/static hostname: app network_mode: host # 添加此行
注意:该方式会降低容器网络隔离性,可能引发端口冲突问题,仅作为临时解决方案。
方案3:授权Docker网段访问Cloud SQL
在Cloud SQL实例的「连接」设置中,添加Docker默认网段(通常为172.17.0.0/16)到授权网络列表,允许该网段访问5432端口。
注意:此方式安全性较低,不推荐生产环境使用。
内容的提问来源于stack exchange,提问作者Ahmad Othman
相关产品推荐
相关产品推荐

