在docker容器内使用SSH密钥

时间:2013-08-08 21:23:00

标签: ssh-keys docker

我有一个应用程序,使用Git执行各种有趣的东西(比如运行git clone& git push),我正在尝试停靠它。

我遇到了一个问题,虽然我需要能够在容器中添加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 pull

这样的git命令

34 个答案:

答案 0 :(得分:98)

如果您需要在构建时使用SSH,这是一个更难的问题。例如,如果您使用git clone,或者我的案例pipnpm从私有存储库下载。

我找到的解决方案是使用--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并且具有实验性功能,则可以将--squash附加到将合并图层的构建命令,删除SSH密钥并将其隐藏docker history

答案 1 :(得分:79)

使用Ubuntu时,ssh_config不正确。你需要添加

RUN  echo "    IdentityFile ~/.ssh/id_rsa" >> /etc/ssh/ssh_config

到您的Dockerfile,以使其识别您的ssh密钥。

答案 2 :(得分:75)

  

注意:仅对私有且始终的图片使用此方法!

即使您在添加图层命令后删除了图层命令中的密钥,ssh密钥仍会存储在图像中(请参阅this post中的注释)。

在我的情况下,这没关系,所以这就是我正在使用的:

# 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

答案 3 :(得分:50)

如果您使用的是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

答案 4 :(得分:40)

为了在容器中注入ssh密钥,您有多种解决方案:

  1. 使用带有ADD指令的Dockerfile,您可以在构建过程中注入它

  2. 只需执行cat id_rsa | docker run -i <image> sh -c 'cat > /root/.ssh/id_rsa'

  3. 之类的操作
  4. 使用docker cp命令,允许您在容器运行时注入文件。

答案 5 :(得分:31)

扩展Peter Grainger's answer我可以使用自Docker 17.05以来可用的multi-stage build。官方页面说明:

  

使用多阶段构建,您可以在Dockerfile中使用多个FROM语句。每个FROM指令可以使用不同的基础,并且每个指令都开始构建的新阶段。您可以选择性地将工件从一个阶段复制到另一个阶段,在最终图像中留下您不想要的所有内容。

这里记住这一点是我Dockerfile的例子,包括三个构建阶段。它旨在创建客户端Web应用程序的生产映像。

# Stage 1: get sources from npm and git over ssh
FROM node:carbon AS sources
ARG SSH_KEY
ARG SSH_KEY_PASSPHRASE
RUN mkdir -p /root/.ssh && \
    chmod 0700 /root/.ssh && \
    ssh-keyscan bitbucket.org > /root/.ssh/known_hosts && \
    echo "${SSH_KEY}" > /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa
WORKDIR /app/
COPY package*.json yarn.lock /app/
RUN eval `ssh-agent -s` && \
    printf "${SSH_KEY_PASSPHRASE}\n" | ssh-add $HOME/.ssh/id_rsa && \
    yarn --pure-lockfile --mutex file --network-concurrency 1 && \
    rm -rf /root/.ssh/

# Stage 2: build minified production code
FROM node:carbon AS production
WORKDIR /app/
COPY --from=sources /app/ /app/
COPY . /app/
RUN yarn build:prod

# Stage 3: include only built production files and host them with Node Express server
FROM node:carbon
WORKDIR /app/
RUN yarn add express
COPY --from=production /app/dist/ /app/dist/
COPY server.js /app/
EXPOSE 33330
CMD ["node", "server.js"]

.dockerignore重复.gitignore文件的内容(它会阻止复制项目的node_modules和生成的dist目录):

.idea
dist
node_modules
*.log

构建图像的命令示例:

$ docker build -t ezze/geoport:0.6.0 \
  --build-arg SSH_KEY=$(cat ~/.ssh/id_rsa) \
  --build-arg SSH_KEY_PASSPHRASE=my_super_secret \
  ./

如果您的私人SSH密钥没有密码短语,请指定空SSH_KEY_PASSPHRASE参数。

这是它的工作原理:

