You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Docker容器共享主机已安装的SSL证书?

目标

我希望确保安装在主机上的SSL证书可被该主机上运行的Docker容器使用。

我的环境配置
  • VM:运行Debian 11的Google Cloud Compute Engine实例,此前Web应用直接运行在此VM上,SSL证书也安装于此。
  • SSL证书:通过LetsEncrypt为域名安装,证书文件存储在VM的/root/etc/letsencrypt/live路径下。证书受权限保护,且无sudo密码(GCE预构建VM未设置),无法下载这些文件。
  • Docker:正迁移至Docker容器架构,用docker-compose定义Web应用和后端服务。Web应用需访问SSL证书。每个服务的Dockerfile仅复制本地代码库,运行时执行startup_script.sh(从GCP Secret Manager下载密钥并启动应用)。本地执行docker compose build可成功构建镜像。

docker-compose配置

version: '3.12'

services:
  app:
    build:
      context: .
      dockerfile: docker/app/Dockerfile
    ports:
      - "8000"

应用Dockerfile

FROM python:3.12.0-bullseye
WORKDIR /home
COPY repo /home/repo
WORKDIR /home/repo
COPY /scripts/startup_script.sh /usr/local/bin
RUN chmod +x /usr/local/bin/startup_script.sh

CMD ["/usr/local/bin/startup_script.sh"]

启动脚本

#!/bin/bash

#Download secrets
mkdir -p secrets
gcloud secrets versions access "latest" --secret=google_workspace_credentials --out-file=secrets/credentials.json
gcloud secrets versions access "latest" --secret=credentials_webapp --out-file=secrets/credentials_webapp

#Copy over the google workspace credentials
cp "$HOME"/secrets/credentials.json auth/credentials.json
cp "$HOME"/secrets/credentials_webapp auth/credentials_web.json

#Acquire SSL Certificate
...don't know what to do here

#Setup the runtime packages
pip install -r requirements.txt

#Run the programs
python3 app.py
已尝试/考虑的方案
  • 方案1:将证书复制到本地并用于构建Docker镜像
    不可行,因为需要sudo密码才能从VM复制证书,且将密钥存储在镜像中存在安全风险。
  • 方案2:在容器启动脚本中运行certbot获取新SSL证书
    存在问题:无法确认获取是否成功;密钥直接加入镜像不安全;LetsEncrypt等CA服务有请求速率限制。但该方案无需处理主机密钥,可在任意主机启动容器。
  • 方案3:运行容器时挂载证书文件
    参考过相关方法,通过docker run path/to/certs挂载证书文件,但担心证书受权限保护无法生效,且不理解该方案原理。
  • 方案4:开放容器端口接收主机传输的证书
    不知道具体实现方法,但安全性较高。
问题

作为新手开发者,我应该采用哪种方案?请给出具体实现步骤及示例代码!


补充说明

正在使用Traefik,但需要检查docker-compose配置。当前配置包含Traefik服务和使用证书的Web应用。由于在本地构建镜像而非在有证书的VM上构建,所以尝试在运行时CMD中复制证书。

当前Traefik相关docker-compose配置:

services:
  traefik:
    image: traefik:v2.5
    command:
      - sh
      - -c
      - |
        mkdir -p /certs
        cp /etc/letsencrypt/live/dreamdai.io /certs/
        traefik
        --api.insecure=true
        --providers.docker=true
        --providers.docker.exposedbydefault=false
        --entrypoints.web.address=:80
        --entrypoints.websecure.address=:443
    ports:
      - "80:80"
      - "8080:8080"
      - "443:443"

  webapp:
    image: webapp
    build:
      context: .
      dockerfile: docker/webapp.dockerfile
    labels:
      - "traefik.http.routers.webapp.rule=Host(`dreamdai.io`)"
      - "traefik.http.routers.webapp.entrypoints=websecure"
      - "traefik.http.routers.webapp.tls=true"
      - "traefik.http.routers.webapp.tls.certresolver=myresolver"

执行docker compose build traefik后日志显示"[+] Building 0.0s (0/0)"并立即退出,无法构建Traefik服务镜像。


解决方案

优先选择:挂载主机证书到容器(方案3优化)

核心原理

