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

事前準備

自分の Node イメージを構築 で、 Node JS イメージ構築手順を実行します。

概要

前章ではサンプルアプリケーションを作成し、イメージ作成に使うための Dockerfile を作成しました。そして docker build コマンドを使い、イメージを作成しました。次は、イメージを準備できましたので、アプリケーションを正しく実行できるかどうか確認するため、このイメージを実行します。

コンテナでは、通常のオペレーティングシステムの手順を除外しています。このコンテナのプロセスは隔離されており、独自のファイルシステムを持ち、独自のネットワーク機能を持ち、ホストから分離されている独自のプロセスツリーも持ちます。

コンテナ内でイメージを実行するには、 docker run コマンドを使います。 docker run コマンドには1つのパラメータが必要であり、それはイメージ名です。これまで作成したイメージ使い、正しく起動できるかどうかを確認しましょう。ターミナル内で以下のコマンドを実行します。

$ docker run node-docker

このコマンドを実行すると、コマンドプロンプトには何も応答がないのが分かるでしょう。これは、アプリケーションが REST サーバであり、リクエスト要求を受け付けるためのループを実行中のため、 OS がコンテナを停止するまで制御は戻りません。

新しいターミナルを開き、 curl コマンドを使って GET リクエストを作成しましょう。

$ curl --request POST \
  --url http://localhost:8000/test \
  --header 'content-type: application/json' \
  --data '{"msg": "testing"}'
curl: (7) Failed to connect to localhost port 8000: Connection refused

curl コマンドが失敗したのは、サーバへの接続が拒否されたからです。つまり、ローカルホストのポート 8000 へ接続できません。これは、ネットワークを隔離した状態でコンテナを実行しているからです。コンテナを停止し、ローカルネットワーク上でポート 8000 を公開して再起動しましょう。

コンテナを停止するには、 ctrl-c を押します。これでターミナルにプロンプトが戻ります。

コンテナのポートを公開するには、docker run コマンドで --publish フラグ(短縮形は -p ) を使います。 --publish 命令は [host port]:[container port] 形式です。そのため、コンテナ外のポート 3000 に コンテナ内のポート 8000 を公開するには、 --publish フラグに 3000:8000 を渡します。

コンテナを起動し、ホスト上のポート 8000 にポート 8000 を公開します。

$ docker run --publish 8000:8000 node-docker

これで先ほどの curl コマンドは応答を返すでしょう。新しく開いたターミナルに戻ります。

$ curl --request POST \
  --url http://localhost:8000/test \
  --header 'content-type: application/json' \
  --data '{"msg": "testing"}'
{"code":"success","payload":[{"msg":"testing","id":"dc0e2c2b-793d-433c-8645-b3a553ea26de","createDate":"2020-09-01T17:36:09.897Z"}]}

成功です! コンテナ内で実行しているアプリケーションにポート 8000 で接続できました。コンテナを実行しているターミナルに切り替えると、コンソールに POST リクエストのログが表示されるでしょう。

2020-09-01T17:36:09:8770 INFO: POST /test

ctrl-c を押してコンテナを停止します。

デタッチドモードで実行

サンプルアプリケーションは今のところ順調ですが、これはウェブサーバであり、ターミナルをコンテナに接続しておく必要はありません。Docker はアプリケーションを デタッチド モード(detouched mode) やバックグラウンドとして実行できます。そのためには、 --detach か短縮形の -d を使います。 Docker はこれまでと同じように実行しますが、今回はコンテナから「 離れ(detachb)」、ターミナルに戻るようにします。

$ docker run -d -p 8000:8000 node-docker
ce02b3179f0f10085db9edfccd731101868f58631bdf918ca490ff6fd223a93b

Docker はバックグラウンドでコンテナを起動し、ターミナル上にはコンテナ ID を表示します。

再び、コンテナが正しく動作するか確認しましょう。先ほどと同じ curl コマンドを実行します。

$ curl --request POST \
  --url http://localhost:8000/test \
  --header 'content-type: application/json' \
  --data '{"msg": "testing"}'
{"code":"success","payload":[{"msg":"testing","id":"dc0e2c2b-793d-433c-8645-b3a553ea26de","createDate":"2020-09-01T17:36:09.897Z"}]}

コンテナ一覧

コンテナはバックグラウンドで実行していますので、コンテナが実行中かどうかを知るには、あるいは、マシン上で何のコンテナが実行中かを知るにはどうしたらよいでしょうか。そうですね、 docker ps コマンドを実行できます。Linux でマシン上のプロセス一覧を表示するには、 ps コマンドを実行します。同様に、マシン上で実行しているコンテナを一覧表示するには docker ps コマンドを実行できます。

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
ce02b3179f0f        node-docker         "docker-entrypoint.s…"   6 minutes ago       Up 6 minutes        0.0.0.0:8000->8000/tcp   wonderful_kalam

ps コマンドは実行中コンテナの一群を表示します。コンテナ ID 、コンテナ内で実行しているイメージ、コンテナ起動時に使うコマンド、作成時、状態、ポートと公開ポート、コンテナ名の表示が見えます。

おそらく、コンテナに割り当てられている名前を不思議に思うでしょう。コンテナ起動時に名前を指定しませんでしたが、Docker がランダムな名前を生成しました。この名前は変更できますが、まずはコンテナの停止が必要です。コンテナを停止するには、 docker stop コマンドを実行してコンテナを停止します。コマンドにはコンテナ名かコンテナ ID を渡す必要があります。

