Dockerコンテナー内でのSSHキーの使用


324

git cloneやgit pushを実行するなど、Gitを使ってさまざまな楽しいことを実行するアプリがあります。

コンテナ「ユーザー」が使用するために、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"]

app.js 次のようなgitコマンドを実行します git pull


3
この問題に近づく人は誰でも、セキュリティホールを作成し、注意しないとここでそれを忘れるのは簡単なので、終盤まで考えるべきです。すべての答えを読んで、賢く選択してください。
Josh Habdas

回答:


144

ビルド時にSSHを使用する必要がある場合、これはより難しい問題です。たとえば、あなたが使用している場合git clone、または私の場合pipnpmプライベートリポジトリからダウンロードします。

私が見つけた解決策は、--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 .

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

更新: Docker 1.13を使用していて実験的な機能がある場合は--squash、ビルドコマンドに追加して、レイヤーをマージし、SSHキーを削除してから非表示にすることができますdocker history


13
このGitHub問題スレッドは、このアプローチがまだ安全ではないことを示しています。別の同様のソリューションについては、このコメントを参照してください。
eczajk 2017年

4
押しつぶす代わりの別の解決策は、同じRUNコマンドでキーを追加および削除し、追加と削除の間に、必要な目的に使用することです。
Benjamin HammerNørgaard2018年

2
おそらくid_rsa.pub必要ないので、ファイルを作成するための行を削除できます。
LCB 2018年

1
押しつぶす代わりに、マルチステージイメージビルドを利用します
Richard Kiefer

キーがパスワードで保護されている場合は、$(openssl rsa -in ~/.ssh/id_rsa)代わりに使用してください
BroiSatse

89

Ubuntuを使用しているときに判明した、ssh_configは正しくありません。追加する必要があります

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

Dockerfileに追加して、sshキーを認識できるようにします。


2
あなたは、おそらくも、このような正しいユーザ名を設定する必要がありますRUN echo " Host example.com" >> /root/.ssh/config RUN echo " User <someusername>" >> /root/.ssh/config
monofone

1
なぜ誰かがホストマシンからコンテナに秘密鍵をコピーするのですか?コマンドは大丈夫ですが、上記のことをすることに意味がありません...
Vladimir Djuricic

12
これは安全ではありません!Dockerの最新の1.13バージョンについては、以下の私のソリューションを参照してください。@ebensing
Daniel van Flymen 2017年

1
@VladimirDjuricicただし、デプロイメントキーなどがあります。
Zelphir Kaltstahl

実際には、ssh-keygen -Aを実行して、Ubuntu最小コンテナーでsshを適切にセットアップする必要があります。次に、pub / privキーを追加して、sshdを起動します。私のdockerfileに次のエントリがあります:ステップの1つとして「RUN ssh-keygen -A」。
piotrektt

84

:このアプローチは、プライベートで常に使用される画像にのみ使用してください

追加後にレイヤーコマンドでキーを削除しても、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

91
これにより、キーが画像に保持されます。そうしないでください。
CppLearner 2016

12
@CppLearner正解です。これはキーを画像に保存するため、場合によってはセキュリティ上の問題になる可能性があります。それを強調してくれてありがとう。ただし、これが完全に節約できる多くの状況があります。たとえば、プライベートリポジトリに保存されているイメージや、ローカルキーをイメージにコピーする本番サーバー上に直接構築されたイメージなどです。
yellowcap

2
また、Dockerfile内にベンダーをインストールする場合、ベンダーがインストールされたら、sshキーの削除を妨げるものは何もありません。
SebScoFr 2016年

2
@SebScoFr、後のコマンドでキーを削除した場合でも、明らかにキーはいずれかのレイヤーに格納されます(更新された回答のリンクを参照)。したがって、イメージは常にsshキーを公開し、ソリューションはプライベートイメージにのみ使用する必要があります。
yellowcap 2017年

1
@yellowcap not if you --squash the build
Anoyz