Docker的绑定挂载可以将主机上的文件/目录直接映射到容器内部,容器可直接读取这些文件,无需复制或重新生成证书,既安全又高效。证书的权限保护指的是私钥文件的访问权限(通常是600),只要挂载后容器内进程有读取权限即可,无需输入密码。

具体实现步骤

1. 调整docker-compose配置,挂载主机证书目录

修改你的docker-compose.yml,为app服务添加挂载配置,同时给Traefik挂载证书目录:

针对Web应用容器:

version: '3.12'

services:
  app:
    build:
      context: .
      dockerfile: docker/app/Dockerfile
    ports:
      - "8000"
    # 添加挂载配置,只读模式避免容器修改证书
    volumes:
      - /root/etc/letsencrypt/live/dreamdai.io:/home/repo/certs:ro
2. 修改启动脚本,使用挂载的证书

更新startup_script.sh中的证书获取部分:

#Acquire SSL Certificate
# 直接使用挂载到容器内的证书文件,设置环境变量供app.py读取
export SSL_CERT_PATH="/home/repo/certs/fullchain.pem"
export SSL_KEY_PATH="/home/repo/certs/privkey.pem"

之后在app.py中读取这两个环境变量,配置SSL服务即可。

3. 修复Traefik配置问题

你无法构建Traefik镜像的原因是:Traefik服务使用了官方镜像(image字段),docker compose build traefik会跳过构建(无build配置)。正确做法是直接运行Traefik,同时挂载证书目录:

services:
  traefik:
    image: traefik:v2.5
    command:
      - --api.insecure=true
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      # 指定证书读取目录
      - --certificatesresolvers.myresolver.file.directory=/certs
    ports:
      - "80:80"
      - "8080:8080"
      - "443:443"
    volumes:
      # 挂载主机证书目录到容器内
      - /root/etc/letsencrypt/live/dreamdai.io:/certs:ro
      # 挂载Docker套接字,让Traefik自动发现容器
      - /var/run/docker.sock:/var/run/docker.sock:ro

  webapp:
    image: webapp
    build:
      context: .
      dockerfile: docker/webapp.dockerfile
    labels:
      - "traefik.http.routers.webapp.rule=Host(`dreamdai.io`)"
      - "traefik.http.routers.webapp.entrypoints=websecure"
      - "traefik.http.routers.webapp.tls=true"
      - "traefik.http.routers.webapp.tls.certresolver=myresolver"
4. 验证权限

确保主机上的证书目录允许Docker进程读取:

# 查看证书目录权限
ls -ld /root/etc/letsencrypt/live/dreamdai.io
# 调整权限,让docker用户组拥有读取权限
sudo chgrp docker /root/etc/letsencrypt/live/dreamdai.io
sudo chmod g+r /root/etc/letsencrypt/live/dreamdai.io
sudo chgrp docker /root/etc/letsencrypt/live/dreamdai.io/*.pem
sudo chmod g+r /root/etc/letsencrypt/live/dreamdai.io/*.pem

注:若没有sudo密码,可尝试通过SSH密钥登录root(GCE预构建VM通常支持),或联系GCP管理员调整权限。

备选方案:让Traefik自动管理证书

如果挂载主机证书遇到权限问题,可配置Traefik自动通过LetsEncrypt获取证书,无需依赖主机已有的证书:

services:
  traefik:
    image: traefik:v2.5
    command:
      - --api.insecure=true
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      # HTTP自动跳转HTTPS
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=https
      # 配置LetsEncrypt证书解析器
      - --certificatesresolvers.myresolver.acme.httpchallenge=true
      - --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web
      - --certificatesresolvers.myresolver.acme.email=your-email@example.com
      - --certificatesresolvers.myresolver.acme.storage=/acme.json
    ports:
      - "80:80"
      - "8080:8080"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      # 持久化证书文件
      - traefik-acme:/acme.json

  webapp:
    image: webapp
    build:
      context: .
      dockerfile: docker/webapp.dockerfile
    labels:
      - "traefik.http.routers.webapp.rule=Host(`dreamdai.io`)"
      - "traefik.http.routers.webapp.entrypoints=websecure"
      - "traefik.http.routers.webapp.tls=true"
      - "traefik.http.routers.webapp.tls.certresolver=myresolver"

volumes:
  traefik-acme:

该方案无需处理主机证书,Traefik会自动申请并维护证书,适合新手快速上手。


内容的提问来源于stack exchange,提问作者ylime

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 12:39:52