2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

演習で学ぶコンテナ入門

Last updated at Posted at 2021-12-23

0.はじめに

公式を含め、世の中にたくさん Docker のチュートリアルがありますが、自分の昔の作業メモを中心に内容を整理して解説を加えたら、必要最低限をおさえた実践的なものができるのではないだろうか。という発想で作って見ました。

決して網羅的ではなく、文中で使ってないコマンドについて一覧のリストを作ったりもしていません。それは「こういう事はできないのかな」と思った時に、公式の Docker docs や、翻訳版の Docker docs、グーグル検索で見つけてもらって、その代わりに文章量を減らして読みやすくしよう。という発想です。(それでも書いてみると、結構、長くなりました…)

人によって必要な知識の範囲は違うと思いますが、お役に立ててれば幸いです。

1.とりあえずコンテナを動かす

1.1.コンテナを実行する環境を作る

コンテナの実行環境として、docker desktop を使用します。Windows 版、Mac版がありますが、以下からダウンロードします。

個人用であれば無償です。

何が一番楽でお金がかからないだろうか。と考えた結果、Mac でも Windows でも共通に使えて、作業も楽なので、Docker Desktop を選択してみました。
Linux の仮想マシンを立てて、そこで docker を動かすなど選択肢はたくさんあると思いますのでお好きなもので構いません。

このドキュメントを書いた、筆者の環境は 「Windows 10」 + 「Docker Desktop for Windows」 + 「WSL2」 です。

1.2.コンテナを動かしてみる

例として、nginx のコンテナを動かしてみます。このコンテナはDocker Hub上に既にあるものを使用します。

コンテナは覚えなければいけない概念などがいろいろありますが、細かい話は後に譲るとして、このセクションでは、まずは単純に動かしてみて、「雰囲気」を掴んでみる事にしてみます。

Docker Hubからnginxのイメージをダウンロードして、コンテナを実行するには以下のコマンドを実行します。

docker run nginx

これだけです。ただこれだと

$ docker run nginx
<省略>
2021/11/18 07:46:52 [notice] 1#1: nginx/1.21.3
2021/11/18 07:46:52 [notice] 1#1: built by gcc 8.3.0 (Debian 8.3.0-6)
2021/11/18 07:46:52 [notice] 1#1: OS: Linux 4.19.84-microsoft-standard
2021/11/18 07:46:52 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2021/11/18 07:46:52 [notice] 1#1: start worker processes
2021/11/18 07:46:52 [notice] 1#1: start worker process 31
2021/11/18 07:46:52 [notice] 1#1: start worker process 32
2021/11/18 07:46:52 [notice] 1#1: start worker process 33
2021/11/18 07:46:52 [notice] 1#1: start worker process 34
2021/11/18 07:46:52 [notice] 1#1: start worker process 35
2021/11/18 07:46:52 [notice] 1#1: start worker process 36
2021/11/18 07:46:52 [notice] 1#1: start worker process 37
2021/11/18 07:46:52 [notice] 1#1: start worker process 38
2021/11/18 07:46:52 [notice] 1#1: start worker process 39
2021/11/18 07:46:52 [notice] 1#1: start worker process 40
2021/11/18 07:46:52 [notice] 1#1: start worker process 41
2021/11/18 07:46:52 [notice] 1#1: start worker process 42

のようにプロンプトが戻ってこないので 「Ctrl + C」で処理を停止してください。

次に以下を実行してみます。

$ docker run -d nginx
b0d570e09018fac53c58db702ca09c7689b200bd58bf3fad79748d240a8e3129
$

今度はプロンプトが戻ってきたと思います。ここで使われている -d 「デタッチ」を意味します。先ほど、-d を付けなかった時にプロンプトが返ってこなかった事と較べると、なんとなく「デタッチ」の感覚がつかめると思います。

稼働中のコンテナの確認

起動中のコンテナを確認するには、docker ps を実行します。

$ docker ps    # 起動中のコンテナの確認
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS     NAMES
b0d570e09018   nginx     "/docker-entrypoint.…"   5 seconds ago   Up 3 seconds   80/tcp    eager_benz
$

ps からイメージできるように、稼働中のコンテナをリストしてくれます。
一つのコンテナが起動しているのがわかると思います。コンテナが仮想マシンとは違い「隔離されたプロセス」である事をなんとなく示唆してくれるコマンド名になっています。

一番後ろのNAMESのコラムを見るとeager_benzと名前が付いてます。
この名前は自分が指定した名前も付ける事ができますが、ユーザーが指定しなければ勝手につけられます。
ランダムな名前は、「形容詞」+「著名人の名前」の形で生成されています。namesgenerator というパッケージで生成されておりソースはこちらです。

CONTAINER ID (b0d570e09018) NAME (eager_benz) は、勝手に付けられるユニークな値で、コンテナの停止や開始時に識別子として使用する事ができます。

コンテナ名でコンテナを停止

コンテナを停止するには、 docker stop <コンテナ名 | CONTAINER ID> を使用します。
まずはコンテナ名を指定して停止させてみます。

$ docker stop eager_benz   # 起動したコンテナの停止
eager_benz
$

docker ps で、起動しているコンテナが居ない事の確認

$ docker ps  
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
$

コンテナIDでコンテナを停止

さっきは eager_benz というコンテナ名を指定してを停止させましたが、CONTAINER IDを使って以下のように停止させる事もできます。

$ docker stop b0d570e09018     # 最後の IDは docker ps で表示されていた CONTAINER ID

停止したコンテナは完全に消えたわけではなく、停止した状態で残っています。以下のコマンドで停止中のコンテナを表示させる事ができます。

$ docker ps -a
CONTAINER ID   IMAGE                                                     COMMAND                  CREATED          STATUS                      PORTS                  NAMES
b0d570e09018   nginx                                                     "/docker-entrypoint.…"   20 minutes ago   Exited (0) 5 minutes ago                           eager_benz
$ 

CONTAINER ID や、 NAMES の欄の値が起動していた時と同じ値である事を確認して下さい。

停止したコンテナの削除

完全にコンテナを消去するには、docker rm <コンテナ名 | CONTAINER ID> を使用します。

$ docker rm eager_benz
eager_benz