56

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

23
unixドメインソケットはプロキシされないため、docker-machine(VirtualBoxを使用)またはDocker for Mac(xhyveを使用)のどちらを使用していても、これはMacホストでは機能しません。
ジョーショー

SSH_AUTH_SOCK変数で、ssh-agentへのパスが含まれています
Aistis


1
ssh-forwardingがmacOSホストでもサポートされるようになりました-のパスをマウントする代わりに、$SSH_AUTH_SOCKこのパスをマウントする必要があります- /run/host-services/ssh-auth.sock
Jakub Kukul

47

Peter Graingerの答えを拡張する Docker 17.05以降に利用可能なマルチステージビルドを使用することができました。公式ページの状態:

マルチステージビルドでFROMは、Dockerfileで複数のステートメントを使用します。各FROM命令は異なるベースを使用でき、それぞれがビルドの新しいステージを開始します。あるステージから別のステージにアーティファクトを選択的にコピーして、最終的なイメージに必要のないものをすべて残すことができます。

ここでこれを覚えておくとDockerfile、3つのビルド段階を含める私の例になります。クライアント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"]

.dockerignore.gitignoreファイルの内容を繰り返します(プロジェクトのnode_modules結果のdistディレクトリがコピーされるのを防ぎます):

.idea
dist
node_modules
*.log

イメージをビルドするコマンドの例:

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

SSH秘密鍵にパスフレーズがない場合は、空のSSH_KEY_PASSPHRASE引数を指定してください。

これはどのように機能するかです:

1)。最初のステージのみでpackage.jsonyarn.lockファイルとSSH秘密鍵がという名前の最初の中間イメージにコピーされsourcesます。これ以上のSSHキーパスフレーズプロンプトを回避するために、自動的にに追加されssh-agentます。最後に、yarnコマンドはNPMから必要なすべての依存関係をインストールし、SSH経由でBitbucketからプライベートgitリポジトリを複製します。

2)。第2ステージでは、Webアプリケーションのソースコードをビルドおよび縮小して、distという名前の次の中間イメージのディレクトリに配置しproductionます。インストール済みのソースコードは、最初のステージで作成node_modulesされたイメージから次の行でコピーされることに注意してくださいsources

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

おそらく次の行かもしれません:

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

ここにはnode_modules、最初の中間イメージのディレクトリのみがありSSH_KEYSSH_KEY_PASSPHRASE引数はありません。ビルドに必要な残りのすべては、プロジェクトディレクトリからコピーされます。

3)。3番目のステージでは、名前が付けられた2番目の中間イメージのディレクトリezze/geoport:0.6.0のみを含め、Webサーバーを起動するためにNode Expressをインストールすることにより、タグ付けされる最終イメージのサイズを縮小します。distproduction

画像を一覧表示すると、次のような出力が得られます。

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

タグ付けされていないイメージは、最初と2番目の中間ビルドステージに対応します。

走れば

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

最終画像にはSSH_KEYとの言及はありませんSSH_KEY_PASSPHRASE


古い投稿ですが、これを強調したいのは、これが18.09より前の場合の最善の方法です。スカッシュは不要であり、リスクが発生しやすくなります。マルチステージを使用すると、必要なアーティファクトのみを取り込むことができます。スカッシュは不要なファイルのオプトアウト、マルチステージはオプトインと考えてください。この答えはもっと高くする必要があります。画像にSSHキーを焼き付けるのはひどい習慣です。
mritalian

@ezzeこの非常に便利な投稿をありがとうございました:) SSH-agentは私を狂わせています、私はあなたがしたのと同じようなことをしました:私はDockerビルドログに正しく表示しますIdentity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)が、別のRUNまたは同じRUNコマンドを実行するssh-add -lと、「エージェントにはIDがありません」と表示されます。私の髪の毛を引っ張り始めて、どんな考え?
アレックス

40

