🎯 最終演習

DockerでWebサーバーを立てて片付けるまでを通しでやってみよう(総合演習)

ここまでの Docker レッスンで学んだコマンドをひとつの流れにつないで、コンテナの一生を最後まで見届けます

やることは「イメージを取得する → コンテナとして起動する → 動いているか確かめる → 止めて片付ける」。Dockerを使う日は、ほぼ毎日この順序をなぞることになります。

この4つが手に馴染むと、Dockerは急に怖くなくなります。コンテナは壊れたら消して作り直せばよい——その感覚が身につくのが、この演習のいちばんの狙いです。

ページの一番下に本物の疑似ターミナルがあります。読むだけで終わらせず、必ず自分で打ってみてください。状態はコマンドをまたいで続くので、上から順に打てばそのまま完走できます。

完成イメージ

最後まで進むと、こう表示されるところまで作ります。下の実行結果は、このページを作るときに実際にコードを走らせて得たものです。

$ docker ps -a
CONTAINER ID   IMAGE          COMMAND     STATUS          PORTS       NAMES
$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE

STEP 1手元を確かめて、イメージを取ってくる

🎯 このステップのゴール: docker images で「まだ何も無い」ことを見てから、nginx のイメージを取得する

まずdocker --versionで、Dockerが動いていることを確かめます。これが返らないときは、Dockerそのものが起動していません

次がdocker images手元にあるイメージの一覧で、いまは見出しだけで中身が空です。この「空の状態」を先に見ておくのが大事で、次のコマンドで何が増えたのかがはっきり分かります。

docker pull nginxで、Webサーバーの公式イメージを取ってきます。イメージは「設計図」、コンテナは「そこから起動した実物」——この2つの区別が、Dockerを理解する土台になります。

取得の途中でPull completeDigestが流れます。イメージは層(レイヤー)の積み重ねでできており、すでに持っている層は再取得されません。2回目以降が速いのはこのためです。

もう一度docker imagesを打つと、nginx が1件だけ増えています。まだ起動はしていません。設計図を手に入れただけの状態です。

打つコマンド
docker --version
docker images
docker pull nginx
docker images
実行結果
$ docker --version
Docker version 24.0.7, build afdd53b
Docker Compose version v2.24.5
$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
$ docker pull nginx
latest: Pulling from library/nginx
a1b2c3d4e5f6: Pull complete
Digest: sha256:00009e3779b1...
Status: Downloaded newer image for nginx:latest
$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
nginx        latest    00009e3779b1   数秒前            142MB

STEP 2コンテナとして起動して、外から見えるようにする

🎯 このステップのゴール: docker run に -d・--name・-p を付けて、名前の付いたコンテナを裏で動かす

いよいよ起動です。docker run -d --name web -p 8080:80 nginx——3つのオプションにそれぞれ役割があります

-dは「裏で動かす」。付けないとログが画面に流れ続け、そのターミナルが使えなくなります。動かし続けるものには、ほぼ必ず付けます

--name webは名前付けです。付けないとDockerがvibrant_einsteinのような名前を勝手に付けます。以降のコマンドをすべてwebという名前で指定できるので、付けておくと後が楽になります。

-p 8080:80が、この演習でいちばん間違えやすいところです。左がパソコン側、右がコンテナ側。「パソコンの8080番に来た通信を、コンテナの80番へ渡す」という意味で、逆に書くと繋がりません

返ってきた長い英数字がコンテナIDです。docker psで確認すると、STATUS が runningPORTS に 8080:80と出ています。ここまで来れば、ブラウザでlocalhost:8080を開けばnginxの画面が見える状態です。

