Yuki's Tech Blog

仕事で得た知見や勉強した技術を書きます。

【さわって学ぶクラウドインフラ docker 基礎からのコンテナ構築】第4章 Dockerの基本操作で知らなかったことをざっくりまとめてみた

目次

docker runコマンドは何をやっているか

docker runコマンドは、「docker pull」、「docker create」、「docker start」という3つの一連のコマンドをまとめて実行する利便性を重視したコマンドです。「実行したいコマンド」は省略でき、省略したときは、イメージの制作者が設定した既定のコマンドが指定されたことになります。

docker run コマンドは以下の書式です。

docker run オプション イメージ名 実行したいコマンド
docker run -dit --name my-apache-app -p 8080:80 -v "$PWD":/usr/local/apache2/htdocs/ httpd:2.4

上のコマンドは以下と同じことをしています。

docker pull httpd:2.4
docker create --name my-apache-app -p 8080:80 -v "$PWD":/usr/local/apache2/htdocs/ httpd:2.4
docker start my-apache-app

コンテナ起動から終了までの流れを以下に図示しました。

(注) イメージが既に存在する場合、docker pullは実行せず、docker createとdocker startのみ実行します。

Dockerイメージの取得

Dockerイメージは、Docker HubにあるDockerリポジトリから取得します。取得するときはdocker pullコマンドを実行します。

docker pull イメージ名 or イメージID

(※) イメージ名にはタグを指定できます。タグとは Dockerイメージのバージョンみたいなものです。タグ名を指定するときは、半角のコロンで区切ります。タグ名を省略したときは、最新版を意味する「latest」という特殊なタグが指定されたものとみなされます。

(注) docker pullで入手したイメージは、Dockerホストに保存されます。もう一度、同じイメージをdocker pullしても、ダウンロードし直されることはありません。 保持しているイメージはdocker image lsコマンドで確認できます。

ubuntu@ip-10-0-12-65:~$ docker pull httpd
Using default tag: latest
latest: Pulling from library/httpd
e9995326b091: Pull complete 
ee55ccd48c8f: Pull complete 
bc66ebea7efe: Pull complete 
5d0f831d3c0b: Pull complete 
e559e5380898: Pull complete 
Digest: sha256:6551a833f2b232fb9e627c4815217d84894446c2b94046bfdd1d9309ec09c042
Status: Downloaded newer image for httpd:latest
docker.io/library/httpd:latest
ubuntu@ip-10-0-12-65:~$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
httpd        latest    fe8735c23ec5   3 weeks ago   145MB

Dockerコンテナの作成

docker createコマンドを実行することで、DockerイメージからDockerコンテナを作成することができます。「実行したいコマンド」は省略でき、省略したときは、イメージの制作者が設定した既定のコマンドが指定されたことになります。 この実行したいコマンドはdocker startを実行すると、実行できます。

docker create オプション Dockerイメージ名 or イメージID 実行したいコマンド

以下のhttpdのコンテナを作るコマンドを実行する場合、「実行したいコマンド」を省略しています。この場合、httpdイメージの制作者が定めた既定のコマンド(Apacheを実行し、通信を待ち続けるためのコマンド)が暗黙的に指定されます。

docker create --name my-apache-app -p 8080:80 -v "$PWD":/usr/local/apache2/htdocs/ httpd:2.4

nameオプションによる名前づけ

nameオプションを指定しないと、ランダムなコンテナ名が付けられます。 そのため、docker createでコンテナを作成する際は、nameオプションを指定してコンテナに名前をつけます。

pオプションによるポート設定

「 -p」オプションを指定することで、 Dockerホストのポート番号とコンテナのポート番号をマッピングすることができます。

-p Dockerホストのポート番号:コンテナのポート番号

例えば、「-p 8080:80」の場合、DockerホストのTCPポート8080番を、コンテナの80番に紐づけるという意味です。このようなポートマッピングをすることで、「http://DockerホストのIP:8080:でアクセスすると、その通信がコンテナのポート80番に転送され、Apacheが公開している内容が見えるようになります。