コンテナー内にsshキーを挿入するには、複数のソリューションがあります。

  1. DockerfileをADD命令とともに使用すると、ビルドプロセス中にそれを注入できます

  2. 単に次のようなことをしています cat id_rsa | docker run -i <image> sh -c 'cat > /root/.ssh/id_rsa'

  3. 使用するdocker cpコンテナの実行中にファイルを注入することを可能にするコマンドを。


2
だから、今のところ、それを/root/.ssh/id_rsaにコピーしようとしましたが、Gitから「ホストキーの検証に失敗しました。致命的:リモートエンドが予期せずハングアップしました」というエラーが表示されます。なんらかの理由でキーを使用していません。だから私はそれが実際にシステムにsshキーなのでそれを使用するように指示するために私がする必要がある何かがあると思いますか?これをデバッグする方法が正確にわかりません。(そして、このキーはホストから問題なく実行されるので機能することを知っています)
2013

/ etc / ssh / ssh_configが正しい鍵ファイルをターゲットにしていることを確認できますか?
2013

1
Dockerコンテナーのファイルを検査する良い方法はありますか?または、有効な構成でコピーしてみますか?
2013

3
私は 'base'イメージを試してみてapt-get install openssh-server、自分のキーを/root/.ssh/id_rsaに入れて配置しましたが、うまくいきました。どんな画像を使用していますか?
2013

コンテナのファイルを検査する必要がある場合、最良の方法は「cat」を使用して結果のイメージをコミットして実行することです。
2013

15

クロスプラットフォームソリューションの1つは、バインドマウントを使用して、ホストの.sshフォルダーをコンテナーに共有することです。

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

エージェント転送と同様に、このアプローチは公開鍵をコンテナーにアクセス可能にします。追加の利点は、非rootユーザーでも機能し、GitHubに接続できることです。ただし、考慮すべき1つの注意点は、.sshフォルダーのすべてのコンテンツ(秘密キーを含む)が共有されるため、このアプローチは、開発および信頼されたコンテナーイメージに対してのみ望ましいものです。


1
これはうまくいくかもしれませんが、その間docker buildだけではありませんdocker run
Alexander Mills

3
それがまさにポイントです。sshキーをdockerファイル内に配置する必要はありません。
Mohammad Azim

2
SSHエージェント転送がLinuxの外では機能しないことを考えると、これは、大騒ぎせずに開発環境で稼働させるための優れたソリューションになります。
Josh Habdas

私はdocker-compose upローカルのWindows 10でDockerを実行しています。そのシナリオでソリューションをどのように使用すればよいですか?
llaaalu

基本的には、Docker Composeでボリュームをマッピングする方法を尋ねています。上にこれに答える答えがあります。具体的にWindows用のこのかもしれないのヘルプstackoverflow.com/questions/41334021/...
モハマド・アジム

14

Dockerコンテナーは、独自の「サービス」と見なす必要があります。懸念事項を分離するには、機能を分離する必要があります。

1)データはデータコンテナー内にある必要があります。リンクされたボリュームを使用して、リポジトリのクローンを作成します。そのデータコンテナは、それを必要とするサービスにリンクできます。

2)コンテナーを使用してgitクローンタスクを実行します(つまり、唯一のジョブはクローンです)、実行時にデータコンテナーをコンテナーにリンクします。

3)ssh-keyについても同じです:(上記のように)ボリュームにして、必要に応じてgit cloneサービスにリンクします

このようにして、クローンタスクとキーの両方が一時的で、必要な場合にのみアクティブになります。

アプリ自体がgitインターフェースである場合は、githubまたはbitbucket REST APIを直接検討して作業を行うことをお勧めします。それが、そのために設計されたものです。


13

この行は問題です:

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

イメージにコピーするファイルを指定するときは、Dockerfileがあるディレクトリへの相対パスのみを使用できます。したがって、代わりに次を使用する必要があります。

ADD id_rsa /root/.ssh/id_rsa