打つコマンド
docker run -d --name web -p 8080:80 nginx
docker ps
実行結果
$ docker run -d --name web -p 8080:80 nginx
00003c6ef362
$ docker ps
CONTAINER ID   IMAGE          COMMAND     STATUS          PORTS       NAMES
00003c6ef362   nginx:latest   (image既定のコ  running         8080:80     web

STEP 3本当に動いているのか、中を覗いて確かめる

🎯 このステップのゴール: docker logs と docker top で、コンテナの中で何が起きているかを見る

-dで裏に回したので、画面には何も出てきません。動いているかどうかを知る手段が要ります。

docker logs webが最初の一手です。コンテナの中のプログラムが出力した内容が読めます。listening on port 80と出ていれば、nginxはちゃんと待ち受けています。

うまく動かないときも、まずここを見ます。設定ファイルの書き間違いも、必要なファイルが無いことも、たいていログに出ています。「起動したのにすぐ終わる」ときは、docker ps -aで見つけてからdocker logs——これが調査の型です。

docker top webでは、コンテナの中で動いているプロセスが見えます。nginxのマスタープロセスとワーカープロセスが並んでいます。

ここにコンテナの正体が現れています。コンテナの中のプロセスは、ホストから見れば普通のプロセスです。仮想マシンのように別のOSが丸ごと動いているわけではなく、隔離されているだけ——だからコンテナは数秒で起動します

打つコマンド
docker logs web
docker top web
実行結果
$ docker logs web
[notice] nginx:latest を起動しました
[notice] listening on port 80
[info] Ready to accept connections
$ docker top web
UID    PID    PPID   CMD
root   1234   1      nginx: master process
root   1256   1234   nginx: worker process

STEP 4起動時の設定を読み、ファイルを送り込む

🎯 このステップのゴール: docker inspect で設定を確かめ、docker cp で手元のファイルをコンテナへ渡す

docker inspect webは、そのコンテナの設定をすべて表示するコマンドです。IDや元になったイメージ、いまの状態が読み取れます。

これが必要になる理由があります。ポートの公開も名前も、docker runを打った瞬間に固定されます。あとから変えることはできません。だから「このコンテナはどんなオプションで起動したのか」を後から知る手段が要るのです。

実際の出力は数百行になるので、実務では--formatで必要な項目だけを取り出します。

次にdocker cpで、手元のindex.htmlをコンテナの中に送り込みます。nginxが公開しているフォルダに置けば、ブラウザに映る内容が自分のページに変わります

ただし、この方法は覚え書きにしないでください。docker cpで入れたファイルは、コンテナを作り直すと消えます本来はDockerfileのCOPYで焼き込むか、-vで外のフォルダを繋ぎます。どちらも「作り直しても同じ結果になる」やり方です。手作業で中身を直した環境は、再現できません——これはDockerを使う意味そのものに関わる話です。

打つコマンド
docker inspect web
docker cp ./index.html web:/usr/share/nginx/html/
実行結果
$ docker inspect web
[
  {
    "Id": "00003c6ef362",
    "Name": "/web",
    "Image": "nginx:latest",
    "State": { "Status": "running" }
  }
]
$ docker cp ./index.html web:/usr/share/nginx/html/
./index.html を web:/usr/share/nginx/html/ にコピーしました

STEP 5止めて、また動かす

🎯 このステップのゴール: stop と start の違い、そして「止めても消えていない」ことを目で確かめる

docker stop webで停止します。いきなり切るのではなく、まず「終わってください」という合図を送り、10秒待ってから強制終了します。この猶予のあいだに、コンテナの中のプログラムは書きかけのファイルを保存したり、接続を閉じたりできます。

止めた直後にdocker psを打つと、何も出てきません。ここで「消えた」と思うのが、Dockerを始めた人がまず引っかかる場所です。

docker ps -aを打ってください。-aを付けると、停止中のものも含めて全部が出ます。webexitedという状態で、ちゃんと残っています。

コンテナは停止しても消えません。中のファイルもログもそのままです。だから落ちたコンテナのログを後から読める——さっき見たdocker logsが、失敗の調査に使える理由がこれです。

docker start webで再開します。停止する前の状態がそのまま戻りますdocker runとの違いがここで、runは毎回新しいコンテナを作り、startは既にあるものを動かし直します何度もrunを打つと停止したコンテナが溜まっていくのは、この違いを知らないときに起こります。

打つコマンド
docker stop web
docker ps
docker ps -a
docker start web
docker ps
実行結果
$ docker stop web
web
$ docker ps
CONTAINER ID   IMAGE          COMMAND     STATUS          PORTS       NAMES
$ docker ps -a
CONTAINER ID   IMAGE          COMMAND     STATUS          PORTS       NAMES
00003c6ef362   nginx:latest   (image既定のコ  exited (0)      8080:80     web
$ docker start web
web
$ docker ps
CONTAINER ID   IMAGE          COMMAND     STATUS          PORTS       NAMES
00003c6ef362   nginx:latest   (image既定のコ  running         8080:80     web

STEP 6きれいに片付けて完了

🎯 このステップのゴール: コンテナとイメージを順に削除し、最初の空の状態に戻す

最後は片付けです。順序に決まりがあります

動いているコンテナは削除できません。まずdocker stop webで止め、それからdocker rm webで消します。

ここで何が失われるかを、はっきり意識してください。docker rmすると、そのコンテナの中で作ったファイルも、さっきdocker cpで送り込んだファイルも、全部消えます。コンテナは「イメージの上に載った書き込み層」で動いていて、削除するとその層ごと捨てられるからです。残したいデータは、あらかじめボリュームで外に置いておく必要があります。

次にdocker rmi nginxでイメージを消します。rmiはremove imageの略です。コンテナが残っているとイメージは消せません——だからコンテナが先、イメージが後、という順序になります。

最後にdocker ps -adocker imagesで確かめます。どちらも見出しだけ——ステップ1で見た、あの空の状態に戻りました。

これで完走です。取得 → 起動 → 確認 → 停止 → 削除。この一周を自分の手で回せたなら、Dockerの日常操作はもう扱えます。あとはDockerfileで自分のイメージを作る、Composeで複数のコンテナをまとめて動かす——どちらもこの一周の上に乗っているだけです。

ページ下の疑似ターミナルで、ここまでを最初から自分の手で通してみてください。読んで分かるのと打てるのは、別物です。

打つコマンド
docker stop web
docker rm web
docker rmi nginx
docker ps -a
docker images
実行結果
$ docker stop web
web
$ docker rm web
web
$ docker rmi nginx
Untagged: nginx:latest
Deleted: sha256:00009e3779b1...
$ docker ps -a
CONTAINER ID   IMAGE          COMMAND     STATUS          PORTS       NAMES
$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE

仕上げ自分で最初から打ってみよう

🎯 このステップのゴール: ここまでの流れを、自分の手で最後まで通す

下は本物の疑似ターミナルです。まっさらな状態から始まるので、STEP1のコマンドから順に打って、マージまで辿り着いてください。読んで分かった気になるのと、自分で打てるのとは別物です。

詰まったら上のステップに戻って構いません。resetと打てば最初からやり直せます。

$

よくある質問

コンテナIDがページと違います

それで正常です。コンテナIDもイメージIDも、起動のたびに新しく作られます。このページに載っているIDは、生成時に実際に実行して得たものをそのまま載せているだけで、あなたの手元と一致する必要はありません。

止めたのにディスクの空きが増えません

停止と削除は別物だからです。docker stopはプログラムを止めるだけで、コンテナ本体もイメージもディスクに残ります。

本当に消したいならdocker rm(コンテナ)とdocker rmi(イメージ)まで進めます。溜まったものをまとめて片付けるならdocker system pruneですが、--volumesを付けるとデータごと消えて戻せません。実行する前にdocker system dfで何がどれだけ使っているかを見てください。

ブラウザで localhost:8080 を開いても表示されません

まずdocker psPORTS列を見てください。ここが空欄なら、-pを付け忘れています。コンテナは隔離されたネットワークにいるので、この指定が外から届く唯一の入口です。

PORTSが出ているのに繋がらないなら、左右を逆に書いていないかを確認します。-p 8080:80の左がパソコン側、右がコンテナ側です。

それでも駄目ならdocker logsです。コンテナ自体が起動直後に落ちていることがあります。

この演習では Dockerfile を書かないんですか?

この疑似ターミナルにはエディタが無いため、ここでは公式イメージをそのまま動かす構成にしています。

Dockerfileの書き方はレッスン側で扱っていますFROMで土台を選び、COPYでファイルを入れ、CMDで起動時のコマンドを決める——そこまで進むと、この演習で使ったdocker run自分で作ったイメージに対して打てるようになります。

🚩 次はこのカテゴリへ

コンテナを手元で動かせるようになったら、次はそれを置く場所です。AWSカテゴリでは、サーバーを借りる、ファイルを置く、権限を渡す、といったクラウドの基本操作をコマンドで練習できます。Dockerで作ったものを世に出すとき、必ず通る道です。

AWSコマンドのレッスンへ進む
広告スペース(バナー)
広告スペース(記事内)