我有一个应用程序,执行各种有趣的东西与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
这一行是个问题:
ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa
当指定要复制到映像中的文件时,只能使用相对路径——相对于Dockerfile所在的目录。所以你应该用:
ADD id_rsa /root/.ssh/id_rsa
将id_rsa文件放到Dockerfile所在的目录中。
查看更多详细信息:http://docs.docker.io/reference/builder/#add
我们在docker构建时进行npm安装时也遇到了类似的问题。
从Daniel van Flymen的解决方案中受到启发,并将其与git url重写相结合,我们找到了一个更简单的方法来从私有github reppos中验证npm安装-我们使用oauth2令牌而不是密钥。
在我们的例子中,npm依赖项被指定为“git+https://github.com/…”
对于容器中的身份验证,url需要重写以适合ssh身份验证(ssh://git@github.com/)或令牌身份验证(https://${GITHUB_TOKEN}@github.com/)
构建命令:
docker build -t sometag --build-arg GITHUB_TOKEN=$GITHUB_TOKEN .
不幸的是,我在docker 1.9上,所以——squash选项还没有,最终需要添加它
Dockerfile:
FROM node:5.10.0
ARG GITHUB_TOKEN
#Install dependencies
COPY package.json ./
# add rewrite rule to authenticate github user
RUN git config --global url."https://${GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"
RUN npm install
# remove the secret token from the git config file, remember to use --squash option for docker build, when it becomes available in docker 1.13
RUN git config --global --unset url."https://${GITHUB_TOKEN}@github.com/".insteadOf
# Expose the ports that the app uses
EXPOSE 8000
#Copy server and client code
COPY server /server
COPY clients /clients
如果您不关心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"]