コンテナが消えたか確認します。

$ docker ps -a
CONTAINER ID   IMAGE                                                     COMMAND                  CREATED          STATUS                      PORTS                  NAMES
$

イメージのリスト

コンテナは消えましたが、コンテナの元になったイメージ nginxは、そのまま残っています。
イメージを確認するには docker images で確認します。

$ docker images
REPOSITORY                                                TAG       IMAGE ID       CREATED         SIZE
nginx                                                     latest    ea335eea17ab   1 weeks ago     141MB
$

コンテナのイメージと、それから作成されるコンテナの関係がなんとなく理解できたかなと思います。

イメージコンテナは、大半のコンテキストで同じ意味の言葉として使用でき、合体させてコンテナ・イメージ 等と曖昧に使うケースもありますが、dockerコマンドの世界では、dockerイメージdockerコンテナは、明確に違うものを示します。

関係を図示すると以下のようになります。
image.png
dockerイメージから作成されるのが dockerコンテナになります。

イメージの削除

イメージを削除するには、docker rmi <REPOSITORY名:TAG> で削除します。

$ docker rmi nginx:latest
Untagged: nginx:latest
Untagged: nginx@sha256:097c3a0913d7e3a5b01b6c685a60c03632fc7a2b50bc8e35bcaa3691d788226e
Deleted: sha256:ea335eea17ab984571cd4a3bcf90a0413773b559c75ef4cda07d0ce952b00291
Deleted: sha256:cc284e9b1cbed75793782165a07a0c2139d8ec0116d1d562c0e2e504ed586238
Deleted: sha256:6207e091bef7f1c94a109cb455ba163d53d7c2c641de65e71d3a0f33c0ebd8ae
Deleted: sha256:97a18ff8c6973f64d763f004cad932319a1428e0502c0ec3e671e78b2f14256b
Deleted: sha256:319130834f01416a2e8f9a4f2b2fa082c702ac21f16e0e2a206e23d53a0a3bae
Deleted: sha256:1bc375f72973dc110c9629a694bc7476bf878d244287c0214e6436afd6a9d1b0
$

dockerの世界では、TAGも名前の一部で、イメージを削除する時はTAGも指定する必要がある事に注意して下さい。

1.3.レポジトリとタグとイメージ名

ここでは「レポジトリ」名、「タグ」名、「イメージ」名について、少し考えて見ます。

docker images の出力をよく見てみます。

$ docker images
REPOSITORY                                                TAG       IMAGE ID       CREATED         SIZE
nginx                                                     latest    f652ca386ed1   3 weeks ago     141MB
nginx                                                     1.20      aedf7f31bdab   5 weeks ago     141MB
redhat/ubi8                                               latest    cc0656847854   7 weeks ago     216MB
ubuntu                                                    latest    ba6acccedd29   2 months ago    72.8MB

ヘッダー部分の所にREPOSITORYと書いています。

少し前のステップで、イメージの削除は docker rmi <REPOSITORY名:TAG> で行う。とさらっと書きましたが、直感的にはイメージ名で良いような気もします。このREPOSITORYとは何でしょうか。

イメージはlatestや、1.0等のバージョンを表すタグを付ける事で、同じグループのイメージである事を示す事ができます。dockerでは、このグループの概念をレポジトリと読んでいます。

image.png
ですので、docker imagesの出力では、イメージ名ではなくレポジトリという表現になっています。

レポジトリ名 だけでは、イメージを任意に区別できないので、docker コマンドの引数に イメージ 名を指定する場合は、 レポジトリ 名 + タグ 名の形で指定します。

例外として docker start nginx のように タグ を省略した場合、自動的に docker start nginx:latest のように latest が付加されて解釈する事があります。

但し latestタグ は、 イメージ を作成時に、タグ の指定を省略した時にデフォルトで使われる値で、別の値を指定する事もできます。そのため、タグ を省略した時に latestタグ がついた イメージ が存在しない時はエラーになります。

ユニークなイメージ

また、忘れてはいけないのはIMAGE IDでもイメージを区別できます。
IMAGE IDが同じでも違う レポジトリ名 + タグ名を持つイメージも存在します。以下の例は、あるイメージを別のイメージにコピーし作成した時の出力例です。同じ IMAGE IDを持っています。

$ docker images
REPOSITORY                                                TAG       IMAGE ID       CREATED         SIZE  
copy                                                      1.0       6c364457d832   3 days ago      303MB 
nginx-ubi8                                                1.0       6c364457d832   3 days ago      303MB 
...

dockerの世界では、一意に決まるユニークなイメージを想像した時に、レポジトリ名 + タグ名 としての一意なのか、IMAGE IDとして一意なのか2通りがあります。

Docker のイメージ名とは?

Docker のマニュアルをイメージ名(image name)で検索すると、imagne nameという言葉の使われている場所は非常に少ないのですが、例えば、Get an instance’s image name (インスタンスの「イメージ名」を取得する) で紹介されている docker inspect コマンドで得られる imagne name とされるものは tag を含んだ <レポジトリ>:<タグ> の値です。(タグがlatestの場合は省略される)

$ docker inspect --format='{{.Config.Image}}' c3775755f851
nginx:1.20
$ 

ただ、一般的には タグ を抜いた レポジトリ 名の事を イメージ 名と呼んで説明しているケースもあり、 イメージ(名) の定義はきちんと定まっておらず曖昧に使われているのが現状で、インターネットを検索すると呼び方に関する議論も見つける事ができます。英語圏でもこの議論が見つかるので、翻訳の問題ではないようです。言葉の使われ方が安定していなのは、初学者にはつらい所です。

以下は docker tag コマンドのヘルプですが、 レポジトリ名 と解釈される所は SOURCE_IMAGE/TARGET_IMAGE と記載されていて [:TAG] を付ける事ができるとされています。つまり、ここでは SOURCE_IMAGE/TARGET_IMAGE (つまりイメージ名) が REPOSITORY 名と同じ意味で使われています。

$ docker tag --help
Usage:  docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

さらに、実際のコマンド実行時にどのように使われているかに目を向けると、 docker run nginx と書いた時の nginx は、 <レポジトリ名>:<タグ名> です。これは、表記上、省略されているだけで、実際には nginxnginx:latest と解釈されます。ですので、タグが無い=レポジトリ名という区別も単純にはできません。

