Docker部署Django应用无法通过Gmail SMTP发邮件,本地运行正常
问题:Docker部署Django应用后邮件发送失败(SSL证书验证错误)
我开发了一个带邮件验证码功能的Django应用,本地PyCharm运行时邮件发送正常,但Docker容器化部署后其他功能正常,仅邮件发送失效,执行email.send()时报错:
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1002)
家庭私有网络,587端口未被阻塞。以下是我的配置文件:
Dockerfile配置
FROM python:3.11.4-slim-buster # set work directory WORKDIR /usr/src/app # set environment variables ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 # install system dependencies RUN apt-get update \ && apt-get -y install libpq-dev gcc \ && pip install psycopg2 # install dependencies RUN pip install --upgrade pip COPY ./requirements.txt . RUN pip install -r requirements.txt # copy main.sh COPY ./main.sh . RUN sed -i 's/\r$//g' /usr/src/app/main.sh RUN chmod +x /usr/src/app/main.sh # copy project COPY . . # run main.sh ENTRYPOINT ["/usr/src/app/main.sh"]
docker-compose.yml配置
version: '3.9' services: backend: build: context: ./backend command: python manage.py runserver 0.0.0.0:8000 ports: - 8000:8000 - 587:587 volumes: - ./backend/:/usr/src/app/ environment: - DB_NAME=db_name - DB_USER=db_user - DB_PASSWORD=db_pass - DB_HOST=db - DB_PORT=5432 - EMAIL_USE_TLS=True - EMAIL_FROM=email@gmail.com - EMAIL_HOST=smtp.gmail.com - EMAIL_HOST_USER=email@gmail.com - EMAIL_HOST_PASSWORD=password - EMAIL_PORT=587 depends_on: - db db: restart: always image: postgres:15 volumes: - postgres_data:/var/lib/postgresql/data/ environment: - POSTGRES_DB=db - POSTGRES_USER=db_user - POSTGRES_PASSWORD=db_pass volumes: postgres_data:
解决方案
方法1:安装系统根证书(生产环境推荐)
slim版Debian镜像默认缺少完整的根证书链,导致Python无法验证SMTP服务器的合法SSL证书。修改Dockerfile的系统依赖安装步骤,添加证书包并更新:
RUN apt-get update \ && apt-get -y install libpq-dev gcc ca-certificates \ && pip install psycopg2 \ && update-ca-certificates
ca-certificates包含全球通用的根证书,update-ca-certificates会将证书同步到系统信任存储,让Python的SSL验证正常工作。
方法2:临时跳过SSL验证(仅测试环境)
如果只是测试需求,可以临时关闭SSL证书验证(生产环境禁止使用,存在安全风险):
在Django的settings.py中添加如下配置:
import ssl EMAIL_SSL_CONTEXT = ssl.create_default_context() EMAIL_SSL_CONTEXT.check_hostname = False EMAIL_SSL_CONTEXT.verify_mode = ssl.CERT_NONE
方法3:排查家庭网络SSL拦截
部分家庭路由器或网关设备会开启SSL流量拦截功能,生成自签名证书替换原始证书,导致验证失败。解决方式:
- 登录路由器管理后台,关闭SSL拦截/深度包检测功能
- 提取网关的自签名证书,添加到Docker容器的
/usr/local/share/ca-certificates/目录,然后执行update-ca-certificates
内容的提问来源于stack exchange,提问作者Mateusz Szczepek
相关产品推荐
相关产品推荐

