【注意】最后更新于 July 27, 2021,文中内容可能已过时,请谨慎使用。
在构建容器镜像时,有的时候需要在Dockerfile中使用一些敏感信息,例如下面的Dockerfile:
1
2
3
4
5
|
FROM python:3
......
WORKDIR /usr/src/app
RUN pip3 install -r /usr/src/app/requirements.txt -i https://username:password@pypi.company.com/simple
......
|
这是构建一个python应用镜像的Dockerfile,在从私有pip源安装依赖时需要在Dockerfile中用到私有源仓库的用户名和密码。如果像上面这个Dockerfile这样写的话,用户名和密码就会暴露在构建出的镜像中,并随着镜像的分发泄露出去。
在使用buildkit
构建容器镜像时,可以使用secret
解决这个问题。先看一下buildctl build
命令的选项:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
buildctl build --help
NAME:
buildctl build - build
USAGE:
To build and push an image using Dockerfile:
$ buildctl build --frontend dockerfile.v0 --opt target=foo --opt build-arg:foo=bar --local context=. --local dockerfile=. --output type=image,name=docker.io/username/image,push=true
OPTIONS:
--output value, -o value Define exports for build result, e.g. --output type=image,name=docker.io/username/image,push=true
--progress value Set type of progress (auto, plain, tty). Use plain to show container output (default: "auto")
--trace value Path to trace file. Defaults to no tracing.
--local value Allow build access to the local directory
--frontend value Define frontend used for build
--opt value Define custom options for frontend, e.g. --opt target=foo --opt build-arg:foo=bar
--no-cache Disable cache for all the vertices
--export-cache value Export build cache, e.g. --export-cache type=registry,ref=example.com/foo/bar, or --export-cache type=local,dest=path/to/dir
--import-cache value Import build cache, e.g. --import-cache type=registry,ref=example.com/foo/bar, or --import-cache type=local,src=path/to/dir
--secret value Secret value exposed to the build. Format id=secretname,src=filepath
--allow value Allow extra privileged entitlement, e.g. network.host, security.insecure
--ssh value Allow forwarding SSH agent to the builder. Format default|<id>[=<socket>|<key>[,<key>]]
--metadata-file value Output build metadata (e.g., image digest) to a file as JSON
|
注意到buildctl build
有一个--secret
的选项,选项值的格式是id=secretID,src=filepath
。
表示在使用buildctl构建镜像时可以通过--secret
将外部的一个文件以指定的id名传递到Dockerfile中。
那么在Dockerfile中如何使用外部传入的secret呢?
Dockerfile的RUN指令支持一个--mount
的选项,可以secret挂载进去,具体用法RUN --mount=type=secret,id=secretID
,secret将以文件的形式默认挂载到构建容器环境中的/run/secrets/secretID
,而镜像构建结束后这个文件将不再存在。使用这种方式就可以避免将敏感信息构建到镜像中。
本文一开始的python应用镜像构建例子中可以修改如下:
1
2
|
RUN --mount=type=secret,id=pypiSecret secretFile=`cat /run/secrets/pypiSecret` && \
pip3 install -r /usr/src/app/requirements.txt -i https://$secretFile@pypi.company.com/simple
|
使用buildctl的--secret
将外部的pypiSecret文件传递进去:
1
2
3
4
5
|
buildctl build --frontend dockerfile.v0
--local 'context=./' \
--local 'dockerfile=./' \
--output 'type=image,push=true,"name=your.harbor.com/project/pyapp:latest"' \
--secret 'id=pypiSecret,src=/somedir/pypiSeceretFile'
|
注意Dockerfile的RUN指令还可以定制secret文件的挂载位置,默认是/run/secrets,可以使用RUN指令--mount
选项的dst
选项值修改:
1
|
RUN --mount=type=secret,id=mysecret,dst=/foobar cat /foobar
|
总结
secret是buildkit和Dockerfile中专门用来处理容器镜像构建中所需敏感数据传递问题的解决方案。
Dockerfile中的RUN指令除了支持RUN --mount=type=secret
外,mount的type还支持cache
,bind
,tmpfs
,ssh
,这里不再展开介绍。
参考