我有一个应用程序,使用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"]
Run Code Online (Sandbox Code Playgroud)
app.js 像git一样运行git命令 git pull
Dan*_*men 125
如果您需要在构建时使用SSH,这是一个更难的问题.例如,如果您正在使用git clone,或者在我的情况下,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 .
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
更新:如果您正在使用Docker 1.13并且具有实验性功能,则可以附加--squash到将合并图层的构建命令,删除SSH密钥并将其隐藏起来docker history.
ebe*_*ing 84
使用Ubuntu时,ssh_config不正确.你需要添加
RUN echo " IdentityFile ~/.ssh/id_rsa" >> /etc/ssh/ssh_config
Run Code Online (Sandbox Code Playgroud)
到您的Dockerfile,以使其识别您的ssh密钥.
yel*_*cap 78
注意:只对私有的图像使用此方法,并且永远都是!
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
Run Code Online (Sandbox Code Playgroud)
Ais*_*tis 53
如果你正在使用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
Run Code Online (Sandbox Code Playgroud)
fun*_*man 46
根据文档:
docker 版本有一个 --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
Run Code Online (Sandbox Code Playgroud)
创建 Dockerfile 后,使用--ssh与 SSH 代理连接的选项:
$ docker build --ssh default .
Run Code Online (Sandbox Code Playgroud)
另外,请查看https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066
cre*_*ack 40
为了在容器中注入ssh密钥,您有多个解决方案:
使用带有ADD指令的Dockerfile ,您可以在构建过程中注入它
简单地做一些事情 cat id_rsa | docker run -i <image> sh -c 'cat > /root/.ssh/id_rsa'
使用docker cp允许您在容器运行时注入文件的命令.
Ezz*_*zze 38
扩展Peter Grainger的答案我能够使用自Docker 17.05以来的多阶段构建.官方页面说明:
对于多阶段构建,您可以
FROM在Dockerfile中使用多个语句.每条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"]
Run Code Online (Sandbox Code Playgroud)
.dockerignore重复.gitignore文件的内容(它会阻止node_modules并导致dist项目的结果目录被复制):
.idea
dist
node_modules
*.log
Run Code Online (Sandbox Code Playgroud)
构建映像的命令示例:
$ docker build -t ezze/geoport:0.6.0 \
--build-arg SSH_KEY="$(cat ~/.ssh/id_rsa)" \
--build-arg SSH_KEY_PASSPHRASE="my_super_secret" \
./
Run Code Online (Sandbox Code Playgroud)
如果您的私有SSH密钥没有密码短语,则只需指定空SSH_KEY_PASSPHRASE参数.
这是它的工作原理:
1).仅在第一个阶段package.json,yarn.lock文件和私有SSH密钥被复制到名为的第一个中间映像sources.为了避免进一步的SSH密钥密码短语提示,它会自动添加到ssh-agent.最后,yarn命令从NPM安装所有必需的依赖项,并通过SSH从Bitbucket克隆私有git存储库.
2).第二阶段构建并缩小Web应用程序的源代码,并将其放在dist下一个名为的中间图像的目录中production.请注意,已安装的源代码node_modules是sources通过以下行从第一个阶段生成的图像中复制的:
COPY --from=sources /app/ /app/
Run Code Online (Sandbox Code Playgroud)
可能它也可能是以下行:
COPY --from=sources /app/node_modules/ /app/node_modules/
Run Code Online (Sandbox Code Playgroud)
我们只有node_modules目录从第一中间的形象在这里,没有SSH_KEY和SSH_KEY_PASSPHRASE参数了.构建所需的所有其余内容都从我们的项目目录中复制.
3).在第三阶段,我们ezze/geoport:0.6.0通过仅包含dist来自第二个中间映像的目录production并安装Node Express来启动Web服务器来减少将被标记的最终映像的大小.
列出图像会得到如下输出:
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
Run Code Online (Sandbox Code Playgroud)
其中未标记的图像与第一和第二中间构建阶段相对应.
如果你跑
$ docker history ezze/geoport:0.6.0 --no-trunc
Run Code Online (Sandbox Code Playgroud)
你不会看到任何提及的SSH_KEY以及SSH_KEY_PASSPHRASE在最终图像.
que*_*o42 15
这里的两个高度评价的答案中有一个危险的错误建议。
\n我发表了评论,但由于我为此损失了很多天,请注意:
\necho "$ssh_prv_key" > /root/.ssh/id_ed25519:)。这将破坏所需的行格式,至少在我的情况下是如此。使用COPY或ADD代替。有关详细信息,请参阅Docker 加载密钥 \xe2\x80\x9c/root/.ssh/id_rsa\xe2\x80\x9d:格式无效。
这也得到了另一位网友的证实:
\n\n\n我收到错误加载密钥“/root/.ssh/id_ed25519”:无效格式。Echo 将为我删除换行符/添加双引号。这仅适用于 ubuntu\alpine:3.10.3 也没有什么不同吗?
\n
如果私钥存储在镜像中,需要注意将公钥从git网站删除,或者不要发布该镜像。如果你照顾好这一点,这是安全的。请参阅下面的 (2.) 了解更好的方法,您也可以“忘记注意”。
\nDockerfile 如下所示:
\nFROM ubuntu:latest\nRUN apt-get update && apt-get install -y git\nRUN mkdir -p /root/.ssh && chmod 700 /root/.ssh\nCOPY /.ssh/id_ed25519 /root/.ssh/id_ed25519\nRUN chmod 600 /root/.ssh/id_ed25519 && \\\n apt-get -yqq install openssh-client && \\\n ssh-keyscan -t ed25519 -H gitlab.com >> /root/.ssh/known_hosts\nRUN git clone git@gitlab.com:GITLAB_USERNAME/test.git\nRUN rm -r /root/.ssh\nRun Code Online (Sandbox Code Playgroud)\n下面是同样事情的更安全的方法,而是使用“多阶段构建”。\n如果您需要一个具有 git repo 目录但没有将私钥存储在其层之一的映像,则需要两个映像,并且您最后只使用第二个。这意味着,您需要FROM两次,然后您可以仅将第一个映像中的 git repo 目录复制到第二个映像,请参阅官方指南“使用多阶段构建”。
我们使用“alpine”作为尽可能小的基础图像,它apk使用apt-get; 您还可以使用apt-get上面的代码而不是使用FROM ubuntu:latest.
Dockerfile 如下所示:
\n# first image only to download the git repo\nFROM alpine as MY_TMP_GIT_IMAGE\n\nRUN apk add --no-cache git\nRUN mkdir -p /root/.ssh && chmod 700 /root/.ssh\nCOPY /.ssh/id_ed25519 /root/.ssh/id_ed25519\nRUN chmod 600 /root/.ssh/id_ed25519\n\nRUN apk -yqq add --no-cache openssh-client && ssh-keyscan -t ed25519 -H gitlab.com >> /root/.ssh/known_hosts\nRUN git clone git@gitlab.com:GITLAB_USERNAME/test.git\nRUN rm -r /root/.ssh\n\n\n# Start of the second image\nFROM MY_BASE_IMAGE\nCOPY --from=MY_TMP_GIT_IMAGE /MY_GIT_REPO ./MY_GIT_REPO\nRun Code Online (Sandbox Code Playgroud)\n我们在这里看到这FROM只是一个命名空间,它就像其下面的行的标题,可以使用别名来寻址。如果没有别名,--from=0将是第一个图像(=FROM命名空间)。
您现在可以发布或共享第二个图像,因为私钥不在其层中,并且您不一定需要在使用一次后从 git 网站中删除公钥!因此,您不需要在每次克隆存储库时创建新的密钥对。当然,请注意,如果有人可能以其他方式获取您的数据,无密码私钥仍然不安全。如果您对此不确定,最好在使用后从服务器中删除公钥,并在每次运行时都有一个新的密钥对。
\n安装Docker桌面;或者在 VirtualBox 中的 WSL2 或 Linux 中使用 docker;或者在独立的 Linux 分区/硬盘中使用 docker。
\n打开命令提示符(PowerShell、终端……)。
\n进入Dockerfile所在目录。
\n创建子文件夹“.ssh/”。
\n出于安全原因,请为每个密钥创建一个新的公共和私有 SSH 密钥对 - 即使您已经有另一个密钥对Dockerfile 运行在命令提示符下的 Dockerfile 文件夹中,输入(注意,这会覆盖而不询问):
\n Write-Output "y" | ssh-keygen -q -t ed25519 -f ./.ssh/id_ed25519 -N \'""\'\nRun Code Online (Sandbox Code Playgroud)\n(如果您使用 PowerShell)或
\n echo "y" | ssh-keygen -q -t ed25519 -f ./.ssh/id_ed25519 -N \'\'\nRun Code Online (Sandbox Code Playgroud)\n(如果您不使用 PowerShell)。
\n您的密钥对现在将位于子文件夹 .ssh/ 中。是否使用该子文件夹取决于您,您也可以将代码更改为COPY id_ed25519 /root/.ssh/id_ed25519;那么您的私钥需要位于您所在的 Dockerfile 目录中。
在编辑器中打开公钥,复制内容并将其发布到您的服务器(例如 GitHub / GitLab --> 配置文件 --> SSH 密钥)。您可以选择任何名称和结束日期。公钥字符串的最终可读注释(如果您没有-C在参数中添加注释,通常是您的计算机名称)ssh-keygen,通常是您的计算机名称)并不重要,只需将其留在那里即可。
开始(不要忘记末尾的“.”,它是构建上下文):
\ndocker build -t 测试。
\n仅适用于 1.):
\n运行后,从服务器中删除公钥(最重要的是,最好是立即删除)。该脚本会从映像中删除私钥,您也可以从本地计算机中删除私钥,因为您不应再使用该密钥对。原因是:即使私钥从镜像中删除,也有人可以从镜像中获取私钥。引用用户的评论:
\n\n\n如果任何人掌握了您的\n图像,他们就可以检索密钥...即使您在后面的层中删除\n该文件,b/c 他们也可以在您添加该文件时返回到步骤 7
\n
攻击者可以等待使用此私钥,直到您再次使用该密钥对。
\n仅适用于 2):
\n至于危险的错误建议这里两个高度赞扬的答案中使用有问题的私钥回显方法的
\n我们在这里看到,答案中一定有问题,因为排名前 1 的答案投票至少与问题投票的水平不符。
\n在排名前 1 的答案的评论列表末尾,只有一条未投票的小评论,命名了相同的私钥回声问题(该答案也引用了该问题)。并且:该批评意见是在答复三年后提出的。
\n我自己已经对排名第一的答案投了赞成票。后来我才意识到这对我不起作用。因此,群体智能正在发挥作用,但力度不大?如果有人可以向我解释为什么回显私钥可能对其他人有效,但对我无效,请发表评论。否则,326k 浏览量(减去 2 条评论;))将会忽略或忽略第 1 个答案的错误。如果私钥回显代码行不会花费我很多工作日,并且从网上的所有内容中挑选代码绝对令人沮丧,我就不会在这里写这么长的文本。
\nDan*_*der 14
这行是个问题:
ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa
Run Code Online (Sandbox Code Playgroud)
指定要复制到映像中的文件时,只能使用相对路径 - 相对于Dockerfile所在的目录.所以你应该使用:
ADD id_rsa /root/.ssh/id_rsa
Run Code Online (Sandbox Code Playgroud)
并将id_rsa文件放入Dockerfile所在的目录中.
有关详细信息,请查看此内容:http://docs.docker.io/reference/builder/#add
Edi*_*ngo 14
从docker API 1.39+(Check API version with docker version) 开始,docker build 允许--ssh使用代理套接字或密钥的选项,以允许 Docker 引擎转发 SSH 代理连接。
构建命令
export DOCKER_BUILDKIT=1
docker build --ssh default=~/.ssh/id_rsa .
Run Code Online (Sandbox Code Playgroud)
文件
# 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
Run Code Online (Sandbox Code Playgroud)
更多信息:
MrE*_*MrE 13
Docker容器应该被视为自己的"服务".要分开关注点,您应该分开功能:
1)数据应该在数据容器中:使用链接的卷将repo克隆到.然后,该数据容器可以链接到需要它的服务.
2)使用容器运行git克隆任务(即,它唯一的工作就是克隆)在运行时将数据容器链接到它.
3)ssh-key相同:把它放在一个卷(如上所述)并在需要时将它链接到git clone服务
这样,克隆任务和密钥都是短暂的,只有在需要时才有效.
现在,如果您的应用程序本身是一个git接口,您可能需要直接考虑使用github或bitbucket REST API来完成您的工作:这就是它们的设计目标.
小智 13
在docker构建时进行npm install时遇到了类似的问题.
灵感来自Daniel van Flymen的解决方案并将其与git url重写相结合 ,我们发现了一个更简单的方法来验证来自私有github repos的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 .
Run Code Online (Sandbox Code Playgroud)
不幸的是,我在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
Run Code Online (Sandbox Code Playgroud)
Moh*_*zim 11
一种解决方案是使用以下选项将主机的ssh密钥安装到docker中:
docker run -v /home/<host user>/.ssh:/home/<docker user>/.ssh <image>
Run Code Online (Sandbox Code Playgroud)
与上述解决方案类似.但适用于非root用户.与github完美配合.
Dev*_*esh 11
您可以使用多阶段构建来构建容器 这是您可以采用的方法:-
阶段 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
Run Code Online (Sandbox Code Playgroud)
第 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"]
Run Code Online (Sandbox Code Playgroud)
在您的撰写文件中添加 env 属性:
environment:
- SSH_PRIVATE_KEY=${SSH_PRIVATE_KEY}
Run Code Online (Sandbox Code Playgroud)
然后像这样从构建脚本传递参数:
docker-compose build --build-arg SSH_PRIVATE_KEY="$(cat ~/.ssh/id_rsa)"
Run Code Online (Sandbox Code Playgroud)
并移除中间容器以确保安全。 这将帮助你欢呼。
edu*_*upo 10
将ssh身份验证套接字转发到容器:
docker run --rm -ti \
-v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock \
-e SSH_AUTH_SOCK=/tmp/ssh_auth.sock \
-w /src \
my_image
Run Code Online (Sandbox Code Playgroud)
您的脚本将能够执行git clone.
额外:如果您希望克隆文件属于您需要使用的特定用户,chown因为在容器内使用除root之外的其他用户将导致git失败.
您可以在容器的环境中发布一些其他变量:
docker run ...
-e OWNER_USER=$(id -u) \
-e OWNER_GROUP=$(id -g) \
...
Run Code Online (Sandbox Code Playgroud)
克隆后,必须执行chown $OWNER_USER:$OWNER_GROUP -R <source_folder>以在离开容器之前设置正确的所有权,以便容器外的非root用户可以访问这些文件.
这个问题真的很烦人.因为你不能在dockerfile上下文之外添加/复制任何文件,这意味着不可能只将〜/ .ssh/id_rsa链接到图像的/root/.ssh/id_rsa,当你肯定需要一个键来做一些sshed的东西时喜欢来自私人仓库链接的git clone ...,在建造你的码头图像时.
无论如何,我找到了一个解决方法,不是那么说服,但确实对我有用.
在您的dockerfile中:
一次拍摄的剧本:
任何时候你必须使用一些ssh要求从这个映像运行一个容器,只需为run命令添加-v,如:
docker run -v~/.ssh/id_rsa:/root/.ssh/id_rsa --name container image命令
此解决方案在项目源和构建的docker镜像中都没有私钥,因此不再需要担心安全问题.
此处详细介绍了Docker 容器内 SSH 挑战的简要概述。为了在不泄露机密的情况下从容器内连接到受信任的遥控器,有几种方法:
~/.ssh给容器。(仅限开发,可能不安全)除此之外,在使用 Compose 时,还可以使用在运行时可访问的单独 docker 容器中运行的密钥库。由于创建和管理密钥库(例如HashiCorp 的 Vault )所需的机器,这里的缺点是额外的复杂性。
对于在独立 Docker 容器中使用 SSH 密钥,请参阅上面链接的方法,并根据您的特定需求考虑每种方法的缺点。但是,如果您在 Compose 中运行并希望在运行时共享应用程序的密钥(反映 OP 的实用性),请尝试以下操作:
docker-compose.env文件并将其添加到您的.gitignore文件中。docker-compose.yml并添加env_file需要密钥的服务。process.node.DEPLOYER_RSA_PUBKEY在 Node.js 应用程序的情况下。上述方法是开发和测试的理想选择,虽然它可以满足生产要求,但在生产中,您最好使用上述其他方法之一。
其他资源:
'你可以有选择地让远程服务器访问你的本地ssh-agent,就像它在服务器上运行一样'
https://developer.github.com/guides/using-ssh-agent-forwarding/
小智 7
我今天遇到了同样的问题和以前的帖子稍微修改过的版本我发现这种方法对我来说更有用
docker run -it -v ~/.ssh/id_rsa:/root/.my-key:ro image /bin/bash
Run Code Online (Sandbox Code Playgroud)
(注意readonly标志,所以容器在任何情况下都不会弄乱我的ssh密钥.)
在容器里面我现在可以运行:
ssh-agent bash -c "ssh-add ~/.my-key; git clone <gitrepourl> <target>"
Run Code Online (Sandbox Code Playgroud)
所以我没有得到Bad owner or permissions on /root/.ssh/..@kross注意到的那个错误
如果您不关心 SSH 密钥的安全性,这里有很多很好的答案。如果你这样做,最好的答案,我发现是从上面的评论的链接此GitHub的评论通过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 .
Run Code Online (Sandbox Code Playgroud)
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"]
Run Code Online (Sandbox Code Playgroud)
您还可以在主机和容器之间链接.ssh目录,我不知道这种方法是否有任何安全隐患,但它可能是最简单的方法.这样的事情应该有效:
$ sudo docker run -it -v /root/.ssh:/root/.ssh someimage bash
Run Code Online (Sandbox Code Playgroud)
请记住,docker使用sudo运行(除非你没有),如果是这种情况你将使用root ssh密钥.
小智 6
无需将密钥保存在 Docker 映像层或通过 ssh_agent 体操即可实现此目的的一种简单而安全的方法是:
作为 中的步骤之一Dockerfile,.ssh通过添加以下内容来创建目录:
RUN mkdir -p /root/.ssh
下面表示您希望将 ssh 目录挂载为卷:
VOLUME [ "/root/.ssh" ]
ssh_config通过添加以下行,确保您的容器知道在哪里可以找到公钥:
RUN echo " IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config
.ssh在运行时将本地用户的目录公开给容器:
docker run -v ~/.ssh:/root/.ssh -it image_name
或者在dockerCompose.yml服务的音量键下添加:
- "~/.ssh:/root/.ssh"
你的finalDockerfile应该包含如下内容:
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" ]
Run Code Online (Sandbox Code Playgroud)
小智 6
正如eczajk在Daniel van Flymen的回答中已经评论的那样,删除密钥和使用似乎并不安全--squash,因为它们仍会在历史记录中可见(docker history --no-trunc)。
现在,可以在Docker 18.09中使用“构建机密”功能。就我而言,我使用主机SSH密钥在Dockerfile中使用以下命令克隆了一个私人git repo:
# syntax=docker/dockerfile:experimental
[...]
RUN --mount=type=ssh git clone [...]
[...]
Run Code Online (Sandbox Code Playgroud)
为了能够使用它,您需要在运行之前启用新的BuildKit后端docker build:
export DOCKER_BUILDKIT=1
Run Code Online (Sandbox Code Playgroud)
并且您需要将--ssh default参数添加到docker build。
有关此的更多信息:https : //medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066
我整理了一个非常简单的解决方案,适用于我的用例,我使用“构建器”docker 映像来构建单独部署的可执行文件。换句话说,我的“构建器”映像永远不会离开我的本地机器,只需要在构建阶段访问私有存储库/依赖项。
您无需为此解决方案更改 Dockerfile。
当你运行你的容器时,挂载你的~/.ssh目录(这样可以避免将密钥直接烘焙到镜像中,而是确保它们在构建阶段只在短时间内可供单个容器实例使用)。就我而言,我有几个构建脚本可以自动化我的部署。
在我的build-and-package.sh脚本中,我像这样运行容器:
# 之前做一些脚本的东西 ... 码头工人运行--rm \ -v ~/.ssh:/root/.ssh \ -v "$workspace":/workspace \ -w /工作区生成器\ bash -cl "./scripts/ build-init.sh $executable" ... # 之后做一些脚本的事情(即从工作区中拉出构建的可执行文件等)
该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
Run Code Online (Sandbox Code Playgroud)
因此,我们不是swift build直接在docker run命令中执行命令(或任何与您的环境相关的构建命令),而是执行build-init.sh启动 的脚本ssh-agent,然后将我们的 ssh 密钥添加到代理,最后执行我们的swift build命令。
注意 1:为此,您需要确保您的 ssh 密钥没有密码,否则该ssh-add /root/.ssh/id_rsa行将要求密码并中断构建脚本。
注意 2:确保您对脚本文件设置了正确的文件权限,以便它们可以运行。
希望这为具有类似用例的其他人提供了一个简单的解决方案。
| 归档时间: |
|
| 查看次数: |
228111 次 |
| 最近记录: |