イメージの構築と実行

必要条件

  • Part 1 の概要とセットアップを一通り読んでください。

Docker におけるアプリケーション構築を始めましょう。アプリケーション階層の最下部となるところから始めることにします。これがコンテナであり、このページにて取り扱います。このレベルの上位にあるのがサービスです。サービスは、アプリケーション実行中のコンテナの動きを定義します。このことは Part3 で扱います。最後に、最上位にあるのがスタックです。サービス間の対話方法を定義します。これは Part5 で扱います。

  • スタック Stack
  • サービス Services
  • コンテナ(今ここにいます)

新しい開発環境

Python アプリケーションを書き始めるにあたり、自分のマシン上に Python ランタイムをインストールするのが、これまでは一番初めの仕事でした。しかし、サーバ上でもアプリケーションが期待する通りに問題なく動作するには、マシンと同じ環境を作成しなくてはいけません。

Docker であれば、移動可能な Python ランタイムをイメージ内に収容しているため、インストールは不要です。そして、ベース Python イメージにはアプリのコードも一緒に構築できますし、アプリを確実に動かすための依存関係やランタイムも全て運べます。

移動可能なイメージは Dockerfile と呼ばれるモノで定義します。

Dockerfile でコンテナの定義

Dockerfile では、コンテナ内の環境で何をするかを定義します。ネットワーク・インターフェースとディスク・ドライバのようなリソースは、システム上の他の環境からは隔離された環境内に仮想化されています。このようなリソースに接続するには、ポートを外の世界にマッピング(割り当て)する必要がありますし、どのファイルを環境に「複製」(copy in)するか指定する必要もあります。しかしながら、これらの作業を Dockerfile における構築時の定義で済ませておけば、どこで実行しても同じ挙動となります。

はじめに

これまで開発環境のセットアップを整えましたので、コンテナ化アプリケーションの開発を始められるようになりました。一般的に、開発ワークフローとは以下のようなものです。

  1. アプリケーションの各コンポーネントに対する個々のコンテナを Docker イメージから作成し、作成およびテストします。
  2. コンテナと支える基盤(インフラ)を組み合わせ、アプリケーションを完成します。
  3. 完成したコンテナ化アプリケーションをテスト、共有、デプロイします。

このチュートリアルの段階では、ワークフローの手順1にフォーカスします。ここでは、コンテナのベースとなるイメージを作成します。Docker イメージが扱うプライベート・ファイルシステムとは、コンテナ化したプロセスを実行する場所だと忘れないでください。つまり、アプリケーションを実行するために必要な何かを含むイメージを作成する必要があります。

セットアップ

それでは node-bulletin-board プロジェクト例をダウンロードしましょう。これは Node.js で書かれたシンプルな掲示板アプリケーションです。

Git

Git を使用しているのであれば、GitHub からプロジェクト例をクローンできます。

git clone https://github.com/dockersamples/node-bulletin-board
cd node-bulletin-board/bulletin-board-app

Windows (Git 無し)

Windows マシンを使用中で、Git をインストールせずにプロジェクト例をダウンロードしたい場合は、PowerShell 上で以下のコマンドを実行します。

curl.exe -LO https://github.com/dockersamples/node-bulletin-board/archive/master.zip
tar.exe xf master.zip
cd node-bulletin-board-master\bulletin-board-app

Mac or Linux (Git 無し)

Mac あるいは Linux マシンを使用中で、Git をインストールせずにプロジェクト例をダウンロードしたい場合は、ターミナル上で以下のコマンドを実行します。

curl -LO https://github.com/dockersamples/node-bulletin-board/archive/master.zip
unzip master.zip
cd node-bulletin-board-master/bulletin-board-app

Dockerfile でコンテナを定義

プロジェクトのダウンロード後は、掲示板アプリケーション内にある Dockerfile (ドッカーファイル)と呼ぶファイルを見ます。Dockerfile にはコンテナに対するプライベート・ファイルシステムを、どのようにして構成するかの記述があります。また、このイメージをベースとして、コンテナをどのようにして実行するかといった、複数のメタデータも含められます。