1)。在第一阶段,只有package.jsonyarn.lock个文件和私有SSH密钥被复制到名为sources的第一个中间图像。为了避免进一步的SSH密钥密码短语提示,它会自动添加到ssh-agent。最后yarn命令从NPM安装所有必需的依赖项,并通过SSH从Bitbucket克隆私有git存储库。

2)。第二阶段构建并缩小Web应用程序的源代码,并将其放在名为dist的下一个中间映像的production目录中。请注意,已安装node_modules的源代码是从第一阶段在此行生成的名为sources的图像中复制的:

COPY --from=sources /app/ /app/

也可能是以下几行:

COPY --from=sources /app/node_modules/ /app/node_modules/

我们这里只有第一个中间图像的node_modules目录,不再有SSH_KEYSSH_KEY_PASSPHRASE个参数。构建所需的所有其余部分都从我们的项目目录中复制。

3)。在第三阶段,我们通过仅包含来自名为ezze/geoport:0.6.0的第二个中间图像的dist目录并安装Node Express来标记为production来缩小最终图像的大小。服务器

列出图像会得到如下输出:

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ezze/geoport        0.6.0               8e8809c4e996        3 hours ago         717MB
<none>              <none>              1f6518644324        3 hours ago         1.1GB
<none>              <none>              fa00f1182917        4 hours ago         1.63GB
node                carbon              b87c2ad8344d        4 weeks ago         676MB

其中未标记的图像与第一个和第二个中间构建阶段相对应。

如果你跑

$ docker history ezze/geoport:0.6.0 --no-trunc

在最终图片中,您不会看到SSH_KEYSSH_KEY_PASSPHRASE的任何提及。

答案 6 :(得分:15)

这一行是个问题:

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

答案 7 :(得分:13)

Docker容器应被视为&#39;服务&#39;他们自己的。要分开关注点,您应该将功能分开:

1)数据应位于数据容器中:使用链接卷将repo克隆到。然后,该数据容器可以链接到需要它的服务。

2)使用容器运行git克隆任务(即它只有克隆作业),在运行它时将数据容器链接到它。

3)对于ssh-key也是如此:把它放在一个卷(如上所述)并在需要时将它链接到git clone服务

这样,克隆任务和密钥都是短暂的,只在需要时才有效。

现在,如果您的应用程序本身是一个git界面,您可能需要直接考虑使用github或bitbucket REST API来完成您的工作:这就是它们的设计目标。

答案 8 :(得分:12)

在docker构建时进行npm安装时遇到了类似的问题。

受到来自Daniel van Flymen的解决方案的启发并将其与git url rewrite相结合,我们发现了一个更简单的方法来验证来自私有github repos的npm安装 - 我们使用了oauth2令牌而不是密钥。

在我们的例子中,npm依赖项被指定为&#34; git + https://github.com/ ...&#34;

对于容器中的身份验证,需要将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

答案 9 :(得分:10)

将ssh身份验证套接字转发到容器:

git clone

您的脚本将能够执行chown

额外:如果您希望克隆文件属于特定用户,则需要使用git,因为在容器内使用除root之外的其他用户将导致docker run ... -e OWNER_USER=$(id -u) \ -e OWNER_GROUP=$(id -g) \ ... 失败。

您可以在容器的环境中发布一些其他变量:

chown $OWNER_USER:$OWNER_GROUP -R <source_folder>

克隆后,必须执行{{1}}以在离开容器之前设置正确的所有权,以便容器外的非root用户可以访问这些文件。

答案 10 :(得分:10)

您可以使用多阶段构建来构建容器 这是您可以采用的方法:-

第1阶段使用ssh构建映像

FROM ubuntu as sshImage
LABEL stage=sshImage
ARG SSH_PRIVATE_KEY
WORKDIR /root/temp

RUN apt-get update && \
    apt-get install -y git npm 

RUN mkdir /root/.ssh/ &&\
    echo "${SSH_PRIVATE_KEY}" > /root/.ssh/id_rsa &&\
    chmod 600 /root/.ssh/id_rsa &&\
    touch /root/.ssh/known_hosts &&\
    ssh-keyscan github.com >> /root/.ssh/known_hosts

