チュートリアル: VS Code でボリュームを使用してコンテナー アプリにデータを保持する
このチュートリアルでは、コンテナー アプリケーションにデータを保持する方法について説明します。 それを実行または更新するとき、データを引き続き使用できます。 データの保持に使用されるボリュームには、主に 2 種類があります。 このチュートリアルでは、名前付きボリュームについて説明します。
また、ホスト上の正確なマウント ポイントを制御する バインド マウント についても説明します。 バインド マウントを使用してデータを保持できますが、それによってコンテナーにさらにデータを追加できます。 アプリケーションで作業している場合は、バインド マウントを使用してソース コードをコンテナーにマウントし、コードの変更が表示されるようにすることで、変更をすぐに確認することができます。
このチュートリアルでは、イメージ レイヤー、レイヤー キャッシュ、マルチステージ ビルドも紹介します。
このチュートリアルでは、次の作業を行う方法について説明します。
- コンテナー間のデータについて理解する。
- 名前付きボリュームを使用してデータを保持する。
- バインド マウントを使用する。
- イメージ レイヤーを表示する。
- キャッシュの依存関係。
- マルチステージ ビルドについて理解する。
必須コンポーネント
このチュートリアルは、Visual Studio Code を使った Docker アプリの作成と共有に関する前回のチュートリアルの続きです。 まずそちらから始めてください。前提条件が記載されています。
コンテナー間のデータについて理解する
このセクションでは、2 つのコンテナーを起動し、それぞれにファイルを作成します。 あるコンテナーで作成されたファイルは別のコンテナーでは使用できません。
このコマンドを使用して
ubuntu
コンテナーを起動します。docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
このコマンドにより、
&&
を使用して 2 つのコマンドを呼び出します。 最初の部分では、1 つの乱数を選択し、それを/data.txt
に書き込んでいます。 2 つ目のコマンドでは、コンテナーの実行を維持するためにファイルを監視しています。VS Code の Docker 領域で、ubuntu コンテナーを右クリックし、[Attach Shell]\(シェルのアタッチ\) を選択します。
Ubuntu コンテナーでシェルを実行しているターミナルが表示されます。
次のコマンドを実行して、
/data.txt
ファイルの内容を確認します。cat /data.txt
ターミナルには、1 から 10000 までの数値が表示されます。
コマンド ラインを使用してこの結果を表示するには、
docker ps
コマンドを使用してコンテナー ID を取得し、次のコマンドを実行します。docker exec <container-id> cat /data.txt
別の
ubuntu
コンテナーを起動します。docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
このコマンドを使用して、フォルダーの内容を確認します。
docker run -it ubuntu ls /
data.txt
ファイルはないはずです。これは、最初のコンテナーのみのスクラッチ領域に書き込まれたためです。これら 2 つの Ubuntu コンテナーを選択します。 右クリックして [削除] を選択します。 コマンド ラインからは、
docker rm -f
コマンドを使用して削除できます。
名前付きボリュームを使用して Todo データを保持する
todo アプリの既定では、そのデータが SQLite Database の /etc/todos/todo.db
に保存されます。
SQLite Database は、データを 1 つのファイルに格納するリレーショナル データベースです。
このアプローチは、小規模なプロジェクトに適しています。
ホスト上に 1 つのファイルを保持できます。 それを次のコンテナーで使用できるようにすると、アプリケーションで最後に中断した箇所を選択できます。 ボリュームを作成し、データが格納されているディレクトリにアタッチ (または マウント) することで、データを保持できます。 コンテナーによって todo.db ファイルに書き込まれると、そのデータがホストのボリューム内に保持されます。
このセクションでは、名前付きボリュームを使用します。 ディスク上のボリュームの物理的な場所が Docker で維持されます。 ボリュームの名前を参照すると、Docker によって適切なデータが提供されます。
docker volume create
コマンドを使用してボリュームを作成します。docker volume create todo-db
[コンテナー] の getting-started を選択して右クリックします。 [停止] を選択してアプリ コンテナーを停止します。
コマンド ラインからコンテナーを停止するには、
docker stop
コマンドを使用します。次のコマンドを使用して、getting-started コンテナーを起動します。
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
volume パラメーターで、マウントするボリュームと場所
/etc/todos
を指定します。ブラウザーを更新してアプリを再読み込みします。 ブラウザー ウィンドウを閉じた場合は、
http://localhost:3000/
に移動します。 Todo リストに項目をいくつか追加します。Todo アプリの getting-started コンテナーを削除します。 Docker 領域のコンテナーを右クリックし、[削除] を選択するか、
docker stop
およびdocker rm
コマンドを使用します。上記と同じコマンドを使用して、新しいコンテナーを起動します。
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
このコマンドにより、先ほどと同じドライブをマウントします。 ブラウザーを更新します。 追加した項目はまだ一覧に表示されています。
getting-started コンテナーをもう一度削除します。
以下で説明する名前付きボリュームとバインド マウントは、既定の Docker エンジン インストールでサポートされる主なボリュームの種類です。
プロパティ | 名前付きボリューム | バインド マウント |
---|---|---|
ホストの場所 | Docker で選択される | 自分で制御する |
マウントの例 (-v を使用) |
my-volume:/usr/local/data | /path/to/data:/usr/local/data |
新しいボリュームにコンテナーの内容が設定される | はい | いいえ |
ボリューム ドライバーがサポートされる | はい | いいえ |
NFS、SFTP、NetApp などをサポートするために使用できる多数のボリューム ドライバー プラグインがあります。 これらのプラグインは、Swarm や Kubernetes などのクラスター環境内の複数のホストでコンテナーを実行するために特に重要です。
Docker で 実際に データが保存される場所について疑問がある場合は、次のコマンドを実行します。
docker volume inspect todo-db
出力を確認します。このような結果になります。
[
{
"CreatedAt": "2019-09-26T02:18:36Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
"Name": "todo-db",
"Options": {},
"Scope": "local"
}
]
Mountpoint
は、データが保存される実際の場所です。
ほとんどのコンピューターでは、ホストからこのディレクトリにアクセスするにはルート アクセス権が必要です。
バインド マウントを使用する
ホスト上の正確なマウント ポイントを制御するには、バインド マウントを使用します。 このアプローチは、データを保持しますが、より多くのデータをコンテナーに提供するためによく使用されます。 バインド マウントを使用してソース コードをコンテナーにマウントし、コードの変更が表示されるようにすることで、変更をすぐに確認することができます。
開発ワークフローをサポートするためにコンテナーを実行するには、次の手順を行います。
getting-started
コンテナーを削除します。app
フォルダーで、次のコマンドを実行します。docker run -dp 3000:3000 -w /app -v ${PWD}:/app node:20-alpine sh -c "yarn install && yarn run dev"
このコマンドには、次のパラメーターが含まれています。
-dp 3000:3000
- 先ほどと同じです。 デタッチ モードで実行し、ポート マッピングを作成します。-w /app
- コンテナー内の作業ディレクトリ。-v ${PWD}:/app"
- コンテナー内のホストから現在のディレクトリを/app
ディレクトリにバインド マウントします。node:20-alpine
- 使用するイメージ。 このイメージは、Dockerfile からのアプリのベース イメージです。sh -c "yarn install && yarn run dev"
コマンド。sh
を使用してシェルを起動し、yarn install
を実行してすべての依存関係をインストールします。 その後、yarn run dev
が実行されます。package.json
を見ると、dev
スクリプトでnodemon
が開始されています。
docker logs
を使用してログを監視することができます。docker logs -f <container-id>
$ nodemon 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 キーを選択します。
VS Code で、src/static/js/app.js を開きます。 109 行目の "Add Item" というボタンのテキストを変更します。
- {submitting ? 'Adding...' : 'Add Item'} + {submitting ? 'Adding...' : 'Add'}
変更内容を保存します。
ブラウザーを更新します。 変更が反映されるはずです。
イメージ レイヤーを表示する
イメージを構成するレイヤーを確認できます。
docker image history
コマンドを実行すると、イメージ内の各レイヤーの作成に使用されたコマンドを確認できます。
docker image history
を使用して、チュートリアルでこれまでに作成した getting-started イメージ内のレイヤーを確認します。docker image history getting-started
結果は、次の出力のようになります。
IMAGE CREATED CREATED BY SIZE COMMENT a78a40cbf866 18 seconds ago /bin/sh -c #(nop) CMD ["node" "/app/src/ind… 0B f1d1808565d6 19 seconds ago /bin/sh -c yarn install --production 85.4MB a2c054d14948 36 seconds ago /bin/sh -c #(nop) COPY dir:5dc710ad87c789593… 198kB 9577ae713121 37 seconds ago /bin/sh -c #(nop) WORKDIR /app 0B b95baba1cfdb 13 days ago /bin/sh -c #(nop) CMD ["node"] 0B <missing> 13 days ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B <missing> 13 days ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B <missing> 13 days ago /bin/sh -c apk add --no-cache --virtual .bui… 5.35MB <missing> 13 days ago /bin/sh -c #(nop) ENV YARN_VERSION=1.21.1 0B <missing> 13 days ago /bin/sh -c addgroup -g 1000 node && addu… 74.3MB <missing> 13 days ago /bin/sh -c #(nop) ENV NODE_VERSION=12.14.1 0B <missing> 13 days ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B <missing> 13 days ago /bin/sh -c #(nop) ADD file:e69d441d729412d24… 5.59MB
各行は、イメージ内のレイヤーを表します。 出力には、一番新しいレイヤーが一番上に表示され、一番下にあるのがベースです。 この情報を使用すると、各レイヤーのサイズを確認できるため、大きなイメージの診断に役立ちます。
複数の行が切り捨てられて表示されます。
--no-trunc
パラメーターを追加すると、完全な出力が得られます。docker image history --no-trunc getting-started
キャッシュの依存関係
レイヤーが変更されたら、すべてのダウンストリーム レイヤーも再作成する必要があります。 もう一度 Dockerfile を次に示します。
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "/app/src/index.js"]
Dockerfile 内の各コマンドが、イメージ内の新しいレイヤーになります。
レイヤーの数を最小限に抑えるために、依存関係のキャッシュをサポートするために Dockerfile を再構築できます。
ノードベースのアプリケーションの場合、これらの依存関係は package.json
ファイルで定義されます。
アプローチとして、最初にそのファイルのみをコピーし、依存関係をインストールして、"その後に" それ以外のすべてをコピーします。
このプロセスでは、package.json
に変更があった場合にのみ、yarn の依存関係を再作成します。
Dockerfile を更新して最初に
package.json
をコピーし、依存関係をインストールしてから、他のすべてのものをコピーします。 新しいファイルを次に示します。FROM node:20-alpine WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install --production COPY . . CMD ["node", "/app/src/index.js"]
docker build
を使用して新しいイメージを作成します。docker build -t getting-started .
次の結果のような出力が表示されます。
Sending build context to Docker daemon 219.1kB Step 1/6 : FROM node:12-alpine ---> b0dc3a5e5e9e Step 2/6 : WORKDIR /app ---> Using cache ---> 9577ae713121 Step 3/6 : COPY package* yarn.lock ./ ---> bd5306f49fc8 Step 4/6 : RUN yarn install --production ---> Running in d53a06c9e4c2 yarn install v1.17.3 [1/4] Resolving packages... [2/4] Fetching packages... info fsevents@1.2.9: The platform "linux" is incompatible with this module. info "fsevents@1.2.9" is an optional dependency and failed compatibility check. Excluding it from installation. [3/4] Linking dependencies... [4/4] Building fresh packages... Done in 10.89s. Removing intermediate container d53a06c9e4c2 ---> 4e68fbc2d704 Step 5/6 : COPY . . ---> a239a11f68d8 Step 6/6 : CMD ["node", "/app/src/index.js"] ---> Running in 49999f68df8f Removing intermediate container 49999f68df8f ---> e709c03bc597 Successfully built e709c03bc597 Successfully tagged getting-started:latest
すべてのレイヤーがリビルドされました。 Dockerfile を変更したため、これは予想された結果です。
src/static/index.html に変更を加えます。 たとえば、タイトルを "The Awesome Todo App" に変更します。
docker build
を再度使用して Docker イメージをビルドします。 今回の出力は少し異なります。Sending build context to Docker daemon 219.1kB Step 1/6 : FROM node:12-alpine ---> b0dc3a5e5e9e Step 2/6 : WORKDIR /app ---> Using cache ---> 9577ae713121 Step 3/6 : COPY package* yarn.lock ./ ---> Using cache ---> bd5306f49fc8 Step 4/6 : RUN yarn install --production ---> Using cache ---> 4e68fbc2d704 Step 5/6 : COPY . . ---> cccde25a3d9a Step 6/6 : CMD ["node", "/app/src/index.js"] ---> Running in 2be75662c150 Removing intermediate container 2be75662c150 ---> 458e5c6f080c Successfully built 458e5c6f080c Successfully tagged getting-started:latest
ビルド キャッシュを使用しているため、はるかに高速になっているはずです。
マルチステージ ビルド
マルチステージ ビルドは、複数のステージを使用してイメージを作成するのに役立つ非常に強力なツールです。 これにはいくつかの利点があります。
- ビルド時間の依存関係とランタイムの依存関係が区別される
- アプリで実行する必要のあるもののみを出荷することで全体のイメージ サイズを縮小する
このセクションでは、簡単な例を示します。
Maven/Tomcat の例
Java ベースのアプリケーションをビルドする際は、ソース コードを Java バイトコードにコンパイルするために JDK が必要です。 その JDK は運用環境では必要ありません。 アプリのビルドに役立つ Maven や Gradle のようなツールを使用しているかもしれません。 それらのツールも最終イメージでは必要ありません。
FROM maven AS build
WORKDIR /app
COPY . .
RUN mvn package
FROM tomcat
COPY --from=build /app/target/file.war /usr/local/tomcat/webapps
この例では、build
という 1 つのステージを使用して、Maven を使用した実際の Java ビルドを実行しています。
"FROM tomcat" から始まる 2 番目のステージでは、build
ステージからのファイルをコピーします。
最終イメージは作成される最後のステージにすぎず、--target
パラメーターを使用してオーバーライドできます。
React の例
React アプリケーションをビルドしている場合は、JavaScript コード、SASS スタイルシートなどを静的な HTML、JavaScript、CSS にコンパイルするために Node 環境が必要です。 サーバー側レンダリングを行っていない場合は、運用ビルド用の Node 環境も必要ありません。
FROM node:20-alpine AS build
WORKDIR /app
COPY package* yarn.lock ./
RUN yarn install
COPY public ./public
COPY src ./src
RUN yarn run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
この例では、node:20
イメージを使用してビルドを実行します。これにより、レイヤー キャッシュが最大化され、その後に出力が nginx コンテナーにコピーされます。
リソースをクリーンアップする
この一連のチュートリアルを続行するには、これまでに行ったすべてのことを保持します。
次の手順
コンテナー アプリのデータを保持するオプションについて学習しました。
次に行いたいこと
Docker Compose を使用して複数のコンテナーを使用する:
Azure Container Apps にデプロイする:
Azure App Service に配置する
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示