docker では、省略した記述が許されているため nginx と書いた時にそれはコンテキストによって レポジトリ であったり、 イメージ名 でもありえます。さらに前述した docker tag コマンドのヘルプのように、タグを抜いた部分を「 イメージ (名)」と呼んでいるケースもあります。

はじめのうちは混乱する部分なので、頭を柔軟に保つ必要があります。

このガイドでは基本的に <レポジトリ名>:<タグ> の組み合わせを イメージ (名)と呼ぶ事にします。

1.4. レポジトリ名の実際

レポジトリ(名)イメージ(名) についての基本を学んだので、初学者が混乱する レポジトリ 名の表記の種類について、実例をみながら理解を深めてみます。

以下は NGINX 社が提供している nginx イメージの レポジトリ です。この レポジトリ 名は nginx です。
この ポジトリ の最新イメージを使用したい時は、nginx:latest のように指定します。

image.png

以下は、 Ubuntu Linux のディストリビューターである Canonical 社が提供している nginx イメージの レポジトリ です。このレポジトリ名は ubuntu/nginx です。
このレポジトリの最新イメージを使用したい時は、ubuntu/nginx:latest のように指定します。

image.png

以下は、 Canonical 社が提供しているコンテナ用の ubuntu OSの レポジトリ です。この レポジトリ 名は ubuntu/nginx です。
この レポジトリ の最新イメージを使用したい時は、ubuntu:latest のように指定します。

image.png

以下は、 Red Hat 社が提供しているコンテナ用の RHEL OS の レポジトリです。 Red Hat 社は、コンテナ用の OSイメージは RHEL 8 のようには呼ばず UBI (Universal Base Image) 8 のように呼びます。これは ubi8 のイメージです。レポジトリ名は redhat/ubi8 です。
この レポジトリ の最新イメージを使用したい時は、 redhat/ubi8:latest のように指定します。

image.png

はじめのうちは、 / が入って居ると「 / の前が レポジトリ名 で…」のように考えてしまいますが、 レポジトリ 名 には / が入って居る場合もありますし、そうで無い場合もあります。

アプリケーションの提供ベンダーの名前が必ず / で区切られて レポジトリ 名に含まれている。という事もありません。

後述しますが、 Docker Hub のユーザー名を / を使って レポジトリ 名の中に付加するケースもあるので、 / の前が必ずベンダー名という事もありません。

レポジトリ 名には / が入って居る場合もあるし、そうでない場合もある。区切りの意味もその時々」くらいに考えておいて、 / に必要以上に惑わされないようにしましょう。

1.5.このセクションで使用したコマンド

初めのうちはコマンドを覚えられないと思うので、このセクションで使用した基本的なコマンドをまとめておきます。

1.5.1. コンテナの作成と起動

イメージ名 nginxDocker Hub からダウンロードして、 -d (デタッチ) で起動します。コンテナ名は自動でランダム付きます。

docker run -d nginx

上では、タグを省略しているので latest を付けて nginx:latest と解釈されます。

尚、解説の中では使いませんでしたが、コンテナ名を自分で指定したい場合は --name <付けたい名前> のように指定できます。

docker run -d --name <my-contaienr> nginx

1.5.2. 起動しているコンテナの一覧

起動しているコンテナの一覧を表示します。

docker ps

1.5.3. コンテナを停止

起動しているコンテナを停止します。

$docker stop eager_benz   

上記では コンテナ 名を指定していますが、 CONTAINER ID を指定して停止する事もできます。

1.5.4. コンテナを起動

本文中では使用しなかったのですが、停止しているコンテナを起動するには以下の通りです。
停止させる時の stopstart 変わるだけです。

docker start eager_benz   

上記では コンテナ 名を指定していますが、 CONTAINER ID を指定する事もできます。

1.5.5. 停止したものも含めたコンテナの一覧

停止したものも含めたコンテナの一覧を表示します。

docker ps -a 

1.5.6. コンテナの削除

コンテナを削除します。

docker rm eager_benz 

上記では コンテナ 名を指定していますが、 CONTAINER ID を指定して削除する事もできます。

1.5.7. イメージの削除

イメージをローカルの レポジトリ (自分が使用している端末の レポジトリ )から削除します。

docker rmi nginx:latest   

上記では イメージ 名を指定していますが、 IMAGE ID を指定して削除する事もできます。
尚、このイメージを使用したコンテナが存在している時は削除できないようになっています。

2.コンテナを使う上での暗黙の了解とPULL

ここでは、演習に入る前に、少し寄り道して docker pull について学んでみます。

2.1. Docker Hub 上のイメージを使用する

単純にコンテナをダウンロードするだけであれば、

docker pull nginx

でダウンロード(PULL)する事ができます。

docker run というコマンドを前の章で使いましたが、実は、docker run コマンドは docker pulldocker createdocker startの3つのコマンドをまとめたコマンドです。

以下に docker で良く使うコマンドの関係性を図示してみました。

2-1-dockerhub.png

dockerイメージ は、レポジトリ と呼ばれる場所に保管されています。 レポジトリ は、インターネット上にもありますし、 コンテナ が実行されるローカルにもあります。

通常、一つの レポジトリ には、 一つの イメージ のいろいろなバージョンが保管されます。さらに、この レポジトリ がたくさん集まった場所を レジストリ と呼びます。インターネット上にある レジストリ で一番、有名なのは Docker Hub です。 docker コマンドを実行すると特に何も指定しなくても、 Docker Hub を参照に行くようになっています。

docker run を実行すると、インターネット上の Docker Hub レポジトリ から、ローカルの レポジトリイメージ がダウンロード( pull )され、そこから コンテナcreate され start で起動されます。

既にローカルにpullされたイメージがある場合は、docker runを実行してもインターネットから再ダウンロード(pull)される事はありません。

createstartはとりあえず置いておいて、ここでは pull に注目します。

docker pull nginx

では、単にnginxと指定していますが、幾つかの暗黙の省略が含まれています。

