重学容器28: 容器镜像构建技巧之使用secret给Dockerfile传递敏感信息
2021-07-27
在构建容器镜像时,有的时候需要在Dockerfile中使用一些敏感信息,例如下面的Dockerfile:
1FROM python:3
2......
3WORKDIR /usr/src/app
4RUN pip3 install -r /usr/src/app/requirements.txt -i https://username:[email protected]/simple
5......
这是构建一个python应用镜像的Dockerfile,在从私有pip源安装依赖时需要在Dockerfile中用到私有源仓库的用户名和密码。如果像上面这个Dockerfile这样写的话,用户名和密码就会暴露在构建出的镜像中,并随着镜像的分发泄露出去。
在使用buildkit
构建容器镜像时,可以使用secret
解决这个问题。先看一下buildctl build
命令的选项:
1buildctl build --help
2NAME:
3 buildctl build - build
4
5USAGE:
6
7 To build and push an image using Dockerfile:
8 $ 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
9
10
11OPTIONS:
12 --output value, -o value Define exports for build result, e.g. --output type=image,name=docker.io/username/image,push=true
13 --progress value Set type of progress (auto, plain, tty). Use plain to show container output (default: "auto")
14 --trace value Path to trace file. Defaults to no tracing.
15 --local value Allow build access to the local directory
16 --frontend value Define frontend used for build
17 --opt value Define custom options for frontend, e.g. --opt target=foo --opt build-arg:foo=bar
18 --no-cache Disable cache for all the vertices
19 --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
20 --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
21 --secret value Secret value exposed to the build. Format id=secretname,src=filepath
22 --allow value Allow extra privileged entitlement, e.g. network.host, security.insecure
23 --ssh value Allow forwarding SSH agent to the builder. Format default|<id>[=<socket>|<key>[,<key>]]
24 --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应用镜像构建例子中可以修改如下:
1RUN --mount=type=secret,id=pypiSecret secretFile=`cat /run/secrets/pypiSecret` && \
2 pip3 install -r /usr/src/app/requirements.txt -i https://$secretFile@pypi.company.com/simple
使用buildctl的--secret
将外部的pypiSecret文件传递进去:
1buildctl build --frontend dockerfile.v0
2 --local 'context=./' \
3 --local 'dockerfile=./' \
4 --output 'type=image,push=true,"name=your.harbor.com/project/pyapp:latest"' \
5 --secret 'id=pypiSecret,src=/somedir/pypiSeceretFile'
注意Dockerfile的RUN指令还可以定制secret文件的挂载位置,默认是/run/secrets,可以使用RUN指令--mount
选项的dst
选项值修改:
1RUN --mount=type=secret,id=mysecret,dst=/foobar cat /foobar
总结 #
secret是buildkit和Dockerfile中专门用来处理容器镜像构建中所需敏感数据传递问题的解决方案。
Dockerfile中的RUN指令除了支持RUN --mount=type=secret
外,mount的type还支持cache
,bind
,tmpfs
,ssh
,这里不再展开介绍。