レポート課題44・5日目・180分×2T3情報工学4_[学生番号]_[氏名].pdf
4・5日目 Webサーバー
Webサーバーの定番ソフトNginxをコンテナで動かし、自分で書いたHTMLのページをブラウザに届けます。後半では、Webサーバーが残した記録(アクセスログ)を集計し、グラフつきのレポートにします。
この日のゴール
- Nginxのコンテナが Docker Compose で動き、80番でWebページを返している
- Ubuntuに置いた
/opt/nginx/html/index.htmlが、Windowsのブラウザで表示される - アクセスの記録(アクセスログ)が Ubuntu 側の
/opt/nginx/log/access.logに残っている - GoAccessでアクセスログを集計したレポートが、ブラウザで見られる
この日に出てくる主な言葉:
DNS(BIND9)の構築は付録2にまとめられていて、この日のページから参照されています。
Webページが表示されるまで
ブラウザにURLを打ち込むと、ブラウザ(クライアント)とWebサーバーの間で、HTTPという約束事に沿ったやり取りが1往復行われます。考察のヒント課題1は、この流れを一般論ではなく、自分の実験の値(IPアドレス、ポート80、パス、返ってきた200)で説明すると具体的になります。名前で開いた場合は、最初に名前をIPアドレスに変換する段階が加わります。
URLの読み方
http://通信の方式(HTTP)192.168.100.xxx相手のサーバー(IPアドレスか名前):80ポート番号。http なら省略すると80/goaccess-report.htmlサーバーの中のどのファイルか(パス)パスを / だけにすると、Webサーバーは決まったファイル(Nginxでは index.html)を返します。
結果の番号(ステータスコード)
| 番号 | 意味 | この実験で出る場面 |
|---|---|---|
200 OK | 成功 | ページが正しく表示されたとき |
403 Forbidden | 見せられない | index.html を置く前に / を開いたとき(手順2)考察のヒント403 や 404 が出たことも立派な結果です。「どの段階で、なぜその番号が返ったか」を説明できれば、Webサーバーの仕組みを理解していることを示せます。 |
404 Not Found | そのファイルはない | ファイル名の打ち間違い(大文字・小文字も区別される) |
502 Bad Gateway | 取り次ぎ先が応えない | 6・7日目、Open WebUIがまだ起動していないとき |
compose.yaml を読む
この日のcompose.yamlには、Nginx(Webサーバー)と GoAccess(ログの集計係)の2つのサービスが書かれています。
services:
nginx:
image: nginx:stable
container_name: nginx-proxy
ports:
- "80:80"
volumes:
- /opt/nginx/html:/usr/share/nginx/html:ro
- /opt/nginx/log:/var/log/nginx
restart: unless-stopped
goaccess:
image: allinurl/goaccess
container_name: goaccess-report
profiles: ["tools"]
volumes:
- /opt/nginx/log:/srv/log:ro
- /opt/nginx/html:/srv/report
command:
- --log-format=COMBINED
- -f
- /srv/log/access.log
- -o
- /srv/report/goaccess-report.html| 行 | 意味 |
|---|---|
image: nginx:stable | Nginxの安定版のイメージを使う |
container_name: nginx-proxy | コンテナの名前。6日目に「proxy(取り次ぎ役)」として使うので、この名前になっている |
ports: - "80:80" | Ubuntuの80番を、コンテナの80番につなぐ |
volumes: | Ubuntuのディレクトリを、コンテナの中のディレクトリとして見せる(バインドマウント。下の図) |
:ro | read only(読み取り専用)。コンテナの中からは書き換えられない |
profiles: ["tools"] | 普段の up では起動しない道具として登録する(プロファイル)。使うときだけ docker compose run で呼ぶ |
command: | GoAccessに渡す指示。「COMBINED形式のログ /srv/log/access.log を読み、結果を /srv/report/goaccess-report.html に書け」 |
ホストのディレクトリをコンテナに見せる
ホストのディレクトリを重ねて見せると、コンテナのイメージに最初から入っていた同じ場所の中身は見えなくなります。これが、次の手順2で最初に「403」が出る理由です。考察のヒントHTMLをUbuntu側に置いたので、ページを書き換えてもコンテナを作り直す必要がなく、コンテナを消してもページとログは残ります。「プログラム(コンテナ)」と「データ(HTML・ログ)」を分けることの利点が、課題2の軸になります。
手順の解説
スクリーンショット(エビデンス)を撮るところ。マウスを乗せると撮るタイミングが表示され、押すとページ下のエビデンス一覧の該当項目へ移動します。考察を書くときに知っておきたいこと。マウスを乗せる(スマホでは押す)とヒントが表示されます。
2.1 第1段階:Nginxだけを動かす
ディレクトリとcompose.yamlを作る
sudo mkdir -p /opt/nginx/html
sudo mkdir -p /opt/nginx/log
sudo nano /opt/nginx/compose.yamlnanoが開いたら、上の compose.yaml の内容を貼り付けて保存します。
Nginxを起動して最初の確認をする
cd /opt/nginx
sudo docker compose config
sudo docker compose up -d
sudo docker compose ps3日目と同じ流れです。ps で nginx-proxy が Up になり、PORTS に 0.0.0.0:80->80/tcp と出ていれば起動しています。エビデンス2の撮影ポイント撮影ポイント エビデンス2手順2の cd /opt/nginx のあとで sudo docker compose ps を実行した直後。nginx-proxy の STATUS が Up、PORTS が 0.0.0.0:80->80/tcp になっていることが分かるように撮る。エビデンス一覧の項目へ移動 ↓goaccess はプロファイル付きなので、ここでは起動しません。
curl http://localhostここで「403 Forbidden」が出るのは正常
この時点の /opt/nginx/html は空っぽです。それがコンテナの配信場所に重ねて見せられているので、Nginxは返すべき index.html を見つけられず、403 Forbidden のページを返します。次の手順3でHTMLを置けば解決します。考察のヒント予想と違う結果が出たときに、その理由を仕組みから説明できると、考察の評価が上がります。この403は「空のディレクトリを重ねたことで、イメージに入っていたページが見えなくなった」ことで説明できます。
3日目に見たとおり、Dockerが公開した80番は、ufwで許可していなくても外から届きます(3日目の解説)。
HTMLのページを書く
sudo nano /opt/nginx/html/index.html<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>T3 Lab Web Server</title>
</head>
<body>
<h1>T3 Lab Web Server</h1>
<p>Nginx on Docker is running.</p>
</body>
</html>HTMLは、文章を <タグ> で囲んで、「ここは見出し」「ここは段落」と意味を付けていく言語です。
| 部分 | 意味 |
|---|---|
<!doctype html> | 「これは今のHTMLの文書です」という宣言 |
<html lang="ja"> | 文書の始まり。主な言語は日本語 |
<head> 〜 </head> | 画面には出ない、文書についての情報 |
<meta charset="utf-8"> | 文字の符号化方式。日本語を書くなら必須で、ないと文字化けする |
<title> | ブラウザのタブに出る題名 |
<body> 〜 </body> | 画面に表示される本体 |
<h1> | いちばん大きな見出し |
<p> | 段落 |
中身は自由に変えてかまいません。保存した瞬間から、Nginxはこのファイルを返すようになります。コンテナを作り直す必要がないのは、バインドマウントでUbuntuのファイルをそのまま見せているからです(課題2の材料)。
見出しや表、色づかいを整えたページにしたいときは、サイトを制作で部品を組み合わせて index.html を作り、ここに置き換えられます(必須ではありません)。
ブラウザで表示する
WindowsのブラウザでURL欄に http://192.168.100.xxx/ を入れ、書いたページが表示されることを確かめます。エビデンス1の撮影ポイント撮影ポイント エビデンス1手順4で、ブラウザに手順3で書いたページが表示された時点。URL欄の http://192.168.100.xxx/ も写るように撮る。サーバーの中で curl http://localhost を実行し、HTMLが返ってきた画面でもよい。エビデンス一覧の項目へ移動 ↓サーバーの中からは curl http://localhost でもHTMLの中身が返ってきます。
2.2 第2段階:アクセスログを集計する
手順4までにブラウザでページを開くたびに、Nginxはその記録をアクセスログに1行ずつ書き足しています。第2段階では、GoAccessというツールでそれを集計し、グラフつきのHTMLのレポートにします。集計する前に、ブラウザで何度かページを再読み込みしたり、わざと存在しないページ(http://192.168.100.xxx/nothing.html など)を開いたりして、記録を増やしておくと、レポートが見やすくなります。
アクセスログの1行を読む
192.168.100.50 - - [29/Sep/2026:10:15:32 +0000] "GET / HTTP/1.1" 200 180 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) … Chrome/… Safari/537.36"192.168.100.50アクセスしてきた相手のIPアドレス- -利用者の識別(今回は使われていない)[29/Sep/2026:10:15:32 +0000]日時(+0000 はUTC)"GET / HTTP/1.1"要求の内容200結果の番号(ステータスコード)180返したデータの大きさ(バイト)"-"どのページから来たか(直接なら -)"Mozilla/5.0 …"ブラウザの種類(User-Agent)この並び方が「COMBINED(コンバインド)形式」で、GoAccessに --log-format=COMBINED と伝えているのはこのためです。考察のヒントわざと存在しないページを開いて404を記録しておくと、課題3で「異常がレポートのどこにどう現れるか」を、自分のデータで具体的に示せます。
GoAccessでレポートを作る
cd /opt/nginx
sudo docker compose run --rm goaccessdocker compose runこのサービスを1回だけ動かす--rm終わったらコンテナを消すgoaccesscompose.yaml に書いたサービスの名前GoAccessのコンテナは、ログを読み(/opt/nginx/log を読み取り専用で)、レポートを書き出し(/opt/nginx/html に)、終わると消えます。書き出し先がNginxの配信場所と同じディレクトリなので、できたレポートはすぐにブラウザで見られます。ログが空だとレポートも空っぽになるので、先にアクセスを増やしておきます。エビデンス4の撮影ポイント撮影ポイント エビデンス4手順5でGoAccessを動かす前(後でもよい)に、sudo ls -l /opt/nginx/log/access.log を実行した直後。ファイルがUbuntu側にあり、大きさが0でない(記録がたまっている)ことが分かるように撮る。エビデンス一覧の項目へ移動 ↓
レポートは実行した時点の集計です。新しいアクセスを反映させたいときは、もう一度このコマンドを実行します。
レポートを見る
ブラウザで http://192.168.100.xxx/goaccess-report.html を開きます。エビデンス5の撮影ポイント撮影ポイント エビデンス5手順6で、ブラウザにGoAccessのレポートが表示された時点。URL欄と、上部の集計(Total Requests、Unique Visitors など)が写るように撮る。エビデンス一覧の項目へ移動 ↓英語の表示ですが、主な欄は次のとおりです。
- Unique visitors per day
- 日ごとの訪問者数
- Requested Files
- よく要求されたページ
- Not Found URLs (404s)
- 存在しないページへの要求。打ち間違いや、弱点を探す自動のアクセスが現れる
- Visitor Hostnames and IPs
- アクセス元のIPアドレス
- Operating Systems / Browsers
- アクセスしてきたOSやブラウザの種類
- HTTP Status Codes
- 結果の番号ごとの件数
課題3(運用監視や障害調査での利点)を考えるときは、「生のログを目で追う場合と比べて、何が一目で分かるようになったか」を具体的に書けるよう、レポートの中で気づいたことをメモしておきましょう。考察のヒント生のログを目で追う場合と比べて、何が一目で分かるようになったかを書きます。404の件数、アクセス元の偏り、時間帯など、自分のレポートで実際に見えたことを例に挙げると説得力が出ます。
docker compose logs にアクセスの記録が出ない理由
エビデンス3では docker compose logs --tail 20 でNginxのログを見ますが、ここに出るのは主に起動時のメッセージ(Configuration complete; ready for start up など)です。Nginxの公式イメージは、本来アクセスログを画面側(docker compose logs で見える側)に出す作りですが、この構成では /var/log/nginx にUbuntuのディレクトリを重ねているため、アクセスログはファイル /opt/nginx/log/access.log に書かれます。アクセスの記録はそちらで確かめます。
シェルスクリプトとAIの活用(目的にあるが手順がない項目)
指導書の目的と手順の差
この日の目的には「AI(Gemini等)を活用したトラブルシューティングを体験し、シェルスクリプトによる自動化を行う」とありますが、具体的な手順は書かれていません。授業で指示があるはずなので、ここでは理解のための予備知識と、練習用の例をまとめます。
シェルスクリプトとは
シェルスクリプトは、打ちたいコマンドを順番に書いておいたファイルです。一度書けば、何度でも同じ順番・同じ内容で実行できます。手作業の打ち間違いがなくなり、手順そのものが記録として残ります。指導書の基礎知識が「手動でのサーバー構築作業はミスを誘発しやすい」と書いているのは、このためです。考察のヒント手作業とスクリプトを比べるときは、打ち間違い、同じ結果の再現、ほかの人への引き継ぎ、作業の記録の4点で比べると、自動化の意義を整理しやすくなります。
次は、この日の確認作業をまとめて行う練習用の例です(指導書の手順ではありません)。
nano ~/check-web.sh#!/bin/bash
# check-web.sh : Webサーバーの状態をまとめて確認する
set -eu
cd /opt/nginx
echo "== コンテナの状態 =="
sudo docker compose ps
echo "== トップページの応答コード =="
curl -s -o /dev/null -w "%{http_code}\n" http://localhost
echo "== アクセスログの行数 =="
sudo wc -l /opt/nginx/log/access.log| 行 | 意味 |
|---|---|
#!/bin/bash | このファイルを bash で実行する、という指定(シバン(#!))。必ず1行目に書く |
# … | コメント(説明のメモ) |
set -eu | 途中でエラーが起きたらそこで止まる(-e)、書き間違えた変数を使ったら止まる(-u)。失敗に気づかず先へ進むのを防ぐ |
echo "…" | 文字を表示する。見出しの代わり |
curl -s -o /dev/null -w "%{http_code}\n" … | ページの中身は捨てて(-o /dev/null)、結果の番号だけを表示する。200 なら正常 |
wc -l | ファイルの行数を数える。アクセスログ1行=アクセス1回 |
保存したら、実行してよいファイルという権限を付けてから実行します。
chmod 755 ~/check-web.sh
~/check-web.shこのように、確認・集計・設定の反映など、毎回同じ手順になる作業は、スクリプトにすると楽で確実になります。レポートにスクリプトを載せるときは、全体を貼るのではなく、工夫した部分を抜き出して本文で説明します(ソースコードの載せ方)。
AIをトラブルシューティングに使うとき
指導書は、AIを「支援役」として使う前提を示しています。質問するときは、環境・やったこと・出たエラーの全文を伝えると、的外れな答えが減ります。そのまま使える相談の型をトラブル対処集にまとめました。AIの提案は必ず自分で意味を確かめてから実行し、レポートで使った場合は付記に書きます。
結果と考察のための確認コマンド
第1段階(Nginxのみ):エビデンス3の撮影ポイント撮影ポイント エビデンス3第1段階の確認で sudo docker compose logs --tail 20 を実行した直後(/opt/nginx で)。起動時のメッセージ(Configuration complete; ready for start up など)が写っていればよい。アクセスの記録はファイル側に書かれるので、ここには出ない。エビデンス一覧の項目へ移動 ↓
curl http://localhost
cd /opt/nginx
sudo docker compose ps
sudo docker compose logs --tail 20第2段階(Nginx+GoAccess):
cd /opt/nginx
sudo ls -l /opt/nginx/log/access.log
sudo docker compose run --rm goaccessエビデンス(スクリーンショット5点)
cd /opt/nginx && … の && は、「左のコマンドが成功したら、続けて右のコマンドを実行する」という意味です。
課題を考えるための材料
課題1Webサーバーがブラウザからの要求に応じてコンテンツを返す仕組みを説明せよ。
知っておくとよい事実
- ブラウザは、URLから相手(名前ならIPアドレスに変換する)とポート(http なら80)を決めて接続し、HTTPのリクエストを送る
- リクエストには、方法(GET など)、欲しいファイルのパス、ブラウザの情報などが含まれる(3日目の whoami の表示がまさにその中身)
- Webサーバーは、パスに対応するファイルを探し、結果の番号(ステータスコード)と中身をレスポンスとして返す
- ブラウザは受け取ったHTMLを解釈して画面を描く
考える観点
- 図1のような流れを、自分の実験の具体的な値(IPアドレス、パス、200や403)で説明できるか
- この実験では、Nginxがコンテナの中にいる。Windowsから届いた通信が、どこを通ってNginxにたどり着くか(ポート公開)
- 手順2の403や、存在しないページの404は、この仕組みのどこで起きたのか
課題2ホスト側で作成したHTMLファイルをDockerコンテナにマウントして配信する方式には、どのような利点があるか説明せよ。
知っておくとよい事実
- コンテナの中に直接書いたファイルは、コンテナを削除すると一緒に消える
- バインドマウントでは、コンテナの中の場所が、実際にはホストのディレクトリそのものになる(図2)
:roを付けると、コンテナの側からは書き換えられない- 同じディレクトリを、Nginx(読むだけ)とGoAccess(書き込む)という別々のコンテナで共有している
考える観点
- ページを書き換えるたびにイメージを作り直す方式と比べて、何が楽になり、何が安全になるか
- Nginxのイメージを新しい版に入れ替えるとき、中身(HTML)はどうなるか
- 「プログラム(コンテナ)」と「データ(HTML・ログ)」を分けておくことの意味
課題3アクセスログをGoAccessで可視化することで、運用監視や障害調査にどのような利点があるか説明せよ。
知っておくとよい事実
- アクセスログには、1回のアクセスごとに、相手・日時・要求・結果・大きさ・ブラウザが記録される
- アクセスが増えると、ログは人が目で追えない量になる
- GoAccessは、ステータスコードごとの件数、よく見られたページ、404の一覧、アクセス元などを集計して表やグラフにする
考える観点
- 「障害が起きている」ことに、どの欄を見れば早く気づけるか(404や5xxの急増など)
- 不審なアクセス(存在しないページを大量に探すなど)は、レポートのどこに現れそうか
- アクセスの多い時間帯やページが分かると、運用上どんな判断に使えるか
- 自分のレポートで実際に見えたことを例に挙げると、説得力が増す