次の方法で共有


チュートリアル: VS Code でボリュームを使用してコンテナー アプリにデータを保持する

このチュートリアルでは、コンテナー アプリケーションにデータを保持する方法について説明します。 実行または更新しても、データは引き続き使用できます。 データを保持するために使用されるボリュームには、主に 2 つの種類があります。 このチュートリアルでは、名前付きボリュームについて説明します。

また、バインド マウント について学習します。これは、ホスト上の正確なマウントポイントを制御します。 バインド マウントを使用してデータを保持できますが、コンテナーにさらにデータを追加することもできます。 アプリケーションで作業する場合は、バインド マウントを使用してソース コードをコンテナーにマウントし、コードの変更を確認したり、応答したり、変更をすぐに確認したりすることができます。

このチュートリアルでは、イメージレイヤー、レイヤーキャッシュ、マルチステージビルドも紹介します。

このチュートリアルでは、次の方法について説明します。

  • コンテナー間のデータを理解する。
  • 名前付きボリュームを使用してデータを保持します。
  • バインド マウントを使用する。
  • イメージ レイヤーを表示します。
  • キャッシュの依存関係。
  • マルチステージ ビルドについて理解する。

前提 条件

このチュートリアルでは、前のチュートリアル「 Visual Studio Code でコンテナー アプリを作成して共有する」を続けます。 前提条件を含む、その 1 つから始めます。

コンテナー間のデータを理解する

このセクションでは、2 つのコンテナーを開始し、それぞれにファイルを作成します。 あるコンテナーで作成されたファイルは、別のコンテナーでは使用できません。

  1. 次のコマンドを使用して、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 番目のコマンドは、コンテナーを実行し続けるためにファイルを監視しています。

  2. VS Code のコンテナー エクスプローラーで、ubuntu コンテナーを右クリックし、[ Attach Shell]\(シェルのアタッチ\) を選択します。

    スクリーンショットは、コンテナーが選択されたコンテナー ツール拡張機能と、アタッチ シェルが選択されたコンテキスト メニューを示しています。

    Ubuntu コンテナーでシェルを実行しているターミナルが開きます。

  3. 次のコマンドを実行して、/data.txt ファイルの内容を確認します。

    cat /data.txt
    

    ターミナルには、1 から 10000 までの数値が表示されます。

    コマンド ラインを使用してこの結果を表示するには、docker ps コマンドを使用してコンテナー ID を取得し、次のコマンドを実行します。

    docker exec <container-id> cat /data.txt
    
  4. 別の ubuntu コンテナーを起動します。

    docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
    
  5. このコマンドを使用して、フォルダーの内容を確認します。

    docker run -it ubuntu ls /
    

    最初のコンテナーのみのスクラッチ領域に書き込まれたため、そこに data.txt ファイルは存在しません。

  6. これら 2 つの Ubuntu コンテナーを選択します。 右クリックし、[削除] 選択します。 コマンド ラインから、docker rm -f コマンドを使用して削除できます。

名前付きボリュームを使用して todo データを保持する

既定では、todo アプリはデータを /etc/todos/todo.db に格納します。 SQLite データベースは、データを 1 つのファイルに格納するリレーショナル データベースです。 このアプローチは、小規模なプロジェクトに対して機能します。

ホスト上に 1 つのファイルを保持できます。 次のコンテナーで使用できるようにすると、アプリケーションは中断した場所から再開できます。 ボリュームを作成してアタッチするか、マウントして、データが格納されているフォルダーに接続することで、データを保持できます。 コンテナーは todo.db ファイルに書き込み、そのデータはボリューム内のホストに保持されます。

このセクションでは、という名前のボリュームを使用します。 Docker は、ディスク上のボリュームの物理的な場所を維持します。 ボリュームの名前を参照すると、Docker によって適切なデータが提供されます。

  1. docker volume create コマンドを使用してボリュームを作成します。

    docker volume create todo-db
    
  2. [コンテナー] で、getting-started を選んで右クリックします。 [停止] を選択して、アプリ コンテナーを停止します。

    コマンド ラインからコンテナーを停止するには、docker stop コマンドを使用します。

  3. 次のコマンドを使用して、getting-started コンテナーを開始します。

    docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
    

    ボリューム パラメーターは、マウントするボリュームと場所 /etc/todosを指定します。

  4. ブラウザーを更新してアプリを再読み込みします。 ブラウザー ウィンドウを閉じた場合は、http://localhost:3000/に移動します。 todo リストにいくつかの項目を追加します。

    スクリーンショットは、いくつかの項目がリストに追加されたサンプル アプリを示しています。

  5. todo アプリの 入門 コンテナを削除します。 コンテナー エクスプローラーでコンテナーを右クリックし、[ 削除 ] を選択するか、 docker stop コマンドと docker rm コマンドを使用します。

  6. 同じコマンドを使用して新しいコンテナーを開始します。

    docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
    

    このコマンドは、以前と同じドライブをマウントします。 ブラウザーを更新します。 追加した項目は引き続き一覧に表示されます。

  7. 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 は、データが格納される実際の場所です。 ほとんどのコンピューターでは、ホストからこのディレクトリにアクセスするにはルート アクセスが必要です。

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