docker コマンドでは、nginx と指定しただけで Docker Hub というコンテナレジストリにアクセスして、nginxという名前のコンテナでlatestというタグが付いたものを探してダウンロード(pull)してきます。

なので省略されていますが、上のコマンドは以下のものと同じになります。

docker pull nginx:latest

タグは、:(コロン)を挟んで付加します。タグの latest 部分は、1.20のようにバージョンを付ける事もあります。

docker pull nginx:1.20

Registry 上のイメージにどんなタグが付いているかの一覧の取得は、標準の docker コマンドではサポートされておらず、Docker Hub にアクセスして確認する必要があります。

2.2. Docker Hub 以外のイメージを使用する

コンテナのイメージを Docker Hub 以外のレジストリからダウンロード(pull)してきたい場合は、明示的に指定する必要があります。例えば、

docker pull quay.io/centos/centos

は、 quay.io という Red Hat 社のコンテナレジストリの centos/centos という レポジトリ 名 の latest という タグ が付いたものを(ローカルに無ければ) ダウンロード( pull )してきます。

この例であげている レポジトリcentos/centos は、名前の中に / が入っています。 レポジトリ 名は、このように / が中に入っていたり、単純に centos のように / が無い名前までいろいろあり得ます。必ずしも / があるからと言って、 レポジトリ 名と レジストリ 名の区切りという訳ではないので、慣れる必要があります。

上記のコマンドは以下と同じになります。

docker pull quay.io/centos/centos:latest

ダウンロードしてきた nginxというイメージは、ローカルに保存され、次回、同じイメージが要求された時には、既にダウンロードされたものが使用されます。

演習1: Nginx のコンテナを起動する

こんどは、もう少しきちんと、コンテナを作成してみます。docker run -d nginx にもう少しオプションを足してみます。

以下のコマンドで、イメージ「nginx」から、コンテナ「my-nginx」が作成され起動します。

 docker run -d -p 8080:80  --name  my-nginx   nginx

オプションについて解説します。これらは基本的なオプションなので暗記する必要があると思って下さい。

-d
これは「デタッチ」モードを意味します。前のステップでdocker run nginx を実行した時に、作業中のコンソールにカーソルが戻ってこなかったのを覚えていると思います。このオプションを付ける事で、コンテナを今使っているコンソールから切り離す(デタッチ)する事ができます。

-p 8080:80
コンテナは、言うなれば、ただのプロセスです。同じOS上で同じポート番号を使用する複数のプロセスがあると、ポートの取り合いが起きて上手く動く動きません。

image.png

上記のコマンドでは、OSから見たコンテナのポート「8080」をコンテナ内の「80」番ポートにフォワードする設定をしています。これにより既に OS上に80番ポートを使うアプリケーションが稼働している場合の(多くの場合ありがちです) 競合を避けています。反対に「8080」はそのOS上で使われてなければ、他の任意のポート(例えば8090) でも大丈夫です。

同じホストOS上でたくさんのコンテナを使うには、同じIPアドレスを使う事になるので、ポートの衝突を避ける必要があります。
個別にIPアドレスを持つ VM(仮想マシン)では、ポートが同じでもIPが違うのでアプリケーションのポートが衝突する事はありません。アプリケーション(コンテナ)のポートを変更するという考え方は、コンテナならではの作法になります。

コンテナ内で80番ポートを使うのは、このnginxのイメージが 80LISTEN するように作られているという暗黙の了解によるものです。もし全く知らないアプリケーションで、どこにもどのポートをLISTENしているか記述されてない場合は全く検討がつかないものになります。

--name my-nginx
イメージ nginx を元に作成するコンテナ名を指定します。特に指定しない場合はランダムな名前が付けられます。以前の実験では、何も指定しなかったために docker によってeager_benz と言う名前が付けられていました。

nginx
コンテナ my-nginxの元になるイメージ名です。これは暗黙の了解で、Docker Hub上の nginx:latestが検索されて使用されます。Docker Hub以外のレジストリ上のイメージを指定するには、明示的にそのレジストリ名を指定する必要があります。

実際の実行結果は以下になります。

$ docker run -d -p 8080:80  --name  my-nginx   nginx
e0cc77bc866fe504b8053a7b201b7a469ec61d98a4fd3a6618be382e87fda34c

$

コマンドプロンプトにカーソルが戻ってきました。-dオプションのおかげです。

もう一度、上記のコマンドの引数を軽くおさらいしておきます。これはコンテナをやって行く以上覚えなければいけないものなので、頭にたたきこんでおきましょう。

-d デタッチ。コンテナの起動後に、コンテナと今使っているコンソールを切り離します。
-p 8080:80 8080番ポートへのアクセスを、コンテナの80番ポートにフォワードする
--name my-nginx イメージ「nginx」を元に作る自分のコンテナの名前
nginx コンテナの元になるイメージ(この場合、インターネット上の Docker Hub 上に置かれているイメージ)

実行中のコンテナの確認

実行中のコンテナは、以下のコマンドで確認できます。

docker ps

実際の実行結果は以下の通りです。

$ docker ps
CONTAINER ID   IMAGE                       COMMAND                  CREATED          STATUS                      PORTS                  NAMES
7e7ffed26222   nginx                      "/docker-entrypoint.…"   33 minutes ago   Up 9 minutes                0.0.0.0:8080->80/tcp   my-nginx
$

次にこのコンテナに、ブラウザを使ってアクセスしてみます。アクセスポートは、コンテナ作成時に指定した 8080 になります。コンテナ外部の8080ポートからコンテナ内部の80ポートにフォワードされます。

image.png

無事アクセスできました。

毎回ブラウザを立ちあげるのも大変なので、CLIツールの curlを使ってアクセスにも慣れておきます。以下でアクセスできます。

curl localhost:8080

実際に実行してみます。

$ curl localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

$

出力結果が大量にでますが、これは HTML のテキストがそのままコマンドプロンプトに表示されているためです。
コンソールは、ブラウザのように HTMLを解釈する機能ないためこのような出力になります。

コンテナを停止する

以下のコマンドで起動中のコンテナを停止する事ができます。

docker stop <コンテナ名>

実際に停止してみます。

$ docker stop my-nginx
my-nginx
$ 

稼働中のコンテナを確認する

docker ps