そして、id_rsaファイルをDockerfileと同じディレクトリに配置します。

詳細はこちらをご覧ください:http : //docs.docker.io/reference/builder/#add


4
これは、秘密キーを簡単に忘れられる可能性のあるイメージに挿入するため、セキュリティの問題でもあります。
Mike D

docker cp画像ではなくコンテナに入れるだけですよね?
Alexander Mills

13

dockerビルド時にnpm installを実行すると、同様の問題が発生しました。

Daniel van Flymenのソリューションに触発され、それをgit url rewriteと組み合わせて 、プライベートgithubリポジトリから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 . 

残念ながら、私は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

11

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

スクリプトはを実行できますgit clone

Extra:chownコンテナ内でroot以外のユーザーを使用するとgit失敗するため、クローンファイルを特定のユーザーに所属させる場合は、使用する必要があります。

このパブリッシュをコンテナの環境に行うには、いくつかの追加の変数を使用できます。

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

クローンを作成したらchown $OWNER_USER:$OWNER_GROUP -R <source_folder>、コンテナを離れる前に実行して適切な所有権を設定する必要があります。これにより、コンテナ以外の非rootユーザーがファイルにアクセスできるようになります。


1
新しいDockerバージョン-u root:$(id -u $USER)では、少なくともユーザーに同じプライマリグループが所有するファイルを渡すことができます。sudoこれにより、0600権限のあるものが作成されていない限り、すべてのファイルを少なくとも読み取り可能にする必要があります。
dragon788

@ dragon788私はあなたがタイプミスを持っていると思います:で-u root:$(id -u $USER)なければなりません-g
edupo 2017年

いいね!私はモバイルからそれを修正することができないようです、すぐにデスクトップで試します。
dragon788

私が持っている/tmp/ssh_auth.sock: No such file or directory、それはです今/tmp/ssh-vid8Zzi8UILE/agent.46016私のホストマシン上で
vladkras

@vladkrasエラーはかなり一般的です。/tmpコンテナー内のアクセス許可が原因である可能性があります。または、docker runコマンドのタイプミス。bindステートメントが正しいことを確認してください-v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock。順序が重要であり、セミコロンも重要です。詳細についてはDockerのドキュメントを確認してください。
edupo 2017年

10

eczajkはすでにDaniel van Flymenの回答でコメントしているので、キーを削除して使用しても安全ではないようです。キー--squashはまだ履歴に表示されます(docker history --no-trunc)。

Docker 18.09の代わりに、「シークレットの作成」機能を使用できるようになりました。私の場合、ホストのSSHキーを使用してプライベートgitリポジトリのクローンを作成し、Dockerfileに次のようにしました。

# syntax=docker/dockerfile:experimental

[...]

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

[...]

これを使用するには、実行する前に新しいBuildKitバックエンドを有効にする必要がありますdocker build

export DOCKER_BUILDKIT=1

また、--ssh defaultパラメータをに追加する必要がありますdocker build

これに関する詳細はこちら:https : //medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066


1
最高のソリューション私見。1)とのssh-agentに自分の秘密鍵を追加:私は仕事にそれを得るために2つの以上のことをしなければならなかったssh-add ~/.ssh/id_rsaビットバケットのために、すなわち、および2)をknown_hostsファイルにGitのホストを追加しますRUN ssh-keyscan -H bitbucket.org >> ~/.ssh/known_hosts
モリッツRingler

これをまったく機能させることができませんでした。それでもパーミッションエラーが発生します。DockerビルドでフラグPermission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access and the repository exists.を渡し、runコマンドでI --ssh defaultを使用--mount=type=sshしているにもかかわらず、これが発生しますgit clone。ビルドマシンで同じレポを問題なくクローンできます。Dockerビルドコンテナーで失敗するだけです。MacバージョンのDockerが実際にsshクライアントを渡していないのではないかと思います。
PMende

