Skip to content
Dockerワークショップパート5: バインドマウントを使用する

バインドマウントを使用する

パート4 では、ボリュームマウントを使用してデータベースのデータを永続化しました。アプリケーションデータを永続的に保存する必要がある場合、ボリュームマウントは素晴らしい選択です。

バインドマウントは別の種類のマウントで、ホストのファイルシステムのディレクトリをコンテナに共有できます。アプリケーションの開発中は、バインドマウントを使ってソースコードをコンテナにマウントすることができます。ファイルを保存した瞬間に、コンテナはコードの変更を即座に認識します。これにより、ファイルシステムの変更を監視し、それに応じて動作するプロセスをコンテナ内で実行できるようになります。

この章では、バインドマウントと、ファイルの変更を監視してアプリケーションを自動的に再起動するツールである nodemon を使う方法を学びます。ほとんどの他の言語やフレームワークにも、同様のツールがあります。

ボリュームタイプの簡単な比較

以下は、--mount を使用した名前付きボリュームとバインドマウントの例です。

  • 名前付きボリューム: type=volume,src=my-volume,target=/usr/local/data
  • バインドマウント: type=bind,src=/path/to/data,target=/usr/local/data

以下の表は、ボリュームマウントとバインドマウントの主な違いを示しています。

名前付きボリュームバインドマウント
ホスト側の場所Dockerが決定ユーザーが決定
コンテナの内容で新しいボリュームを初期化可能不可
ボリュームドライバーのサポートありなし

バインドマウントを試してみる

アプリケーション開発でバインドマウントを使用する前に、簡単な実験を行い、バインドマウントの動作を実際に確認してみましょう。

  1. getting-started-app ディレクトリが、Docker Desktopのファイル共有設定に定義されたディレクトリ内にあることを確認してください。この設定は、ファイルシステムのどの部分をコンテナと共有できるかを定義します。設定へのアクセス方法については、ファイル共有を参照してください。

  2. ターミナルを開き、getting-started-app ディレクトリに移動します。

  3. 次のコマンドを実行して、バインドマウントを使用して ubuntu コンテナで bash を起動します。

    $ docker run -it --mount type=bind,src="$(pwd)",target=/src ubuntu bash

    --mount type=bind オプションは、Dockerにバインドマウントを作成するよう指示します。src はホストマシンのカレントディレクトリ(getting-started-app)、target はコンテナ内でそのディレクトリを表示する場所(/src)です。

  4. コマンドを実行すると、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
  5. src ディレクトリに移動します。

    これは、コンテナの起動時にマウントしたディレクトリです。このディレクトリの内容を一覧表示すると、ホストマシンの getting-started-app ディレクトリと同じファイルが表示されます。

    root@ac1237fad8db:/# cd src
    root@ac1237fad8db:/src# ls
    Dockerfile  node_modules  package.json  spec  src  yarn.lock
  6. myfile.txt という名前の新しいファイルを作成します。

    root@ac1237fad8db:/src# touch myfile.txt
    root@ac1237fad8db:/src# ls
    Dockerfile  myfile.txt  node_modules  package.json  spec  src  yarn.lock
  7. ホスト上の getting-started-app ディレクトリを開き、myfile.txt ファイルがディレクトリ内にあることを確認します。

    ├── getting-started-app/
    │ ├── Dockerfile
    │ ├── myfile.txt
    │ ├── node_modules/
    │ ├── package.json
    │ ├── spec/
    │ ├── src/
    │ └── yarn.lock
  8. ホスト側から myfile.txt ファイルを削除します。

  9. コンテナ内で、もう一度 app ディレクトリの内容を一覧表示します。ファイルが消えたことを確認します。

    root@ac1237fad8db:/src# ls
    Dockerfile  node_modules  package.json  spec  src  yarn.lock
  10. Ctrl + D を使って、インタラクティブコンテナセッションを終了します。

以上がバインドマウントの簡単な紹介です。この手順では、ファイルがホストとコンテナ間で共有され、変更が即座に反映されることが示されました。これで、バインドマウントを使用してソフトウェアを開発できます。

開発コンテナ

バインドマウントは、ローカル開発環境で一般的に使用されます。その利点は、開発マシンにすべてのビルドツールや環境をインストールする必要がないことです。1つの docker run コマンドで、Dockerが依存関係やツールをプルしてきます。

開発コンテナでアプリを実行する

以下の手順では、バインドマウントを使用して開発コンテナを実行し、以下を行います。

  • ソースコードをコンテナにマウント
  • すべての依存関係をインストール
  • ファイルシステムの変更を監視する nodemon を起動

CLIまたはDocker Desktopを使用して、バインドマウント付きでコンテナを実行できます。

  1. 現在実行中の getting-started コンテナがないことを確認してください。

  2. 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 を起動します。
  3. 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 で終了します。

開発コンテナを使用してアプリを開発する

ホストマシンでアプリを更新し、その変更がコンテナに反映されるか確認します。

  1. src/static/js/app.js ファイルの109行目で、「Add Item」ボタンのテキストを「Add」に変更します。

    - {submitting ? 'Adding...' : 'Add Item'}
    + {submitting ? 'Adding...' : 'Add'}

    ファイルを保存します。

  2. ウェブブラウザでページをリフレッシュすると、バインドマウントのおかげですぐに変更が反映されます。Nodemonは変更を検知してサーバーを再起動します。Nodeサーバーの再起動には数秒かかることがあります。エラーが発生した場合は、数秒後にもう一度リフレッシュしてみてください。

    Screenshot of updated label for Add button

  3. 他に変更したい箇所があれば、自由に変更してください。ファイルを保存するたびに、変更がバインドマウントのおかげでコンテナに反映されます。Nodemonは変更を検知し、コンテナ内でアプリを自動的に再起動します。すべての作業が終わったら、コンテナを停止し、以下のコマンドを使用して新しいイメージをビルドします。

    $ docker build -t getting-started .

まとめ

ここまでで、データベースを永続化し、アプリ開発中にイメージを再ビルドせずに変更が即座に反映されることを確認できました。

ボリュームマウントやバインドマウントに加えて、Dockerはより複雑で専門的なユースケースを処理するための他のマウントタイプやストレージドライバーもサポートしています。

関連情報:

次のステップ

アプリを本番環境に向けて準備するためには、SQLiteからよりスケーラブルなデータベースに移行する必要があります。簡単のため、引き続きリレーショナルデータベースを使用し、アプリケーションをMySQLに切り替えます。しかし、MySQLはどのように実行すればよいのでしょうか?コンテナ間で通信する方法は?次のセクションで学びます。