改めてDockerを理解する⑤[Dockerのバインドマウントについて]

## はじめに
こんにちは！ITスクールRareTECHにてCS（Customer Support）を担当している池村です。今回の記事はDockerのストレージの仕組みであるバインドマウントについてご紹介します。正直これが一番使う気がしますね。

シリーズ記事なので、まず先に以下の記事を読んでいただけますと幸いです。

https://qiita.com/ikemura-ren/items/221cf630ad03fb4b41b3



## バインドマウント
バインドマウントは前回の記事のDockerAreaに作成するボリュームと違って、ご自身のPCの指定したディレクトリとデータを連携するマウント方法です。
Webアプリなどをローカルで作成する場合、やはりこのマウントを使うことが多く、ローカルの環境とコンテナ内のディレクトリを連携することで、リアルタイムにコンテナ内で動くコードを更新できます。

![c52c81c7-497a-43e9-8eb8-0b36982c1010_720.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798971/df7616ac-3f81-02f3-6e91-0c879f6f2046.png)


### マウントしてみる
まずはUbuntuを使って、ローカルのディレクトリ以下をコンテナ内の指定の場所にマウントしてみます。

今回作っておいたディレクトリの環境は以下です。
```Bash:ディレクトリ構成
./test
├── tas.rs
├── test.go
├── test.py
├── test.rb
└── test.sh

1 directory, 5 files
```

```Bash:ubuntuのコンテナを起動する
docker run -it -v ./test:/home/ubuntu/ ubuntu
```

今回は`test`というディレクトリがある場所でdockerを起動しました。
コンテナ内の`/home/ubuntu/`以下のディレクトリにローカル内の`test`内のファイルをマウントします。

以下の画像のようになっていればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798971/901e2d20-90f2-8582-0dbf-378e221fc861.png)

無事マウントされて全てのファイルがコンテナ内にコピーされています。

### ファイルの内容を変更してみる
ではコンテナ内にあるファイルと、ローカルにあるファイル、同じファイルをどちらからも変更してみます。まずはコンテナ内からファイルを変更してみます。
```Bash:test.pyを変更
echo 'print("Hello")' >> test.py
cat test.py
```
コンテナ内でファイルの内容を変更したら、ローカルのファイルの中身を確認してみましょう。以下の画像の場合、上がコンテナ内、したがコンテナ外です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798971/3ec2e5e5-e195-abb4-6af7-92fa52187718.png)

コンテナ内で変更した1行のPythonのプログラムがコンテナ外でも反映されています。

もちろん反対にコンテナ外からファイルを変更しても反映されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798971/43566384-1da0-19cf-4940-b7abc56f7beb.png)

:::note info
これはいろいろ使えそうですね。では次にコンテナの中で簡単なWebサーバーでも動かしてみましょう！
:::


## ローカルのWebサーバープログラムをコンテナの中で起動
では実際に簡単なコードを使って、コンテナの中でプログラムを動かしてみます。

:::note warn
正直言いますと、Dockerfileというものを使った方が早いのですが、今回はいろいろ手動でやっていきます。
:::

この前に立ち上げていたコンテナは一度止めて削除しておきましょう。

### ローカルの`test.py`を書き換える
```Python:書き方
from http.server import HTTPServer, BaseHTTPRequestHandler

class TestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)  
        self.send_header("Content-type", "text/html")
        self.end_headers()
        self.wfile.write(b"Hello World")

HOST = "0.0.0.0"  
PORT = 8000       

with HTTPServer((HOST, PORT), TestHandler) as httpd:
    print(f"Serving on http://0.0.0.0:8000")
    httpd.serve_forever()

```

:::note info
今回はFlaskなども使わず、生のPythonでサーバーを立ち上げます。
:::

### コンテナを立ち上げて環境構築を行う
```Bash:コンテナを立ち上げる
docker run -it -v ./test:/home/ubuntu/ -p 8000:8000 ubuntu
```

:::note warn
`-p`と`8000:8000`はDockerのネットワークに関係してきますが、今回は説明を省きます。今後詳しく解説する記事も書きます。
:::

以下のコマンドを順番にコンテナの中で叩いていきましょう。

```Bash:aptをアップデートする
apt update
```

```Bash:Pythonをインストール
apt install -y python3 python3-pip
```

```Bash:バージョンを確認
python3 --version
```

```Bash:test.pyの起動
python3 test.py
```
```Bash:この文字が出てきていればOKです。
Serving on http://0.0.0.0:8000
```
:::note alert
これのPythonのサーバーがうまく立ち上がっていないのであれば、マウントされている場所が違っている可能性が高いです。見直しましょう。
:::

### ブラウザで確認
ブラウザを開いて、以下のURLを叩いてください。
```Bash:URLをブラウザのURLバーに入力してEnter
http://localhost:8000
```
以下のメッセージがブラウザで確認できましたらOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798971/e1cad867-50c7-3334-1d21-e9a394e183c4.png)

### コードの変更をした場合の挙動について
例えばローカルのコードを変更した場合、マウント先のコンテナの中のファイルも変更はされますが、サーバーを起動した状態では前の状態のままブラウザに表示されます。

今回は生のPythonでサーバーを立ち上げているため、例えば以下のような変更をしたとして解説します。
```Python:コードの変更
self.wfile.write(b"Hello World")
⬇️
self.wfile.write(b"Hello World!!")
```

この場合、まずはサーバーをCtrl + Cで停止して、再度立ち上げます。
そうすることで反映がされます。生のPythonの場合は`watchdog`と呼ばれるライブラリを入れることで、コードが変更されたことをキャッチしてサーバーを再起動してくれるようなものもあります。

Flaskなどのフレームワークを使っている場合は、`debug=True`にしておくと勝手にやってくれます。

フレームワークを使うことが当たり前になっている現在、`watchdog`の使い方に需要はない気もするので解説は省かせていただきます。

## おわりに
読了ありがとうございます。
バインドマウントはWebアプリを開発する際にかなり使われるマウント方法です。
ここはしっかり押さえていきたいですね。

次はDockerのネットワークについて記事にする予定です👇

https://qiita.com/ikemura-ren/items/0e6071f26a847366e585

まとめ記事に戻るにはこちら👇

https://qiita.com/ikemura-ren/items/b961642d55e4e6515203

読んでくれている皆様、ありがとうございます！

![5b712221-0816-43e7-b4b9-8d91c0768f70_720.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798971/3ae98762-9ba3-9e62-a450-12150cffbc93.png)



## 余談
皆様、学習お疲れ様です。勉強は楽しいですね！（学習初期は苦しかった思い出しかないですが😂）
自分自身、Dockerfileを使わずに環境構築を久々に行ったのでとてもいい復習になりました。結局やっていることは一緒ですが。もちろん生のPythonでサーバーを立ち上げるのも同様です。

フレームワークに頼りきってるな〜って反省です。。