@PMendeは、私も同じように直面しているので、あなたが言ったこの問題を理解することができました。
サダンA.

@SadanArshad現在、この機能は、LinuxマシンからDockerを実行している場合にのみサポートされています。DockerコマンドをMacから実行している場合は機能しません(おそらく確認できませんが、おそらくWindowsも同様です)。
PMende '10 / 10/19


9

この問題は本当に厄介な問題です。dockerfileコンテキストの外ではファイルを追加/コピーできないため、〜/ .ssh / id_rsaをイメージの/root/.ssh/id_rsaにリンクするだけでは不可能であり、sshedを実行するために必ずキーが必要な場合Dockerイメージのビルド中のプライベートリポジトリリンクからのgit cloneのような...

とにかく、私は回避策の解決策を見つけましたが、それほど説得力はありませんでしたが、うまくいきました。

  1. あなたのdockerfileで:

    • このファイルを/root/.ssh/id_rsaとして追加します
    • git cloneやcomposerなど、好きなことをしてください...
    • 最後にrm /root/.ssh/id_rsa
  2. 1回の撮影で行うスクリプト:

    • dockerfileを保持するフォルダーにキーをcpします
    • ドッカービルド
    • コピーされたキーのrm
  3. いくつかのssh要件でこのイメージからコンテナーを実行する必要があるときはいつでも、次のようにrunコマンドに-vを追加するだけです。

    docker run -v〜/ .ssh / id_rsa:/root/.ssh/id_rsa --nameコンテナーイメージコマンド

このソリューションの結果、プロジェクトソースとビルドされたDockerイメージの両方に秘密鍵がなくなるため、セキュリティの問題を心配する必要がなくなります。


1
「あなたが追加することはできませんので、/ dockerfileコンテキスト外で任意のファイルをコピーし、」あなたは見たことがありますかdocker cp?「コンテナとホスト間でファイル/フォルダをコピーする」ために使用されます。
Jonathon Reinhart、2015

@JonathonReinhart、指摘してくれてありがとう。はい、docker cpトリックを行うことができます。しかし、この状況では、イメージのビルド中にssh_keyが必要でした。その時点ではコンテナーがありません...とにかく、あいまいな表現を更新します。
ImLeo 16

9

私は今日同じ問題に遭遇し、以前の投稿で少し修正されたバージョンに遭遇しました。

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

(readonlyフラグなので、コンテナーがsshキーを混乱させることはありません。)

コンテナー内で実行できるようになりました:

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

Bad owner or permissions on /root/.ssh/..@krossが指摘したエラーは発生しません


ありがとうございました!これは私にとってそれが機能するための鍵でした:のような単一のコマンドでssh-agentとssh-addを持つことssh-agent bash -c "ssh-add..."。その後、その権利をdocker runに渡すことができます。以前に見つけたすべての例で使用されeval ssh-agent、その後にssh-addが続きましたがeval、docker runコマンドでそれを渡す方法を理解できませんでした。
ライアンマン2017


6

ホストとコンテナの間で.sshディレクトリをリンクすることもできます。この方法がセキュリティに影響するかどうかはわかりませんが、最も簡単な方法かもしれません。このようなものがうまくいくはずです:

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

ルートsshキーを使用する場合は、dockerがsudoで実行されることを覚えておいてください(そうでない場合を除く)。


このメソッドの使用はdocker 0.11で機能しますが、figを使用するとパニックエラーがスローされます。理由はわかりません
Luis Elizondo、

3
これは推奨される方法です。秘訣は、権限のないホストユーザーのキーをコンテナのルートとして使用することです。おっしゃるように、ホストのrootユーザーが譲らないようにしてくださいBad owner or permissions on /root/.ssh/config
KROSS

これは中にのみ使用できdocker run、中には使用できませんdocker build
ccpizza