dcoker ps コマンドで稼働中のコンテナを確認してみます。my-nginx は表示されないはずです。

$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

$

docker ps -a

docker ps-a オプションを付けた docker ps -a を使うと、既に停止したコンテナも確認できます。

docker ps -a

実際に docker ps -a を実行してみます。

$ docker ps -a
CONTAINER ID   IMAGE                    COMMAND                  CREATED         STATUS                          PORTS     NAMES                                   "/docker-entrypoint.…"   8 minutes ago   Exited (0) About a minute ago             my-nginx

STATUSExited (0) になったコンテナmy-nginxが確認できます。

停止しているコンテナを起動する

停止したコンテナは再度、起動させる事ができます。docer start <コンテナ名> で起動できます。

docker start <コンテナ名>

実際にコンテナを起動してみます。

$ docker start my-nginx
my-nginx
$

コンテナの起動を dokcer ps コマンドで確認してみます。

$ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                  NAMES
e0cc77bc866f   nginx     "/docker-entrypoint.…"   15 minutes ago   Up 35 seconds   0.0.0.0:8080->80/tcp   my-nginx
$

以上で演習1は完了です。

演習2: OSのコンテナの実行

演習1では nginxのコンテナを実行しました。

こんどは、先ほどのnginxのようなアプリケーションが何もインストールされてない素のOSのイメージからコンテナを作成してみます。
Docker Hubにあるる ubuntu のイメージを元にコンテナを作成・実行してみます。名前はmy-ubuntuにします。

$ docker run --name my-ubuntu  ubuntu

Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
7b1a6ab2e44d: Pull complete
Digest: sha256:626ffe58f6e7566e00254b638eb7e0f3b11d4da9675088f4781a50ae288f3322
Status: Downloaded newer image for ubuntu:latest

$

ここでは、単にイメージ名としてubuntuとだけ指定しているので、Docker Hubで公開されているubuntulatestのタグが付いたイメージがダウンロード(pull)されます。

稼働しているかどうか docker ps で確認してみます。

$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

$

稼働してからすぐに Exit している事がわかります。

今度は docker ps -a を使用して、停止したコンテナも確認してみます。

$ docker ps -a
CONTAINER ID   IMAGE                                                     COMMAND                  CREATED          STATUS                      PORTS                  NAMES
10b401288650   ubuntu                                                    "bash"                   1 minutes ago   Exited (0) 1 minutes ago                          my-ubuntu

$

これを見るとbashが一瞬実行されたものの、すぐに終了した事がわかります。このようにコンテナでは、フォアグラウンドで稼働するプロセスが無いとすぐに終了してしまいます。

イメージの作りがどのようになっているかは、Docker Hubのページで確認ができますが、CMD["bash"]と書かれており、これはコンテナ起動時にbashが実行されるように作られている事を意味します。が、このbashは、特にする事もないので、プロセスとしてはすぐに終了します。
image.png

演習1では、nginxがフォアグラウンドで稼働していたのでコンテナが稼働し続けてましたが、稼働し続けるプロセスが無いとこのようにコンテナ自体が終了してしまいます。

今度は、-itd という起動オプションを付けて my-ubuntu2 という名前のコンテナを作ります。

docker run -itd --name my-ubuntu2 ubuntu 

ここで -itd というオプションは、使っていると意味をだんだんと忘れてしまい手が勝手に動くようになりますが、以下のような意味があります。

オプション -itd

-i : interactive. Keep STDIN open even if not attached.
-t : Allocate a pseudo-TTY. コンテナに疑似tty(pseudo-TTY)を作る。
-d : Run container in background and print container ID。デタッチ。コンテナをバックグラウンドで動かす。

これらはバラバラのオプションなので -it -d や、 -i -t -dのようにバラバラに指定もできます。
殆どの用途で-itはセットで使われ、-it-itdのように使われます。

-i-t は、コンテナと、自分が使っているホスト上のコンソールが、コンテナと通信できるようにセットアップするためのオプションです。
-itは、今は、ひとかたまりに自分のコンソールからコンテナ内部を覗いて見るのに必要なオプション。と覚えておきましょう。

次に、docker ps コマンドでコンテナの稼働を確認してみます。

$ docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES
34d28c35a11b   ubuntu    "bash"   5 minutes ago   Up 5 minutes             my-ubuntu2

$

今度はコンテナが稼働したままです。

なぜコンテナが起動したままなのか

-tオプションは、コンテナに、pts(疑似端末)を作るオプションです。疑似端末が作成され、起動したbash がインタラクティブモードで接続した状態になります。このbashが起動したままになるため、コンテナが終了せずに稼働し続ける事ができるようになっています。

docker attach でコンテナの中を覗く

コンテナmy-bunutu2 の中を覗いてみます。
これは docker attach <コンテナ名 | CONTAINER ID> で可能です。

docker attach my-ubuntu2
root@34d28c35a11b:/# ps -ef                       
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 04:57 pts/0    00:00:00 bash
root        17     1  0 05:06 pts/0    00:00:00 ps -ef
root@34d28c35a11b:

コマンドプロンプトが変わり、Linux に入った事がわかります。
同時に ps -ef コマンドを実行すると、bash と自分自身である ps -ef しか動いてない事がわかります。
ps -ef の親のプロセスはPID=1bashである事がわかります。

コンテナにはログインの概念が無いので、このattachというのはコンテナ独特の考え方になります。
ログイン時に新規にbash等のシェルが起動するLinuxの通常のログインの仕組みと違い、既に動いていたbashを使用しています。

次にこのbash上でexitをしてみます。

root@34d28c35a11b:/# exit
exit

$

exitすると、はじめに動いていたbashからも exit してしまってコンテナが停止します。

docker ps でコンテナが終了している事を確認します。

$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

$

docker exec でコンテナの中を覗く

先ほどのステップで停止してしまったコンテナをdocker startコマンドで、再度起動します。

$ docker start my-ubuntu2

今度は、docker exec というコマンドでコンテナの中を覗きます。

正確には docker exec は、起動中のコンテナ内で新しいプロセスを起動するプロセスです。コンテナ内で起動する新しいプロセスを引数で指定する必要がありここでは /bin/bashを指定します。

