コンテナーとしてのイメージ実行
読む時間の目安: 3 分
前提条件
Go 言語イメージのビルド において説明した手順をひととおり行っていること。
概要
前節においてはサンプルアプリケーションに対するDockerfile
を生成して、docker build
コマンドによって Docker イメージを生成しました。
イメージのビルドができたので、そのイメージを実行して、アプリケーションが正しく動作することを確認します。
コンテナーというものは、オペレーティングシステム内の通常のプロセスにすぎません。 ただしこのプロセスは他から隔離されていて、独自のファイルシステム、独自のネットワークを持ちます。 またホストからは引き離された独自のプロセスツリーを持ちます。
コンテナー内においてイメージを実行するにはdocker run
コマンドを使います。
このコマンドは 1 つの引数を必要とします。
それはイメージ名です。
ここまでに作り出したイメージを使って、正しく動作することを確認します。
ターミナルから以下のコマンドを実行します。
$ docker run docker-gs-ping
____ __
/ __/___/ / ___
/ _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.2.2
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
O\
⇨ http server started on [::]:8080
このコマンドを実行しても、コマンドプロンプトの入力状態には戻りません。 この理由は、実行したアプリケーションが REST サーバーであって、入ってくる要求を待ち受けるためのループ内で実行されるからです。 つまり OS へ戻る制御はなく、戻るためにはコンテナーを停止させることになります。
さてそこで、このサーバーに対してcurl
コマンドを使ってGET
リクエストを行ってみます。
$ curl http://localhost:8080/
curl: (7) Failed to connect to localhost port 8080: Connection refused
上の curl コマンドは、サーバーへの接続が拒否されたために失敗しました。 localhost のポート 8080 には接続できなかったということです。 この動作は期待どおりであって、コンテナーはネットワークも含めて隔離された環境内で実行されているからです。 一度コンテナーを停止させて、今度はローカルネットワーク上にポート 8080 を公開した上で再起動してみます。
コンテナーを停止するには ctrl-c を入力します。 これによってターミナルのコマンドプロンプトが入力状態に戻ります。
コンテナーのポートを公開するには、docker run コマンドにおいて--publish
フラグ(あるいは-p
フラグ)を指定します。
--publish
フラグの書式は[ホストポート]:[コンテナーポート]
です。
そこでコンテナー内部のポート8080
をコンテナー外部のポート3000
として公開するには、--publish
フラグに3000:8080
と指定します。
コンテナーを起動させ、ポート8080
をホスト上のポート8080
として公開します。
$ docker run --publish 8080:8080 docker-gs-ping
そこで先ほどの curl コマンドを再度実行してみます。
$ curl http://localhost:8080/
Hello, Docker! <3
成功しました。
コンテナー内部で実行されているアプリケーションに対して、ポート 8000 による接続ができました。
コンテナーを実行させたターミナルに戻ってみると、コンソール上にGET
リクエストのログが出力されているはずです。
ctrl-c を入力してコンテナーを停止します。
デタッチモード実行
ここまではうまくいきました。
もっともこのサンプルアプリケーションはウェブサーバーなので、ターミナルからコンテナーに接続するものではありません。
Docker ではコンテナーをデタッチモード(detached mode)、つまりバックグラウンドで実行することができます。
これを行うには--detach
フラグ、あるいは短く-d
フラグを指定します。
Docker は先ほどと同じようにコンテナーを起動させますが、今回はコンテナーから「デタッチされた」つまり切り離されて実行されるので、ターミナルにプロンプトが戻ってきます。
$ docker run -d -p 8080:8080 docker-gs-ping
d75e61fcad1e0c0eca69a3f767be6ba28a66625ce4dc42201a8a323e8313c14e
Docker はバックグラウンドでコンテナーを起動させ、ターミナル上にそのコンテナー ID を出力します。
同じようにコンテナーが適切に動作していることを確認します。
前とまったく同じcurl
コマンドを実行してみます。
$ curl http://localhost:8080/
Hello, Docker! <3
コンテナーの一覧表示
コンテナーをバックグラウンドで実行したので、コンテナーが実行しているかどうか、他にどんなコンテナーがマシン上で動作しているかは、どうやって調べたらよいでしょう。
それはdocker ps
コマンドを使います。
Linux 上であれば、マシン上のプロセス一覧を確認するにはps
コマンドを実行します。
同じように Docker ではdocker ps
を実行します。
このコマンドによって、マシン上で稼働しているコンテナーの一覧が表示されます。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d75e61fcad1e docker-gs-ping "/docker-gs-ping" 41 seconds ago Up 40 seconds 0.0.0.0:8080->8080/tcp inspiring_ishizaka
ps
コマンドは実行中コンテナーに関して、いろいろな情報を表示します。
その情報とは以下です。
コンテナー ID、コンテナー内部で実行しているイメージ、コンテナー起動時に用いられた実行コマンド、コンテナー生成時刻、ステータス、公開ポート、コンテナー名です。
コンテナー名はどうやって決まったんだろうと不思議に思うかもしれません。
コンテナーを起動したときにはコンテナー名を指定したわけではないので、Docker がランダムに名前を生成します。
コンテナー名はこの後すぐに変更していきますが、そのためにはまずコンテナーを停止する必要があります。
コンテナーを停止するにはdocker stop
コマンドを実行します。
このコマンドはそのとおりにコンテナーを停止させます。
この際にはコンテナー名あるいはコンテナー ID を指定します。
$ docker stop inspiring_ishizaka
inspiring_ishizaka
docker ps
コマンドをもう一度実行して、実行中コンテナーの一覧を確認します。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
コンテナーの停止、起動、名前変更
Docker コンテナーは起動させ停止させ、再起動することができます。
コンテナーを停止してもコンテナーが削除されるわけではなく、ステータスが停止となり、コンテナー内のプロセスが停止します。
docker ps
コマンドを実行したときに、出力されるコンテナーはデフォルトでは実行中コンテナーのみです。
--all
または-a
を指定すると、システム上にあるコンテナーすべて、つまり停止、起動にかかわらずすべてが表示されます。
$ docker ps -all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d75e61fcad1e docker-gs-ping "/docker-gs-ping" About a minute ago Exited (2) 23 seconds ago inspiring_ishizaka
f65dbbb9a548 docker-gs-ping "/docker-gs-ping" 3 minutes ago Exited (2) 2 minutes ago wizardly_joliot
aade1bf3d330 docker-gs-ping "/docker-gs-ping" 3 minutes ago Exited (2) 3 minutes ago magical_carson
52d5ce3c15f0 docker-gs-ping "/docker-gs-ping" 9 minutes ago Exited (2) 3 minutes ago gifted_mestorf
ここまでの手順に沿って作業をしていれば、コンテナーがいくつか出力されたはずです。 このコンテナーはこれまでに起動し停止し、そのまま削除していないものです。
停止したコンテナーをここで再起動してみましょう。 停止したコンテナーの名前を確認して、再起動を行う以下のコマンドにおけるコンテナー名を書き換えて指定してください。
$ docker restart inspiring_ishizaka
そこで再びps
コマンドを使ってコンテナー一覧を確認します。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d75e61fcad1e docker-gs-ping "/docker-gs-ping" 2 minutes ago Up 5 seconds 0.0.0.0:8080->8080/tcp inspiring_ishizaka
f65dbbb9a548 docker-gs-ping "/docker-gs-ping" 4 minutes ago Exited (2) 2 minutes ago wizardly_joliot
aade1bf3d330 docker-gs-ping "/docker-gs-ping" 4 minutes ago Exited (2) 4 minutes ago magical_carson
52d5ce3c15f0 docker-gs-ping "/docker-gs-ping" 10 minutes ago Exited (2) 4 minutes ago gifted_mestorf
上で再起動したコンテナーはデタッチモードで起動され、ポート8000
が公開されています。
またコンテナーのステータスを見てみると「Up X seconds」(起動後 X 秒)となっています。
コンテナーを再起動したときには、はじめに起動したときと同じフラグ、同じコマンドによって起動されます。
ではコンテナーすべてを停止して削除します。 そしてランダムな名前になってしまう点を修正していきます。
起動したばかりのコンテナーを停止させます。 システム上の実行中コンテナーの名前を確認して、以下のコマンドにおけるコンテナー名を書き換えて指定してください。
$ docker stop inspiring_ishizaka
inspiring_ishizaka
こうしてコンテナーはすべて停止したので削除します。 コンテナーを削除するということは、実行することも停止状態にすることもできなくなります。 コンテナー内のプロセスはすでに停止され、コンテナーに対するメタデータも削除されています。
コンテナーを削除するには、docker rm
コマンドにコンテナー名を与えて実行します。
このコマンド 1 つに対して複数のコンテナー名を指定することもできます。
同じように、以下のコマンドにおけるコンテナー名を書き換えて指定してください。
$ docker rm inspiring_ishizaka wizardly_joliot magical_carson gifted_mestorf
inspiring_ishizaka
wizardly_joliot
magical_carson
gifted_mestorf
再度docker ps --all
コマンドを実行し、コンテナーすべてがなくなっていることを確認してください。
それでは、うっとうしいランダム名を解決します。 コンテナーに名前をつける理由は単純なものです。 どんなコンテナーが実行されているのかがすぐにわかります。 またどんなアプリケーションやサービスが関連づいているのかがわかります。 ソースコード上での変数の命名規則のようにすれば、単純に読みやすくなります。 だからコンテナーの命名も同じようにします。
コンテナー名をつけるにはrun
コマンドに--name
フラグをつけます。
$ docker run -d -p 8080:8080 --name rest-server docker-gs-ping
3bbc6a3102ea368c8b966e1878a5ea9b1fc61187afaac1276c41db22e4b7f48f
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3bbc6a3102ea docker-gs-ping "/docker-gs-ping" 25 seconds ago Up 24 seconds 0.0.0.0:8080->8080/tcp rest-server
こうしてコンテナーの識別は、名前を使って簡単に行えるようになりました。
次のステップ
本節ではコンテナーの実行、ポート公開を行いました。 またコンテナーのライフサイクルを管理する方法も学びました。 そしてコンテナーに名前づけを行って、識別しやすくしました。 次節ではコンテナー内においてデータベースを実行して、アプリケーションを接続する方法を示します。 以下を参照してください。
フィードバック
本トピック改善のためにフィードバックをお寄せください。 お気づきの点があれば Docker Docs の GitHub リポジトリに issue をあげてください。 あるいは PR の生成 により変更の提案を行ってください。