3
@ccpizza、私はそれを利点と考えています。これらの回答の多くは、秘密鍵をイメージに保存したままにします。後続のレイヤーコマンドでキーを削除した後でも、キーは保存されたままになります。(ビルドではなく)実行時にのみ秘密鍵を導入することにより、それらはコンテナー(イメージではなく)にのみ存在できます。
カウリネーター2018

6

docker API 1.39+(でAPIバージョンを確認するdocker version)dockerビルドから開始--sshすると、Docker EngineがSSHエージェント接続を転送できるように、エージェントソケットまたはキーのオプションを使用できます。

ビルドコマンド

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

より詳しい情報:


1
チルダ拡張は私にはうまくいきませんでした。取得しました:could not parse ssh: [default=~/.ssh/id_rsa]: stat ~/.ssh/id_rsa: no such file or directory。機能しない場合は、絶対パスを使用してください。
slhck

3

SSHキーのセキュリティを気にしない場合、ここに多くの良い答えがあります。もしそうなら、私が見つけた最良の答えは、上記のコメントのリンクから、diegocsandrimによるこのGitHubコメントへのリンクからでした。他の人がそれを見る可能性が高くなるように、そしてレポが消えた場合に備えて、その回答の編集されたバージョンを次に示します:

ここでのほとんどのソリューションは、最終的にイメージに秘密鍵を残すことになります。画像へのアクセス権を持つ誰もがあなたの秘密鍵にアクセスできるので、これは悪いことです。の動作については十分に理解していないためsquash、キーを削除してそのレイヤーをスカッシュした場合でも、これが当てはまる場合があります。

aws s3 cliでキーにアクセスするための事前署名URLを生成し、アクセスを約5分間制限します。この事前署名URLをrepoディレクトリのファイルに保存し、dockerfileでイメージに追加します。

dockerfileには、これらのすべての手順を実行するRUNコマンドがあります。事前に歌うURLを使用してsshキーを取得し、npm installを実行して、sshキーを削除します。

これを1つのコマンドで行うと、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 .

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

1
このソリューションの問題は、pre_sign_urlが毎回変更されるため、packages.jsonファイルに変更がない場合でも、npmインストールをキャッシュできないことです。build.shでキーを取得してビルド引数として設定し、毎回変更されないようにすることをお
York Yang


3

Dockerコンテナ内のSSHの課題の簡潔な概要は、ここ詳しく説明されています。シークレットを漏らさずにコンテナ内から信頼できるリモートに接続するには、いくつかの方法があります。

これらの他に、Composeを使用するときに、実行時にアクセス可能な別のDockerコンテナーで実行されるキーストアを使用する可能性もあります。ここでの欠点は、HashiCorpによるVaultなどのキーストアを作成および管理するために必要な機構により、さらに複雑になることです。

スタンドアロンのDockerコンテナでのSSHキーの使用については、上記の方法を参照し、特定のニーズに応じてそれぞれの欠点を検討してください。ただし、Compose内で実行していて、実行時にアプリのキーを共有したい場合(OPの実用性を反映)、次のようにしてください。

  • docker-compose.envファイルを作成し、ファイルに追加し.gitignoreます。
  • を更新し、キーを必要docker-compose.ymlとするenv_fileサービスを追加します。
  • process.node.DEPLOYER_RSA_PUBKEYNode.jsアプリケーションの場合など、アプリケーションの実行時に環境から公開鍵にアクセスします。

上記のアプローチは、開発とテストに理想的です。本番環境の要件を満たすことはできますが、本番環境では、上記で特定した他の方法のいずれかを使用する方がよいでしょう。

追加のリソース:


3

マルチステージビルドを使用してコンテナーをビルド できます。

ステージ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

ステージ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"] 

作成ファイルにenv属性を追加します。

   environment:
      - SSH_PRIVATE_KEY=${SSH_PRIVATE_KEY}

次に、次のようにビルドスクリプトから引数を渡します。

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

セキュリティのために中間コンテナを削除します。 これはあなたを応援するのに役立ちます。


2

