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

読む時間の目安: 3 分

前提条件

Java イメージのビルド において説明した手順をひととおり行っていること。

概要

前節においてはサンプルアプリケーションを構築し、イメージビルドに利用する Dockerfile を生成しました。 イメージのビルドにはdocker buildというコマンドを使いました。 イメージのビルドができたので、そのイメージを実行して、アプリケーションが正しく動作することを確認します。

コンテナーというものは、オペレーティングシステム内の通常のプロセスにすぎません。 ただしこのプロセスは他から隔離されていて、独自のファイルシステム、独自のネットワークを持ちます。 またホストからは引き離された独自のプロセスツリーを持ちます。

コンテナー内においてイメージを実行するにはdocker runコマンドを使います。 docker runコマンドには 1 つの引数を必要とします。 それはイメージ名です。 ここまでに作り出したイメージを使って、正しく動作することを確認します。 ターミナルから以下のコマンドを実行します。

$ docker run java-docker

このコマンドを実行しても、コマンドプロンプトの入力状態には戻りません。 この理由は、実行したアプリケーションが REST サーバーであって、入ってくる要求を待ち受けるためのループ内で実行されるからです。 つまり OS へ戻る制御はなく、戻るためにはコンテナーを停止させることになります。

さてそこで新たなターミナルを開いて、このサーバーに対してcurlコマンドを使ってGETリクエストを行ってみます。

$ curl --request GET \
--url http://localhost:8080/actuator/health \
--header 'content-type: application/json'
curl: (7) Failed to connect to localhost port 8080: Connection refused

上の curl コマンドは、サーバーへの接続が拒否されたために失敗しました。 localhost のポート 8000 には接続できなかったということです。 この動作は期待どおりであって、コンテナーはネットワークも含めて隔離された環境内で実行されているからです。 一度コンテナーを停止させて、今度はローカルネットワーク上にポート 8000 を公開した上で再起動してみます。

コンテナーを停止するにはctrl-cを入力します。 これによってターミナルのコマンドプロンプトが入力状態に戻ります。

コンテナーのポートを公開するには、docker runコマンドにおいて--publishフラグ(あるいは-pフラグ)を指定します。 --publishフラグの書式は[ホストポート]:[コンテナーポート]です。 そこでコンテナー内部のポート 8000 をコンテナー外部のポート 8080 として公開するには、--publish フラグに 8080:8000 と指定します。

コンテナーを起動させ、ポート 8080 をホスト上のポート 8080 として公開します。

$ docker run --publish 8080:8080 java-docker

そこで先ほどの curl コマンドを再度実行してみます。

$ curl --request GET \
--url http://localhost:8080/actuator/health \
--header 'content-type: application/json'
{"status":"UP"}

成功しました。 コンテナー内部で実行されているアプリケーションに対して、ポート 8080 による接続ができました。

ctrl-c を入力してコンテナーを停止します。

デタッチモード実行

ここまではうまくいきました。 もっともこのサンプルアプリケーションはウェブサーバーなので、コンテナーに接続するものではありません。 Docker ではコンテナーをデタッチモード(detached mode)、つまりバックグラウンドで実行することができます。 これを行うには--detachフラグ、あるいは短く-dフラグを指定します。 Docker は先ほどと同じようにコンテナーを起動させますが、今回はコンテナーから「デタッチされた」つまり切り離されて実行されるので、ターミナルにプロンプトが戻ってきます。

$ docker run -d -p 8080:8080 java-docker
5ff83001608c7b787dbe3885277af018aaac738864d42c4fdf5547369f6ac752

Docker はバックグラウンドでコンテナーを起動させ、ターミナル上にそのコンテナー ID を出力します。

同じようにコンテナーが適切に動作していることを確認します。 前とまったく同じ curl コマンドを実行してみます。

$ curl --request GET \
--url http://localhost:8080/actuator/health \
--header 'content-type: application/json'
{"status":"UP"}

コンテナーの一覧表示

コンテナーをバックグラウンドで実行したので、コンテナーが実行しているかどうか、他にどんなコンテナーがマシン上で動作しているかは、どうやって調べたらよいでしょう。 それはdocker psコマンドを使います。 Linux 上であれば、マシン上のプロセス一覧を確認するには ps コマンドを実行します。 同じように Docker ではdocker psを実行します。 このコマンドによって、マシン上で稼働しているコンテナーの一覧が表示されます。

$ docker ps
CONTAINER ID   IMAGE            COMMAND                  CREATED              STATUS              PORTS                    NAMES
5ff83001608c   java-docker      "./mvnw spring-boot:…"   About a minute ago   Up About a minute   0.0.0.0:8080->8080/tcp   trusting_beaver

docker psコマンドは実行中コンテナーに関して、いろいろな情報を表示します。 その情報とは以下です。 コンテナー ID、コンテナー内部で実行しているイメージ、コンテナー起動時に用いられた実行コマンド、コンテナー生成時刻、ステータス、公開ポート、コンテナー名です。