COPY package*.json ./

RUN npm install

RUN cp -R node_modules prod_node_modules

第2阶段:构建容器

FROM node:10-alpine

RUN mkdir -p /usr/app

WORKDIR /usr/app

COPY ./ ./

COPY --from=sshImage /root/temp/prod_node_modules ./node_modules

EXPOSE 3006

CMD ["npm", "run", "dev"] 

在撰写文件中添加env属性:

   environment:
      - SSH_PRIVATE_KEY=${SSH_PRIVATE_KEY}

然后从构建脚本传递参数,如下所示:

docker-compose build --build-arg SSH_PRIVATE_KEY="$(cat ~/.ssh/id_rsa)"

为安全起见,请删除中间容器。 这将帮助您加油。

答案 11 :(得分:10)

这个问题真的很烦人。因为你不能在dockerfile上下文之外添加/复制任何文件,这意味着不可能只将〜/ .ssh / id_rsa链接到图像的/root/.ssh/id_rsa,当你肯定需要一个键来做一些sshed的东西时比如来自私人仓库链接的git clone ...,在构建docker镜像期间。

无论如何,我找到了一种解决方法,不是那么说服,而是为我工作。

    您的dockerfile中的
    • 将此文件添加为/root/.ssh/id_rsa
    • 做你想做的事,比如git clone,composer ......
    • 最后
    • rm /root/.ssh/id_rsa
  1. 一次拍摄的剧本:

    • cp您持有dockerfile的文件夹的密钥
    • docker build
    • rm复制的密钥
  2. 任何时候你必须从这个图像运行一个带有一些ssh要求的容器,只需为运行命令添加-v,如:

    docker run -v~ / .ssh / id_rsa:/root/.ssh/id_rsa --name container image command

  3. 此解决方案在项目源和构建的docker镜像中都没有私钥,因此不再需要担心安全问题。

答案 12 :(得分:7)

一种解决方案是使用以下选项将主机的ssh密钥安装到docker中:

'../js/layout/my_theme/js/scripts.js': '../js/layout/my_theme/js/scripts.js'

与上述解决方案类似。但适用于非root用户。与github完美配合。

答案 13 :(得分:7)

'您可以有选择地让远程服务器访问您的本地ssh-agent,就像它在服务器上运行一样'

https://developer.github.com/guides/using-ssh-agent-forwarding/

答案 14 :(得分:6)

我今天遇到了同样的问题和以前的帖子稍微修改过的版本我发现这种方法对我来说更有用

docker run -it -v ~/.ssh/id_rsa:/root/.my-key:ro image /bin/bash

(注意readonly标志,所以容器在任何情况下都不会弄乱我的ssh密钥。)

我可以在内部容器中运行:

ssh-agent bash -c "ssh-add ~/.my-key; git clone <gitrepourl> <target>"

所以我没有得到@kross注意到的Bad owner or permissions on /root/.ssh/..错误

答案 15 :(得分:6)

您还可以在主机和容器之间链接.ssh目录,我不知道这种方法是否有任何安全隐患,但它可能是最简单的方法。这样的事情应该有效:

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

请记住,docker使用sudo运行(除非你没有),如果是这种情况,你将使用root ssh密钥。

答案 16 :(得分:5)

现在可以从 18.09 版本开始使用!

根据documentation

<块引用>

docker build 有一个 --ssh 选项,允许 Docker 引擎 转发 SSH 代理连接。

以下是在容器中使用 SSH 的 Dockerfile 示例:

# syntax=docker/dockerfile:experimental
FROM alpine

# Install ssh client and git
RUN apk add --no-cache openssh-client git

# Download public key for github.com
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts

# Clone private repository
RUN --mount=type=ssh git clone git@github.com:myorg/myproject.git myproject

创建 Dockerfile 后,使用 --ssh 选项与 SSH 代理连接:

$ docker build --ssh default .

另外,看看https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066

答案 17 :(得分:2)

起初,一些元噪音

这里有两个高度赞成的答案危险的错误建议

我发表了评论,但由于我已经失去了很多天,请注意:

