Dockerに慣れる : Dockerfile について では
することでカスタムしたコンテナイメージを生成した。 だが、変更したい箇所を確認する度にコンテナイメージを生成するのは記憶領域が逼迫するし、 かったるい。
その辺りを解決する方法として、ホスト内の特定のファイルやディレクトリをコンテナプロセスと共有したりできるようだ。
今回はそれを試してみる。
参考:
- 1.バインドマウント(bind)
- Dockerホストのファイルやディレクトリをコンテナ上にマウントする機能です。 バインドマウントを行うと、コンテナの外にあるファイルを、コンテナの中から読み書き可能になります。
ホストのディレクトリやファイルをコンテナプロセスにマウントするのをバインドマウントと言うらしい。 これが実現できると開発用仮想環境コンテナを作り、開発領域だけマウントして開発することができる。
これをやってみる。
httpdコンテナでバインドマウントする
httpdコンテナに対し、Dockerホスト側に用意したindex.htmlをマウントさせてみます。 ファイルの配置と内容は以下です。
/home/[ユーザーディレクトリ]/docker_httpd/htdocs/index.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <meta http-equiv="content-type" charset="utf-8"> <html> <head> <title>Dockerマウントテスト</title> </head> <body> httpd container working!<br/> Dockerホストのhtmlファイルをマウントしています!<br/> </body> </html>
では、コンテナを起動します。runコマンドに「-v」オプションを指定します。
docker run -d -p 8080:80 -v /home/[ユーザーディレクトリ]/docker_httpd/htdocs/:/usr/local/apache2/htdocs/ httpd
-vオプションで、ホスト側の htdocs をコンテナ側の htdocs にマウントします。
-v <host_path>:<container_path>
適当なディレクトリを作り、内部に index.html を作成する。 そのディレクトリをマウントするのを試してみる。
$ mkdir test
$ cd test/
$ mkdir htdocs
ディレクトリを作った。内部に index.html を作成する。
$ cd htdocs
$ vimr index.html
<!DOCTYPE html>
<html lang="ja-jp">
<head>
<meta charset="utf-8">
<title>
Test page
</title>
</head>
<body>
<p>
This sentence wrote in host.
</p>
</body>
</html>
マウントして実行してみる。
$ docker run -d -p 8080:80 -v htdocs/:/usr/local/apache2/htdocs/ httpd
Unable to find image 'httpd:latest' locally
latest: Pulling from library/httpd
8559a31e96f4: Pull complete
bd517d441028: Pull complete
f67007e59c3c: Pull complete
83c578481926: Pull complete
f3cbcb88690d: Pull complete
Digest: sha256:387f896f9b6867c7fa543f7d1a686b0ebe777ed13f6f11efc8b94bec743a1e51
Status: Downloaded newer image for httpd:latest
docker: Error response from daemon: create htdocs/: "htdocs/" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path.
See 'docker run --help'.
最後にエラーが出て無理だった。 読んでみると、
/
を使用できない、つまりコマンド実行と同階層にファイルがある必要があるということだそうだ。
ホスト側のマウント先を指定する場合
docker run -v [ホストディレクトリの絶対パス]:[コンテナの絶対パス] [イメージ名] [コマンド]
docker run -v /lib/modules:/lib/modules dummy-img /bin/bash
これでホスト側のディレクトリがコンテナにマウントされる。コンテナ上で作ったファイルがホストの方に残る。
docker inspect
するとこんな感じで表示される↓"Mounts": [ { "Source": "/lib/modules", "Destination": "/lib/modules", "Mode": "", "RW": true, "Propagation": "rprivate" } ]
マウントするとデフォルトで
read-write mode
なので"RW": true
になってる。
こちらも絶対パスって書いてある。仕方ないので絶対パスにする。
$ docker run -d -p 8080:80 -v /Users/test_user/sandbox/test/htdocs:/usr/local/apache2/htdocs httpd
69bbdaa723cb7eed234fd27c55f0a4e164e5a3a7f14ec013c953add4667148c9
ブラウザで確認してみる。 http://localhost:8080
ここで一旦、コンテナの中に入ってみます。
docker exec -it [コンテナID] /bin/bash
では、そのままコンテナ側からindex.htmlを編集してみます。
準備ができたら、index.htmlを編集します。以下(ピンクの行)の様に追記しました。
vi /usr/local/apache2/htdocs/index.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <meta http-equiv="content-type" charset="utf-8"> <html> <head> <title>Dockerマウントテスト</title> </head> <body> httpd container working!<br/> Dockerホストのhtmlファイルをマウントしています!<br/> マウント後にコンテナ側から更新した内容も、反映される<br/> </body> </html>
内容を保存してブラウザをリロードすると、追記した内容が画面に反映されています。
ピンクの行の部分をうまく引用できてないが、内部から編集を行ってみる。
vim
のインストールなどのログは省略。
$ docker exec -it funny_burnell /bin/bash
# apt update && apt upgrade && apt install vim
# vim htdocs/index.html
<!DOCTYPE html>
<html lang="ja-jp">
<head>
<meta charset="utf-8">
<title>
Test page
</title>
</head>
<body>
<p>
This sentence wrote in host.
</p>
<p>
This sentence wrote in container.
</p>
</body>
</html>
<p>
This sentence wrote in container.
</p>
の部分を追加した。ブラウザで見てみる。
コンテナを ctrl-p
ctrl-q
で抜けてホスト側のファイルを確認してみる
# read escape sequence
$ cat htdocs/index.html
<!DOCTYPE html>
<html lang="ja-jp">
<head>
<meta charset="utf-8">
<title>
Test page
</title>
</head>
<body>
<p>
This sentence wrote in host.
</p>
<p>
This sentence wrote in container.
</p>
</body>
</html>
変更が反映されている。
コンテナプロセスを終了した後 index.html がどうなっているか確認する。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
69bbdaa723cb httpd "httpd-foreground" 19 minutes ago Up 19 minutes 0.0.0.0:8080->80/tcp funny_burnell
$ docker rm -f funny_burnell
funny_burnell
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ cat htdocs/index.html
<!DOCTYPE html>
<html lang="ja-jp">
<head>
<meta charset="utf-8">
<title>
Test page
</title>
</head>
<body>
<p>
This sentence wrote in host.
</p>
<p>
This sentence wrote in container.
</p>
</body>
</html>
コンテナ内で変更したものも問題なくそのまま保存されている。