つまり、いいえ、あなたのVOLUME
指示は正しくありません。
Dockerfileは、VOLUME
コンテナ側のパスを指定して1つ以上のボリュームを指定します。ただし、イメージ作成者がホストパスを指定することはできません。ホスト側では、Dockerルート内に非常に長いIDのような名前でボリュームが作成されます。私のマシンではこれは/var/lib/docker/volumes
。
注:自動生成された名前は非常に長く、人間の観点からは意味がないため、これらのボリュームは「無名」または「匿名」と呼ばれることがよくあります。
「。」を使用する例 ドットを最初の引数にするか2番目の引数にするかに関係なく、文字は私のマシンでも実行されません。私はこのエラーメッセージを受け取ります:
docker:デーモンからのエラー応答:ociランタイムエラー:container_linux.go:265:コンテナープロセスの開始により「process_linux.go:368:コンテナーの初期化により\ "open / dev / ptmx:no such file or directory \"」が発生しました。
私は何をここまで言われてきたことは、おそらく理解しようとする人には非常に貴重ではないことを知っているVOLUME
と-v
、それは確かにあなたが達成しようとする何のためのソリューションを提供していません。したがって、うまくいけば、次の例はこれらの問題にさらに光を当てるでしょう。
ミニチュートリアル:ボリュームの指定
このDockerfileを考えると:
FROM openjdk:8u131-jdk-alpine
VOLUME vol1 vol2
(私たちが指定した場合、このminitutorialの結果については、それは違いはありませんvol1 vol2
か/vol1 /vol2
-なぜ私に聞かないでください)
ビルドする:
docker build -t my-openjdk
実行:
docker run --rm -it my-openjdk
コンテナ内でls
コマンドラインを実行すると、2つのディレクトリが存在することがわかります。/vol1
そして/vol2
。
コンテナを実行すると、ホスト側に2つのディレクトリ、つまり「ボリューム」も作成されます。
コンテナーを実行docker volume ls
している間にホストマシンで実行すると、次のようなものが表示されます(簡潔にするために、名前の中央部分を3つのドットに置き換えました)。
DRIVER VOLUME NAME
local c984...e4fc
local f670...49f0
コンテナに戻り、実行しますtouch /vol1/weird-ass-file
(上記の場所に空のファイルを作成します)。
このファイルは、ホストマシンの名前のないボリュームの1つで使用できます。最初にリストされたボリュームを最初に試行したため、2回試行しましたが、ホストマシンで次のコマンドを使用して、2番目にリストされたボリュームでファイルを見つけました。
sudo ls /var/lib/docker/volumes/f670...49f0/_data
同様に、ホスト上でこのファイルを削除しようとすると、コンテナ内でも削除されます。
注:この_data
フォルダーは「マウントポイント」とも呼ばれます。
コンテナーを終了し、ホスト上のボリュームをリストします。彼らはなくなっています。--rm
コンテナーを実行するときにフラグを使用しました。このオプションは、出口のコンテナーだけでなくボリュームも効果的に消去します。
新しいコンテナを実行しますが、次を使用してボリュームを指定します-v
。
docker run --rm -it -v /vol3 my-openjdk
これにより、3番目のボリュームが追加され、システム全体に3つの名前のないボリュームができます。指定した場合、コマンドはクラッシュしました-v vol3
。引数は、コンテナー内の絶対パスでなければなりません。ホスト側では、新しい3番目のボリュームは匿名で、他の2つのボリュームと一緒に存在します/var/lib/docker/volumes/
。
Dockerfile
実行時にホストからコンテナにファイルを取り込もうとするときに、が一種の問題を引き起こすホストパスにマップできないと以前に述べました。別の-v
構文でこの問題を解決します。
コンテナー内で./src
同期したいプロジェクトフォルダーにサブフォルダーがあるとします/src
。このコマンドはトリックを行います:
docker run -it -v $(pwd)/src:/src my-openjdk
:
キャラクターの両側は絶対パスを期待しています。左側はホストマシン上の絶対パス、右側はコンテナ内の絶対パスです。pwd
「現在/作業ディレクトリを印刷」するコマンドです。コマンドを入れる$()
入れると、コマンドが括弧で囲まれ、サブシェルで実行され、プロジェクトディレクトリへの絶対パスが返されます。
すべてをまとめると./src/Hello.java
、ホストマシンのプロジェクトフォルダに次の内容が含まれていると想定します。
public class Hello {
public static void main(String... ignored) {
System.out.println("Hello, World!");
}
}
このDockerfileを作成します。
FROM openjdk:8u131-jdk-alpine
WORKDIR /src
ENTRYPOINT javac Hello.java && java Hello
次のコマンドを実行します。
docker run -v $(pwd)/src:/src my-openjdk
これは「Hello、World!」と印刷します。
最良の部分は、2回目の実行で別の出力用の新しいメッセージで.javaファイルを完全に自由に変更できることです-イメージを再構築する必要はありません=)
最後の発言
私はDockerを使い始めたばかりで、前述の「チュートリアル」は、3日間のコマンドラインハッカソンから集めた情報を反映しています。私の発言を裏付ける明確な英語のようなドキュメントへのリンクを提供できなかったことを恥ずかしく思いますが、正直なところ、これはドキュメントの不足と個人的な努力によるものではないと思います。私の例では、現在の設定である「Windows 10-> Vagrant 2.0.0-> Docker 17.09.0-ce」を使用して、これらの例が宣伝どおりに機能することを知っています。
このチュートリアルでは、「Dockerfileでコンテナーのパスを指定し、runコマンドでホストパスのみを指定する方法」という問題は解決されません。方法があるかもしれませんが、私はそれを見つけていません。
最後VOLUME
に、Dockerfile で指定することは珍しいことではないが、を使用しないことがベストプラクティスであると直感しますVOLUME
。2つの理由があります。すでに特定した最初の理由:ホストパスを指定できません。これは、Dockerfileがホストマシンの詳細に大きく依存しないため、これは良いことです。しかし、2番目の理由は--rm
、コンテナーの実行時にオプションを使用するのを忘れることがあるためです。コンテナを削除することを覚えているかもしれませんが、ボリュームを削除するのを忘れているかもしれません。さらに、人間の記憶力が最も優れている場合でも、すべての匿名ボリュームのうちどれを削除しても安全かを判断するのは困難な作業になる場合があります。