Docker Swarm部署Django连接DigitalOcean PostgreSQL证书权限错误
出现could not open certificate file "/root/.postgresql/postgresql.crt": Permission denied错误的核心原因是:Docker容器内不存在该证书文件,或者运行容器的用户没有访问权限——宿主机的证书路径在容器内是独立的文件系统,默认不会共享,即使容器以root运行,也没有宿主机的/root/.postgresql目录。
解决方案步骤
1. 准备DigitalOcean PostgreSQL证书
从宿主机的/root/.postgresql/目录复制postgresql.crt和postgresql.key到你的项目根目录下新建的certs文件夹中。如果宿主机没有相关文件,可直接从DigitalOcean控制台下载PostgreSQL的CA证书。
2. 修改Dockerfile,添加证书复制和权限设置
在Dockerfile末尾添加以下内容,把证书复制到容器内并设置安全权限:
# 创建证书存放目录 RUN mkdir -p /backend/certs # 复制本地证书到容器内 COPY ./certs/postgresql.crt /backend/certs/ COPY ./certs/postgresql.key /backend/certs/ # 密钥必须设置600权限,否则psql会拒绝使用 RUN chmod 600 /backend/certs/postgresql.key # 证书设置644权限即可 RUN chmod 644 /backend/certs/postgresql.crt
3. 更新Django数据库配置,指定SSL参数
修改settings.py中的DATABASES配置,添加SSL选项指定证书路径:
DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql", "NAME": "dbname", "USER": "user", "PASSWORD": "pass", "HOST": "xxxx.db.ondigitalocean.com", "PORT": "25060", "OPTIONS": { "sslmode": "require", "sslrootcert": "/backend/certs/postgresql.crt", "sslcert": "/backend/certs/postgresql.crt", "sslkey": "/backend/certs/postgresql.key", }, } }
注:DigitalOcean的PostgreSQL强制要求SSL连接,
sslmode=require是必填项;若仅需CA证书验证,可只保留sslrootcert参数。
4. 重新构建镜像并部署到Docker Swarm
重新构建镜像:
docker build --build-arg GIT_ACCESS_TOKEN=your_token -t your-image-name .
更新Swarm服务:
docker service update --image your-image-name your-service-name
备选方案(仅临时测试用,不推荐生产环境)
如果不想将证书打包进镜像,可通过挂载宿主机证书目录到容器,但需确保容器有访问权限:
在Swarm服务配置(docker-compose.yml)中添加卷挂载,并指定容器以root用户运行:
services: backend: # 其他配置 volumes: - /root/.postgresql:/root/.postgresql:ro user: root
注意:以root用户运行容器存在安全隐患,生产环境优先选择方案一。
验证方法
进入容器内部,用psql命令测试数据库连接,确认证书配置正确:
docker exec -it your-container-id bash psql "sslmode=require host=xxxx.db.ondigitalocean.com port=25060 dbname=dbname user=user password=pass sslrootcert=/backend/certs/postgresql.crt"
如果能正常进入psql交互界面,说明配置无误。
内容的提问来源于stack exchange,提问作者Krystian Kazimierczak