$ docker exec -it my-ubuntu2 /bin/bash
root@34d28c35a11b:/# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 05:15 pts/0    00:00:00 bash
root        21     0  0 05:18 pts/1    00:00:00 /bin/bash
root        29    21  0 05:18 pts/1    00:00:00 ps -ef
root@34d28c35a11b:/#

中でps -ef コマンドを実行すると、今度は3つのプロセスが動いており ps -ef の親プロセス IDは PID=21です。つまPID=21docker execによって新規に起動されたbash(/bin/bash)です。

このbash(/bin/bash)が接続しているTTYpts/1 になっていて、コンテナ内にもともと存在しているpts/0とは別である事がわかります。

コンテナから exit してみます。

root@34d28c35a11b:/# exit
exit

$

docker ps で確認すると、attachでコンテナに接続した時とは違い、コンテナがまだ稼働したままである事がわかります。

$ docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS         PORTS     NAMES
34d28c35a11b   ubuntu    "/bin/bash"   23 minutes ago   Up 5 minutes             my-ubuntu2

$

docker exec では新規に /bin/bash をコンテナ内で起動したので、exitで終了したのは新規に起動した /bin/bashだけになります。

一方でdocker attachでは、元々、-tオプションを付けた事でコンテナ内で起動していたシェルに接続(attach)し、そのシェルを exitしてしまったため、他にプロセスがなくなりコンテナが終了してしまいました。

なんとかく attachexecのそれぞれで、コンテナの中を見る時の動きの違いがわかったと思います。

以上で演習2は完了です。お疲れ様でした。

演習3: オリジナルの nginx のイメージを作る

手動作業によるイメージのビルド

Docker Hubからダウンロードした親イメージに、自分のアプリケーションとファイルを追加して新しいイメージを作ります。

ここで行う作業の流れを図示すると以下の通りです。

image.png

親イメージに、ファイルを追加したり、コンテナ実行時のコマンドを設定して、新しいイメージを作る事をビルドと言います。

この親イメージとして、Linuxベンダーが提供しているベース・イメージDocker Hubから取得する所からはじめます。

通常、コンテナのイメージは、一つの親イメージに修正を積みかさねる事で新しいイメージを作っていきますが、ベース・イメージとは、それ以上の親がいない大元のイメージを指します。

ベース・イメージをダウンロードする

ここではRed Hatが提供する RHEL8のベースイメージである ubi8Docker Hubからダウンロード(pull)して使用します。

image.png
Docker Hub上のredhat/ubi8のレポジトリへのリンクはこちらです。

イメージを作成する場合は、適当なイメージを使用するとマルウェアなどが含まれている可能性があるので、提供元のわかっているイメージを使用するようにしましょう。

以下のコマンドを実行して、Red Hat社のUBIイメージをダウンロード(pull)します。

$ docker pull redhat/ubi8

特にドメイン名を指定していませんが、お約束として Docker Hubredhat/ubi8を探しに行ってpullしています。

pullしたイメージdocker imagesコマンドで確認します。

$ docker images
REPOSITORY                                                TAG       IMAGE ID       CREATED        SIZE
redhat/ubi8                                               latest    cc0656847854   7 days ago     216MB
$

pull したイメージを元に nginx-ubi8 という名前のコンテナを作成します。

$ docker run -dit -p 8080:80 --name nginx-ubi8 redhat/ubi8:latest

docker ps で起動を確認します。

$ docker ps
CONTAINER ID   IMAGE                COMMAND       CREATED         STATUS         PORTS                  NAMES
76304e983f34   redhat/ubi8:latest   "/bin/bash"   4 seconds ago   Up 3 seconds   0.0.0.0:8080->80/tcp   nginx-ubi8
$

docker exec コマンドを使い、コンテ内に新規にシェルを起動しコンテナの中に入ります。

$ docker exec -it nginx-ubi8  /bin/bash
[root@76304e983f34 /]#

コンテナの中に入ると、プロンプトが $ から [root@76304e983f34 /] 等に変わっているはずです。

このコンテナには特に何もアプリケーションがインストールされていないので、インストールしていきます。

ここからの作業は普通の Linuxと殆ど同じです。

yum で nginx をインストール

コンテナ内で、yumコマンド等でnginxをインストールします。

yum install -y nginx

nginx.conf を編集して 標準出力にログを吐くように変更

nginx.conf (nginxの構成ファイル)の編集は、コンテナを動かす事だけ考えるのであれば必須ではないですが、将来必ず通る道なので、コンテナ向きに少しカスタマイズします。

コンテナでは、コンテナ内のファイルシステムに書き込まれたデータは、コンテナの削除時に消えてしまいます。

基本的にコンテナは作って、廃棄して、また作って。を繰り返すものなので、保存したいデータはコンテナの外に書き出す作法になっています。ログも残したい場合は、その作法に従います。

Docker では標準出力と標準エラー出力をコンテナを動かしているホスト上に残す事ができ、吐き出したログはdocker logsコマンドでホスト上で確認できます。

nginxの構成ファイルであるnginx.confを編集して、nginx のログを標準出力、標準エラー出力に書き出すように編集します。

編集は vi で行います。viの使い方はここでは省略します。

/etc/nginx/nginx.conf
# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
# error_log /var/log/nginx/error.log;
error_log /dev/stderr; #(1) stderrに出力先を変更
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /dev/stdout  main; #(2) stdoutに出力先を変更する

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2 default_server;
#        listen       [::]:443 ssl http2 default_server;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers PROFILE=SYSTEM;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        location / {
#        }
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

}

ログの出力先の変更は2箇所で行ってます。
何かあった時もコンテナに入って確認してくも、コンテナの外からログを確認できるので便利です。

nginx を起動します。

コンテナ内でnginxを起動します。

nginx

このベースイメージには ps コマンドが入ってないのでここでは起動を確認せず、後でホストOSから curlでアクセス確認します。
yum -y install procpsで psコマンドをインストールするしてもOKですが、コンテナは基本的に小さく作る事が作法になっているので、できるだけ不要なものは入れないようにします。

コンテナからexit します。

exit

nginx にアクセスできる事を確認します。

$ curl localhost:8080

コンテナ内にコンテナの外の index.html をコピーする

