我有一个应用程序,执行各种有趣的东西与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(17.05)的后续版本中,您可以使用多阶段构建。哪个是最安全的选择,因为之前的构建只能被后续的构建使用,然后被销毁

有关更多信息,请参阅我的stackoverflow问题的答案

其他回答

我们在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,那么这个问题就更难解决了。例如,如果你使用git克隆,或者在我的情况下,pip和npm从私有存储库下载。

我发现的解决方案是使用——build-arg标志添加键。然后你可以使用新的实验——squash命令(添加1.13)来合并图层,这样键在删除后就不再可用了。以下是我的解决方案:

建造的命令

$ docker build -t example --build-arg ssh_prv_key="$(cat ~/.ssh/id_rsa)" --build-arg ssh_pub_key="$(cat ~/.ssh/id_rsa.pub)" --squash .

Dockerfile

FROM python:3.6-slim

ARG ssh_prv_key
ARG ssh_pub_key

RUN apt-get update && \
    apt-get install -y \
        git \
        openssh-server \
        libmysqlclient-dev

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

# Add the keys and set permissions
RUN echo "$ssh_prv_key" > /root/.ssh/id_rsa && \
    echo "$ssh_pub_key" > /root/.ssh/id_rsa.pub && \
    chmod 600 /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa.pub

# Avoid cache purge by adding requirements first
ADD ./requirements.txt /app/requirements.txt

WORKDIR /app/

RUN pip install -r requirements.txt

# Remove SSH keys
RUN rm -rf /root/.ssh/

# Add the rest of the files
ADD . .

CMD python manage.py runserver

更新:如果你正在使用Docker 1.13并且有实验功能,你可以在build命令中添加——squash,它将合并层,删除SSH密钥并从Docker历史记录中隐藏它们。

我把一个非常简单的解决方案放在一起,它适用于我的用例,我使用一个“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:确保在脚本文件上设置了适当的文件权限,以便它们可以运行。

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

注意:只使用这种方法的图像是私有的,将永远是!

ssh密钥仍然存储在映像中,即使您在添加密钥后在层命令中删除密钥(参见本文中的评论)。

在我的情况下,这是可以的,所以这是我使用的:

# Setup for ssh onto github
RUN mkdir -p /root/.ssh
ADD id_rsa /root/.ssh/id_rsa
RUN chmod 700 /root/.ssh/id_rsa
RUN echo "Host github.com\n\tStrictHostKeyChecking no\n" >> /root/.ssh/config

如果您不关心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"]