我有一个应用程序,执行各种有趣的东西与Git(像运行Git克隆& Git推送),我试图docker-ize它。

我遇到了一个问题,虽然我需要能够添加一个SSH密钥到容器的容器“用户”使用。

我试着把它复制到/root/。ssh/,更改$HOME,创建一个git ssh包装器,仍然没有运气。

以下是Dockerfile供参考:

#DOCKER-VERSION 0.3.4                                                           

from  ubuntu:12.04                                                              

RUN  apt-get update                                                             
RUN  apt-get install python-software-properties python g++ make git-core openssh-server -y
RUN  add-apt-repository ppa:chris-lea/node.js                                   
RUN  echo "deb http://archive.ubuntu.com/ubuntu precise universe" >> /etc/apt/sources.list
RUN  apt-get update                                                             
RUN  apt-get install nodejs -y                                                  

ADD . /src                                                                       
ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa                             
RUN   cd /src; npm install                                                      

EXPOSE  808:808                                                                 

CMD   [ "node", "/src/app.js"]

App.js运行git命令,比如git pull


当前回答

以下是Docker容器中SSH所面临的挑战的简要概述。要从容器内连接到可信的远程而不泄漏机密,有以下几种方法:

SSH代理转发(只支持linux,不是直接的) 内置SSH,使用BuildKit(实验性,Compose还不支持) 使用绑定挂载来公开~/。SSH到容器。(仅限开发,潜在不安全) Docker Secrets(跨平台,增加复杂性)

除此之外,在使用Compose时,还可以使用在运行时可访问的独立docker容器中运行的密钥存储。这里的缺点是由于创建和管理密钥存储库(如HashiCorp的Vault)所需的机制而增加了复杂性。

对于在独立的Docker容器中使用SSH密钥,请参阅上面链接的方法,并根据您的具体需求考虑每种方法的缺点。然而,如果你在Compose中运行,并且想要在运行时共享一个应用程序的密钥(反映OP的实用性)试试这个:

创建一个docker-compose。Env文件并将其添加到.gitignore文件中。 更新docker-compose。Yml并为需要密钥的服务添加env_file。 在应用程序运行时从环境中访问公钥,例如process.node。Node.js应用中的DEPLOYER_RSA_PUBKEY。

上述方法非常适合开发和测试,虽然它可以满足生产需求,但在生产中,您最好使用上述其他方法之一。

额外的资源:

Docker文档:使用绑定挂载 Docker Docs:使用Docker机密管理敏感数据 堆栈溢出:在docker容器内使用SSH密钥 Stack Overflow:在macOS上使用ssh-agent和docker

其他回答

我试图用另一种方式解决这个问题:向映像添加公共ssh密钥。但在我的试验中,我发现“docker cp”是用于从容器复制到主机的。creak回答的第3项似乎在说你可以使用docker cp向容器中注入文件。参见https://docs.docker.com/engine/reference/commandline/cp/

摘录

将文件/文件夹从容器的文件系统复制到主机路径。 路径相对于文件系统的根目录。 用途:docker cp CONTAINER:PATH HOSTPATH 将PATH中的文件/文件夹复制到HOSTPATH中

你也可以在主机和容器之间链接你的.ssh目录,我不知道这种方法是否有任何安全隐患,但它可能是最简单的方法。像这样的东西应该工作:

$ sudo docker run -it -v /root/.ssh:/root/.ssh someimage bash

记住docker使用sudo运行(除非你不这样做),如果是这种情况,你将使用根ssh密钥。

一个简单而安全的方法来实现这一点,而不需要将密钥保存在Docker镜像层中,或通过ssh_agent体操:

As one of the steps in your Dockerfile, create a .ssh directory by adding: RUN mkdir -p /root/.ssh Below that indicate that you would like to mount the ssh directory as a volume: VOLUME [ "/root/.ssh" ] Ensure that your container's ssh_config knows where to find the public keys by adding this line: RUN echo " IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config Expose you local user's .ssh directory to the container at runtime: docker run -v ~/.ssh:/root/.ssh -it image_name Or in your dockerCompose.yml add this under the service's volume key: - "~/.ssh:/root/.ssh"

你最终的Dockerfile应该包含如下内容:

FROM node:6.9.1

RUN mkdir -p /root/.ssh
RUN  echo "    IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config

VOLUME [ "/root/.ssh" ]

EXPOSE 3000

CMD [ "launch" ]

如果你正在使用Docker Compose,一个简单的选择是像这样转发SSH代理:

something:
    container_name: something
    volumes:
        - $SSH_AUTH_SOCK:/ssh-agent # Forward local machine SSH key to docker
    environment:
        SSH_AUTH_SOCK: /ssh-agent

或者等效地,如果使用docker run:

$ docker run --mount type=bind,source=$SSH_AUTH_SOCK,target=/ssh-agent \
             --env SSH_AUTH_SOCK=/ssh-agent \
             some-image

我把一个非常简单的解决方案放在一起,它适用于我的用例,我使用一个“builder”docker映像来构建一个单独部署的可执行文件。换句话说,我的“构建器”映像永远不会离开我的本地机器,并且只需要在构建阶段访问私有回购/依赖。

对于这个解决方案,您不需要更改Dockerfile。

运行容器时,挂载~/。SSH目录(这避免了必须将键直接烘焙到映像中,而是确保它们在构建阶段只在短时间内对单个容器实例可用)。在我的例子中,我有几个构建脚本来自动化我的部署。

在我的build-and-package.sh脚本中,我像这样运行容器:

# do some script stuff before    

...

docker run --rm \
   -v ~/.ssh:/root/.ssh \
   -v "$workspace":/workspace \
   -w /workspace builder \
   bash -cl "./scripts/build-init.sh $executable"

...

# do some script stuff after (i.e. pull the built executable out of the workspace, etc.)

build-init.sh脚本如下所示:

#!/bin/bash

set -eu

executable=$1

# start the ssh agent
eval $(ssh-agent) > /dev/null

# add the ssh key (ssh key should not have a passphrase)
ssh-add /root/.ssh/id_rsa

# execute the build command
swift build --product $executable -c release

因此,我们不是直接在docker run命令中执行swift构建命令(或任何与您的环境相关的构建命令),而是执行build-init.sh脚本,该脚本启动ssh-agent,然后将ssh密钥添加到代理,最后执行swift构建命令。

注1:为了使其工作,您需要确保您的ssh密钥没有密码短语,否则ssh-add /root/。Ssh /id_rsa行将要求口令并中断构建脚本。

注意2:确保在脚本文件上设置了适当的文件权限,以便它们可以运行。

希望这为具有类似用例的其他人提供了一个简单的解决方案。