コンテナー名はどうやって決まったんだろうと不思議に思うかもしれません。 コンテナーを起動したときにはコンテナー名を指定したわけではないので、Docker がランダムに名前を生成します。 コンテナー名はこの後すぐに変更していきますが、そのためにはまずコンテナーを停止する必要があります。 コンテナーを停止するにはdocker stopコマンドを実行します。 このコマンドはそのとおりにコンテナーを停止させます。 この際にはコンテナー名あるいはコンテナー ID を指定します。

$ docker stop trusting_beaver
trusting_beaver

docker psコマンドをもう一度実行して、実行中コンテナーの一覧を確認します。

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

コンテナーの停止、起動、名前変更

Docker コンテナーは起動させ停止させ、再起動することができます。 コンテナーを停止してもコンテナーが削除されるわけではなく、ステータスが停止となり、コンテナー内のプロセスが停止します。 docker psコマンドを実行したときに、出力されるコンテナーはデフォルトでは実行中コンテナーのみです。 --allまたは-aを指定すると、システム上にあるコンテナーすべて、つまり停止、起動にかかわらずすべてが表示されます。

$ docker ps -a
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS                        PORTS                    NAMES
5ff83001608c   java-docker         "./mvnw spring-boot:…"   5 minutes ago    Exited (143) 18 seconds ago                            trusting_beaver
630f2872ddf5   java-docker         "./mvnw spring-boot:…"   11 minutes ago   Exited (1) 8 minutes ago                               modest_khayyam
a28f9d587d95   java-docker         "./mvnw spring-boot:…"   17 minutes ago   Exited (1) 11 minutes ago                              lucid_greider

ここまでのコンテナーがいくつか出力されたはずです。 このコンテナーはこれまでに起動し停止し、そのまま削除していないものです。

停止したコンテナーをここで再起動してみましょう。 停止したコンテナーの名前を確認して、restartコマンドにおけるコンテナー名を書き換えて指定してください。

$ docker restart trusting_beaver

そこで再びdocker psコマンドを使ってコンテナー一覧を確認します。

$ docker ps -a
CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS                      PORTS                    NAMES
5ff83001608c   java-docker   "./mvnw spring-boot:…"   10 minutes ago   Up 2 seconds                0.0.0.0:8080->8080/tcp   trusting_beaver
630f2872ddf5   java-docker   "./mvnw spring-boot:…"   16 minutes ago   Exited (1) 13 minutes ago                            modest_khayyam
a28f9d587d95   java-docker   "./mvnw spring-boot:…"   22 minutes ago   Exited (1) 16 minutes ago                            lucid_greider

上で再起動したコンテナーはデタッチモードで起動され、ポート 8000 が公開されています。 またコンテナーのステータスを見てみると「Up X seconds」(起動後 X 秒)となっています。 コンテナーを再起動したときには、はじめに起動したときと同じフラグ、同じコマンドによって起動されます。

ではコンテナーすべてを停止して削除します。 そしてランダムな名前になってしまう点を修正していきます。 実行中のコンテナー名を確認してください。 そして以下のコマンドにおけるコンテナー名を、確認したコンテナー名に置き換えてください。

$ docker stop trusting_beaver
trusting_beaver

こうしてコンテナーはすべて停止したので削除します。 コンテナーを削除すると、コンテナー内のプロセスはすでに停止され、コンテナーに対するメタデータも削除されています。

コンテナーを削除するには、docker rmコマンドにコンテナー名を与えて実行します。 このコマンド 1 つに対して複数のコンテナー名を指定することもできます。 同じように、以下のコマンドにおけるコンテナー名を書き換えて実行してください。

$ docker rm trusting_beaver modest_khayyam lucid_greider
trusting_beaver
modest_khayyam
lucid_greider

再度docker ps --allコマンドを実行し、コンテナーすべてが削除されていることを確認してください。

それでは、ランダムな名称になる問題を解決します。 コンテナーに名前をつける理由は単純なものです。 どんなコンテナーが実行されているのかがすぐにわかります。 またどんなアプリケーションやサービスが関連づいているのかがわかります。

コンテナー名をつけるにはdocker runコマンドに--nameフラグをつけます。

$ docker run --rm -d -p 8080:8080 --name springboot-server java-docker
2e907c68d1c98be37d2b2c2ac6b16f353c85b3757e549254de68746a94a8a8d3
$ docker ps
CONTAINER ID   IMAGE         COMMAND                  CREATED         STATUS         PORTS                    NAMES
2e907c68d1c9   java-docker   "./mvnw spring-boot:…"   8 seconds ago   Up 8 seconds   0.0.0.0:8080->8080/tcp   springboot-server

より良くなりました。 こうしてコンテナーの識別は、名前を使って簡単に行えるようになりました。

次のステップ

本節ではコンテナーの実行、ポート公開、デタッチモードでの実行を行いました。 またコンテナーの起動、停止、再起動という制御を行いました。 そしてコンテナーに名前づけを行って、識別しやすくしました。

次節ではコンテナー内においてデータベースを実行して、アプリケーションを接続する方法を示します。 以下を参照してください。

アプリケーションの開発方法

フィードバック

本トピック改善のためにフィードバックをお寄せください。 お気づきの点があれば Docker Docs の GitHub リポジトリに issue をあげてください。 あるいは PR の生成 により変更の提案を行ってください。


Java, run, image, container