掲示板アプリケーションの Dockerfile が、どのように使われているかの情報は サンプル Dockerfile をご覧ください。

イメージの構築とテスト

これでソースコードと Dockerfile を準備しましたので、初めてのイメージを構築(ビルド)する時です。そして、コンテナが期待通りに動作するかどうか確かめましょう。

ターミナルまたは PowerShell で cd コマンドを使い、 node-bulletin-board/bulletin-board-app ディレクトリに移動します。掲示板イメージを構築するためには、以下のコマンドを実行します。

docker build --tag bulletinboard:1.0 .

Docker を見ると、Dockerfile 中の命令ごとに、命令したとおりにイメージを構築しています。成功すると、 Successfully tagged bulletinboard:1.0 というメッセージを表示して構築処理が終了します。

注釈

Windows 利用者の方へ:この例は Linux コンテナを使います。環境が Linux コンテナとして動作しているのを確認するため、システムトレイ上の Docker ロゴを右クリックし、 Switch to Linux containers (Linux コンテナへ切り替え)をクリックします。心配しないでください、このチュートリアルで実行するすべてのコマンドは、Windows コンテナとしても同様に機能します。イメージの実行後、「 SECURITY WARNING’」(セキュリティ警告)のタイトルがついたメッセージを表示し、イメージに対してファイル追加時に、読み書き実行権限の設定を確認する場合があります。今回の例では、センシティブな情報(機微情報)を扱っていませんので、この警告は無視して構いません。

コンテナとしてイメージを実行

  1. 以下のコマンドを実行し、作成した新しいイメージをベースとするコンテナを起動します。
docker run --publish 8000:8080 --detach --name bb bulletinboard:1.0

ここではいくつかのフラグを指定しています。

  • --publish ホストのポート 8000 に入ってくるトラフィックを、コンテナのポート 8080 に転送するよう Docker に依頼します。コンテナは、自身で一連のプライベートなポート を持っています。そのため、ネットワーク側から到達したい場合は、この方法でトラフィックを転送する必要があります。そうしなければ、ファイアウォールのルールは、デフォルトのセキュリティ方針により、コンテナに到達する全てのネットワーク・トラフィックを拒否します。
  • --detach このコンテナをバックグラウンドで実行するよう、Docker に依頼します。
  • --name 続くコマンドで、コンテナを参照できる名前を指定します。今回の例では bb です。
  1. アプリケーションに接続するため、ブラウザで localhost:8000 で開きます。そうすると、掲示板アプリケーションが稼働しているのが見えるでしょう。この段階で、コンテナがすべて期待通りに動作しているのを確認できるでしょう。つまり、これでユニットテスト等を実行できるようになります。
  1. 掲示板コンテナが正しく動作するのに満足したら、コンテナを削除できます。
docker rm --force bb

--force オプションは、実行中のコンテナを停止させて、コンテナが削除されることを可能にします。最初にコンテナを docker stop bb で停止したら、 --force を使って削除する必要はありません。

まとめ

これまでの時点で、イメージ構築、アプリケーションをシンプルにコンテナ化して処理、コンテナ内でアプリケーションが正常に実行できることに成功しました。次のステップでは Docker Hub 上にイメージを共有します。これにより、ダウンロードが簡単になり、配布先のあらゆるマシン上で実行可能になります。

サンプル Dockerfile

Dockerfile を書くことは、アプリケーションをコンテナ化する第一のステップです。それぞれの Dockerfile 命令が、イメージをどのように構築するかの1つ1つのレシピ(手順)と考えてください。

# 親イメージとして公式イメージを使う
FROM node:current-slim

# 作業用(working)ディレクトリを指定
WORKDIR /usr/src/app

# ホスト上のファイルを現在の場所にコピー
COPY package.json .