不要将私钥回显到文件中(意思是:echo "$ssh_prv_key" > /root/.ssh/id_ed25519)。这将破坏所需的行格式,至少在我的情况下是这样。

改用 COPYADD。有关详细信息,请参阅 Docker Load key “/root/.ssh/id_rsa”: invalid format

这也得到了另一位用户的证实:

<块引用>

我收到错误加载密钥“/root/.ssh/id_ed25519”:格式无效。回声会 为我删除换行符/双引号。这是否仅适用于 ubuntu 或者 alpine:3.10.3 有什么不同?


1.一种将私钥保存在图像中的工作方式(不太好!)

如果私钥存储在镜像中,则需要注意从git网站删除公钥,或者不发布镜像。如果你注意这一点,这是安全的。请参阅下面的 (2.) 以获得更好的方法,您也可以“忘记注意”。

Dockerfile 如下所示:

FROM ubuntu:latest
RUN apt-get update && apt-get install -y git
RUN mkdir -p /root/.ssh && chmod 700 /root/.ssh
COPY /.ssh/id_ed25519 /root/.ssh/id_ed25519
RUN chmod 600 /root/.ssh/id_ed25519 && \
    apt-get -yqq install openssh-client && \
    ssh-keyscan -t ed25519 -H gitlab.com >> /root/.ssh/known_hosts
RUN git clone git@gitlab.com:GITLAB_USERNAME/test.git
RUN rm -r /root/.ssh

2.一种不将私钥保留在图像中的工作方式(好!)

以下是同样的事情的更安全的方式。 如果您需要一个具有 git repo 目录私钥存储在其中一层的图像,则需要两个图像,并且最后只使用第二个。这意味着,您需要 FROM 两次,然后您可以 copy only the git repo directory from the first to the second image,查看 official guide "Use multi-stage builds"

我们使用“alpine”作为最小可能的基础镜像,它使用 apk 而不是 apt-get;您也可以将 apt-get 与上述代码一起使用,而不是使用 FROM ubuntu:latest

Dockerfile 如下所示:

# first image only to download the git repo
FROM alpine as MY_TMP_GIT_IMAGE

RUN apk add --no-cache git
RUN mkdir -p /root/.ssh &&  chmod 700 /root/.ssh
COPY /.ssh/id_ed25519 /root/.ssh/id_ed25519
RUN chmod 600 /root/.ssh/id_ed25519

RUN apk -yqq add --no-cache openssh-client && ssh-keyscan -t ed25519 -H gitlab.com >> /root/.ssh/known_hosts
RUN git clone git@gitlab.com:GITLAB_USERNAME/test.git
RUN rm -r /root/.ssh


# Start of the second image
FROM MY_BASE_IMAGE
COPY --from=MY_TMP_GIT_IMAGE /MY_GIT_REPO ./MY_GIT_REPO

我们在这里看到 FROM 只是一个命名空间,它就像它下面的行的标题,可以用别名寻址。如果没有别名,--from=0 将是第一个图像(=FROM 命名空间)。

您现在可以发布或共享第二个图像,因为私钥不在其层中,并且您不必在使用一次后从 git 网站删除公钥! 因此,您不需要在每次克隆 repo 时创建新的密钥对。当然,请注意,如果有人可能以其他方式获取您的数据,则无密码私钥仍然不安全。 如果您对此不确定,最好在使用后从服务器中删除公钥,并在每次运行时使用新的密钥对。