デフォルトの index.html は、実験用としては少し懲りすぎているので、以下のようなシンプルな index.html ファイルをテキストエディタで作成します。

index.html
<html>
    <head>
        <title>Test Page for the Nginx HTTP Server on Red Hat Enterprise Linux</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    </head>
    <body>
       <p> Hello World </p>
    </body>
</html>

docker cp コマンドを使うとホストOS上のファイルを、コンテナ内にコピーできます。

以下のコマンドで、作成した index.htmlをコンテナ内の/usr/share/nginx/html/index.htmlに上書きします。

$ docker cp index.html nginx-ubi8:/usr/share/nginx/html/index.html

イメージを Commit する

今、稼働しているコンテナnginx-ubi8をイメージ化します。
イメージ名はタグ1.0を付加してnginx-ubi8:1.0 とする事にします。

これはdocker container commit というコマンドで実行できます。

$ docker container commit -c 'ENTRYPOINT ["nginx"]'  -c 'CMD ["-g","daemon off;"]'  nginx-ubi8  nginx-ubi8:1.0

ここで付けたオプションは以下の通りです。

-c 'ENTRYPOINT ["nginx"]': ENTRYPOINTはコンテナ実行時に、実行するコマンドと引数です。コンテナ開始時にnginxが実行されます。
-c 'CMD ["-g","daemon off;"]': CMDの指定値は、ENTRYPOINTの指定がある場合は、その引数となります。
nginx-ubi8: 生成するイメージの元になるコンテナ名です。
nginx-ubi8:1.0:コンテナから作成するイメージの名前です。

-c で指定している ENTRYPOINT や、CMDの少し難しく見えますが結果として、nginx -g "daemon off;" というコマンドがコンテナ起動時に実行されて、nginx が起動する事になります。

daemon offは、nginx のオプションで、通常だとバックグラウンドプロセスとして稼働する nginx をフォアグラウンドプロセスとして実行するためのオプションです。

これはコンテナがフォアグラウンドプロセスが無いと終了してしまうために、通常バックグラウンドでデーモンとして稼働する nginx をフォアグラウンドプロセスにするためのオプションです。コンテナが稼働し続けるにはフォアグラウンドで稼働し続けるプロセスが必要です。

作成したイメージの確認

イメージが作成されたか確認します。

$ docker images
REPOSITORY                                                TAG       IMAGE ID       CREATED         SIZE
nginx-ubi8                                                1.0       3b9b3870655f   5 seconds ago   303MB
redhat/ubi8                                               latest    cc0656847854   7 days ago           216MB

nginx-ubi8 で、TAG1.0 のつまり nginx-ubi8:1.0 が作成されているのがわかります。

自分が作成したイメージからコンテナを作る

自分が作成したイメージがきちんと使えるかコンテナを作って確認してみます。

イメージ名 nginx-ubi8:1.0 を指定して以下のように実行します。
8080ポートが使ったコンテナが動いてなけれれば8080を使っても良いですが、今度は8090を使ってみます。

$ docker run -d -p 8090:80 --name my-ubi-nginx nginx-ubi8:1.0

curl で確認してみると以下のような出力が返ってくるはずです。

$ curl localhost:8090
<html>
    <head>
        <title>Test Page for the Nginx HTTP Server on Red Hat Enterprise Linux</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    </head>
    <body>
       <p> Hello World </p>
    </body>
</html>
$

またアクセスログをコンテナ内のファイルに吐く設定から、標準出力に出すように変更したので、docker logsコマンドで nginx のアクセスログが確認できるはずです。先ほど curl でアクセスしたので以下のようにログが出ているはずです。

$ docker logs my-ubi-nginx
172.17.0.1 - - [16/Dec/2021:08:06:39 +0000] "GET / HTTP/1.1" 200 305 "-" "curl/7.58.0" "-"
$

Docker Hubに push する。

せっかくなので作成したイメージを Docker Hub にアカウントを作って保管します。

  1. Docker Hub にアカウントを作ります。(詳細は省略します)
  2. コマンドラインから Docker Hub にログインします。
$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: <username>
Password: 
Login Succeeded
$ 
  1. Docker Hub 用の名前を付ける

ローカルで作成したイメージ nginx-ibu8:1.0 に対して、レポジトリに保管するための別の名前を付けます。
Docker Hubに保管するための名前は、<username>/nginx-ibu8:1.0 のフォーマットである必要があります。

間に/が入る名前ははじめは少々気持ち悪いですが、Dockerの世界はこういうものだと割り切りましょう。

docker tag コマンドで以下のようにする事で、別の名前のイメージができます。

$  docker tag nginx-ubi8:1.0 <username>/nginx-ubi8:1.0

これで新しい名前のイメージができているはずです。
docker images を確認します。全く同じものですが、頭に <username>が付加された名前のイメージができているはずです。

ここでのは、yuhkih という私のテスト・アカウント名を使っています。

$ docker images
REPOSITORY                                                TAG       IMAGE ID       CREATED         SIZE
nginx-ubi8                                                1.0       bee26a68d934   3 days ago      303MB
yuhkih/nginx-ubi8                                         1.0       bee26a68d934   3 days ago      303MB
$

別名のイメージができたら、後は Docker Hubpushするだけです。
docker push コマンドでPUSHします。

$ docker push yuhkih/nginx-ubi8:1.0
The push refers to repository [docker.io/yuhkih/nginx-ubi8]
6f0e4904cc79: Pushed
0488bd866f64: Mounted from redhat/ubi8
0d3f22d60daf: Mounted from redhat/ubi8
1.0: digest: sha256:d77410be816bfede89bf99abf4b3b43b82c8bbe31c4d817b09a99ea7b03a16bb size: 949
$ 

以上で、Docker Hubへのpushは完了です。

これでどこに居ても、どの端末を使ってもDocker Hubに繋がる環境であれば、自分が作成したイメージをpullして使えるようになりました。

以上で演習3は完了です。お疲れ様でした。

演習4 : Dockerfile を使ってオリジナルの nginx のイメージを作る

今度は演習3と同じ内容をDockerfileを使用して行います。Dockerfileでビルドの作業をスクリプト化できます。

image.png

Dockerfile を書く

