私はGitでさまざまな楽しいもの(git clone&git Pushの実行など)を実行するアプリを持っていて、それをドッカー化しようとしています。
私は私が問題に遭遇していますが、私はコンテナ「ユーザー」が使うためにコンテナに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 pull
のようなgitコマンドを実行します
Ubuntuを使用しているときに判明、ssh_configは正しくありません。追加する必要があります
RUN echo " IdentityFile ~/.ssh/id_rsa" >> /etc/ssh/ssh_config
あなたのsshキーを認識させるためにあなたのDockerfileに。
構築時にSSHを使用する必要がある場合、それはより難しい問題です。例えばgit clone
を使用している場合、または私の場合はpip
とnpm
をプライベートリポジトリからダウンロードする場合です。
私が見つけた解決策は--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を使っていて実験的な機能を持っている場合は、buildコマンドに--squash
を追加してレイヤーを結合し、SSHキーを削除してdocker history
から隠すことができます。
注 :このアプローチは、 非公開で常に !になるイメージに対してのみ使用してください。
追加した後にlayerコマンドでキーを削除しても、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
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
Sshキーをコンテナ内に注入するには、複数の解決策があります。
ADD
命令でDockerfileを使用すると、ビルドプロセス中にそれを挿入できます。
単にcat id_rsa | docker run -i <image> sh -c 'cat > /root/.ssh/id_rsa'
のようなことをするだけです
コンテナの実行中にファイルを注入することを可能にするdocker cp
コマンドを使用します。
拡大{ Peter Grainger's answer 私はDocker 17.05から利用可能な マルチステージビルド を使うことができました。公式ページには次のように記載されています。
マルチステージビルドでは、Dockerfileで複数の
FROM
ステートメントを使用します。それぞれのFROM
命令は異なるベースを使用することができ、それらはそれぞれビルドの新しい段階を開始します。成果物をあるステージから別のステージに選択的にコピーし、不要なものはすべて最終イメージに残しておくことができます。
これを念頭に置いているのは、3つのビルド段階を含むDockerfile
の例です。クライアント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.json
、yarn.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_KEY
とSSH_KEY_PASSPHRASE
引数はもうありません。ビルドに必要な残りはすべて私たちのプロジェクトディレクトリからコピーされます。
3)。 3番目の段階では、dist
という2番目の中間イメージからproduction
ディレクトリのみを含め、Webサーバーを起動するためにNode Expressをインストールすることによって、ezze/geoport:0.6.0
としてタグ付けされる最終イメージのサイズを縮小します。
画像を一覧表示すると、次のような出力が得られます。
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
タグ付けされていないイメージは、1番目と2番目の中間ビルドステージに対応します。
走れば
$ docker history ezze/geoport:0.6.0 --no-trunc
最終的な画像にSSH_KEY
とSSH_KEY_PASSPHRASE
の言及はありません。
この行は問題です。
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
Dockerコンテナーは、それ自体の「サービス」と見なすべきです。懸念を分けるには、機能を分けるべきです:
1)データはデータコンテナに格納する必要があります。レポジトリのクローンを作成するには、リンクされたボリュームを使用します。そのデータコンテナは、それを必要とするサービスにリンクすることができます。
2)コンテナーを使用して、gitクローン作成タスクを実行します(つまり、実行するときにデータコンテナーをリンクするのはジョブのみがクローン作成です)。
3)ssh-keyについても同じです。(上記のように)ボリュームにして、必要なときにgit cloneサービスにリンクします。
このようにして、クローン作成タスクとキーの両方が一時的であり、必要なときにのみアクティブになります。
アプリ自体がgitインターフェースの場合は、githubまたはbitbucket REST APIを直接使用して作業を行うことをお勧めします。それがそれらのために設計されたものです。
Docker build timeでnpm installを実行したときにも同様の問題がありました。
Daniel van Flymen からの解決策にインスパイアされ、 git url rewrite と組み合わせることで、プライベートgithubリポジトリからnpm installを認証するための少し簡単な方法が見つかりました。
私たちの場合、npm依存関係は "git + https://github.com/ ..."として指定されています。
コンテナでの認証の場合、URLはssh認証(ssh://[email protected]/)またはトークン認証(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
この問題は本当に面倒なものです。 dockerfileのコンテキストの外にファイルを追加/コピーすることはできないので、〜/ .ssh/id_rsaをimageの/root/.ssh/id_rsaにリンクすることは不可能であり、あなたが間違いなく何かをするためにキーが必要なときDockerイメージの作成中に、プライベートレポジトリリンクからGitクローンを作成するのと同じです。
とにかく、私は回避策の解決策を見つけました、それほど説得力はありませんでしたが、私のために働きました。
あなたのdockerfileで:
1回の撮影で実行するスクリプト
sshの要件を満たしながらこのイメージからコンテナを実行する必要があるときはいつでも、runコマンドに-vを追加するだけです。
docker run -v〜/ .ssh/id_rsa:/root/.ssh/id_rsa --nameコンテナイメージコマンド
このソリューションでは、プロジェクトのソースと構築されたdockerイメージの両方に秘密鍵が存在しないため、セキュリティ上の問題がなくなります。
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:クローンファイルを特定のユーザに所属させたい場合は、コンテナ内でroot以外のユーザを使用するとchown
が失敗するため、git
を使用する必要があります。
あなたはコンテナの環境にいくつかの追加の変数を公開することができます:
docker run ...
-e OWNER_USER=$(id -u) \
-e OWNER_GROUP=$(id -g) \
...
クローンを作成したら、コンテナを離れる前にchown $OWNER_USER:$OWNER_GROUP -R <source_folder>
を実行して適切な所有権を設定する必要があります。これにより、コンテナの外部にいるroot以外のユーザがファイルにアクセスできるようになります。
「リモートサーバーからローカルのssh-agentに、サーバー上で実行されているかのように選択的にアクセスさせることができます。」
https://developer.github.com/guides/using-ssh-agent-forwarding/ /
1つの解決策は、以下のオプションでHostのsshキーをdockerにマウントすることです。
docker run -v /home/<Host user>/.ssh:/home/<docker user>/.ssh <image>
上記の解決方法に似ています。しかし、root以外のユーザーでも動作します。 githubと完璧に連携します。
私は今日同じ問題に遭遇しました、そして私はこのアプローチが私にとってより有用であると以前の記事で少し修正したバージョン
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>"
そのため、@ krossが指摘したBad owner or permissions on /root/.ssh/..
エラーは発生しません。
.sshディレクトリをホストとコンテナの間でリンクすることもできます。この方法にセキュリティ上の影響があるかどうかはわかりませんが、最も簡単な方法の可能性があります。このようなものでうまくいくはずです。
$ Sudo docker run -it -v /root/.ssh:/root/.ssh someimage bash
DockerはSudoで動作します(あなたがそうでない限り)、その場合はrootのsshキーを使うことになるでしょう。
Docker(17.05)のそれ以降のバージョンでは マルチステージビルド を使うことができます。これまでのビルドは後続のビルドでしか使用できず、その後破棄されるため、最も安全な方法です。
私のstackoverflowの質問に対する答え を参照してください。
EczajkはすでにDaniel van Flymenの回答でコメントしていたように、それらはまだ歴史の中に見られるので(--squash
)、キーを削除してdocker history --no-trunc
を使用するのは安全ではないようです。
代わりにDocker 18.09では、 "build secrets"機能を使うことができます。私の場合は、私のDockerfileに次のように私のホストのSSHキーを使用してプライベートGitリポジトリを複製しました。
# syntax=docker/dockerfile:experimental
[...]
RUN --mount=type=ssh git clone [...]
[...]
これを使用するには、docker build
を実行する前に新しいBuildKitバックエンドを有効にする必要があります。
export DOCKER_BUILDKIT=1
そして--ssh default
パラメータをdocker build
に追加する必要があります。
これについてのより多くの情報はここに: https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066
共有フォルダを使用して認証済みのキーをコンテナに渡したり、次のような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の実行には、ホスト上の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 を見るとよいでしょう。これは、コンテナ上でシェルを開いてコンテナ内でコマンドを実行するための別の方法のようです。
確かにパーティーに遅れて、その場でオンザフライであなたのホストオペレーティングシステムのキーがrootで利用できるようになるでしょうこれについてはどうですか:
docker run -v ~/.ssh:/mnt -it my_image /bin/bash -c "ln -s /mnt /root/.ssh; ssh [email protected]"
私はDockerfileを使ってキーをインストールすることに賛成していません。あなたのコンテナを繰り返すと秘密キーが残ってしまうかもしれないからです。
SSH鍵のセキュリティを気にしないのであれば、ここにたくさんの良い答えがあります。もしそうなら、私が見つけた最良の答えは このGitHubのコメント by diegocsandrim への上のコメントのリンクからでした。他の人がそれを見る可能性が高くなるように、そしてレポがこれまでになくなった場合のために、ここにその答えの編集版があります:
ここでのほとんどの解決策は、イメージに秘密鍵を残すことになります。画像にアクセスできる人なら誰でもあなたの秘密鍵にアクセスできるので、これは悪いことです。 squash
の振る舞いについては十分にわかっていないので、キーを削除してそのレイヤーを隠したとしても、これは当てはまります。
Aws s3 cliでキーにアクセスするための事前署名URLを生成し、アクセスを約5分間制限します。この事前署名URLをrepoディレクトリ内のファイルに保存し、次にそれを画像に追加します。
Dockerfileには、これらすべての手順を実行するRUNコマンドがあります。事前に歌うURLを使用してsshキーを取得し、npm installを実行してsshキーを削除します。
これを1回のコマンドで実行すると、sshキーはどのレイヤにも格納されませんが、署名前のURLは格納されます。5分後にはURLが有効にならないため、これは問題になりません。
ビルドスクリプトは次のようになります。
# 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 [email protected] || true && \
npm install --production && \
rm ./my_key && \
rm -rf ~/.ssh/*
ENTRYPOINT ["npm", "run"]
CMD ["start"]
私は他の方法で問題を解決しようとしています:公開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
秘密を使用して、実行時にコンテナが必要とする機密データを管理できますが、画像やソース管理には保存したくありません。
- ユーザー名とパスワード
- TLS証明書とキー
- SSHキー
- データベースや内部サーバーの名前など、その他の重要なデータ
- 一般的な文字列またはバイナリコンテンツ(最大500 kb)
実行時に使用する(ビルドではない)コンテナに署名キーを追加する方法を見つけようとしていたところ、この問題に遭遇しました。 Dockerの秘密は私のユースケースの解決策のように思われます、そして誰もまだそれを言及していないので私はそれを追加します。
最も簡単な方法は、ランチパッドアカウントを取得して使用することです: ssh-import-id
Dockerイメージレイヤーにキーを保存したり、ssh_agent体操をしたりせずにこれを実現するための簡単で安全な方法は次のとおりです。
Dockerfile
の手順の1つとして、以下を追加して.ssh
ディレクトリを作成します。
RUN mkdir -p /root/.ssh
その下にsshディレクトリをボリュームとしてマウントしたいことを示します。
VOLUME [ "/root/.ssh" ]
次の行を追加して、コンテナのssh_config
が公開鍵の場所を知っていることを確認してください。
RUN echo " IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config
実行時にローカルユーザーの.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" ]
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