キーをDockerイメージレイヤーに保存せずに、またはssh_agentの体操を行わずに、これを実現する簡単で安全な方法は次のとおりです。

  1. のステップの1つとして、以下を追加しDockerfile.sshディレクトリを作成します。

    RUN mkdir -p /root/.ssh

  2. その下は、sshディレクトリをボリュームとしてマウントすることを示しています。

    VOLUME [ "/root/.ssh" ]

  3. ssh_config次の行を追加して、コンテナが公開鍵の場所を知っていることを確認します。

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

  4. .ssh実行時にローカルユーザーのディレクトリをコンテナに公開します。

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

    またはdockerCompose.yml、サービスのボリュームキーの下にこれを追加します:

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

ファイナルにDockerfileは次のようなものが含まれている必要があります:

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

私は別の方法で問題を解決しようとしています:イメージに公開SSHキーを追加します。しかし、私の裁判で、「docker cp」がコンテナからホストにコピーするためのものであることを発見しました。creakによる回答の項目3は、docker cpを使用してファイルをコンテナーに挿入できることを示しているようです。https://docs.docker.com/engine/reference/commandline/cp/を参照してください

抜粋

コンテナーのファイルシステムからホストパスにファイル/フォルダーをコピーします。パスは、ファイルシステムのルートを基準にしています。

  Usage: docker cp CONTAINER:PATH HOSTPATH

  Copy files/folders from the PATH to the HOSTPATH

このURLは壊れているようです。
slm 2014

これは廃止されたか、正しくありません。少なくとも1.8.2の時点で、どちらの方向にもコピーできます。
Jonathon Reinhart、2015

1

共有フォルダを使用して承認済みのキーをコンテナに渡し、次のようなdockerファイルを使用して権限を設定できます。

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

そして、あなたのdocker runには次のようなものが含まれており、ホスト上のauthディレクトリ(authorised_keysを保持)をコンテナーと共有し、ホストのポート7001からアクセスできるsshポートを開きます。

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

コンテナーのシェルを開いてコンテナー内でコマンドを実行する別の方法であると思われるhttps://github.com/jpetazzo/nsenterを確認することをお勧めします。


1

確かにパーティーの後半では、ホストオペレーティングシステムのキーをオンザフライでコンテナー内のrootで使用できるようにする方法はどうでしょうか。

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

コンテナーの反復により秘密鍵が残される可能性があるため、私はDockerfileを使用して鍵をインストールすることに賛成しません。


0

シークレットを使用して、コンテナーが実行時に必要とする機密データを管理できますが、次のようなイメージやソース管理に保存したくない場合があります。

  • ユーザー名とパスワード
  • TLS証明書とキー
  • SSHキー
  • データベースや内部サーバーの名前など、その他の重要なデータ
  • 汎用文字列またはバイナリコンテンツ(最大500 kbのサイズ)

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

実行時に(ビルドではなく)使用する署名キーをコンテナーに追加する方法を見つけようとしていて、この質問に出くわしました。Dockerシークレットは私のユースケースの解決策のようです。まだ誰も言及していないので、追加します。


0

私の場合、リモートリポジトリからのnodejsおよび 'npm i'に問題がありました。nodejsコンテナーに「node」ユーザーを追加し、コンテナーの〜/ .sshに700を追加するように修正しました。

Dockerfile:

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

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

その後それは働き始めました


-1

最も簡単な方法は、ランチパッドアカウントを取得して使用する:ssh-import-id


8
問題は秘密鍵についてでした。ssh-import-id公開鍵のみをインポートするように見えます。
cddr

-1

実行中のDockerコンテナでは、docker -i(インタラクティブ)オプションを使用してssh-keygenを発行できます。これにより、コンテナーのプロンプトが転送され、Dockerコンテナー内にキーが作成されます。


1
そして何?許可がないため、この後は何もできません。
Jonathon Reinhart、2015

-1

debian / root / authorized_keysの場合:

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.