バインドマウントを使用する
パート4 では、ボリュームマウントを使用してデータベースのデータを永続化しました。アプリケーションデータを永続的に保存する必要がある場合、ボリュームマウントは素晴らしい選択です。
バインドマウントは別の種類のマウントで、ホストのファイルシステムのディレクトリをコンテナに共有できます。アプリケーションの開発中は、バインドマウントを使ってソースコードをコンテナにマウントすることができます。ファイルを保存した瞬間に、コンテナはコードの変更を即座に認識します。これにより、ファイルシステムの変更を監視し、それに応じて動作するプロセスをコンテナ内で実行できるようになります。
この章では、バインドマウントと、ファイルの変更を監視してアプリケーションを自動的に再起動するツールである nodemon を使う方法を学びます。ほとんどの他の言語やフレームワークにも、同様のツールがあります。
ボリュームタイプの簡単な比較
以下は、--mount
を使用した名前付きボリュームとバインドマウントの例です。
- 名前付きボリューム:
type=volume,src=my-volume,target=/usr/local/data
- バインドマウント:
type=bind,src=/path/to/data,target=/usr/local/data
以下の表は、ボリュームマウントとバインドマウントの主な違いを示しています。
名前付きボリューム | バインドマウント | |
---|---|---|
ホスト側の場所 | Dockerが決定 | ユーザーが決定 |
コンテナの内容で新しいボリュームを初期化 | 可能 | 不可 |
ボリュームドライバーのサポート | あり | なし |
バインドマウントを試してみる
アプリケーション開発でバインドマウントを使用する前に、簡単な実験を行い、バインドマウントの動作を実際に確認してみましょう。
-
getting-started-app
ディレクトリが、Docker Desktopのファイル共有設定に定義されたディレクトリ内にあることを確認してください。この設定は、ファイルシステムのどの部分をコンテナと共有できるかを定義します。設定へのアクセス方法については、ファイル共有を参照してください。 -
ターミナルを開き、
getting-started-app
ディレクトリに移動します。 -
次のコマンドを実行して、バインドマウントを使用して
ubuntu
コンテナでbash
を起動します。$ docker run -it --mount type=bind,src="$(pwd)",target=/src ubuntu bash
--mount type=bind
オプションは、Dockerにバインドマウントを作成するよう指示します。src
はホストマシンのカレントディレクトリ(getting-started-app
)、target
はコンテナ内でそのディレクトリを表示する場所(/src
)です。 -
コマンドを実行すると、Dockerはコンテナのファイルシステムのルートディレクトリでインタラクティブな
bash
セッションを開始します。root@ac1237fad8db:/# pwd / root@ac1237fad8db:/# ls bin dev home media opt root sbin srv tmp var boot etc lib mnt proc run src sys usr
-
src
ディレクトリに移動します。これは、コンテナの起動時にマウントしたディレクトリです。このディレクトリの内容を一覧表示すると、ホストマシンの
getting-started-app
ディレクトリと同じファイルが表示されます。root@ac1237fad8db:/# cd src root@ac1237fad8db:/src# ls Dockerfile node_modules package.json spec src yarn.lock
-
myfile.txt
という名前の新しいファイルを作成します。root@ac1237fad8db:/src# touch myfile.txt root@ac1237fad8db:/src# ls Dockerfile myfile.txt node_modules package.json spec src yarn.lock
-
ホスト上の
getting-started-app
ディレクトリを開き、myfile.txt
ファイルがディレクトリ内にあることを確認します。├── getting-started-app/ │ ├── Dockerfile │ ├── myfile.txt │ ├── node_modules/ │ ├── package.json │ ├── spec/ │ ├── src/ │ └── yarn.lock
-
ホスト側から
myfile.txt
ファイルを削除します。 -
コンテナ内で、もう一度
app
ディレクトリの内容を一覧表示します。ファイルが消えたことを確認します。root@ac1237fad8db:/src# ls Dockerfile node_modules package.json spec src yarn.lock
-
Ctrl
+D
を使って、インタラクティブコンテナセッションを終了します。
以上がバインドマウントの簡単な紹介です。この手順では、ファイルがホストとコンテナ間で共有され、変更が即座に反映されることが示されました。これで、バインドマウントを使用してソフトウェアを開発できます。
開発コンテナ
バインドマウントは、ローカル開発環境で一般的に使用されます。その利点は、開発マシンにすべてのビルドツールや環境をインストールする必要がないことです。1つの docker run
コマンドで、Dockerが依存関係やツールをプルしてきます。
開発コンテナでアプリを実行する
以下の手順では、バインドマウントを使用して開発コンテナを実行し、以下を行います。
- ソースコードをコンテナにマウント
- すべての依存関係をインストール
- ファイルシステムの変更を監視する
nodemon
を起動
CLIまたはDocker Desktopを使用して、バインドマウント付きでコンテナを実行できます。
-
現在実行中の
getting-started
コンテナがないことを確認してください。 -
getting-started-app
ディレクトリから以下のコマンドを実行します。$ docker run -dp 127.0.0.1:3000:3000 \ -w /app --mount type=bind,src="$(pwd)",target=/app \ node:18-alpine \ sh -c "yarn install && yarn run dev"
コマンドの内訳は以下の通りです:
-dp 127.0.0.1:3000:3000
- 以前と同様に、デタッチモード(バックグラウンド)で実行し、ポートマッピングを作成します。-w /app
- 「作業ディレクトリ」を設定します。これは、コマンドが実行されるカレントディレクトリです。--mount type=bind,src="$(pwd)",target=/app
- カレントディレクトリをホストからコンテナの/app
ディレクトリにバインドマウントします。node:18-alpine
- 使用するイメージ。このイメージは、Dockerfileで指定されたベースイメージです。sh -c "yarn install && yarn run dev"
- コマンド。sh
を使ってシェルを起動し、yarn install
を実行してパッケージをインストールし、その後yarn run dev
を実行して開発サーバーを起動します。package.json
に記載されているdev
スクリプトはnodemon
を起動します。
-
docker logs <container-id>
を使用してログを確認できます。以下が表示されたら準備完了です。$ docker logs -f <container-id> nodemon -L src/index.js [nodemon] 2.0.20 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node src/index.js` Using sqlite database at /etc/todos/todo.db Listening on port 3000
ログの確認を終えたら、
Ctrl
+C
で終了します。
開発コンテナを使用してアプリを開発する
ホストマシンでアプリを更新し、その変更がコンテナに反映されるか確認します。
-
src/static/js/app.js
ファイルの109行目で、「Add Item」ボタンのテキストを「Add」に変更します。- {submitting ? 'Adding...' : 'Add Item'} + {submitting ? 'Adding...' : 'Add'}
ファイルを保存します。
-
ウェブブラウザでページをリフレッシュすると、バインドマウントのおかげですぐに変更が反映されます。Nodemonは変更を検知してサーバーを再起動します。Nodeサーバーの再起動には数秒かかることがあります。エラーが発生した場合は、数秒後にもう一度リフレッシュしてみてください。
-
他に変更したい箇所があれば、自由に変更してください。ファイルを保存するたびに、変更がバインドマウントのおかげでコンテナに反映されます。Nodemonは変更を検知し、コンテナ内でアプリを自動的に再起動します。すべての作業が終わったら、コンテナを停止し、以下のコマンドを使用して新しいイメージをビルドします。
$ docker build -t getting-started .
まとめ
ここまでで、データベースを永続化し、アプリ開発中にイメージを再ビルドせずに変更が即座に反映されることを確認できました。
ボリュームマウントやバインドマウントに加えて、Dockerはより複雑で専門的なユースケースを処理するための他のマウントタイプやストレージドライバーもサポートしています。
関連情報:
次のステップ
アプリを本番環境に向けて準備するためには、SQLiteからよりスケーラブルなデータベースに移行する必要があります。簡単のため、引き続きリレーショナルデータベースを使用し、アプリケーションをMySQLに切り替えます。しかし、MySQLはどのように実行すればよいのでしょうか?コンテナ間で通信する方法は?次のセクションで学びます。