Clone private git repo with dockerfile
我复制了这段代码,从周围的各种工作文件中,这里是我的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | FROM ubuntu MAINTAINER Luke Crooks"[email protected]" # Update aptitude with new repo RUN apt-get update # Install software RUN apt-get install -y git python-virtualenv # Make ssh dir RUN mkdir /root/.ssh/ # Copy over private key, and set permissions ADD id_rsa /root/.ssh/id_rsa RUN chmod 700 /root/.ssh/id_rsa RUN chown -R root:root /root/.ssh # Create known_hosts RUN touch /root/.ssh/known_hosts # Remove host checking RUN echo"Host bitbucket.org \tStrictHostKeyChecking no ">> /root/.ssh/config # Clone the conf files into the docker container RUN git clone [email protected]:Pumalo/docker-conf.git /home/docker-conf |
这给了我错误
1 2 3 4 5 6 7 8 9 10 | Step 10 : RUN git clone [email protected]:Pumalo/docker-conf.git /home/docker-conf ---> Running in 0d244d812a54 Cloning into '/home/docker-conf'... Warning: Permanently added 'bitbucket.org,131.103.20.167' (RSA) to the list of known hosts. Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. 2014/04/30 16:07:28 The command [/bin/sh -c git clone [email protected]:Pumalo/docker-conf.git /home/docker-conf] returned a non-zero code: 128 |
这是我第一次使用dockerfiles,但从我读过的(和从工作配置中获取的)内容来看,我看不出这为什么不起作用。
我的ID_rsa和我的dockerfile在同一个文件夹中,是本地密钥的副本,可以克隆这个repo。没问题。
编辑:
在我的dockerfile中,我可以添加:
1 | RUN cat /root/.ssh/id_rsa |
它会打印出正确的钥匙,所以我知道它是正确复制的。
我也试着按照诺亚的建议去做:
1 2 3 | RUN echo"Host bitbucket.org \tIdentityFile /root/.ssh/id_rsa \tStrictHostKeyChecking no">> /etc/ssh/ssh_config |
很遗憾,这也行不通。
我的密钥受密码保护,这导致了问题的发生,下面列出了一个工作文件(供将来的谷歌用户使用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | FROM ubuntu MAINTAINER Luke Crooks"[email protected]" # Update aptitude with new repo RUN apt-get update # Install software RUN apt-get install -y git # Make ssh dir RUN mkdir /root/.ssh/ # Copy over private key, and set permissions # Warning! Anyone who gets their hands on this image will be able # to retrieve this private key file from the corresponding image layer ADD id_rsa /root/.ssh/id_rsa # Create known_hosts RUN touch /root/.ssh/known_hosts # Add bitbuckets key RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts # Clone the conf files into the docker container RUN git clone [email protected]:User/repo.git |
您应该为那个docker映像创建新的ssh密钥集,因为您可能不想在其中嵌入您自己的私钥。要使其工作,您必须将该密钥添加到Git存储库中的部署密钥中。以下是完整的配方:
使用
将repo-key.pub添加到存储库部署密钥中。在GitHub上,转到[Your Repository]->Settings->Deploy Keys
在Dockerfile中添加类似的内容:
1 2 3 4 5 6 | ADD repo-key / RUN \ chmod 600 /repo-key && \ echo"IdentityFile /repo-key">> /etc/ssh/ssh_config && \ echo -e"StrictHostKeyChecking no">> /etc/ssh/ssh_config && \ // your git clone commands here... |
请注意,上面关闭了严格的hostkeychecking,因此您不需要.ssh/known_主机。尽管我可能更喜欢上面其中一个答案中使用ssh-keyscan的解决方案。
没有必要乱弄ssh配置。使用包含环境变量的配置文件(而不是docker file),并让shell脚本在运行时更新docker文件。您将令牌保存在dockerfiles之外,并且可以通过https克隆(不需要生成或传递ssh密钥)。
转到设置>个人访问令牌
- 生成启用
repo 作用域的个人访问令牌。 - 像这样的克隆:
git clone https://[email protected]/user-or-org/repo 。
一些评论指出,如果您使用共享dockerfile,这可能会向项目中的其他人公开您的访问密钥。虽然这可能是或可能不是您的特定用例所关注的问题,但您可以通过以下几种方法来处理:
- 使用shell脚本接受可以将密钥作为变量包含的参数。用
sed 或类似文件替换dockerfile中的变量,即用sh rundocker.sh MYTOKEN=foo 调用脚本,该脚本将在https://{{MY_TOKEN}}@github.com/user-or-org/repo 上替换。请注意,您也可以使用配置文件(以.yml或任何您想要的格式)来执行相同的操作,但要使用环境变量。 - 仅为该项目创建GitHub用户(并为其生成访问令牌)
对于BitBucket存储库,生成对repo和project具有读访问权限的app password(BitBucket设置->访问管理->app password,请参见图)。
那么您应该使用的命令是:
1 | git clone https://username:[email protected]/reponame/projectname.git |
另一个选项是使用多阶段Docker构建,以确保最终映像中不包含ssh密钥。
正如我在文章中所描述的,您可以准备具有Git克隆所需依赖项的中间映像,然后将所需文件
此外,如果我们使用cx1(7)中间层,甚至可以在完成后从机器中删除它们。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # Choose and name our temporary image. FROM alpine as intermediate # Add metadata identifying these images as our build containers (this will be useful later!) LABEL stage=intermediate # Take an SSH key as a build argument. ARG SSH_KEY # Install dependencies required to git clone. RUN apk update && \ apk add --update git && \ apk add --update openssh # 1. Create the SSH directory. # 2. Populate the private key file. # 3. Set the required permissions. # 4. Add github to our list of known hosts for ssh. RUN mkdir -p /root/.ssh/ && \ echo"$SSH_KEY"> /root/.ssh/id_rsa && \ chmod -R 600 /root/.ssh/ && \ ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts # Clone a repository (my website in this case) RUN git clone [email protected]:janakerman/janakerman.git # Choose the base image for our final image FROM alpine # Copy across the files from our `intermediate` container RUN mkdir files COPY --from=intermediate /janakerman/README.md /files/README.md |
然后我们可以建立:
1 2 | MY_KEY=$(cat ~/.ssh/id_rsa) docker build --build-arg SSH_KEY="$MY_KEY" --tag clone-example . |
证明我们的ssh密钥已丢失:
1 | docker run -ti --rm clone-example cat /root/.ssh/id_rsa |
从生成计算机中清除中间图像:
1 | docker rmi -f $(docker images -q --filter label=stage=intermediate) |
上述解决方案对BitBucket无效。我想这就是诀窍:
1 2 3 4 | RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts \ && eval `ssh-agent` \ && ssh-add ~/.ssh/[key] \ && git clone [email protected]:[team]/[repo].git |
您通常不想在Docker构建中执行私有回购的
相反,通常的做法是在您选择的CI工具中从Docker外部克隆git repo,并简单地将文件
如果要将凭据添加到构建中,请考虑使用多阶段构建进行此操作,并且只将这些凭据放在早期阶段,而这些早期阶段永远不会标记并推送到构建主机之外。结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | FROM ubuntu as clone # Update aptitude with new repo RUN apt-get update \ && apt-get install -y git # Make ssh dir # Create known_hosts # Add bitbuckets key RUN mkdir /root/.ssh/ \ && touch /root/.ssh/known_hosts \ && ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts # Copy over private key, and set permissions # Warning! Anyone who gets their hands on this image will be able # to retrieve this private key file from the corresponding image layer COPY id_rsa /root/.ssh/id_rsa # Clone the conf files into the docker container RUN git clone [email protected]:User/repo.git FROM ubuntu as release LABEL maintainer="Luke Crooks <[email protected]>" COPY --from=clone /repo /repo ... |
最近,buildKit测试了一些实验性功能,这些功能允许您将ssh密钥作为从未写入映像的挂载传递:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # syntax=docker/dockerfile:experimental FROM ubuntu as clone LABEL maintainer="Luke Crooks <[email protected]>" # Update aptitude with new repo RUN apt-get update \ && apt-get install -y git # Make ssh dir # Create known_hosts # Add bitbuckets key RUN mkdir /root/.ssh/ \ && touch /root/.ssh/known_hosts \ && ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts # Clone the conf files into the docker container RUN --mount=type=secret,id=ssh_id,target=/root/.ssh/id_rsa \ git clone [email protected]:User/repo.git |
你可以用以下方法建立它:
1 2 | $ DOCKER_BUILDKIT=1 docker build -t your_image_name \ --secret id=ssh_id,src=$(pwd)/id_rsa . |
请注意,这仍然要求您的ssh密钥不受密码保护,但您至少可以在单个阶段运行构建,删除复制命令,并避免ssh凭据成为映像的一部分。
buildkit还为ssh添加了一个功能,它允许您仍然拥有受密码保护的ssh密钥,结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # syntax=docker/dockerfile:experimental FROM ubuntu as clone LABEL maintainer="Luke Crooks <[email protected]>" # Update aptitude with new repo RUN apt-get update \ && apt-get install -y git # Make ssh dir # Create known_hosts # Add bitbuckets key RUN mkdir /root/.ssh/ \ && touch /root/.ssh/known_hosts \ && ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts # Clone the conf files into the docker container RUN --mount=type=ssh \ git clone [email protected]:User/repo.git |
你可以用以下方法建立它:
1 2 3 4 5 | $ eval $(ssh-agent) $ ssh-add ~/.ssh/id_rsa (Input your passphrase here) $ DOCKER_BUILDKIT=1 docker build -t your_image_name \ --ssh default=$SSH_AUTH_SOCK . |
同样,这会被注入到构建中,而不会被写入图像层,从而消除了凭证可能意外泄漏的风险。
要强制Docker运行
1 2 3 4 5 | # inject a datestamp arg which is treated as an environment variable and # will break the cache for the next RUN command ARG DATE_STAMP # Clone the conf files into the docker container RUN git clone [email protected]:User/repo.git |
然后,在docker build命令中注入更改的参数:
1 2 | date_stamp=$(date +%Y%m%d-%H%M%S) docker build --build-arg DATE_STAMP=$date_stamp . |