如何从 Dockerfile 构建镜像的指南

  • 安装Docker桌面;或者在 VirtualBox 中的 WSL2 或 Linux 中使用 docker;或者在独立的 Linux 分区/硬盘中使用 docker。

  • 打开命令提示符(PowerShell、终端等)。

  • 转到 Dockerfile 的目录。

  • 创建一个子文件夹“.ssh/”。

  • 出于安全原因,为每个 Dockerfile 运行创建一个 公共和私有 SSH 密钥对 - 即使您已经拥有另一个密钥对。在命令提示符下,在 Dockerfile 的文件夹中,输入(注意,这会自动覆盖):

      Write-Output "y" | ssh-keygen -q -t ed25519 -f ./.ssh/id_ed25519 -N '""'
    

    (如果您使用 PowerShell)或

      echo "y" | ssh-keygen -q -t ed25519 -f ./.ssh/id_ed25519 -N ''
    

    (如果您不使用 PowerShell)。

    您的密钥对现在将位于子文件夹 .ssh/ 中。是否使用该子文件夹取决于您,您也可以将代码更改为COPY id_ed25519 /root/.ssh/id_ed25519;那么您的私钥需要位于您所在的 Dockerfile 目录中。

  • 在编辑器中打开公钥,复制内容并将其发布到您的服务器(例如 GitHub / GitLab --> 配置文件 --> SSH 密钥)。您可以选择任何名称和结束日期。公钥字符串的最终可读注释(如果您没有在 -C 的参数中添加 ssh-keygen 注释,通常是您的计算机名称)并不重要,只需将其留在那里即可。

  • 开始(不要忘记末尾的“.”,这是构建上下文):

    docker build -t test .

仅适用于 1。):

  • 运行后,从服务器中删除公钥(最重要,最好一次)。该脚本会从映像中删除私钥,您也可以从本地计算机中删除私钥,因为您不应再次使用该密钥对。原因:有人可以get the private key from the image even if it was removed from the image。引用 a user's 评论:

    <块引用>

    如果有人抓住了你的 图像,他们可以检索密钥...即使您删除该文件 后面一层,b/c,当你添加它时,他们可以回到第 7 步

    攻击者可以使用此私钥等待,直到您再次使用该密钥对。

仅适用于 2.):

  • 运行后,由于第二个映像是构建后唯一剩余的映像,因此我们不一定需要从客户端和主机中删除密钥对。我们仍然有一个很小的风险,即无密码私钥是从某个地方的本地计算机中获取的。这就是为什么您仍然可以从 git 服务器中删除公钥的原因。您还可以删除任何存储的私钥。但在许多主要目标是自动构建映像而不是安全性的项目中,它可能不需要。

最后,还有一些元噪音

至于使用有问题的私钥回声方法的两个高度赞成的答案中危险错误的建议,以下是撰写本文时的投票: >

我们在这里看到答案中一定有问题,因为前 1 个答案的投票至少在问题投票的水平上。

在前 1 个答案的评论列表末尾只有一个小的且未投票的评论,命名了相同的私钥回声问题(本答案中也引用了该问题)。并且:该批评性评论是在回答三年后发表的。

我自己对前 1 个答案投了赞成票。后来我才意识到它对我不起作用。因此,群体智能正在发挥作用,但进展缓慢?如果有人可以向我解释为什么回显私钥可能对其他人有效,但对我无效,请发表评论。否则,326k 次观看(减去 2 条评论;))会监督或忽略前 1 个答案的错误。 如果那个回显的私钥代码行不会花费我很多工作日,我不会在这里写这么长的文本,从网上的所有代码中挑选绝对令人沮丧的代码。< /p>

答案 18 :(得分:2)

在更高版本的docker(17.05)中,您可以使用multi stage builds。哪个是最安全的选项,因为之前的版本只能由后续构建使用,然后销毁

有关详细信息,请参阅the answer to my stackoverflow question

答案 19 :(得分:2)