$ docker stop wonderful_kalam
wonderful_kalam

実行中のコンテナ一覧を表示するため、 docker ps コマンドに戻ります。

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

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

Docker コンテナは起動、停止、再起動できます。コンテナを停止しても削除はされず、状態は停止済み(stopped)となり、コンテナ内のプロセスは停止します。 docker ps コマンドを実行すると、デフォルトの出力は実行中のコンテナのみです。 --all か短縮形の -a を渡すと、システム上で停止中か起動しているかにかかわらず、全てのコンテナを表示します。

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
ce02b3179f0f        node-docker         "docker-entrypoint.s…"   16 minutes ago      Exited (0) 5 minutes ago                        wonderful_kalam
ec45285c456d        node-docker         "docker-entrypoint.s…"   28 minutes ago      Exited (0) 20 minutes ago                       agitated_moser
fb7a41809e5d        node-docker         "docker-entrypoint.s…"   37 minutes ago      Exited (0) 36 minutes ago                       goofy_khayyam

先ほどとは違い、複数のコンテナが表示されました。これらのコンテナは起動中か、停止中ですが削除はされていなかったものです。

停止しているコンテナを再起動しましょう。先ほど停止したコンテナの名前を探し、次の再起動コマンドのコンテナ名の部分を置き換えてください。

$ docker restart wonderful_kalam

それから、再び ps コマンドを使ってコンテナを一覧表示します。

$ docker ps --all
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                    NAMES
ce02b3179f0f        node-docker         "docker-entrypoint.s…"   19 minutes ago      Up 8 seconds                0.0.0.0:8000->8000/tcp   wonderful_kalam
ec45285c456d        node-docker         "docker-entrypoint.s…"   31 minutes ago      Exited (0) 23 minutes ago                            agitated_moser
fb7a41809e5d        node-docker         "docker-entrypoint.s…"   40 minutes ago      Exited (0) 39 minutes ago                            goofy_khayyam

再起動したコンテナの状態はデタッチドモードで起動済みとなり、ポート 8000 を公開しています。また、コンテナの状態を見てみると「Up X seconds」(起動 X 秒)となっています。コンテナを再起動する場合、元元のコンテナを起動したときと同じフラグやコマンドで起動します。

コンテナをすべて停止して削除するには、ランダムな名前を調べる必要があります。

起動したコンテナを停止します。実行中のコンテナ名を調べ、以下のコマンドにあるコンテナ名を、自分のシステム上にあるコンテナの名前に置き換えます。

$ docker stop wonderful_kalam
wonderful_kalam

これで全てのコンテナが停止しましたので、これらを削除しましょう。コンテナを削除すると、二度と起動できないだけでなく、停止中の状態としても表示されません。コンテナ内のプロセスが停止されているだけなく、コンテナのメタデータも削除されています。

$ docker ps --all
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                    NAMES
ce02b3179f0f        node-docker         "docker-entrypoint.s…"   19 minutes ago      Up 8 seconds                0.0.0.0:8000->8000/tcp   wonderful_kalam
ec45285c456d        node-docker         "docker-entrypoint.s…"   31 minutes ago      Exited (0) 23 minutes ago                            agitated_moser
fb7a41809e5d        node-docker         "docker-entrypoint.s…"   40 minutes ago      Exited (0) 39 minutes ago                            goofy_khayyam

コンテナを削除するには、シンプルに docker rm コマンドへコンテナ名を渡すだけです。1つのコマンド内で、複数のコンテナ名を渡せます。

もう一度、以下のコマンドにあるコンテナ名を自分のシステム上のものへと置き換えて、コマンドを実行します。

$ docker rm wonderful_kalam agitated_moser goofy_khayyam
wonderful_kalam
agitated_moser
goofy_khayyam

docker ps --all コマンドを実行し、全てのコンテナが消えたのを確認します。

次は厄介なランダムな名前の問題を解決しましょう。標準的な解決策としては、シンプルな理由からコンテナに対して名前を付けます。そうすると、どのようなコンテナを実行しているかや、何のアプリケーションやサービスが関連付けられているかが分かりやすくなるためです。コード内の変数に分かりやすい名前を付けるのと同じように、コンテナに名前を付けて分かりやすくします。

コンテナに名前を付けるには、 run コマンドに --name フラグを付けます。

$ docker run -d -p 8000:8000 --name rest-server node-docker
1aa5d46418a68705c81782a58456a4ccdb56a309cb5e6bd399478d01eaa5cdda
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
1aa5d46418a6        node-docker         "docker-entrypoint.s…"   3 seconds ago       Up 3 seconds        0.0.0.0:8000->8000/tcp   rest-server

これで名前に基づいてコンテナを簡単に区別できます。

次のステップ

この章では、コンテナの実行、ポートの公開、デタッチドモードでのコンテナ実行について説明しました。また、コンテナを管理するために起動、停止、再起動の方法を設営しました。ほかにも、コンテナを簡単に識別できるよう、コンテナに対して名前を付ける方法を説明しました。次の章では、コンテナ内でデータベースを実行する方法と、アプリケーションに接続する方法を説明します。

フィードバック

フィードバックを通し、このトピックの改善を支援ください。考えがあれば、 Docker Docs GitHub リポジトリに issue を作成して教えてください。あるいは、更新の提案のために RP を作成 してください。

参考

Run your image as a container

https://docs.docker.com/language/nodejs/run-containers/