【发布时间】:2019-09-19 14:47:15
【问题描述】:
我有一个私人仓库,其中包含我想要 pip 安装的软件包。我花了很多时间阅读各种论坛和文章,了解安全执行此操作的不同方法。对于如何最好地做到这一点(如果可能的话)似乎没有达成共识。我显然不想在我的 dockerfile 中公开任何 ssh 密钥/秘密——我想小心通过 docker 历史记录使它们可用。
【问题讨论】:
标签: git ssh-keys docker-image
我有一个私人仓库,其中包含我想要 pip 安装的软件包。我花了很多时间阅读各种论坛和文章,了解安全执行此操作的不同方法。对于如何最好地做到这一点(如果可能的话)似乎没有达成共识。我显然不想在我的 dockerfile 中公开任何 ssh 密钥/秘密——我想小心通过 docker 历史记录使它们可用。
【问题讨论】:
标签: git ssh-keys docker-image
如“Securely build small python docker image from private git repos”中所述,您需要使用 Docker 18.09+
--ssh
您可以使用--ssh标志将现有的 SSH 代理密钥转发给构建器。 docker 不会传输关键数据,而是只会通知构建器此类功能可用。
现在,当构建器需要通过 SSH 访问远程服务器时,它会回拨到客户端并要求它签署此连接所需的特定请求。
密钥本身永远不会离开客户端,并且会尽快由于请求访问的命令已完成,因此构建器端没有信息可以稍后重新建立该远程连接。秘密:
在/var/run/secrets的构建过程中提供一个挂载选项,仅适用于使用它的命令,并且不包含在创建的层中。
即:
docker build --ssh github_ssh_key=/path/to/.ssh/git_ssh_id_rsa .
只有代理连接与该命令共享,而不是私钥的实际内容。
Dockerfile 中没有其他命令/步骤可以访问它。
Dockerfile 在多阶段的第一步中会给出一个键名github_ssh_key,这样我们就可以在调用docker build 时使用它:
RUN --mount=type=ssh,id=github_ssh_key pip wheel \
--no-cache \
--requirement requirements.txt \
--wheel-dir=/app/wheels
OP Jesus Garcia 确实报告了(在 cmets 中)使其工作:
我必须使用 2 个单独的
RUN命令。我不确定这是否是这个新功能的限制,或者我试图在
RUN中将多个命令串在一起的方式,但是当我将它添加为other commands && /bin/sh -c "mount=type=ssh,id=github_ssh_key pip install private-repo"时,我一直收到一个 publickey permission denied 错误与RUN --mount=type=ssh,id=github_ssh_key pip install private-repo && more commands ...
【讨论】:
RUN --mount-type=ssh ... 部分时遇到了问题。我得到了/bin/sh: 1: --mount=type=ssh,: not found 我做了一些谷歌搜索,但我找不到任何有用的东西。
DOCKER_BUILDKIT=1。
/bin/sh -c "mount=type=ssh,id=github_ssh_key pip install private-repo" 运行它来消除错误,但我现在得到了Permission denied (publickey). #12 35.87 fatal: Could not read from remote repository.
RUN 命令。我不确定这是否是这个新功能的限制,或者我试图在我的RUN 中将多个命令串在一起的方式,但是当我将它添加为other commands && /bin/sh -c "mount=type=ssh,id=github_ssh_key pip install private-repo" 和@987654344 时,我一直收到公钥权限被拒绝错误@ 感谢您向我指出 --ssh 标志功能
这对我来说适用于 docker 19.03.5(但应该适用于 18.09+):
假设你的私人仓库在 Github 上,github.com/user/repo.git 并且你想将 pip install 它作为 docker 构建的一部分。 repo 的 ssh 密钥位于主机上~/.ssh/my_key。
在 Dockerfile 中:
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
RUN --mount=type=ssh pip install git+ssh://git@github.com/user/repo.git
然后,在主机上:
export DOCKER_BUILDKIT=1
eval `ssh-agent`
ssh-add ~/.ssh/my_key
docker build --ssh default=$SSH_AUTH_SOCK .
【讨论】:
尽管使用了现代 (19.03.8) Docker,但如果没有我在 Alexandra Ulsh's blog post 中找到的额外行,上述解决方案都对我不起作用(即使在添加 DOCKER_BUILDKIT=1 之后),我认为这足以值得额外回答而不是被埋在cmets中。
虽然
--secret标志出现在Docker的生产版本中, 有一些迹象表明支持仍处于试验阶段。例如,使用构建机密的 Dockerfile 的第一行必须 是
# syntax = docker/dockerfile:1.0-experimental。没有这条线 你会得到错误failed to create LLB definition: Dockerfile parse error line 6: Unknown flag: mount。此行使 Docker CLI 能够为 Moby BuildKit 使用“experimental Dockerfile frontend”。
TL;DR 在 Dockerfile 顶部添加评论 # syntax = docker/dockerfile:1.0-experimental,然后关注 Dave Rejkher's answer。
【讨论】:
我使用的是 Docker 版本 19.03.13(构建 4484c46d9d),并且使用 --ssh 中描述的功能 VonC's 和 Dave Reikher's 答案对我不起作用。我仍然不断收到以下错误:
错误:命令出错,退出状态为 128:git clone -q 'ssh://git@hostname:port/group/repository.git' /tmp/pip-install-8eeeaipo/baseapi 检查日志以获取完整命令输出。
请注意,我不是来自 Github 存储库的 pip install-ing,而是来自一些 真正 私有/内部存储库。来自Docker docs on --ssh 的示例也显示了一个“github.com”repo URL。我不确定是否是这种情况(不应该是这样),但我已经追踪到 pip/git 无法识别 URL 的主机名,而如果使用“github.com”它可以作为广告。
我只使用普通的 --secret 函数(仍然是 BuildKit 的一部分),通过传入 SSH 密钥 (~/.ssh/id_rsa) 和 ~/.ssh/known_hosts 文件作为机密来使它工作。
Dockerfile
# syntax=docker/dockerfile:1.0-experimental
FROM python:3.8-alpine3.11
RUN apk add openssh-client git
RUN mkdir -p -m 0600 /root/.ssh
RUN --mount=type=secret,id=known_hosts,dst=/root/.ssh/known_hosts \
--mount=type=secret,id=ssh_key,dst=/root/.ssh/id_rsa \
ssh-keyscan -H -t rsa hostname.of.private.repo \
&& pip install --no-cache-dir git+ssh://git@hostname:port/group/repository.git@12345678#egg=baseapi
构建命令
DOCKER_BUILDKIT=1 docker build \
--secret id=known_hosts,src=~/.ssh/known_hosts \
--secret id=ssh_key,src=~/.ssh/id_rsa \
-t name:tag \
-f Dockerfile \
.
我检查了构建映像上的~/.ssh 文件夹,它似乎仍然正确,它不保留 SSH 密钥。挂载的文件仍然存在,但它们是空的:
/app # ls -l ~/.ssh/
total 0
-rwxr-xr-x 1 root root 0 Nov 19 11:29 id_rsa
-rwxr-xr-x 1 root root 0 Nov 19 11:29 known_hosts
/app # cat ~/.ssh/id_rsa
/app # cat ~/.ssh/known_hosts
尝试pip install 相同的私有包应该会失败。
供参考:
* Docker: 19.03.13 (build 4484c46d9d)
* Image
- pip 20.2.4 from /usr/local/lib/python3.8/site-packages/pip (python 3.8)
- git 2.22.4
- OpenSSH_8.1p1, OpenSSL 1.1.1g 21 Apr 2020
【讨论】:
apk 是 Alpine 的包管理器。如果您没有找到命令,那么您的 Docker 映像可能不在 Alpine 上。使用容器上可用的任何一个。
使用RUN --mount=type=ssh
ci.yml
build_docker:
stage: build
image: docker:latest
variables:
DOCKER_HOST: tcp://docker:2375
# This instructs Docker not to start over TLS.
DOCKER_TLS_CERTDIR: ""
before_script:
- apk add --no-cache curl jq python3 py3-pip git bind-tools openssh-client
- echo $DOCKERPASS | docker login --username $DOCKERUSER --password-stdin
- mkdir -p -m 0700 ~/.ssh
- ssh-keyscan private-url >> ~/.ssh/known_hosts
- chmod 600 $SSH_KEY
services:
- docker:dind
script:
- export DOCKER_BUILDKIT=1
- eval $(ssh-agent)
- ssh-add $SSH_KEY
- docker build -t tag_name --ssh default=$SSH_AUTH_SOCK .
dockerfile
FROM puckel/docker-airflow:1.10.1
ARG SSH_PRIVATE_KEY
USER root
RUN apt-get update && apt-get install -y git openssh-client
RUN ssh-keyscan private-url >> ~/.ssh/known_hosts
COPY requirements.txt .
RUN --mount=type=ssh pip install git+ssh://private-url/project/repo.git
RUN pip install -r requirements.txt
【讨论】: