Sử dụng các khóa SSH bên trong container docker


324

Tôi có một ứng dụng thực thi nhiều nội dung thú vị khác nhau với Git (như chạy git clone & git đẩy) và tôi đang cố gắng cập bến nó.

Tôi đang gặp phải một vấn đề mặc dù tôi cần có thể thêm khóa SSH vào vùng chứa để 'người dùng' của container sử dụng.

Tôi đã thử sao chép nó vào /root/.ssh/, thay đổi $HOME, tạo ra một trình bao bọc git ssh, và vẫn không gặp may.

Dưới đây là Dockerfile để tham khảo:

#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 chạy các lệnh git như git pull


3
Bất cứ ai tiếp cận câu hỏi này đều phải suy nghĩ mặc dù trò chơi kết thúc vì dễ tạo ra lỗ hổng bảo mật và quên nó ở đây nếu bạn không cẩn thận. Đọc tất cả các câu trả lời và chọn một cách khôn ngoan.
Josh Habdas

Câu trả lời:


144

Đó là một vấn đề khó hơn nếu bạn cần sử dụng SSH khi xây dựng. Ví dụ: nếu bạn đang sử dụng git clone, hoặc trong trường hợp của tôi pipnpmđể tải xuống từ kho lưu trữ riêng.

Giải pháp tôi tìm thấy là thêm các phím của bạn bằng --build-argcờ. Sau đó, bạn có thể sử dụng --squashlệnh thử nghiệm mới (đã thêm 1.13) để hợp nhất các lớp để các khóa không còn khả dụng sau khi xóa. Đây là giải pháp của tôi:

Xây dựng lệnh

$ 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

Cập nhật: Nếu bạn đang sử dụng Docker 1.13 và có các tính năng thử nghiệm, bạn có thể nối thêm --squashlệnh xây dựng sẽ hợp nhất các lớp, xóa các khóa SSH và ẩn chúng khỏi docker history.


13
Chuỗi vấn đề GitHub này sẽ chỉ ra rằng phương pháp này vẫn không an toàn. Xem bình luận này cho một giải pháp tương tự.
eczajk

4
Một giải pháp khác thay vì đè bẹp là thêm và xóa khóa trong cùng một lệnh RUN, và giữa việc thêm và xóa bạn sử dụng nó cho những gì bạn cần.
Benjamin Hammer Nørgaard

2
Có lẽ bạn có thể xóa các dòng để tạo id_rsa.pubtệp vì nó không bắt buộc.
LCB

1
Thay vì đè bẹp, hãy sử dụng các bản dựng hình ảnh nhiều giai đoạn .
Richard Kiefer

Nếu khóa của bạn được bảo vệ bằng mật khẩu, $(openssl rsa -in ~/.ssh/id_rsa)thay vào đó hãy sử dụng
BroiSatse

89

Hóa ra khi sử dụng Ubuntu, ssh_config không chính xác. Bạn cần phải thêm

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

vào Dockerfile của bạn để nhận nó nhận ra khóa ssh của bạn.


2
Có lẽ bạn cũng cần đặt đúng tên người dùng như thế nàyRUN echo " Host example.com" >> /root/.ssh/config RUN echo " User <someusername>" >> /root/.ssh/config
monofone

1
Tại sao ai đó sao chép khóa riêng từ máy chủ sang container. Chỉ huy vẫn ổn, nhưng tôi không thấy có ý nghĩa gì khi thực hiện những điều đã nói ở trên ...
Vladimir Djuricic

12
Điều này không an toàn! Xem giải pháp của tôi dưới đây để biết phiên bản 1.13 mới nhất của Docker. @ebensing
Daniel van Flymen

1
@VladimirDjuricic Có những thứ như khóa triển khai.
Zelphir Kaltstahl

thực sự bạn cần chạy ssh-keygen -A để thiết lập ssh đúng cách trên bộ chứa tối thiểu ubfox. Sau đó, bạn có thể thêm khóa pub / private và bắt đầu sshd. Tôi có mục này trong dockerfile của mình: 'RUN ssh-keygen -A' là một trong những bước.
piotrektt

84

Lưu ý : chỉ sử dụng phương pháp này cho hình ảnh riêng tư và sẽ luôn như vậy!

Khóa ssh vẫn được lưu trong ảnh, ngay cả khi bạn loại bỏ khóa trong lệnh lớp sau khi thêm nó (xem bình luận trong bài này ).

Trong trường hợp của tôi, điều này là ổn, vì vậy đây là những gì tôi đang sử dụng:

# 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

91
Điều này sẽ giữ chìa khóa của bạn trong hình ảnh, đừng làm điều đó.
CppLearner

12
@CppLearner bạn nói đúng, điều này không lưu trữ khóa trong hình ảnh và đó có thể là vấn đề bảo mật trong một số trường hợp. Cảm ơn đã làm nổi bật điều đó. Tuy nhiên, có nhiều tình huống mà điều này là hoàn toàn tiết kiệm. Ví dụ: đối với hình ảnh được lưu trữ trong kho lưu trữ riêng hoặc hình ảnh được xây dựng trực tiếp trên máy chủ sản xuất sao chép các khóa cục bộ vào hình ảnh.
yellowcap

2
Ngoài ra, nếu bạn cài đặt các nhà cung cấp của mình trong Dockerfile, không có gì ngăn bạn xóa khóa ssh sau khi các nhà cung cấp được cài đặt.
SebScoFr

2
@SebScoFr, rõ ràng các khóa sẽ được lưu trữ trong một trong các lớp, ngay cả khi bạn loại bỏ chúng trong một lệnh sau (xem liên kết trong câu trả lời được cập nhật). Vì vậy, hình ảnh sẽ luôn hiển thị phím ssh và giải pháp chỉ nên được sử dụng cho hình ảnh riêng tư!
yellowcap

1
@yellowcap không nếu bạn - phá hủy bản dựng
Anoyz

56

Nếu bạn đang sử dụng docker, soạn thảo một lựa chọn dễ dàng là chuyển tiếp tác nhân SSH như thế:

something:
    container_name: something
    volumes:
        - $SSH_AUTH_SOCK:/ssh-agent # Forward local machine SSH key to docker
    environment:
        SSH_AUTH_SOCK: /ssh-agent

23
Chỉ cần lưu ý rằng điều này không hoạt động đối với máy chủ Mac, cho dù sử dụng docker-machine (thông qua VirtualBox) hoặc Docker cho Mac (sử dụng xhyve) vì các socket miền unix không được ủy quyền.
Joe Shaw

SSH_AUTH_SOCKlà một biến, chứa đường dẫn đến tác nhân ssh
Aistis

2
biết thêm chi tiết về SSH_AUTH_SOCK blog.joncairns.com/2013/12/under Hiểu
sh

1
ssh-redirect hiện cũng được hỗ trợ trên các máy chủ macOS - thay vì gắn đường dẫn của $SSH_AUTH_SOCK, bạn phải gắn đường dẫn này - /run/host-services/ssh-auth.sock.
Jakub Kukul

47

Mở rộng câu trả lời của Peter Grainger Tôi đã có thể sử dụng bản dựng nhiều giai đoạn có sẵn kể từ Docker 17.05. Trang chính thức nêu rõ:

Với các bản dựng nhiều giai đoạn, bạn sử dụng nhiều FROMcâu lệnh trong Dockerfile của mình. Mỗi FROMhướng dẫn có thể sử dụng một cơ sở khác nhau và mỗi hướng dẫn bắt đầu một giai đoạn mới của quá trình xây dựng. Bạn có thể sao chép có chọn lọc các tạo tác từ giai đoạn này sang giai đoạn khác, bỏ lại mọi thứ bạn không muốn trong hình ảnh cuối cùng.

Ghi nhớ điều này ở đây là ví dụ của tôi Dockerfilebao gồm ba giai đoạn xây dựng. Nó có nghĩa là để tạo ra một hình ảnh sản xuất của ứng dụng web khách.

# 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"]

.dockerignorelặp lại nội dung của .gitignoretệp (nó ngăn chặn node_modulesvà dẫn đến các distthư mục của dự án bị sao chép):

.idea
dist
node_modules
*.log

Ví dụ lệnh để xây dựng một hình ảnh:

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

Nếu khóa SSH riêng của bạn không có cụm mật khẩu, chỉ cần xác định SSH_KEY_PASSPHRASEđối số trống .

Đây là cách nó hoạt động:

1). Chỉ ở giai đoạn đầu tiên package.json,yarn.lock các tệp và khóa SSH riêng được sao chép sang hình ảnh trung gian đầu tiên có tên sources. Để tránh nhắc nhở mật khẩu khóa SSH, nó sẽ tự động được thêm vào ssh-agent. Cuối cùng, yarnlệnh sẽ cài đặt tất cả các phụ thuộc cần thiết từ NPM và sao chép kho git riêng từ Bitbucket qua SSH.

2). Giai đoạn thứ hai xây dựng và thu nhỏ mã nguồn của ứng dụng web và đặt nó vào distthư mục của hình ảnh trung gian tiếp theo có tên production. Lưu ý rằng mã nguồn đã cài đặt node_modulesđược sao chép từ hình ảnh có tênsources được tạo ở giai đoạn đầu tiên bởi dòng này:

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

Có lẽ nó cũng có thể là dòng sau:

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

Chúng tôi chỉ có node_modules thư mục từ hình ảnh trung gian đầu tiên ở đây, không SSH_KEYSSH_KEY_PASSPHRASEđối số nữa. Tất cả phần còn lại cần thiết để xây dựng được sao chép từ thư mục dự án của chúng tôi.

3). Ở giai đoạn thứ ba, chúng tôi giảm kích thước của hình ảnh cuối cùng sẽ được gắn thẻ ezze/geoport:0.6.0bằng cách chỉ bao gồmdist thư mục từ hình ảnh trung gian thứ hai có tên productionvà cài đặt Node Express để khởi động máy chủ web.

Danh sách hình ảnh cung cấp một đầu ra như thế này:

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

trong đó các hình ảnh không được gắn thẻ sẽ chuyển sang giai đoạn xây dựng trung gian thứ nhất và thứ hai.

Nếu bạn chạy

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

bạn sẽ không thấy bất kỳ đề cập nào SSH_KEYSSH_KEY_PASSPHRASEtrong hình ảnh cuối cùng.


Bài viết cũ, nhưng tôi muốn nhấn mạnh đây là cách tốt nhất để làm nó trước ngày 18 tháng 9. Squash là không cần thiết, và dễ bị rủi ro. Với nhiều giai đoạn, bạn biết rằng bạn chỉ mang lại những đồ tạo tác bạn muốn. Hãy nghĩ về squash là từ chối các tệp bạn không muốn và đa cấp là chọn tham gia. Câu trả lời này cần phải cao hơn. Nướng các phím ssh của bạn trong hình ảnh là thực hành khủng khiếp.
mritalian

@ezze Cảm ơn bạn rất nhiều vì bài đăng rất hữu ích này :) Tác nhân SSH đang khiến tôi phát điên, tôi đã làm một việc tương tự như những gì bạn đã làm: Tôi thấy chính xác trong nhật ký xây dựng docker Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)nhưng khi tôi kiểm tra RUN khác hoặc thậm chí trong cùng RUN ra lệnh bằng cách thực hiện ssh-add -lnó cho tôi biết rằng "Tác nhân không có danh tính". Bắt đầu nhổ tóc, có suy nghĩ gì không?
Alex

40

Để đưa khóa ssh cho bạn, trong một vùng chứa, bạn có nhiều giải pháp:

  1. Sử dụng Dockerfile với ADDhướng dẫn, bạn có thể tiêm nó trong quá trình xây dựng của mình

  2. Đơn giản chỉ cần làm một cái gì đó như cat id_rsa | docker run -i <image> sh -c 'cat > /root/.ssh/id_rsa'

  3. Sử dụng docker cplệnh cho phép bạn tiêm tệp trong khi container đang chạy.


2
Vì vậy, đến bây giờ, tôi đã thử sao chép nó vào /root/.ssh/id_rsa nhưng vẫn nhận được lỗi "Xác minh khóa máy chủ không thành công. Lỗi nghiêm trọng: Đầu từ xa bị treo bất ngờ" từ Git, điều mà tôi khá chắc chắn là nó không sử dụng chìa khóa vì lý do gì. Vì vậy, tôi nghĩ rằng tôi cần phải làm gì khác để thực sự nói với hệ thống sử dụng nó làm khóa ssh? Không chắc chắn chính xác làm thế nào để gỡ lỗi này. (và tôi biết khóa này hoạt động vì nó chạy mà không gặp sự cố từ máy chủ)
tăng lên vào

bạn có thể đảm bảo / etc / ssh / ssh_config nhắm mục tiêu đúng tệp chính không?
creack

1
Có cách nào tốt để kiểm tra các tập tin của docker không? Hoặc tôi chỉ nên thử và sao chép trong một cấu hình hợp lệ?
tăng 8/8/13

3
Tôi vừa thử với hình ảnh 'cơ sở', thực hiện apt-get install openssh-servervà đưa khóa của mình vào /root/.ssh/id_rsa và nó hoạt động tốt. Bạn đang sử dụng hình ảnh gì?
creack

nếu bạn cần kiểm tra tệp chứa, cách tốt nhất là cam kết và chạy hình ảnh kết quả bằng 'cat'.
creack

15

Một giải pháp đa nền tảng là sử dụng liên kết gắn kết để chia sẻ .sshthư mục của máy chủ lưu trữ vào thùng chứa:

docker run -v /home/<host user>/.ssh:/home/<docker user>/.ssh <image>

Tương tự như tác nhân chuyển tiếp phương pháp này sẽ làm cho các khóa công khai có thể truy cập vào container. Một ưu điểm nữa là nó cũng hoạt động với người dùng không phải root và sẽ giúp bạn kết nối với GitHub. Tuy nhiên, một lưu ý cần xem xét là tất cả nội dung (bao gồm cả khóa riêng) từ .sshthư mục sẽ được chia sẻ, vì vậy phương pháp này chỉ được mong muốn để phát triển và chỉ dành cho hình ảnh container đáng tin cậy.


1
điều này có thể hoạt động, nhưng không docker buildchỉ trong thời giandocker run
Alexander Mills

3
Đó chính xác là vấn đề. Bạn không muốn đặt các khóa ssh của mình trong tệp docker.
Mohammad Azim

2
Với việc chuyển tiếp tác nhân SSH không hoạt động bên ngoài Linux, điều này tạo ra một giải pháp tốt để khởi động và chạy trong môi trường phát triển mà không có quá nhiều phiền phức.
Josh Habdas

Tôi đang chạy docker bằng docker-compose upWindows cục bộ 10. Tôi nên sử dụng giải pháp của bạn trong kịch bản đó như thế nào?
llaaalu

Về cơ bản, bạn đang hỏi làm thế nào để ánh xạ âm lượng trong docker compose. Trên đây là một câu trả lời trả lời này. Cụ thể cho Windows, điều này có thể giúp stackoverflow.com/questions/41334021/ từ
Mohammad Azim

14

Docker container nên được coi là "dịch vụ" của riêng họ. Để tách mối quan tâm, bạn nên tách chức năng:

1) Dữ liệu phải ở trong bộ chứa dữ liệu: sử dụng âm lượng được liên kết để sao chép repo vào. Kho chứa dữ liệu đó sau đó có thể được liên kết với dịch vụ cần nó.

2) Sử dụng bộ chứa để chạy tác vụ nhân bản git, (nghĩa là công việc duy nhất của nó là nhân bản) liên kết bộ chứa dữ liệu với nó khi bạn chạy nó.

3) Tương tự cho khóa ssh: đặt nó là một ổ đĩa (như được đề xuất ở trên) và liên kết nó với dịch vụ git clone khi bạn cần

Bằng cách đó, cả nhiệm vụ nhân bản và chìa khóa đều phù du và chỉ hoạt động khi cần thiết.

Bây giờ nếu bản thân ứng dụng của bạn là giao diện git, bạn có thể muốn xem xét các API REST của github hoặc bitbucket để thực hiện công việc của mình: đó là những gì chúng được thiết kế cho.


13

Dòng này là một vấn đề:

ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa

Khi chỉ định các tệp bạn muốn sao chép vào hình ảnh, bạn chỉ có thể sử dụng các đường dẫn tương đối - liên quan đến thư mục chứa Dockerfile của bạn. Vì vậy, thay vào đó bạn nên sử dụng:

ADD id_rsa /root/.ssh/id_rsa

Và đặt tệp id_rsa vào cùng thư mục chứa Dockerfile của bạn.

Kiểm tra điều này để biết thêm chi tiết: http://docs.docker.io/reference/builder/#add


4
Đây cũng là vấn đề bảo mật vì nó đặt một khóa riêng vào một hình ảnh có thể dễ dàng bị lãng quên.
Mike D

docker cpChỉ cần đặt nó trong container và không phải hình ảnh, phải không?
Alexander Mills

13

Chúng tôi đã gặp vấn đề tương tự khi thực hiện cài đặt npm trong thời gian xây dựng docker.

Lấy cảm hứng từ giải pháp từ Daniel van Flymen và kết hợp nó với git url viết lại , chúng tôi đã tìm thấy một phương pháp đơn giản hơn một chút để xác thực cài đặt npm từ repos github riêng tư - chúng tôi đã sử dụng mã thông báo oauth2 thay vì các phím.

Trong trường hợp của chúng tôi, các phụ thuộc npm được chỉ định là "git + https://github.com/ ..."

Để xác thực trong bộ chứa, các url cần phải được viết lại để phù hợp với xác thực ssh (ssh: //git@github.com/) hoặc xác thực mã thông báo (https: // $ {GITHUB_TOKEN} @ github.com /)

Lệnh xây dựng:

docker build -t sometag --build-arg GITHUB_TOKEN=$GITHUB_TOKEN . 

Thật không may, tôi đang sử dụng docker 1.9, vì vậy - tùy chọn -sash vẫn chưa có, cuối cùng nó cần được thêm vào

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

11

Chuyển tiếp ổ cắm xác thực ssh đến vùng chứa:

docker run --rm -ti \
        -v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock \
        -e SSH_AUTH_SOCK=/tmp/ssh_auth.sock \
        -w /src \
        my_image

Kịch bản của bạn sẽ có thể thực hiện a git clone.

Bổ sung: Nếu bạn muốn các tệp được sao chép thuộc về một người dùng cụ thể bạn cần sử dụng chownvì việc sử dụng người dùng khác ngoài root bên trong vùng chứa sẽ gitkhông thành công.

Bạn có thể thực hiện việc xuất bản này lên môi trường chứa một số biến bổ sung:

docker run ...
        -e OWNER_USER=$(id -u) \
        -e OWNER_GROUP=$(id -g) \
        ...

Sau khi sao chép, bạn phải thực thi chown $OWNER_USER:$OWNER_GROUP -R <source_folder>để đặt quyền sở hữu phù hợp trước khi bạn rời khỏi vùng chứa để người dùng không truy cập được bên ngoài vùng chứa.


1
Trong các phiên bản Docker mới hơn, bạn có thể chuyển -u root:$(id -u $USER)đến ít nhất các tệp thuộc sở hữu của cùng một nhóm chính với người dùng của mình, điều này sẽ làm cho tất cả chúng ít nhất có thể đọc được mà không sudotrừ khi có thứ gì đó tạo ra chúng với 0600quyền.
dragon788

@ dragon788 Tôi nghĩ bạn có một lỗi đánh máy: -u root:$(id -u $USER)nên như vậy -g.
edupo

Cuộc gọi tốt Tôi dường như không thể sửa nó từ thiết bị di động, sẽ thử trên máy tính để bàn sớm.
dragon788

/tmp/ssh_auth.sock: No such file or directoryBây giờ tôi có nó /tmp/ssh-vid8Zzi8UILE/agent.46016trên máy chủ của mình
vladkras

@vladkras lỗi khá chung chung. Có thể được gây ra do quyền trên /tmpcontainer của bạn. Hoặc một lỗi đánh máy trên lệnh chạy docker. Hãy chắc chắn rằng câu lệnh liên kết là chính xác -v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock: Thứ tự là quan trọng và dấu chấm phẩy cũng quan trọng. Vui lòng kiểm tra tài liệu docker để được giúp đỡ thêm.
edupo

10

Như eczajk đã nhận xét trong câu trả lời của Daniel van Flymen, dường như không an toàn để xóa các phím và sử dụng --squash, vì chúng vẫn sẽ hiển thị trong lịch sử ( docker history --no-trunc).

Thay vào đó với Docker 18.09, giờ đây bạn có thể sử dụng tính năng "xây dựng bí mật". Trong trường hợp của tôi, tôi đã nhân bản một repo git riêng bằng cách sử dụng khóa SSH của máy chủ với phần sau trong Dockerfile của tôi:

# syntax=docker/dockerfile:experimental

[...]

RUN --mount=type=ssh git clone [...]

[...]

Để có thể sử dụng điều này, bạn cần kích hoạt phụ trợ BuildKit mới trước khi chạy docker build:

export DOCKER_BUILDKIT=1

Và bạn cần thêm --ssh defaulttham số docker build.

Thông tin thêm về điều này tại đây: https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066


1
Giải pháp tốt nhất IMHO. Tôi đã phải làm thêm hai điều nữa để nó hoạt động: 1) thêm khóa riêng của tôi vào ssh-agent ssh-add ~/.ssh/id_rsavà 2) thêm máy chủ git vào know_hosts, tức là cho bitbucket:RUN ssh-keyscan -H bitbucket.org >> ~/.ssh/known_hosts
Moritz Ringler

Tôi đã không thể làm cho điều này để làm việc cả. Tôi vẫn nhận được lỗi về quyền: Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access and the repository exists.Điều này mặc dù đã chuyển --ssh defaultcờ trong bản dựng docker của tôi và sử dụng --mount=type=sshtrong lệnh chạy nơi tôi git clone. Tôi có thể sao chép cùng một repo không có vấn đề gì trên máy dựng. Nó chỉ đơn giản là thất bại trong container xây dựng docker. Tôi nghi ngờ rằng phiên bản mac của Docker không thực sự vượt qua ứng dụng khách ssh.
PMende

@PMende bạn có thể tìm ra vấn đề này mà bạn đề cập vì tôi cũng đang đối mặt như vậy.
Sadan A.

@SadanArshad Hóa ra chức năng này hiện chỉ được hỗ trợ nếu bạn đang chạy Docker từ máy Linux. Nó không hoạt động nếu bạn đang chạy các lệnh Docker của mình từ máy Mac (và có lẽ cả Windows, mặc dù tôi không thể xác nhận).
PMende

Quá tệ khi không hoạt động với docker-compose ... github.com/docker/compose/issues/6440
Alexis Wilke

9

Vấn đề này thực sự là một vấn đề gây phiền nhiễu. Vì bạn không thể thêm / sao chép bất kỳ tệp nào bên ngoài ngữ cảnh dockerfile, điều đó có nghĩa là không thể chỉ liên kết ~ / .ssh / id_rsa vào hình ảnh /root/.ssh/id_rsa và khi bạn chắc chắn cần một khóa để thực hiện một số điều cần thiết như git clone từ một liên kết repo riêng ..., trong quá trình xây dựng hình ảnh docker của bạn.

Dù sao, tôi đã tìm thấy một giải pháp để giải quyết, không quá thuyết phục nhưng đã làm việc cho tôi.

  1. trong dockerfile của bạn:

    • thêm tệp này dưới dạng /root/.ssh/id_rsa
    • làm những gì bạn muốn, chẳng hạn như git clone, nhà soạn nhạc ...
    • rm /root/.ssh/id_rsa ở cuối
  2. một kịch bản để làm trong một lần chụp:

    • cp chìa khóa của bạn vào thư mục giữ dockerfile
    • xây dựng bến tàu
    • rm khóa sao chép
  3. bất cứ lúc nào bạn phải chạy một container từ hình ảnh này với một số yêu cầu ssh, chỉ cần thêm -v cho lệnh chạy, như:

    docker chạy -v ~ / .ssh / id_rsa: /root/.ssh/id_rsa - tên lệnh chứa hình ảnh container

Giải pháp này không dẫn đến khóa riêng trong cả nguồn dự án và hình ảnh docker được xây dựng, do đó không còn vấn đề bảo mật nào phải lo lắng nữa.


1
"Vì bạn không thể thêm / sao chép bất kỳ tệp nào bên ngoài ngữ cảnh dockerfile," Bạn đã thấy docker cpchưa? Nó được sử dụng để "Sao chép tệp / thư mục giữa một container và máy chủ của bạn."
Jonathon Reinhart

@JonathonReinhart, cảm ơn bạn đã chỉ ra điều đó. Vâng, docker cpcó thể làm các mẹo. Tuy nhiên, trong tình huống này, tôi cần ssh_key trong khi hình ảnh được xây dựng và không có thùng chứa nào tại thời điểm đó ... sẽ cập nhật biểu hiện không rõ ràng của tôi, dù sao cũng cảm ơn.
ImLeo

9

Tôi đã gặp vấn đề tương tự ngày hôm nay và phiên bản sửa đổi một chút với các bài viết trước Tôi thấy cách tiếp cận này hữu ích hơn với tôi

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

(Lưu ý rằng cờ chỉ đọc để container sẽ không làm hỏng khóa ssh của tôi trong mọi trường hợp.)

Bên trong container bây giờ tôi có thể chạy:

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

Vì vậy, tôi không nhận được Bad owner or permissions on /root/.ssh/..lỗi đó được ghi nhận bởi @kross


Cảm ơn bạn! Đây là chìa khóa để làm cho nó hoạt động với tôi: có ssh-agent và ssh-add trong một lệnh như : ssh-agent bash -c "ssh-add...". Sau đó tôi có thể chuyển quyền đó vào docker chạy. Tất cả các ví dụ trước đây tôi thấy được sử dụng eval ssh-agent, theo sau là ssh-add và tôi không thể tìm ra cách nào để chuyển nó evalthông qua lệnh chạy docker.
ryanman

7

'bạn có thể chọn lọc để máy chủ từ xa truy cập vào ssh-agent cục bộ của mình như thể nó đang chạy trên máy chủ'

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


4
docker run -i -t -v $ (readlink -f $ SSH_AUTH_SOCK): / ssh-agent -e SSH_AUTH_SOCK = / ssh-agent ub Ubuntu / bin / bash
Pavel Hlobil

1
fruitl00p đã tạo ra một container đường hầm docker theo cách này: github.com/kingsapes/docker-tunnel
Martin suchanek

6

Bạn cũng có thể liên kết thư mục .ssh của mình giữa máy chủ và vùng chứa, tôi không biết phương thức này có bất kỳ ý nghĩa bảo mật nào không nhưng nó có thể là phương pháp dễ nhất. Một cái gì đó như thế này sẽ hoạt động:

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

Hãy nhớ rằng docker chạy với sudo (trừ khi bạn không), nếu đây là trường hợp bạn sẽ sử dụng các phím ssh gốc.


Sử dụng phương pháp này hoạt động với docker 0.11 nhưng nếu bạn sử dụng fig, nó sẽ gây ra lỗi hoảng loạn. Tôi không biết tại sao
Luis Elizondo

3
Đây sẽ là một phương pháp ưa thích, mẹo sẽ là sử dụng các khóa người dùng máy chủ không được ưu tiên của tôi làm gốc của bộ chứa. Như bạn đã đề cập, cố gắng làm điều đó không phải là năng suất của người dùng root Bad owner or permissions on /root/.ssh/config.
kross

Điều này chỉ có thể được sử dụng trong docker run, nhưng không phải trong thời gian docker build.
ccpizza

3
@ccpizza, tôi xem đó là một lợi thế. Nhiều câu trả lời trong số này để lại các khóa riêng được lưu trữ trong một hình ảnh; khóa vẫn được lưu trữ ngay cả sau khi bạn loại bỏ khóa trong lệnh lớp tiếp theo. Bằng cách giới thiệu các khóa riêng chỉ trong khi chạy (không xây dựng), chúng chỉ có thể tồn tại trong vùng chứa (không phải hình ảnh).
chăn bò

6

Bắt đầu từ docker API 1.39+(Kiểm tra phiên bản API với docker version) xây dựng docker cho phép --sshtùy chọn với ổ cắm tác nhân hoặc khóa để cho phép Docker Engine chuyển tiếp các kết nối tác nhân SSH.

Xây dựng lệnh

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

Thêm thông tin:


1
Việc mở rộng dấu ngã không làm việc cho tôi; Tôi đã nhận được : could not parse ssh: [default=~/.ssh/id_rsa]: stat ~/.ssh/id_rsa: no such file or directory. Sử dụng đường dẫn đầy đủ nếu nó không hoạt động.
slhck

3

Nếu bạn không quan tâm đến tính bảo mật của các khóa SSH, có rất nhiều câu trả lời hay ở đây. Nếu bạn làm như vậy, câu trả lời tốt nhất tôi tìm thấy là từ một liên kết trong một bình luận ở trên đến bình luận GitHub này của diegocsandrim . Vì vậy, những người khác có nhiều khả năng nhìn thấy nó hơn, và trong trường hợp repo đó biến mất, đây là phiên bản chỉnh sửa của câu trả lời đó:

Hầu hết các giải pháp ở đây cuối cùng đều để lại khóa riêng trong ảnh. Điều này là xấu, vì bất cứ ai có quyền truy cập vào hình ảnh đều có quyền truy cập vào khóa riêng của bạn. Vì chúng ta không biết đủ về hành vi củasquash , nên điều này vẫn có thể xảy ra ngay cả khi bạn xóa khóa và xóa lớp đó.

Chúng tôi tạo URL ký trước để truy cập khóa bằng aws s3 cli và giới hạn quyền truy cập trong khoảng 5 phút, chúng tôi lưu URL đăng nhập trước này vào một tệp trong thư mục repo, sau đó trong dockerfile chúng tôi thêm nó vào hình ảnh.

Trong dockerfile, chúng ta có lệnh RUN thực hiện tất cả các bước sau: sử dụng URL trước khi hát để lấy khóa ssh, chạy cài đặt npm và xóa khóa ssh.

Bằng cách thực hiện điều này trong một lệnh duy nhất, khóa ssh sẽ không được lưu trữ trong bất kỳ lớp nào, nhưng URL ký trước sẽ được lưu trữ và đây không phải là vấn đề vì URL sẽ không hợp lệ sau 5 phút.

Kịch bản xây dựng trông như sau:

# build.sh
aws s3 presign s3://my_bucket/my_key --expires-in 300 > ./pre_sign_url
docker build -t my-service .

Dockerfile trông như thế này:

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"]

1
Vấn đề với giải pháp này là bởi vì pre_sign_url sẽ thay đổi mỗi lần, cài đặt npm không thể được lưu trong bộ nhớ cache ngay cả khi không có thay đổi nào đối với tệp tests.json. Tốt hơn là lấy khóa trong build.sh và đặt nó làm đối số xây dựng để nó sẽ không thay đổi mỗi lần
York Yang


3

Tổng quan ngắn gọn về những thách thức của SSH trong các container Docker được trình bày chi tiết tại đây . Để kết nối với điều khiển từ xa đáng tin cậy từ trong một container mà không bị rò rỉ bí mật, có một số cách:

Ngoài ra, còn có khả năng sử dụng kho lưu trữ khóa chạy trong bộ chứa docker riêng biệt có thể truy cập khi chạy khi sử dụng Compose. Hạn chế ở đây là sự phức tạp bổ sung do máy móc cần thiết để tạo và quản lý kho lưu trữ khóa như Vault của HashiCorp .

Để sử dụng khóa SSH trong bộ chứa Docker độc lập, hãy xem các phương thức được liên kết ở trên và xem xét các nhược điểm của từng tùy thuộc vào nhu cầu cụ thể của bạn. Tuy nhiên, nếu bạn đang chạy bên trong Soạn thảo và muốn chia sẻ khóa cho ứng dụng khi chạy (phản ánh thực tiễn của OP), hãy thử điều này:

  • Tạo một docker-compose.envtập tin và thêm nó vào của bạn.gitignore tập tin .
  • Cập nhật docker-compose.ymlvà thêmenv_file cho dịch vụ yêu cầu chìa khóa.
  • Truy cập khóa công khai từ môi trường trong thời gian chạy ứng dụng, ví dụ process.node.DEPLOYER_RSA_PUBKEYtrong trường hợp ứng dụng Node.js.

Cách tiếp cận trên là lý tưởng để phát triển và thử nghiệm và, trong khi nó có thể đáp ứng các yêu cầu sản xuất, trong sản xuất, bạn nên sử dụng một trong những phương pháp khác được xác định ở trên.

Tài nguyên bổ sung:


3

Bạn có thể sử dụng xây dựng nhiều giai đoạn để xây dựng container Đây là cách tiếp cận bạn có thể thực hiện: -

Giai đoạn 1 xây dựng hình ảnh với 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

Giai đoạn 2: xây dựng container của bạn

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"] 

thêm thuộc tính env trong tệp soạn thảo của bạn:

   environment:
      - SSH_PRIVATE_KEY=${SSH_PRIVATE_KEY}

sau đó vượt qua args từ tập lệnh xây dựng như thế này:

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

Và loại bỏ các container trung gian nó để bảo mật. Điều này sẽ giúp bạn cổ vũ.


2

Một cách đơn giản và an toàn để đạt được điều này mà không cần lưu khóa của bạn trong lớp hình ảnh Docker hoặc thông qua thể dục dụng cụ ssh_agent là:

  1. Là một trong các bước trong của bạn Dockerfile, tạo một .sshthư mục bằng cách thêm:

    RUN mkdir -p /root/.ssh

  2. Dưới đây chỉ ra rằng bạn muốn gắn thư mục ssh dưới dạng ổ đĩa:

    VOLUME [ "/root/.ssh" ]

  3. Đảm bảo rằng bộ chứa của bạn ssh_configbiết nơi tìm các khóa công khai bằng cách thêm dòng này:

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

  4. Cho phép .sshthư mục người dùng cục bộ của bạn vào vùng chứa trong thời gian chạy:

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

    Hoặc trong dockerCompose.ymlphần thêm của bạn dưới phím âm lượng của dịch vụ:

    - "~/.ssh:/root/.ssh"

Cuối cùng của bạn Dockerfilenên chứa một cái gì đó như:

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" ]

1

Tôi đang cố gắng giải quyết vấn đề theo cách khác: thêm khóa ssh công khai vào hình ảnh. Nhưng trong các thử nghiệm của mình, tôi phát hiện ra rằng "docker cp" là để sao chép TỪ một container vào máy chủ. Mục 3 trong câu trả lời của creak dường như đang nói rằng bạn có thể sử dụng cp docker để tiêm các tệp vào một thùng chứa. Xem https://docs.docker.com/engine/reference/commandline/cp/

đoạn trích

Sao chép tập tin / thư mục từ hệ thống tập tin chứa vào đường dẫn máy chủ. Đường dẫn có liên quan đến thư mục gốc của hệ thống tập tin.

  Usage: docker cp CONTAINER:PATH HOSTPATH

  Copy files/folders from the PATH to the HOSTPATH

URL này dường như bị phá vỡ ngay bây giờ.
slm

Điều này là lỗi thời hoặc không chính xác. Nó có thể sao chép một trong hai hướng, kể từ ngày 1.8.2 mới nhất.
Jonathon Reinhart

1

Bạn có thể chuyển các khóa được ủy quyền vào vùng chứa của mình bằng thư mục dùng chung và đặt quyền bằng tệp docker như thế này:

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

Và docker run của bạn chứa một cái gì đó như sau để chia sẻ thư mục auth trên máy chủ (giữ Authorised_keys) với container sau đó mở cổng ssh có thể truy cập qua cổng 7001 trên máy chủ.

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

Bạn có thể muốn xem https://github.com/jpetazzo/nsenter dường như là một cách khác để mở shell trên container và thực thi các lệnh trong container.


1

Đến buổi tiệc muộn, điều này sẽ làm cho các khóa hệ điều hành máy chủ của bạn có sẵn để root bên trong container, nhanh chóng:

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

Tôi không ủng hộ việc sử dụng Dockerfile để cài đặt các khóa vì các lần lặp trong vùng chứa của bạn có thể để lại các khóa riêng tư.


0

Bạn có thể sử dụng các bí mật để quản lý mọi dữ liệu nhạy cảm mà container cần trong thời gian chạy nhưng bạn không muốn lưu trữ trong hình ảnh hoặc trong kiểm soát nguồn, chẳng hạn như:

  • Tên người dùng và mật khẩu
  • Chứng chỉ và khóa TLS
  • Khóa SSH
  • Dữ liệu quan trọng khác như tên của cơ sở dữ liệu hoặc máy chủ nội bộ
  • Chuỗi chung hoặc nội dung nhị phân (kích thước tối đa 500 kb)

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

Tôi đã cố gắng tìm ra cách thêm khóa ký vào một container để sử dụng trong thời gian chạy (không xây dựng) và đã gặp câu hỏi này. Bí mật Docker dường như là giải pháp cho trường hợp sử dụng của tôi và vì chưa có ai đề cập đến nó nên tôi sẽ thêm nó.


0

Trong trường hợp của tôi, tôi đã gặp vấn đề với nodejs và 'npm i' từ một kho lưu trữ từ xa. Tôi đã sửa nó thêm người dùng 'nút' vào vùng chứa nodejs và 700 đến ~ / .ssh trong vùng chứa.

Dockerfile:

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

chạy.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

sau đó nó bắt đầu hoạt động


-1

Cách đơn giản nhất, lấy tài khoản launchpad và sử dụng: ssh-import-id


8
Câu hỏi là về khóa riêng. ssh-import-idCó vẻ như nó chỉ nhập khóa công khai.
cddr

-1

Trong bộ chứa docker đang chạy, bạn có thể phát hành ssh-keygen với tùy chọn docker -i (tương tác). Điều này sẽ chuyển tiếp lời nhắc của container để tạo khóa bên trong container docker.


1
Và rồi chuyện gì xảy ra? Bạn không thể làm bất cứ điều gì sau đó, bởi vì bạn không được phép làm như vậy.
Jonathon Reinhart

-1

Đối với debian / root / ủy quyền

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