Docker-ファイルをイメージからホストにコピーするにはどうすればよいですか?


115

私の質問は、コンテナからホストへのファイルのコピーに関するこの質問に関連しています。依存関係をフェッチし、ソースからビルドアーティファクトをコンパイルし、実行可能ファイルを実行するDockerfileがあります。ビルドアーティファクトもコピーしたい(私の場合は '../ target / `で.zip生成されたものですがsbt dist、この質問はjar、バイナリなどにも当てはまると思います)。

docker cp画像ではなくコンテナで機能します。ファイルを取り出すためだけにコンテナを起動する必要がありますか?スクリプト/bin/bashで、バックグラウンドでインタラクティブモードで実行し、ファイルをコピーしてからコンテナーを強制終了しようとしましたが、これは厄介なようです。もっと良い方法はありますか?

一方、1つのファイルを取得するためだけに.tar実行した後、ファイルをアンパックすることは避けたいと思いdocker save $IMAGENAMEます(ただし、今のところ、これが最も単純で、最も遅いオプションのようです)。

私はドッカーボリュームを使用します、例えば:

docker run -v hostdir:out $IMAGENAME /bin/cp/../blah.zip /out

しかし、私はboot2dockerOSXで実行していて、Macホストファイルシステムに直接書き込む方法がわかりません(読み書きボリュームがboot2docker VM内にマウントされているためblah.zip、イメージから抽出するスクリプトを簡単に共有できません)その他。

回答:


172

画像からファイルをコピーするには、一時的なコンテナを作成し、そこからファイルをコピーしてから削除します。

id=$(docker create image-name)
docker cp $id:path - > local-tar-file
docker rm -v $id

createコマンドが追加/削除された
dockerの

2
@ThorSummoner docker createはdocker 1.3で導入されました、blog.docker.com / 2014/10 /…
Igor Bukanov

1
なぜこれが正解に選ばれなかったのか分かりません。
CentAu

1
間違いなく正しい答えです!!! コンテナー内には何も依存していません... Golangスクラッチイメージの場合、これが唯一の方法です。
マルチェロ

2
stdoutにコピーしてからローカルファイルに送る理由は何ですか?私がこれを行ったとき、ファイルのコンテンツの前後に一連の制御文字をダンプしました。docker cp $id:path > local-tar-file完全に機能するように直接実行します。
よなたん

61

残念ながら、Dockerイメージから直接ファイルをコピーする方法はないようです。最初にコンテナを作成してから、コンテナからファイルをコピーする必要があります。

ただし、画像にcatコマンドが含まれている場合(多くの場合はそうなります)、単一のコマンドで実行できます。

docker run --rm --entrypoint cat yourimage  /path/to/file > path/to/destination

画像にが含まれていない場合はcat、コンテナーを作成docker cpし、Igorの回答で提案されているコマンドを使用します。


1
素晴らしいソリューション。起動後に1秒間クラッシュしたため、コンテナーにアクセスできませんでしたが、コンテナー内のファイルを取得する必要がありました。これは完全に機能しました。
Mirodinho 2017

23

より高速なオプションは、実行中のコンテナからマウントされたボリュームにファイルをコピーすることです。

docker run -v $PWD:/opt/mount --rm --entrypoint cp image:version /data/libraries.tgz /opt/mount/libraries.tgz

実数0分0.446秒

**対**

docker run --rm --entrypoint cat image:version /data/libraries.tgz > libraries.tgz

実質0m9.014s


これはおそらく、最初の例でファイルのレイジー/シャローコピー(コピーオンライトと考えてください)を実行している基になるファイルシステムと、実際に2番目の例でファイルのバイトをコピーすることとの関係が深いです。便利なテストは、cat a >bvs cp a bがここに示すように同様のタイミングを持っているかどうかを調べることです。また、ソースパスと宛先パスが異なるファイルシステムにある場合、どちらの例もバイト単位の完全なコピーになります。
KevinOrr

14

親のコメントは猫の使い方をすでに示しました。同様の方法でtarを使用することもできます。

docker run yourimage tar -c -C /my/directory subfolder | tar x

1
この答えは、元の質問が尋ねるように、ファイルではなくディレクトリをコピーすることです。ただし、+ 1はファイルでも機能し、追加の機能が含まれているためです。許可と所有者の保持です。すごい!
カリガリ

5
実際、私は使用していますdocker run --rm --entrypoint tar _image_ cC _img_directory_ . | tar xvC _host_directory_
カリガリ

6
docker cp $(docker create registry.example.com/ansible-base:latest):/home/ansible/.ssh/id_rsa ./hacked_ssh_key

1行のソリューションを提供したかった

編集:コンテナはこのソリューションで実行する必要さえありません


1

この問題に対する別の(短い)答え:

docker run -v $PWD:/opt/mount --rm -ti image:version bash -c "cp /source/file /opt/mount/"

0

MacOSでboot2dockerを使用しています。「docker cp」に基づくスクリプトは移植可能であることを保証できます。コマンドはboot2docker内でリレーされますが、バイナリストリームはMacで実行されているDockerコマンドラインクライアントにリレーされます。したがって、Dockerクライアントからの書き込み操作はサーバー内で実行され、実行中のクライアントインスタンスに書き戻されます。

私が提供する任意のDockerコンテナとDockerボリュームのバックアップスクリプトを共有しています。私のバックアップスクリプトは、LinuxとMacOSの両方でboot2dockerを使用してテストされています。バックアップはプラットフォーム間で簡単に交換できます。基本的に、スクリプト内で次のコマンドを実行しています。

docker run --name=bckp_for_volume --rm --volumes-from jenkins_jenkins_1 -v /Users/github/jenkins/backups:/backup busybox tar cf /backup/JenkinsBackup-2015-07-09-14-26-15.tar /jenkins

新しいbusyboxコンテナーを実行し、jenkins_jenkins_1という名前で私のjenkinsコンテナーのボリュームをマウントします。ボリューム全体がファイルbackups / JenkinsBackup-2015-07-09-14-26-15.tarに書き込まれます

バックアップまたは復元スクリプトを調整せずに、LinuxコンテナーとMacコンテナーの間でアーカイブを既に移動しました。これが必要な場合は、スクリプト全体のチュートリアルをここで見つけます:blacklabelops / jenkins


0

ホストのローカルパスをコンテナのパスにバインドしcpスクリプトの最後で目的のファイルをそのパスにバインドできます。

$ docker run -d \
  -it \
  --name devtest \
  --mount type=bind,source="$(pwd)"/target,target=/app \
  nginx:latest

その後、後でコピーする必要はありません。

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