Sao chép git repo riêng với dockerfile


240

Tôi đã sao chép mã này từ những gì dường như là các dockerfiles đang hoạt động xung quanh, đây là của tôi:

FROM ubuntu

MAINTAINER Luke Crooks "luke@pumalo.org"

# 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\n\tStrictHostKeyChecking no\n" >> /root/.ssh/config

# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:Pumalo/docker-conf.git /home/docker-conf

Điều này cho tôi lỗi

Step 10 : RUN git clone git@bitbucket.org: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 git@bitbucket.org:Pumalo/docker-conf.git /home/docker-conf] returned a non-zero code: 128

Đây là lần đầu tiên tôi sử dụng dockerfiles, nhưng từ những gì tôi đã đọc (và lấy từ cấu hình làm việc) tôi không thể hiểu tại sao điều này không hoạt động.

Id_rsa của tôi nằm trong cùng thư mục với dockerfile của tôi và là một bản sao của khóa cục bộ của tôi có thể sao chép repo này không có vấn đề gì.

Biên tập:

Trong dockerfile của tôi, tôi có thể thêm:

RUN cat /root/.ssh/id_rsa

Và nó in ra khóa chính xác, vì vậy tôi biết nó được sao chép chính xác.

Tôi cũng đã cố gắng làm như noah khuyên và chạy:

RUN echo "Host bitbucket.org\n\tIdentityFile /root/.ssh/id_rsa\n\tStrictHostKeyChecking no" >> /etc/ssh/ssh_config

Điều đáng buồn này cũng không hoạt động.

Câu trả lời:


300

Khóa của tôi là mật khẩu được bảo vệ gây ra sự cố, một tệp đang hoạt động được liệt kê bên dưới (để được trợ giúp của các nhân viên trong tương lai)

FROM ubuntu

MAINTAINER Luke Crooks "luke@pumalo.org"

# 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 git@bitbucket.org:User/repo.git

11
Chỉ trong trường hợp, đây là một liên kết mô tả cách xóa mật khẩu bảo vệ của khóa
Thomas

82
Chỉ là một FYI, sau khi bạn chạy RUN ssh-keyscan bitbucket.org >> /root/.ssh/ Unknown_hosts, Hình ảnh sẽ lưu nó dưới dạng một lớp. Nếu bất cứ ai nắm giữ hình ảnh của bạn, họ có thể truy xuất khóa ... ngay cả khi bạn xóa tệp đó ở lớp sau, b / c họ có thể quay lại Bước 7 khi bạn thêm nó.
Bernie Perez

23
Cảm ơn câu trả lời hữu ích. Nhưng đối với chúng tôi, quá trình xây dựng thất bại ngẫu nhiên và sau khi điều tra, chúng tôi nhận thấy ssh-keyscanthời gian chờ mặc định là 5 giây mà bitbucket thường vượt quá. ssh-keyscanthậm chí sẽ không báo cáo lỗi. Vì vậy, tốt hơn RUN ssh-keyscan -T 60 bitbucket.org >> /root/.ssh/known_hostsđể chạy để được an toàn.
chất lỏng

5
Ai đó có thể giải thích tại sao chạy ssh-keyscanlà một vấn đề? Tôi hiểu rằng nó chỉ đơn giản là sẽ kéo khóa công khai của Github / Bitbucket. Sự thay thế nào có thể được sử dụng để nó không kết thúc trong một lớp?
Pedro

9
@Pedro Đặc biệt bước keyscan hoàn toàn không phải là một vấn đề, bạn rõ ràng đúng. Nếu bất cứ điều gì, các khóa công khai này nên được lan truyền càng nhiều càng tốt. Xem sshd (8) để biết chi tiết về known_hoststập tin. Mọi người chỉ nêu lên những điều ngẫu nhiên khi âm thanh đủ đáng báo động.
tne

99

Bạn nên tạo khóa SSH mới được đặt cho hình ảnh Docker đó, vì có lẽ bạn không muốn nhúng vào khóa riêng của mình. Để làm cho nó hoạt động, bạn sẽ phải thêm khóa đó vào các khóa triển khai trong kho git của bạn. Đây là công thức hoàn chỉnh:

  1. Tạo các khóa ssh ssh-keygen -q -t rsa -N '' -f repo-keysẽ cung cấp cho bạn các tệp repo-key và repo-key.pub.

  2. Thêm repo-key.pub vào các khóa triển khai kho lưu trữ của bạn.
    Trên GitHub, đi đến [kho lưu trữ của bạn] -> Cài đặt -> Triển khai các khóa

  3. Thêm một cái gì đó như thế này vào Dockerfile của bạn:

    THÊM khóa repo /
    CHẠY \
      chmod 600 / khóa repo && \  
      tiếng vang "IdentityFile / repo-key" >> / etc / ssh / ssh_config && \  
      echo -e "StricthostKeyChecking no" >> / etc / ssh / ssh_config && \  
      // lệnh git clone của bạn ở đây ...
    