eczajk在Daniel van Flymen的回答中已经评论过,删除密钥并使用pragma solidity >=0.4.22 <0.6.0; import"./ContractA.sol"; contract ContractB is ContractA { function getContractAvalue() pure public returns(int){ // For reference that you can also access the function of ContractA in ContractB return ContractA.a; } } 似乎并不安全,因为它们仍会在历史记录(--squash中可见)。

与Docker 18.09相比,您现在可以使用“构建机密”功能。就我而言,我使用主机SSH密钥在Dockerfile中使用以下命令克隆了一个私人git repo:

docker history --no-trunc

要使用此功能,您需要在运行# syntax=docker/dockerfile:experimental [...] RUN --mount=type=ssh git clone [...] [...] 之前启用新的BuildKit后端:

docker build

您需要将export DOCKER_BUILDKIT=1 参数添加到--ssh default

此处的更多信息:https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066

答案 20 :(得分:1)

以下是我在使用 docker composer 构建镜像期间使用 ssh 密钥的方法:

.env

SSH_PRIVATE_KEY=[base64 encoded sshkey]

docker-compose.yml

version: '3'
services:
  incatech_crawler:
    build:
      context: ./
      dockerfile: Dockerfile
      args:
        SSH_PRIVATE_KEY: ${SSH_PRIVATE_KEY} 

docker 文件: ...

# Set the working directory to /app
WORKDIR /usr/src/app/
ARG SSH_PRIVATE_KEY 
 
RUN mkdir /root/.ssh/  
RUN echo -n ${SSH_PRIVATE_KEY} | base64 --decode > /root/.ssh/id_rsa_wakay_user

答案 21 :(得分:1)

就我而言,远程存储库中的nodejs和'npm i'出现了问题。我修复了将“ node”用户添加到nodejs容器,并将700添加到容器中的〜/ .ssh的问题。

Dockerfile:

USER node #added the part
COPY run.sh /usr/local/bin/
CMD ["run.sh"]

run.sh:

#!/bin/bash
chmod 700 -R ~/.ssh/; #added the part

docker-compose.yml:

nodejs:
      build: ./nodejs/10/
      container_name: nodejs
      restart: always
      ports:
        - "3000:3000"
      volumes:
        - ../www/:/var/www/html/:delegated
        - ./ssh:/home/node/.ssh #added the part
      links:
        - mailhog
      networks:
        - work-network

之后它开始工作

答案 22 :(得分:1)

docker API 1.39+(使用docker version检查API版本)开始,docker build允许使用代理套接字或密钥的--ssh选项,以允许Docker Engine转发SSH代理连接。 / p>

构建命令

export DOCKER_BUILDKIT=1
docker build --ssh default=~/.ssh/id_rsa .

Dockerfile

# syntax=docker/dockerfile:experimental
FROM python:3.7

# Install ssh client (if required)
RUN apt-get update -qq
RUN apt-get install openssh-client -y

# Download public key for github.com
RUN --mount=type=ssh mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts

# Clone private repository
RUN --mount=type=ssh git clone git@github.com:myorg/myproject.git myproject

更多信息:

答案 23 :(得分:1)

一种简单而安全的方法,无需将密钥保存在Docker映像层中或通过ssh_agent体操即可实现:

  1. 作为Dockerfile中的步骤之一,通过添加以下内容来创建.ssh目录:

    RUN mkdir -p /root/.ssh

  2. 以下表示您希望将ssh目录挂载为卷:

    VOLUME [ "/root/.ssh" ]

  3. 通过添加以下行,确保容器的ssh_config知道在哪里可以找到公钥:

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

  4. 在运行时将本地用户的.ssh目录暴露给容器:

    docker run -v ~/.ssh:/root/.ssh -it image_name

    或者在您的dockerCompose.yml中,将其添加到服务的音量键下:

    - "~/.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" ]

答案 24 :(得分:1)

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

<强>摘录

  

将文件/文件夹从容器的文件系统复制到主机路径。   路径是相对于文件系统的根目录。

  Usage: docker cp CONTAINER:PATH HOSTPATH

  Copy files/folders from the PATH to the HOSTPATH

答案 25 :(得分:1)

到目前为止,对于这方面来说,这将使你的主机操作系统密钥可以在容器中随时根据这一点来实现:

docker run -v ~/.ssh:/mnt -it my_image /bin/bash -c "ln -s /mnt /root/.ssh; ssh user@10.20.30.40"

我不赞成使用Dockerfile来安装密钥,因为容器的迭代可能会留下私钥。

答案 26 :(得分:1)

如果您不关心SSH密钥的安全性,那么这里有很多好的答案。如果您这样做,我找到的最佳答案是从上面评论中的链接到this GitHub comment diegocsandrim。所以其他人更有可能看到它,并且只是在回购消失的情况下,这是该答案的编辑版本:

此处的大多数解决方案最终会将私钥留在图像中。这很糟糕,因为任何有权访问图像的人都可以访问您的私钥。由于我们对squash的行为了解不多,即使您删除密钥并压缩该图层,情况仍可能如此。

我们生成一个使用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"]

答案 27 :(得分:1)

您可以使用共享文件夹将授权密钥传递到容器,并使用如下的docker文件设置权限:

FROM ubuntu:16.04
RUN apt-get install -y openssh-server
RUN mkdir /var/run/sshd
EXPOSE 22
RUN cp /root/auth/id_rsa.pub /root/.ssh/authorized_keys
RUN rm -f /root/auth
RUN chmod 700 /root/.ssh
RUN chmod 400 /root/.ssh/authorized_keys
RUN chown root. /root/.ssh/authorized_keys
CMD /usr/sbin/sshd -D

您的docker run包含类似以下内容的东西,用于在容器上共享主机上的auth目录(持有authorised_keys),然后打开ssh端口,该端口可通过主机上的端口7001访问。

-d -v /home/thatsme/dockerfiles/auth:/root/auth -–publish=127.0.0.1:7001:22

您可能希望查看https://github.com/jpetazzo/nsenter,这似乎是在容器上打开shell并在容器中执行命令的另一种方法。

答案 28 :(得分:0)

  

您可以使用机密来管理容器中的任何敏感数据   在运行时需要,但您不想存储在图像或源中   控件,例如:

     
      
  • 用户名和密码
  •   
  • TLS证书和密钥
  •   
  • SSH密钥
  •   
  • 其他重要数据,例如数据库或内部服务器的名称
  •   
  • 通用字符串或二进制内容(最大500 kb)
  •   
     

https://docs.docker.com/engine/swarm/secrets/

我试图弄清楚如何向运行时(而不是构建)期间使用的容器添加签名密钥,并遇到了这个问题。 Docker机密似乎是我的用例的解决方案,并且由于没有人提到它,因此我将其添加。

答案 29 :(得分:0)

对于debian / root / authorized_keys:

RUN set -x && apt-get install -y openssh-server

RUN mkdir /var/run/sshd
RUN mkdir -p /root/.ssh
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN  echo "ssh-rsa AAAA....yP3w== rsa-key-project01" >> /root/.ssh/authorized_keys
RUN chmod -R go= /root/.ssh

答案 30 :(得分:0)

detailed here是Docker容器内部SSH挑战的简要概述。为了从容器内连接到受信任的远程对象而不会泄漏秘密,有几种方法:

除这些以外,还可能使用在运行Compose时可在运行时访问的单独Docker容器中运行的密钥存储。由于创建和管理诸如Vault by HashiCorp之类的密钥库所需的机制,这里的缺点是额外的复杂性。

有关在独立Docker容器中使用SSH密钥的信息,请参见上面链接的方法,并根据您的特定需求考虑每种方法的缺点。但是,如果您在Compose内部运行,并且想在运行时共享应用程序的密钥(反映OP的实用性),请尝试以下操作:

  • 创建一个docker-compose.env文件并将其添加到您的.gitignore文件中。
  • 更新您的docker-compose.yml并添加env_file,以获取需要密钥的服务。
  • 在应用程序运行时从环境访问公共密钥,例如process.node.DEPLOYER_RSA_PUBKEY(对于Node.js应用程序)。

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

其他资源:

答案 31 :(得分:0)

我整理了一个非常简单的解决方案,该解决方案适用于我的用例,其中我使用“构建器” 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

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

注意1:为此,您需要确保ssh密钥没有密码短语,否则ssh-add /root/.ssh/id_rsa行将要求输入密码短语并中断构建脚本。

注意2:确保对脚本文件设置了正确的文件许可权,以便可以运行它们。

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

答案 32 :(得分:-1)

最简单的方法,获取启动板帐户并使用:ssh-import-id

答案 33 :(得分:-1)

在正在运行的docker容器中,您可以使用docker -i(交互式)选项发出ssh-keygen。这将转发容器提示以在docker容器内创建密钥。