Dockerfile を使うと、演習3でやった元ネタになるイメージのダウンロード、イメージへの nginx のインストールまでの各種作業をスクリプト化できます。

演習3でやった作業を Dockerfile にすると以下になります。

FROM redhat/ubi8
RUN yum install -y nginx
COPY index.html /usr/bin/share/nginx/html/index.html
COPY nginx.conf /etc/nginx/nginx.conf
CMD ["-g","daemon off;"]   
ENTRYPOINT ["nginx"]

このファイル名はDockerfileという名前にします。この名前は docker で決められている名前です。
変更もできますが、変更した場合は、変更後の名前を引数で指定する必要があり、コマンドが長くなるので、ここではデフォルトの名前を使用します。

Dockerfileの中身の解説は以下の通りです。

FROM redhat/ubi8 : Docker Hub から redhat/ubi8 を PULLします。
RUN yum install -y nginx : redhat/ubi8 に nginx をインストールします。
COPY index.html /usr/share/nginx/html/index.html: ホストOS上の[index.html]をコンテナ内の[/usr/share/nginx/html/index.html]にコピーします。
COPY nginx.conf /etc/nginx/nginx.conf : ホストOS上の[nginx.conf]をコンテナ内の[/etc/nginx/nginx.conf]にコピーします。
CMD ["-g","daemon off;"]: コンテナ実行時に実行するコマンドのオプションです。演習3で[docker container comit]で指定したのと同じものです。
ENTRYPOINT ["nginx"] : コンテナ実行時に実行するコマンドです。演習3で[docker container comit]で指定したのと同じものです

次にコンテナ内にコピーする nginx.confindex.htmlを作ります。コピペ用に以下に内容を書きますが、内容は演習3で作成したものと全く同じです。

演習3では、nginx.conf はコンテナ内で直接編集しましたが(外で作成したものをコンテナ内にコピーしても良かったのですが、たまたまです)、ここではホストOS上にnginx.confを作ります。

/etc/nginx/nginx.conf
# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
# error_log /var/log/nginx/error.log;
error_log /dev/stderr; #(1) stderrに出力先を変更
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /dev/stdout  main; #(2) stdoutに出力先を変更する

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2 default_server;
#        listen       [::]:443 ssl http2 default_server;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers PROFILE=SYSTEM;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        location / {
#        }
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

}
index.html
<html>
    <head>
        <title>Test Page for the Nginx HTTP Server on Red Hat Enterprise Linux</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    </head>
    <body>
       <p> Hello World </p>
    </body>
</html>

これらのファイルはDockerfileと一緒に同じディレクトリに置きます。
必要なファイルが揃っていれば以下のようになっているはずです。

$ ls -ltr
total 16
-rw-r--r-- 1 yuhki yuhki  305 Dec 23 11:33 index.html
-rw-r--r-- 1 yuhki yuhki  178 Dec 23 14:19 Dockerfile
-rw-r--r-- 1 yuhki yuhki 2551 Dec 23 15:15 nginx.conf
$

build する

docker buildコマンドを実行すると、Dockerfileという名前のファイルを探してきてその内容の作業を実行し、新しいイメージを作成してくれます。Dockerfileという名前は変更もできますが、変更した場合は変更後のファイルを引数で指定する必要があります。

新しく生成されるイメージ名をyuhkih/nginx-ubi8-2:1.0にします。

以下のコマンドでビルドを実行します。

$ docker build . -t yuhkih/nginx-ubi8-2:1.0

.で、カレントディレクトリのDockerfileを探しに行きます。

この名前は

yuhkih : 筆者の Docker Hub のユーザー名
nginx-unbi8-2 : このイメージの名前のコア部分
1.0 : このイメージのタグ

をくっつけたものです。
Docker Hub のユーザー名を先頭につけたのは、後で Docker Hub にこのイメージをpushする事を考えているためです。
Docker Hubに保管するイメージは、イメージ名の先頭に<ユーザー名>/を付ける事が決まりになっているため、イメージ作成時にあらかじめ付けておきます。逆に言うと、Docker Hubにイメージをpushせずにローカルで使うだけであれば、こう言った名前の付け方は必要ありません。

最後に1.0という名前のタグを付けていますが、これを付けなかった場合は、latestというタグが自動で付きます。

名前の付け方にいろいろルールがあり面倒ですが、このネーミング・ルールになれる必要があります。

ビルドしたイメージの確認

docker imagesコマンドで、ビルドされたイメージを確認します。

$ docker images
REPOSITORY                                                TAG       IMAGE ID       CREATED         SIZE
yuhkih/nginx-ubi8-2                                       1.0       9539618c5467   5 hours ago     307MB
...

Docker Hub に push する。

作成したイメージを Docker Hubpushします。

Docker Hub にログインします。

$ docker login -u yuhkih -p <パスワード>

Docker Hubpushします。イメージ名の先頭が<user名>/のフォーマットになっている必要があります。

$ docker push yuhkih/nginx-ubi8

Docker Hub に 上がった事を確認する

Repository 名を引数に docker search する事で docker Hub 上のイメージを確認できます。

$ docker search yuhkih
NAME                  DESCRIPTION   STARS     OFFICIAL   AUTOMATED
yuhkih/nginx-ubi8-2                 0
...

無事に docker Hub に上がっている事が確認できました。

以上で演習4は完了です。お疲れ様でした。

閑話休題:コンテナの整理に便利なオプション

docker のイメージから作られたコンテナは、起動する度にドンドン溜まっていきます。

既に使った名前があると、同じ名前のコンテナが作れなかったり、いろいろ不便ですので、使わなくなったコンテナは、こま目に消していく必要があります。

ここでは良く使われる、コンテナの削除に便利なコマンドを紹介します。

docker run 時に --rm オプションを付ける

--rm オプションで、停止 (docker stop)した時に自動的に消えるコンテナを作る事ができます。

docker run --rm -itd --name my-test  <イメージ名>

コンテナを一気に消す

現在稼働中のコンテナ以外のコンテナを一括削除します。

$ docker system prune
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all dangling images
  - all dangling build cache

Are you sure you want to continue? [y/N] y

<snip>

Total reclaimed space: 137.2MB
$ 
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?