Lưu ý rằng ở trên tắt StricthostKeyChecking, vì vậy bạn không cần .ssh / unknown_hosts. Mặc dù tôi có thể thích nhiều giải pháp hơn với ssh-keyscan trong một trong những câu trả lời ở trên.


6
Cảnh báo: trên cấu hình của tôi, echo -e "..." cũng ghi -e bên trong tệp. Chỉ cần loại bỏ cờ và nó hoạt động tốt.
Conliclicultor

Câu trả lời của bạn hoàn toàn hoàn hảo trong việc giúp tôi giải quyết vấn đề của mình. Cảm ơn bạn!
Con trỏ David

Tôi vẫn có cùng một vấn đề:fatal: Could not read from remote repository.
Alex

1
Cảm ơn hàng triệu người! Tôi đang trên bờ vực tuyên bố tình yêu với bạn. Bạn đã giải quyết một vấn đề tôi đã chiến đấu trong nhiều ngày!
alexandra

Câu trả lời được chọn cho câu hỏi này không phải là một câu trả lời hay nữa. Nó đã đúng vào năm 2014 nhưng đến năm 2020 thì đây là câu trả lời đúng.
Bikal Basnet

70

Không cần phải loay hoay với cấu hình ssh. Sử dụng tệp cấu hình (không phải Dockerfile) có chứa các biến môi trường và có tập lệnh shell cập nhật tệp docker của bạn khi chạy. Bạn giữ mã thông báo khỏi Dockerfiles của bạn và bạn có thể sao chép qua https (không cần tạo hoặc chuyển xung quanh các khóa ssh).

Chuyển đến Cài đặt> Mã truy cập cá nhân

  • Tạo mã thông báo truy cập cá nhân với repophạm vi được bật.
  • Nhân bản như thế này: git clone https://MY_TOKEN@github.com/user-or-org/repo

Một số bình luận đã lưu ý rằng nếu bạn sử dụng Dockerfile được chia sẻ, điều này có thể làm lộ khóa truy cập của bạn cho những người khác trong dự án của bạn. Mặc dù điều này có thể hoặc không phải là mối quan tâm cho trường hợp sử dụng cụ thể của bạn, đây là một số cách bạn có thể giải quyết:

  • Sử dụng tập lệnh shell để chấp nhận các đối số có thể chứa khóa của bạn dưới dạng một biến. Thay thế một biến trong Dockerfile của bạn bằng sedhoặc tương tự, tức là gọi tập lệnh sh rundocker.sh MYTOKEN=foosẽ thay thế https://{{MY_TOKEN}}@github.com/user-or-org/repo. Lưu ý rằng bạn cũng có thể sử dụng tệp cấu hình (bằng .yml hoặc bất kỳ định dạng nào bạn muốn) để làm điều tương tự nhưng với các biến môi trường.
  • Tạo người dùng github (và tạo mã thông báo truy cập) cho dự án đó

Bạn đang nói về bối cảnh Settings > Applicationsnào?
turboladen

1
Nhược điểm của phương pháp này là bạn đang lưu trữ thông tin đăng nhập cho một repo riêng trong Dockerfile, trái ngược với cách tiếp cận của @ crooksey, điều này sẽ cho phép bạn tham chiếu khóa được lưu trữ riêng biệt từ Dockerfile. Không có bối cảnh xung quanh việc OP lưu trữ Dockerfile như thế nào, chúng tôi không thể xác định liệu điều này có gây ra sự cố hay không nhưng từ kinh nghiệm cá nhân, tôi muốn lưu trữ Dockerfiles của mình trong một VCS và không muốn cam kết bất cứ điều gì có thông tin xác thực. Khi Docker thực hiện khả năng chuyển các biến env để xây dựng lệnh thì tôi đồng ý đây sẽ là giải pháp sạch nhất.
Jabbslad