(※) pはpublish(公開)の略です。コンテナのポートの一部をホストから公開して、外部から見えるようにするという意味です。また、コンテナは、制作者によって、どのポート番号を使うかが決まっています(そしてそれはドキュメントに記載されています)。

(注) Dockerでは pオプションを指定しない限り、DockerホストとDockerコンテナとの通信はつながりません。Dockerホストを通じてDockerコンテナ内で動いているプログラムと通信するためには、明示的にpオプションの設定が必要です。

vオプションによるマウント設定

「-v」オプションは、 コンテナの特有のディレクトリに、ホストのディレクトリをマウントするオプションです。

-v ホストのディレクトリ:コンテナのディレクトリ

以下の場合、$PWDの値をコンテナの/usr/local/apache2/htdocs/に割り当てています。$PWDは、 dockerコマンドを入力した瞬間の、ホスト側のカレントディレクトリを示す環境変数です。 /usr/local/apache2/htdocs/は、コンテナ側のマウント先のディレクトリです。httpdイメージの制作者は、このディレクトリをWebコンテンツとして(ドキュメントルートとして)公開するように構成しています。

-v "$PWD":/usr/local/apache2/htdocs/

(※) コンテナは、制作者によって、「あるディレクトリにコンテンツを置く」とか「あるディレクトリを基準にコンパイルする」などが決まっています(ドキュメントに記載されています)。そこで、-vオプションを指定して、そのディレクトリにDockerホストのディレクトリを割り当てて処理するようにします。

マウントとは

マウントとは、あるディレクトリに対して、別のディレクトリを被せて、そのディレクトリの内容が見えるようにする設定のことです。マウントしている間、マウント先の元のディレクトリの内容は隠され、マウントを解除すると元に戻ります。 例えばマウント元のディレクトリAをマウント先のディレクトリBにマウントするとします。マウント先でファイルaを置いてマウントを解除した場合、マウント先はマウント前の状態に戻りますが、マウント元はマウント先の情報が同期されるので、マウント先にはファイルaが存在しています。

Dockerコンテナの開始と停止

docker createでコンテナを作成しただけだと、コンテナはまだ起動していません。docker startを実行することで、 コンテナを起動させることができます。実はdocker startはコンテナを起動させるという意味ではなく、コンテナを作成するときに指定した「実行させたいコマンド」を実行するためのコマンドです。 httpdイメージで作成したコンテナの場合、コマンドを指定していないので、docker startを実行すると、既定のコマンド(Apacheを実行し、通信を待ち続けるためのコマンド)が実行されます。 そして、そのコマンドの実行が完了すると、Dockerコンテナは停止します。 httpdコンテナの既定のコマンドは終了することがないように作られています。そのため、コンテナはずっと実行しっぱなしの状態でいられます。コンテナ内で実行中のコマンドを停止するためにはdocker stopコマンドを実行します。コンテナ内で実行中のコマンドの実行が終了するのに伴い、コンテナが停止します。

(※) docker stopでコンテナが停止しない場合、docker killコマンドを使うことで強制停止することができます。

デタッチとアタッチ

稼働中のコンテナは、何かのコマンドがずっと実行しっぱなしです。実行しっぱなしであれば、シェルのプロンプトが表示されないので、そのコマンドが終了するまで次のコマンドを入力できません。この問題はコンテナをバックグラウンドで起動させれば解決します。 コンテナをバックグラウンドで起動させるためには、「-dit」オプションを指定します。 「-dit」オプションを指定しないと、フォアグラウンドでコンテナが起動します。

Image from Gyazo

-ditオプションの役割

-ditは、 「-d」「-i」「-t」の3つのオプションを組み合わせたものです。「-d」が、端末から切り離してバックグラウンドで実行することを指定するオプションです。「-i」と「-t」は、このコンテナを端末(キーボードとディスプレイ)から操作するためのオプションです。順番に意味はなく、-itdでも大丈夫です。コンテナをバッググラウンドで起動させたい場合、「-d」オプションを指定します。コンテナをキーボードで操作したい場合、「-it」オプションを指定します。

