我有一个应用程序,执行各种有趣的东西与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
如果您不关心SSH密钥的安全性,这里有许多很好的答案。如果你有,我找到的最好的答案是从上面一个评论的链接到这个GitHub评论由diegosandrim。所以其他人更有可能看到它,以防回购消失,这里是这个答案的编辑版本:
这里的大多数解决方案最终都将私钥保留在映像中。这很糟糕,因为任何访问映像的人都可以访问您的私钥。由于我们对挤压的行为了解不够,即使你删除键并挤压该层,情况仍然可能是这样。
我们用aws s3 cli生成一个预签名URL来访问密钥,并限制访问大约5分钟,我们将这个预签名URL保存到repo目录下的一个文件中,然后在dockerfile中将其添加到映像中。
在dockerfile中,我们有一个RUN命令,执行所有这些步骤:使用pre-sing URL获取ssh密钥,运行npm install,并删除ssh密钥。
通过在单个命令中执行此操作,ssh密钥将不会存储在任何层中,但将存储预签名URL,这不是问题,因为URL将在5分钟后失效。
构建脚本看起来像:
# build.sh
aws s3 presign s3://my_bucket/my_key --expires-in 300 > ./pre_sign_url
docker build -t my-service .
Dockerfile是这样的:
FROM node
COPY . .
RUN eval "$(ssh-agent -s)" && \
wget -i ./pre_sign_url -q -O - > ./my_key && \
chmod 700 ./my_key && \
ssh-add ./my_key && \
ssh -o StrictHostKeyChecking=no git@github.com || true && \
npm install --production && \
rm ./my_key && \
rm -rf ~/.ssh/*
ENTRYPOINT ["npm", "run"]
CMD ["start"]
我把一个非常简单的解决方案放在一起,它适用于我的用例,我使用一个“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:确保在脚本文件上设置了适当的文件权限,以便它们可以运行。
希望这为具有类似用例的其他人提供了一个简单的解决方案。
一个简单而安全的方法来实现这一点,而不需要将密钥保存在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" ]