一开始,有些元噪声
这里有两个得到高度好评的答案,其中有一个危险的错误建议。
我评论道,但由于我为此损失了很多天,请注意:
不要将私钥回显到文件中(意思是:回显"$ssh_prv_key" > /root/.ssh/id_ed25519)。这将破坏所需的行格式,至少在我的例子中是这样。
使用COPY或ADD代替。参见Docker加载密钥“/root/”。Ssh /id_rsa ":无效的详细格式。
另一名用户也证实了这一点:
我得到错误加载键"/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两次,然后你可以只复制git回购目录从第一个映像到第二个映像,参见官方指南“使用多阶段构建”。
我们使用“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命名空间)。
You could now publish or share the second image, as the private key is not in its layers, and you would not necessarily need to remove the public key from the git website after one usage! Thus, you do not need to create a new key pair at every cloning of the repo. Of course, be aware that a passwordless private key is still insecure if someone might get a hand on your data in another way. If you are not sure about this, better remove the public key from the server after usage, and have a new key pair at every run.
如何从Dockerfile构建映像的指南
Install Docker Desktop; or use docker inside WSL2 or Linux in a VirtualBox; or use docker in a standalone Linux partition / hard drive.
Open a command prompt (PowerShell, terminal, ...).
Go to the directory of the Dockerfile.
Create a subfolder ".ssh/".
For security reasons, create a new public and private SSH key pair - even if you already have another one lying around - for each Dockerfile run. In the command prompt, in your Dockerfile's folder, enter (mind, this overwrites without asking):
Write-Output "y" | ssh-keygen -q -t ed25519 -f ./.ssh/id_ed25519 -N '""'
(if you use PowerShell) or
echo "y" | ssh-keygen -q -t ed25519 -f ./.ssh/id_ed25519 -N ''
(if you do not use PowerShell).
Your key pair will now be in the subfolder .ssh/. It is up to you whether you use that subfolder at all, you can also change the code to COPY id_ed25519 /root/.ssh/id_ed25519; then your private key needs to be in the Dockerfile's directory that you are in.
Open the public key in an editor, copy the content and publish it to your server (e.g. GitHub / GitLab --> profile --> SSH keys). You can choose whatever name and end date. The final readable comment of the public key string (normally your computer name if you did not add a -C comment in the parameters of ssh-keygen) is not important, just leave it there.
Start (Do not forget the "." at the end which is the build context):
docker build -t test .
仅限1人使用。)
After the run, remove the public key from the server (most important, and at best at once). The script removes the private key from the image, and you may also remove the private key from your local computer, since you should never use the key pair again. The reason: someone could get the private key from the image even if it was removed from the image. Quoting a user's comment:
If anyone gets a hold of your
image, they can retrieve the key... even if you delete that file in a
later layer, b/c they can go back to Step 7 when you added it
The attacker could wait with this private key until you use the key pair again.
仅限2人。)
After the run, since the second image is the only image remaining after a build, we do not necessarily need to remove the key pair from client and host. We still have a small risk that the passwordless private key is taken from a local computer somewhere. That is why you may still remove the public key from the git server. You may also remove any stored private keys. But it is probably not needed in many projects where the main aim is rather to automate building the image, and less the security.
最后,更多的元噪声
对于两个高赞答案中使用了有问题的“私钥回声”方法的危险错误建议,以下是本文撰写时的投票情况:
https://stackoverflow.com/a/42125241/11154841 176个赞(前1)
https://stackoverflow.com/a/48565025/11154841 55个赞(前5名)
这个问题获得了32.6万次观看,获得了376个赞
我们在这里看到答案中一定有错误,因为排名前1的答案投票至少不是在问题投票的水平上。
在排名前1的答案的评论列表的末尾,只有一个没有投票的小评论,命名了相同的私钥回声问题(在这个答案中也引用了这个问题)。而且,这一批评性评论是在给出答案三年后提出的。
I have upvoted the top 1 answer myself. I only realised later that it would not work for me. Thus, swarm intelligence is working, but on a low flame? If anyone can explain to me why echoing the private key might work for others, but not for me, please comment. Else, 326k views (minus 2 comments ;) ) would have overseen or left aside the error of the top 1 answer. I would not write such a long text here if that echo-of-the-private-key code line would not have cost me many working days, with absolutely frustrating code picking from everything on the net.