オプション 意味
-d デタッチモード。端末と切り離した状態でバックグラウンドで実行する
-i インタラクティブモード。標準入出力及び標準エラー出力をコンテナに連結する。-iオプションを指定しないと、キー入力はコンテナに伝わりません。そして、コンテナからの出力が届きません。
-t 疑似端末(pseudo-tty)を割り当てる。疑似端末とは、カーソルの移動や文字の削除などの文字入力をサポートする端末のこと。-iオプションを指定しないと、Ctrlキーなどが使えません。

(※) 「-d」を省略して、端末と接続した状態でコンテナを実行することを「アタッチ(attach: 接続されたの意味)」と言います。

デタッチとアタッチの切り替え

アタッチ状態からデタッチ状態に切り替えるためには、「ctrl + P」、「ctrl + Q」を順番に実行します。端末がコンテナとアタッチしているので、端末からの入力をコンテナが受け取ることができます。デタッチは端末とコンテナが切り離されているので、コンテナ内で実行されているコマンドに対して何かキー操作することはできません。デタッチ状態からアタッチ状態にするためには、docker attachコマンドを実行します。

コンテナをメンテナンスする

動作中 or 停止中のコンテナに入り込んで操作するためには、 コンテナの中でシェルを実行して、そのシェルを通じて、さまざまな操作をします。

停止中のコンテナでシェルを実行する

docker runの実行したいコマンドに、/bin/bashを指定します。本来実行される既定のコマンドの代わりに、これらのシェルが起動されるようにします。このときキー操作をするので、「-it」のオプションを指定します。

docker run --name my-apache-app -it httpd:2.4 /bin/bash

lsコマンドを実行してファイルの一覧を確認したり、コンテナ内のファイルを変更したり、アプリケーションをインストールすることができます。シェルを終了させないで、コンテナとデタッチしたい場合は、「ctrl + P」、「ctrl + Q」を順番に実行します。その場合、コンテナはバッググランドで起動しています。コンテナに入った状態でシェルを停止させたい場合、exitを実行します。そうするとコマンドの実行が終了するので、コンテナは停止します。

動作中のコンテナでシェルを実行する

こちらの方が使うケースが多いです。 稼働中のコンテナに対して影響を与えることなくコンテナの中に入り込んで作業するためには、docker execコマンドを実行します。docker execコマンドとは、指定したコンテナの中でプロセスを実行するためのコマンドです。

docker exec -it コンテナ名 実行したいコマンド
docker exec -it my-apache-app /bin/bash

exitコマンドで「実行したいコマンド」を終了させることができます。このコマンドを終了させただけなので、コンテナ自体は起動したままです。

一回限り動かすコンテナの使い方

Dockerではコンテナを常時起動させる以外に、一回限り動かすコンテナの使い方があります。例えば、コンパイラや画像変換ライブラリなどの便利ツールが入ったコンテナを使って、Dcokerホストのファイルを処理したいというケースです。一度インストールしてしまうと、アンインストールが困難であったり、他の環境に影響を与えてしまう場合、このコンテナを使ったやり方だと手軽に試せます。コンテナを破棄して仕舞えば、元の状態にすぐ戻せるからです。コンテナにDockerホストのディレクトリをマウントして、コンテナ内でファイルを処理しています。その結果はマウント元のディレクトリに同期されるので、ファイルに対して処理を間接的に実行することができます。

一度限りしか動かさないコンテナの場合、--rmオプションを指定して、実行が完了したときに、コンテナを削除するようにします。また、すぐに破棄するコンテナに名前をつけても意味がないので、--nameオプションは省略します。

停止しているコンテナや使用していないイメージを一気に削除する

docker container pruneコマンドを実行すると、停止しているコンテナを全てまとめて削除できます。

docker container prune

また、docker image pruneを実行すると、どのコンテナも使用していないイメージを全て削除します。

docker image prune

ちなみに、全てのコンテナを停止させるためには、以下のコマンドを実行します。docker ps -qで、起動しているコンテナのIDのみを取得します。

docker stop $(docker ps -q)

参考記事

さわって学ぶクラウドインフラ docker基礎からのコンテナ構築 | 大澤 文孝, 浅居 尚 |本 | 通販 | Amazon

コンテナに入りたい?それ docker exec でできるよ - Qiita

コマンドでDockerコンテナを停止・削除、イメージの削除をする - Qiita