Docker容器SSL证书

qpgpyjmq  于 2023-01-12  发布在  Docker
关注(0)|答案(7)|浏览(277)

是否有任何优雅的方式来添加SSL证书的图像已经从码头拉?。
我正在寻找一种简单且可重复的方法来将文件添加到/etc/ssl/certs中并运行update-ca-certificates(这应该包括ubuntu和Debian映像)。
我在CoreOS上使用Docker,CoreOS机器信任所需的SSL证书,但Docker容器显然只有默认证书。
我尝试过使用docker run --entrypoint=/bin/bash添加证书并运行update-ca-certificates,但这似乎会永久覆盖入口点。
我现在还在想,直接从主机副本将/etc/ssl/certs挂载到容器上是否更优雅?这样做会隐式地允许容器信任与主机相同的东西。
我正在使用一个讨厌的代理,它会放弃所有的东西:(。它会破坏SSL,使容器有点奇怪。

f87krz0w

f87krz0w1#

使用-v将证书装载到Docker容器上:

docker run -v /host/path/to/certs:/container/path/to/certs -d IMAGE_ID "update-ca-certificates"
cfh9epnr

cfh9epnr2#

我正在尝试做一些类似的事情。正如上面所评论的,我认为你会想用一个自定义的Dockerfile(使用你拉出来的图像作为基础图像),ADD你的证书,然后RUN update-ca-certificates来构建一个新的图像。这样你每次从这个新的图像启动一个容器时都会有一个一致的状态。

# Dockerfile
FROM some-base-image:0.1
ADD you_certificate.crt:/container/cert/path
RUN update-ca-certificates

假设针对该Dockerfile的docker build生成了IMAGE_ID。在下一个docker run -d [any other options] IMAGE_ID中,由该命令启动的容器将包含您的证书信息。简单且可重复。

zzzyeukh

zzzyeukh3#

正如上面的注解所建议的,如果主机上的证书存储与访客兼容,则可以直接挂载它。
在Debian主机(和容器)上,我成功地完成了:

docker run -v /etc/ssl/certs:/etc/ssl/certs:ro ...
6mw9ycah

6mw9ycah4#

您可以使用相对路径将卷装载到容器:

docker run -v `pwd`/certs:/container/path/to/certs ...

注意pwd上的反勾号,它给予了当前的工作目录。它假设certs文件夹在当前目录下,docker run将被执行。这对于本地开发非常有用,并使certs文件夹对您的项目可见。

qij5mzcb

qij5mzcb5#

我编写了一个脚本,它 Package docker并在访客中设置主机的SSL证书。

额外的好处是,你不需要重建任何容器-它应该只是工作。
它被称为docker,所以你可以把它复制到$PATH上高于docker的地方,或者重命名并放在其他地方。
如果你有任何问题,请通过Github告诉我!

v9tzhpje

v9tzhpje6#

这不会直接回答你的问题,但这是我如何解决同样的问题。
我运行的是golang:1.16.4-buster,我尝试的证书都不起作用。我切换到golang:1.17.8-alpine3.15,它从一开始就起作用了,而不需要尝试加载任何证书。另外,一个更小的发行版的好处。

o8x7eapl

o8x7eapl7#

当你谈论CoreOS(Fedora)和Ubuntu/Debian客户机时,真的没有一个很好的方法来解决这个问题。Fedora使用现代标准来组织“信任锚”,而Ubuntu/Debian仍然使用旧的风格。两者并不直接兼容。
在花了很长时间试图解决这个问题的反面(Ubuntu上的Fedora)之后,您的选择是:
1.获取容器映像,以便为通过环境变量添加的自定义证书提供一流的支持(这在精心制作的容器中很常见,但在直接的Ubuntu发行版映像中不会发生)。
1.找到一种方法来运行类似的主机系统(通常不是一个可行的选择),并将主机信任锚挂载到访客信任锚之上。
1.旋转您自己的映像版本,该版本添加了证书或对指定证书的支持(通常无法维护以管理长时间运行的fork)
1.用一个脚本 Package ENTRYPOINT,该脚本从可选的额外主机装载添加和运行CA添加/安装(非常有问题,请参见下文)
1.使用修改的参数运行一次容器,以在主机装载中生成更新的信任存储的副本,然后在容器的后续运行中进行主机装载(执行此操作)。
最好的选择通常是尝试获得容器映像维护者(或自己提交一个PR)来添加对从环境变量加载额外CA证书的支持,因为这是企业用户和自托管者中非常常见的用例。然而,这通常会为一次性容器增加额外的开销,这是不可接受的,而图像维护者可能有其他的理由不这样做,同时也不能解决你的问题。
更改主机和“分叉”映像以旋转自己的映像也不是很好的选择,通常出于部署或可维护性的原因,它们不是初学者。
Package ENTRYPOINT基本上等同于修改容器以支持自定义证书的特别版本,但完全是从映像外部进行的。不 Package ENTRYPOINT的潜在原因与从容器外部进行 Package 的缺点是相同的。但好处是您无需等待映像更新即可执行此操作。* 我通常不推荐使用此选项 *。此解决方案基本上是编写一个您托管的脚本-装载到将执行CA安装的容器中,然后运行任何ENTRYPOINT和CMD。但是,这里有一些主要的陷阱。首先,您需要将其定制为您正在运行的特定容器,以便它运行相同的入口点。使用一些脚本可能可以确定这一点,但是您需要注意那些制作精良的容器,它们具有init系统来处理pid 1问题(https:github.com/Yelp/dumb-init#why-you-need-an-init-system;dr:当强制停止容器需要PID 1 init进程来管理它时,捕捉像中断这样的信号并且不丢失系统资源)。有很多不同的init系统,你不能 Package 一个init系统。另外,如果你使用Docker,你 * 不能用命令行中的多个命令覆盖入口点 *。带有init系统的容器,比如dumb-init,需要一个参数来表示实际运行的命令。因此入口点是一个列表(['/usr/bin/dumb-init', '/usr/bin/my-command'])。Docker只允许通过API指定多命令入口点,而不是通过命令行,因此无法保留dumb-init命令并为第二个参数提供您自己的脚本。

“最佳”解决方案:虽然长时间运行的容器将从上面的选项#1中受益匪浅,但对于一次性容器和即时解决方案来说,最好的办法是生成访客信任锚的主机挂载。

最好的方法是生成一个主机存储的副本,该副本是更新后的容器信任锚的样子,并将其安装在容器信任存储的顶部。最兼容的方法是使用目标容器映像本身来完成此操作,但要覆盖入口点。在与容器关联的项目工作空间中为信任锚装载一个“缓存”文件夹。然而,这在云和CI环境中可能不起作用。另一种选择是保留一个单独的容器卷,它使用两种主要信任锚样式中的每一种(现代的,例如Fedora、Arch等,以及遗留的,例如Debian、Ubuntu、等等),并且从适当类型的通用容器图像中半定期地单独更新。然后,所得到的容器卷仅仅变成卷依赖关系,其中基于目标容器映像类型来选择适当的卷依赖关系。生成其中一个的要点是在主机上装载一个脚本,该脚本将根CA添加到适当的文件夹(仅供参考,传统的信任锚将递归搜索根CA文件夹,但现代的不会),运行信任锚更新命令,然后将生成的信任锚文件夹复制到主机上。

更新日期:

如果它仍然相关,大多数Ubuntu容器基础映像在内部使用cloud-init(现在),它支持许多常见的事情,包括向容器映像添加自定义根CA,例如,它们已经支持选项1。
https://cloudinit.readthedocs.io/en/latest/topics/examples.html#configure-an-instances-trusted-ca-certificates
我相信你可以添加一个文件挂载到/etc/cloud/cloud.cfg.d/,它有YAML,就像在示例链接中一样,它会在容器 Boot 过程中被拾取。你可以很容易地基于你想要的额外的根CA证书通过编程生成YAML。
编辑1:已修复:我从原来的问题中颠倒了主人和客人。还添加了关于cloud-init的更新。编辑2:固定样式排印错误

相关问题