2
@CalvinFroedge bởi địa phương Tôi giả sử bạn có nghĩa là máy chủ của bạn? Tôi không biết cách để hiển thị các biến môi trường trên máy chủ lưu trữ vào thời gian xây dựng, đó là lý do tại sao chúng tôi có các vấn đề mở như github.com/docker/docker/issues/6822 này . Xin vui lòng làm rõ?
Jabbslad

1
Thậm chí sạch hơn (phân tách mối quan tâm): một khối lượng được liên kết cho repo nhân bản + một thùng chứa chuyên dụng chỉ dành cho tác vụ nhân bản + một khối lượng được liên kết chỉ với các khóa SSH (hoặc mã thông báo, như bạn đề xuất). Xem stackoverflow.com/a/30992047 , có thể kết hợp với stackoverflow.com/a/29981990 .
Peterino

9
Ngoài ra câu hỏi là cho một repo BITBucks, không phải là một repo github.
Michael Draper

25

Một tùy chọn khác là sử dụng bản dựng docker nhiều giai đoạn để đảm bảo rằng các khóa SSH của bạn không được bao gồm trong hình ảnh cuối cùng.

Như được mô tả trong bài viết của tôi, bạn có thể chuẩn bị hình ảnh trung gian của mình với các phụ thuộc cần thiết để git clone và sau đó COPYcác tệp cần thiết vào hình ảnh cuối cùng của bạn.

Ngoài ra, nếu chúng LABELta có các lớp trung gian, chúng ta thậm chí có thể xóa chúng khỏi máy khi hoàn tất.

# 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 git@github.com: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

Sau đó chúng ta có thể xây dựng:

MY_KEY=$(cat ~/.ssh/id_rsa)
docker build --build-arg SSH_KEY="$MY_KEY" --tag clone-example .

Chứng minh các khóa SSH của chúng tôi đã biến mất:

docker run -ti --rm clone-example cat /root/.ssh/id_rsa

Làm sạch hình ảnh trung gian từ máy xây dựng:

docker rmi -f $(docker images -q --filter label=stage=intermediate)

ARG SSH_PRIVATE_KEY cần được thay thế bằng ARG SSH_KEY
Joseph Persie

Chúng ta không thể xóa các khóa sau khi git clone được thực hiện?
Broncha

1
Bạn có thể làm, nhưng bạn cần thực hiện nó như một phần của một đơn RUNđể bạn không để lại khóa trong lớp hình ảnh trước đó. Kể từ docker, 1.13bạn có thể sử dụng đối số --squash thử nghiệm sẽ loại bỏ khóa SSH trong các lớp hình ảnh cuối cùng của bạn.
jaker

19

Đối với kho lưu trữ bitbucket, tạo Mật khẩu ứng dụng (cài đặt Bitbucket -> Quản lý truy cập -> Mật khẩu ứng dụng, xem hình ảnh) với quyền truy cập đọc vào repo và dự án.

menu người dùng bitbucket

Sau đó, lệnh mà bạn nên sử dụng là:

git clone https://username:generated_password@bitbucket.org/reponame/projectname.git

1
Đơn giản nhất :) Tôi phải thừa nhận tôi thích cách tiếp cận dựa trên SSH, nhưng tôi không thể tìm thấy bất kỳ tệp nào trong số các tệp đang hoạt động ở trên, v.v.
Janos

Tôi không thấy "Quản lý truy cập" ... Tôi đoán nó đã lỗi thời?
Martin Thoma

1
Đã làm việc! Đơn giản và đơn giản ... Tuyệt vời!
Josemy

2
Tất nhiên ... Bạn chỉ cần nhấp vào ảnh hồ sơ của mình trên thanh bên trái, sau đó vào cài đặt Bitbucket và bạn sẽ thấy một cái gì đó như thế này: imgur.com/EI33zj3
Josemy

1
Điều này làm việc cho tôi. Tuy nhiên, tôi có mô hình con và --recursivekhông hoạt động. Tôi đã phải đưa vào git clonecho mỗi mô hình con, điều này tốt nhưng sẽ rất tuyệt nếu nó hoạt động đệ quy.
Zailyn Tamayo

12

Bạn thường không muốn thực hiện một git clonerepo riêng từ bên trong bản dựng docker. Thực hiện sao chép ở đó liên quan đến việc đặt thông tin đăng nhập ssh riêng bên trong hình ảnh, nơi chúng có thể được trích xuất sau đó bởi bất kỳ ai có quyền truy cập vào hình ảnh của bạn.

Thay vào đó, thực tế phổ biến là sao chép git repo từ bên ngoài docker trong công cụ CI bạn chọn, và chỉ đơn giản là COPYcác tệp vào hình ảnh. Điều này có một lợi ích thứ hai: bộ nhớ đệm docker. Bộ nhớ đệm Docker xem lệnh đang chạy, các biến môi trường mà nó bao gồm, các tệp đầu vào, v.v. và nếu chúng giống hệt với bản dựng trước đó từ cùng bước cha, nó sẽ sử dụng lại bộ đệm trước đó. Với một git clonelệnh, chính lệnh đó là giống hệt nhau, vì vậy docker sẽ sử dụng lại bộ đệm ngay cả khi thay đổi git repo bên ngoài. Tuy nhiên, một COPYlệnh sẽ xem xét các tệp trong ngữ cảnh xây dựng và có thể xem chúng giống hệt nhau hay đã được cập nhật và chỉ sử dụng bộ đệm khi phù hợp.


Nếu bạn định thêm thông tin đăng nhập vào bản dựng của mình, hãy xem xét thực hiện với bản dựng nhiều giai đoạn và chỉ đặt các thông tin đó trong giai đoạn đầu không bao giờ được gắn thẻ và đẩy ra ngoài máy chủ bản dựng của bạn. Kết quả trông như sau:

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 git@bitbucket.org:User/repo.git

FROM ubuntu as release
LABEL maintainer="Luke Crooks <luke@pumalo.org>"

COPY --from=clone /repo /repo
...

Gần đây, BuildKit đã thử nghiệm một số tính năng thử nghiệm cho phép bạn chuyển khóa ssh dưới dạng gắn kết không bao giờ được ghi vào hình ảnh:

# syntax=docker/dockerfile:experimental
FROM ubuntu as clone
LABEL maintainer="Luke Crooks <luke@pumalo.org>"

# 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 git@bitbucket.org:User/repo.git

Và bạn có thể xây dựng nó với:

$ DOCKER_BUILDKIT=1 docker build -t your_image_name \
  --secret id=ssh_id,src=$(pwd)/id_rsa .

Lưu ý rằng điều này vẫn yêu cầu khóa ssh của bạn không được bảo vệ bằng mật khẩu, nhưng ít nhất bạn có thể chạy bản dựng trong một giai đoạn duy nhất, xóa lệnh COPY và tránh thông tin ssh không bao giờ là một phần của hình ảnh.


BuildKit cũng đã thêm một tính năng chỉ dành cho ssh cho phép bạn vẫn có các khóa ssh được bảo vệ bằng mật khẩu, kết quả sẽ như sau:

# syntax=docker/dockerfile:experimental
FROM ubuntu as clone
LABEL maintainer="Luke Crooks <luke@pumalo.org>"

# 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 git@bitbucket.org:User/repo.git

Và bạn có thể xây dựng nó với:

$ 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 .

Một lần nữa, điều này được đưa vào bản dựng mà không bao giờ được ghi vào lớp hình ảnh, loại bỏ rủi ro thông tin có thể vô tình bị rò rỉ.


Để buộc docker chạy git clonengay cả khi các dòng trước đó đã được lưu vào bộ đệm, bạn có thể tiêm ARG bản dựng thay đổi theo từng bản dựng để phá vỡ bộ đệm. Trông giống như:

# 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 git@bitbucket.org:User/repo.git

Sau đó, bạn tiêm mà thay đổi arg trong lệnh xây dựng docker:

date_stamp=$(date +%Y%m%d-%H%M%S)
docker build --build-arg DATE_STAMP=$date_stamp .

Bạn đề nghị sử dụng git từ bên ngoài Docker, tuy nhiên bạn giải thích cách xử lý các phím ssh bằng mọi cách. Khi nào bạn xem xét điều này cần thiết / phù hợp?
JCarlosR

1
@JCarlosR khi bạn không có hệ thống bên ngoài để chạy bản dựng (ví dụ: hệ thống CI / CD có khả năng chạy bản sao trước). Có thể có ngoại lệ, nhưng một bản sao bên trong Dockerfile là mùi mã.
BMitch

1

Các giải pháp trên không hoạt động đối với bitbucket. Tôi đoán điều này thực hiện các mẹo:

RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts \
    && eval `ssh-agent` \
    && ssh-add ~/.ssh/[key] \
    && git clone git@bitbucket.org:[team]/[repo].git
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.