バインド マウント では、ホスト上の正確なマウント ポイントを制御します。 この方法ではデータが保持されますが、多くの場合、より多くのデータをコンテナーに提供するために使用されます。 バインド マウントを使用すると、ソース コードをコンテナーにマウントして、コードの変更を確認したり、応答したり、変更をすぐに確認したりすることができます。

開発ワークフローをサポートするためにコンテナーを実行するには、次の手順を実行します。

  1. getting-started コンテナーを削除します。

  2. app フォルダーで、次のコマンドを実行します。

    docker run -dp 3000:3000 -w /app -v ${PWD}:/app node:lts-alpine sh -c "yarn install && yarn run dev"
    

    このコマンドには、次のパラメーターが含まれています。

    • -dp 3000:3000 以前と同じです。 デタッチ モードで実行し、ポート マッピングを作成します。
    • コンテナー内の作業ディレクトリ -w /app
    • -v ${PWD}:/app" バインドは、コンテナー内のホストから /app ディレクトリに現在のディレクトリをマウントします。
    • node:lts-alpine 使用するイメージ。 このイメージは、Dockerfileからのアプリの基本イメージです。
    • sh -c "yarn install && yarn run dev" はコマンドです。 sh を使用してシェルを起動し、yarn install 実行してすべての依存関係をインストールします。 次に、yarn run dev実行されます。 package.json を見ると、dev スクリプトで nodemon が開始されています。
  3. 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 +選択します。

  4. VS Code で、src/static/js/app.jsを開きます。 109 行目の [項目の追加] ボタンのテキストを変更します。

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

    変更を保存します。

  5. ブラウザーを更新します。 変更が表示されます。

    スクリーンショットは、ボタンに新しいテキストが表示されたサンプル アプリを示しています。

  6. node:lts-alpine コンテナーを削除します。

  7. app フォルダーで、次のコマンドを実行して、前の手順で作成したnode_modules フォルダーを削除します。

    rm -r node_modules
    

イメージ レイヤーを表示する

画像を構成するレイヤーを確認できます。 docker image history コマンドを実行して、イメージ内の各レイヤーの作成に使用されたコマンドを確認します。

  1. docker image history を使用して、チュートリアルで以前に作成した 入門 イメージのレイヤーを確認します。

    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   
    

    各線は、画像内のレイヤーを表します。 出力は、基礎が下にあり、最新のレイヤーが上にあることを示しています。 この情報を使用すると、各レイヤーのサイズを確認でき、大きな画像の診断に役立ちます。

  2. いくつかの行が切り捨てられます。 --no-trunc パラメーターを追加すると、完全な出力が得られます。

    docker image history --no-trunc getting-started
    

キャッシュの依存関係

レイヤーが変更されたら、すべてのダウンストリーム レイヤーも再作成する必要があります。 こちらが再度、Dockerfile です。

FROM node:lts-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "/app/src/index.js"]

Dockerfile 内の各コマンドは、イメージ内の新しいレイヤーになります。 レイヤーの数を最小限に抑えるために、依存関係のキャッシュをサポートするために、Dockerfile を再構築できます。 ノード ベースのアプリケーションの場合、これらの依存関係は package.json ファイルで定義されます。

この方法では、最初にそのファイルのみをコピーし、依存関係をインストールしてから、他のすべてをコピー します。 プロセスは、package.jsonに変更があった場合にのみ、yarn の依存関係を再作成します。

  1. Dockerfile を更新して、最初に package.json にコピーし、依存関係をインストールしてから、他のすべてをコピーします。 新しいファイルを次に示します。

    FROM node:lts-alpine
    WORKDIR /app
    COPY package.json yarn.lock ./
    RUN yarn install --production
    COPY . .
    CMD ["node", "/app/src/index.js"]
    
  2. docker buildを使用して新しいイメージをビルドします。

    docker build -t getting-started .
    

    次のような出力が表示されます。

    Sending build context to Docker daemon  219.1kB
    Step 1/6 : FROM node:lts-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を変更したため、この結果が予想されます。

  3. src/static/index.htmlに変更を加えます。 たとえば、タイトルを 「The Awesome Todo App」と表示するように変更します。

  4. docker build をもう一度使用して Docker イメージをビルドします。 今回は、出力が少し異なって見えるはずです。

    Sending build context to Docker daemon  219.1kB
    Step 1/6 : FROM node:lts-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 

この例では、1 つのステージ (build) を使用して、Maven を使用して実際の Java ビルドを実行します。 2 番目のステージは "FROM tomcat" から始まり、build ステージからファイルをコピーします。 最終的なイメージは、作成される最後のステージのみです。このステージは、--target パラメーターを使用してオーバーライドできます。

React の例

React アプリケーションをビルドするときは、JavaScript コード、Sass スタイルシートなどを静的 HTML、JavaScript、CSS にコンパイルするための Node 環境が必要です。 サーバー側のレンダリングを行っていない場合は、実稼働ビルド用の Node 環境も必要ありません。

FROM node:lts-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:lts-alpine イメージを使用してビルドを実行し、レイヤー のキャッシュを最大化し、出力を nginx コンテナーにコピーします。

リソースのクリーンアップ

この一連のチュートリアルを続けるには、これまでに行ったことをすべて保持してください。

次の手順

コンテナー アプリのデータを保持するオプションについて学習しました。

次に何をしたいですか?