如何将本地计算机的SSH密钥传递给Docker容器?

18
我正在尝试从Dockerfile构建docker镜像,其中需要执行的步骤之一是安装仅可通过私有Gitlab存储库获得的依赖项。这意味着容器将需要访问SSH密钥来进行克隆。我知道这不是最安全的方法,但这只是一个中间容器,一旦放置了运行应用程序所需的所有组件,就会被删除。
问题是,无论我尝试什么,都无法在docker内部获取ssh代理以建立连接。我收到以下错误消息:
npm ERR! Host key verification failed.
npm ERR! fatal: Could not read from remote repository.
npm ERR! 
npm ERR! Please make sure you have the correct access rights
npm ERR! and the repository exists.

如果我尝试仅克隆存储库而不运行npm install,也会发生同样的事情。这是我使用的Dockerfile:
FROM risingstack/alpine:3.4-v6.9.4-4.2.0


RUN apk update

RUN apk add openssh

ARG SSH_KEY

# Authorize SSH Host
RUN mkdir -p /root/.ssh && \
    chmod 700 /root/.ssh && \
    ssh-keyscan github.com > /root/.ssh/known_hosts

# Add the keys and set permissions
RUN echo "$SSH_KEY" > /root/.ssh/id_rsa && \
    chmod 700 /root/.ssh/id_rsa && \


RUN eval "$(ssh-agent -s)" && ssh-add /root/.ssh/id_rsa && ssh -o StrictHostKeyChecking=no git@github.com || true && npm install

并且命令(我将私钥作为构建参数传递):

docker build -t test  --build-arg SSH_KEY="$(cat ~/.ssh/id_rsa)" .
3个回答

15
这对我很有用:
使用此解决方法:https://dev59.com/Dl8d5IYBdhLWcg3wNAGy#47544999,将文件作为构建参数传递。 Dockerfile
ARG SSH_KEY
ENV SSH_KEY=$SSH_KEY

# Make ssh dir
RUN mkdir /root/.ssh/
 
# Create id_rsa from string arg, and set permissions

RUN echo "$SSH_KEY" > /root/.ssh/id_rsa
RUN chmod 600 /root/.ssh/id_rsa
 
# Create known_hosts
RUN touch /root/.ssh/known_hosts

# Add git providers to known_hosts
RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts
RUN ssh-keyscan github.com >> /root/.ssh/known_hosts
RUN ssh-keyscan gitlab.com >> /root/.ssh/known_hosts

构建

docker build -t some-app --build-arg SSH_KEY="$(cat ~/file/outside/build/context/id_rsa)" .

通过这种方式,您可以在构建阶段或运行阶段使用 ENTRYPOINT ["docker-entrypoint.sh"] 执行 git clone git@github.com...(gitlab 或 bitbucket)。

如果您需要将任何文件作为参数传递给容器,则可以使用此方法。

安全性

正如评论者所说,在构建时将文件传递给容器并不安全。解决方法和最佳实践是:在 c.i(jenkins、bamboo、circleci 等)中克隆项目,然后执行 docker build ...。通常只有旧的必需库才会在 docker 中克隆项目,而不是主要源代码。


3
请注意,使用docker history命令的任何用户都可以查看您的SSH私钥。请参考“使用BuildKit构建镜像”部分(https://docs.docker.com/develop/develop-images/build_enhancements/#using-ssh-to-access-private-data-in-builds)了解在构建镜像时安全使用密钥的方法。 - hmartos
你说得对。使用 docker history 命令,你可以查看镜像中的所有内容。但是问题在于需要在构建容器时将一个文件传递给容器。在这种情况下,该文件不应包含敏感信息。 - JRichardsz
这在Windows上行不通。 - yashas123
是的,你说得对。同时也要记住,在99%的需求或云中,Linux被用来构建镜像。在Windows上构建只是为了演示或学习目的,而不是生产目的。 - JRichardsz

3

在运行docker build之前,我会使用已经运行的ssh-agent在主机上克隆它。

如果你真的需要将私钥放在镜像中(你已经承认这是危险的),那么你应该将它放在默认位置$HOME/.ssh/id_rsa,就像你在代码中一样;不要尝试启动ssh-agent。如果你的问题是主机密钥检查过于严格,你也可以注入一个$HOME/.ssh/config文件,或者一个包含主机密钥的$HOME/.ssh/known_hosts文件。由于所有这些都是“文件”,你可能会发现将它们放在Docker构建树中并将其COPY$ HOME/.ssh 中更容易。


1
谢谢,我会尝试一下。不过请注意,我无法复制超出当前上下文的内容,而且ssh密钥始终如此。 - Michał Szydłowski
1
没错,但你可以将它们作为构建序列的一部分复制到当前上下文中(在主机上,在进行docker build之前)。 - David Maze

2
从 Dockerfile 构建一个 Docker 镜像,其中需要执行的步骤之一是安装一个只能通过私有 Gitlab 存储库获得的依赖项。如在 How to mount host volumes into docker containers in Dockerfile during build 的答案中更详细地描述的那样,Docker 还提供了 SSH 代理转发。这使用 --ssh 标志和 --mount=type=ssh 命令,以及任何需要将 SSH 认证委派给主机上的代理的 Dockerfile 的 RUN 命令。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接