# イメージのファイルシステム内でコマンドを実行
RUN npm install

# 実行時、コンテナが特定のポートをリッスンするよう Docker に通知
EXPOSE 8080

# コンテナ内で指定したコマンドを実行
CMD [ "npm", "start" ]

# 残りのソースコードをホスト上からイメージのファイルシステム上にコピー
COPY . .

サンプルの Dockerfile 定義は、以下の手順を踏みます。

  • FROM では既存の node:current-slim イメージで始めます。これは公式イメージ( official image )であり、node.js ベンダーによって構築され、Docker が認定した高品質なイメージであり、Node.js 長期間サポート(LTS)インタプリタと基本的な依存関係を含みます。
  • WORKDIR を使い、以降に続く処理すべてを、イメージのファイルシステムで(決してホスト上ではありません)指定したディレクトリ /usr/src/app 内で行うよう指定します。
  • COPYpackage.json をホスト上からイメージ内の現在の場所( .)にコピーします(今回の例では、 /usr/src/app/package.json にコピーします)。
  • RUN はイメージ・ファイルシステム内で npm install コマンドを実行します(これにより、 package.json を読み込み、アプリケーションの node 依存関係を解決するため、必要なものをインストールします )。
  • COPY によって、残りのアプリケーション・ソースコードをホストからイメージのファイルシステムへコピーします。

これらを見ると、ホスト上でアプリケーションをセットアップしてインストールするのと、ほぼ同じ手順であるのが分かるでしょう。しかしながら、Dockerfile でこれらを処理すると、ポータブルで隔離された Docker イメージ内で同じ事を行えます。

先ほどの手順では、私たちのイメージ上でファイルシステムを構築しました。これに続き、Dockerfile に他の命令も追加できます。

CMD 命令はイメージにメタデータ(metadata)を指定する初めての例です。この命令は、このイメージをベースに起動するコンテナが、どのように実行するかを記述します。今回の例では、 このイメージがコンテナ化したプロセスとして、 npm start をサポートするよう意図しています。

EXPOSE 8080 はコンテナ実行時にポート 8080 をリッスンするよう Docker に伝えます。

これまで見てきたように、シンプルな Dockerfile の編集は良い方法です。常に FROM 命令で始まり、以降のステップでプライベートなファイルシステムを組み上げ、メタデータの指定で締めくくります。ここで取り上げた他にも、Dockerfile には更に多くの命令があります。詳細な一覧は Dockerfile リファレンス をご覧ください。

CLI リファレンス

この記事で扱った全ての CLI コマンドに関する詳しいDockerは、こちらにあります。

  • docker image

  • docker container

  • Dockerfile リファレンス

    docker build -t friendlyname . # このディレクトリ内にある DockerFile でイメージ作成 docker run -p 4000:80 friendlyname # "friendlyname" の実行にあたり、ポート 4000 を 80 に割り当て docker run -d -p 4000:80 friendlyname # 同じですが、デタッチド・モード docker container ls # 全ての実行中コンテナを表示 docker container ls -a # 停止中も含めて全てのコンテナを表示 docker container stop <hash> # 指定したコンテナを丁寧に停止 docker container kill <hash> # 指定したコンテナを強制シャットダウン docker container rm <hash> # マシン上から指定したコンテナを削除 docker container rm $(docker container ls -a -q) # 全てのコンテナを削除 docker image ls -a # マシン上の全てのイメージを表示 docker image rm <image id> # マシン上の特定のイメージを削除 docker image rm $(docker image ls -a -q) # マシン上の全てのイメージを削除 docker login # CLI セッションで Docker の認証を行いログイン docker tag <image> username/repository:tag # レジストリにアップロードする <image> にタグ付け docker push username/repository:tag # タグ付けしたイメージを送信 docker run username/repository:tag # レジストリにあるイメージを実行

参考

Build and run your image
https://docs.docker.com/get-started/part2/