🌐
URLからブラウザ表示までの流れとDockerの役割
URLからブラウザ表示まで
Webリクエストの裏側とDockerの役割
ブラウザにURLを入力してからページが表示されるまで、何が起きているのかを理解する
今日学ぶこと
- URLの仕組み - URLとは何か
- ブラウザからサーバーへ - リクエストの送信
- サーバーでの処理 - データの準備と生成
- ブラウザへの返答 - レスポンスの受信
- ブラウザでの表示 - HTMLのレンダリング
- Dockerの役割 - 開発環境での活用
URLとは?
Uniform Resource Locator
URLはインターネット上のリソースの住所
https://example.com:443/search?q=docker
└─┬─┘ └────┬────┘ └┬┘ └──┬──┘ └───┬───┘
プロトコル ドメイン ポート パス クエリ
各要素の役割
- プロトコル: 通信方法(HTTP/HTTPS)
- ドメイン: サーバーの住所
- ポート: サーバー内の窓口(省略可能)
- パス: サーバー内のファイルの場所
- クエリ: 追加情報(検索ワードなど)
全体の流れ
sequenceDiagram
participant User as ユーザー
participant Browser as ブラウザ
participant DNS as DNSサーバー
participant Server as Webサーバー
participant App as アプリケーション
participant DB as データベース
User->>Browser: URLを入力
Browser->>DNS: ドメイン名の問い合わせ
DNS-->>Browser: IPアドレスを返す
Browser->>Server: HTTPリクエスト送信
Server->>App: リクエストを処理
App->>DB: データ取得
DB-->>App: データ返却
App-->>Server: HTML生成
Server-->>Browser: HTTPレスポンス返却
Browser->>Browser: HTMLをレンダリング
Browser-->>User: ページ表示
ステップ1: URLの入力
ユーザーがブラウザにhttps://example.comと入力
ブラウザがすること
- URLを解析(プロトコル、ドメイン、パスなど)
- キャッシュを確認(前回の訪問データがあるか)
- ドメイン名からIPアドレスを調べる準備
ステップ2: DNS解決
Domain Name System
ドメイン名 → IPアドレス に変換
flowchart LR
A[ブラウザ] -->|example.comは?| B[DNSサーバー]
B -->|192.0.2.1です| A
style A fill:#e1f5ff
style B fill:#fff4e1
なぜ必要?
- 人間:
example.com(覚えやすい) - コンピュータ:
192.0.2.1(実際の住所)
DNSは電話帳のような役割
ステップ3: TCP接続の確立
3ウェイハンドシェイク
サーバーと信頼できる通信路を確立
sequenceDiagram
participant C as クライアント
participant S as サーバー
C->>S: SYN(接続してもいい?)
S->>C: SYN-ACK(OK!こちらも準備完了)
C->>S: ACK(了解!通信開始)
Note over C,S: 接続確立完了
HTTPSの場合は、さらにSSL/TLSによる暗号化を設定
ステップ4: HTTPリクエスト送信
ブラウザがサーバーにリクエストを送信
GET /search?q=docker HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: text/html
Accept-Language: ja
リクエストの構成要素
- メソッド: GET(取得)、POST(送信)など
- パス:
/search?q=docker - ヘッダー: ブラウザ情報、言語設定など
HTTPメソッドの種類
| メソッド | 用途 | 例 |
|---|---|---|
| GET | データ取得 | ページ閲覧、検索 |
| POST | データ送信 | フォーム送信、ログイン |
| PUT | データ更新 | プロフィール編集 |
| DELETE | データ削除 | アカウント削除 |
GET: URLにデータが見える
POST: URLに見えない(ボディに含まれる)
ステップ5: サーバーでの処理
Webサーバーの役割
flowchart TD
A[HTTPリクエスト受信] --> B{リクエストの種類}
B -->|静的ファイル| C[HTMLファイルを読み込み]
B -->|動的処理| D[アプリケーションに転送]
D --> E[ビジネスロジック実行]
E --> F{データベースアクセス必要?}
F -->|必要| G[DB問い合わせ]
F -->|不要| H[HTMLを生成]
G --> H
C --> I[レスポンス作成]
H --> I
style A fill:#e1f5ff
style I fill:#e1ffe1
静的コンテンツ vs 動的コンテンツ
静的コンテンツ
事前に作られたファイル
- HTML、CSS、JavaScript
- 画像、動画
- すぐに返せる
- 高速
例: 会社のトップページ
動的コンテンツ
リクエストごとに生成
- ユーザー情報に基づく
- データベースから取得
- 処理が必要
- 柔軟
例: SNSのタイムライン
データベースとの連携
アプリケーションがデータベースに問い合わせ
sequenceDiagram
participant App as アプリケーション
participant DB as データベース
App->>DB: SELECT * FROM users WHERE id=123
DB->>DB: データ検索
DB-->>App: ユーザー情報を返却
App->>App: HTMLテンプレートに埋め込む
よくあるデータベース
- MySQL / PostgreSQL (リレーショナル)
- MongoDB (ドキュメント型)
- Redis (キャッシュ)
ステップ6: HTTPレスポンス返却
サーバーがブラウザにレスポンスを返す
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 1024
Set-Cookie: session=abc123
<!DOCTYPE html>
<html>
<head><title>検索結果</title></head>
<body>
<h1>Dockerの検索結果</h1>
...
</body>
</html>
HTTPステータスコード
サーバーからの応答状態を示す3桁の数字
| コード | 意味 | 詳細 |
|---|---|---|
| 200 | OK | 成功 |
| 301 | Moved Permanently | 恒久的な移動(リダイレクト) |
| 404 | Not Found | ページが見つからない |
| 500 | Internal Server Error | サーバーエラー |
| 503 | Service Unavailable | サーバー過負荷 |
レスポンスヘッダーの役割
Content-Type: text/html; charset=UTF-8 ← データの種類
Content-Length: 1024 ← データのサイズ
Cache-Control: max-age=3600 ← キャッシュの有効期限
Set-Cookie: session=abc123 ← クッキーの設定
主なContent-Type
text/html- HTMLページapplication/json- JSON データimage/png- PNG画像text/css- CSSファイルapplication/javascript- JavaScript
ステップ7: ブラウザでのレンダリング
HTMLの解析と表示
flowchart TD
A[HTMLを受信] --> B[HTMLをパース]
B --> C{外部リソースあり?}
C -->|CSS| D[CSSファイル取得]
C -->|JavaScript| E[JSファイル取得]
C -->|画像| F[画像ファイル取得]
D --> G[CSSを適用]
E --> H[JavaScriptを実行]
F --> I[画像を配置]
G --> J[レンダリングツリー構築]
H --> J
I --> J
J --> K[画面に描画]
style A fill:#e1f5ff
style K fill:#e1ffe1
レンダリングの詳細プロセス
1. パース(Parse)
HTMLを解析してDOMツリーを構築
2. スタイル計算
CSSを適用してスタイルツリーを構築
3. レイアウト
各要素の位置とサイズを計算
4. ペイント
実際に画面に描画
複数のリクエスト
1つのページ表示に複数のリクエストが発生
https://example.com/index.html ← 最初のHTML
↓
https://example.com/style.css ← CSSファイル
https://example.com/script.js ← JavaScriptファイル
https://example.com/logo.png ← 画像ファイル
https://api.example.com/user/data ← APIからのデータ
これらは並列に取得される(HTTP/2以降)
JavaScriptの実行
JavaScriptで動的な処理を実行
よくある処理
- ユーザーの操作に反応(クリック、スクロール)
- APIからデータを取得(Ajax、Fetch)
- DOMを操作(要素の追加・削除)
- アニメーション効果
// ボタンクリックで追加データを取得
fetch('/api/more-data')
.then(response => response.json())
.then(data => updatePage(data));
ここまでのまとめ
flowchart LR
A[URLを入力] --> B[DNS解決]
B --> C[TCP接続]
C --> D[HTTPリクエスト]
D --> E[サーバー処理]
E --> F[DB問い合わせ]
F --> G[HTTPレスポンス]
G --> H[HTML解析]
H --> I[リソース取得]
I --> J[レンダリング]
J --> K[ページ表示]
style A fill:#e1f5ff
style K fill:#e1ffe1
約1秒以内に数十回の通信とたくさんの処理が行われる!
Dockerが登場する場面
開発環境での活用
従来の問題点:
- 「自分のPCでは動くのに...」
- 開発環境のセットアップが大変
- チームメンバーで環境が異なる
Dockerの解決策
同じコンテナ = 同じ環境
Web開発でのDocker構成
flowchart TD
subgraph Docker環境
A[Nginxコンテナ
Webサーバー] B[Appコンテナ
アプリケーション] C[DBコンテナ
データベース] end User[ユーザー] -->|HTTPリクエスト| A A -->|プロキシ| B B -->|SQL| C C -->|データ| B B -->|HTML| A A -->|HTTPレスポンス| User style User fill:#e1f5ff style A fill:#fff4e1 style B fill:#ffe1e1 style C fill:#e1ffe1
Webサーバー] B[Appコンテナ
アプリケーション] C[DBコンテナ
データベース] end User[ユーザー] -->|HTTPリクエスト| A A -->|プロキシ| B B -->|SQL| C C -->|データ| B B -->|HTML| A A -->|HTTPレスポンス| User style User fill:#e1f5ff style A fill:#fff4e1 style B fill:#ffe1e1 style C fill:#e1ffe1
Docker Composeでの構成例
複数のコンテナを一括管理
docker-compose.yml
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "80:80"
app:
build: ./app
environment:
- DB_HOST=db
db:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=secret
Dockerコンテナ間の通信
flowchart LR
subgraph Docker Network
A[webコンテナ
:80] B[appコンテナ
:3000] C[dbコンテナ
:3306] end Browser[ブラウザ] -->|localhost:80| A A -->|app:3000| B B -->|db:3306| C style Browser fill:#e1f5ff
:80] B[appコンテナ
:3000] C[dbコンテナ
:3306] end Browser[ブラウザ] -->|localhost:80| A A -->|app:3000| B B -->|db:3306| C style Browser fill:#e1f5ff
- コンテナ名で通信できる
- ポートマッピングで外部公開
- 独立したネットワーク空間
実際の開発フロー with Docker
1. 環境起動
docker-compose up -d
2. ブラウザでアクセス
http://localhost
3. コード変更
エディタでファイルを編集
4. 自動反映
コンテナ内のアプリが自動で更新
Dockerのメリット(再確認)
開発者目線
- 環境構築が簡単
- チーム全員が同じ環境
- 本番環境と同じ構成
- 複数バージョンの共存
システム目線
- 軽量で高速起動
- リソース効率が良い
- 簡単にスケール
- 環境の再現性が高い
Dockerがない場合の問題
flowchart TD
A[開発者Aのマシン] -->|Node v14| B[動作OK]
C[開発者Bのマシン] -->|Node v18| D[エラー発生]
E[本番サーバー] -->|Node v16| F[謎のバグ]
style D fill:#ffe1e1
style F fill:#ffe1e1
バージョン違い、OS違いで動作が変わる
Dockerがある場合
flowchart TD
A[開発者Aのマシン] -->|Dockerコンテナ| B[動作OK]
C[開発者Bのマシン] -->|Dockerコンテナ| D[動作OK]
E[本番サーバー] -->|Dockerコンテナ| F[動作OK]
style B fill:#e1ffe1
style D fill:#e1ffe1
style F fill:#e1ffe1
同じイメージ = どこでも同じ動作
Webリクエストの最適化
ブラウザ側
- キャッシュ活用 - 再訪問時に高速化
- 圧縮 - データサイズを削減
- CDN - 近くのサーバーから配信
サーバー側
- データベースクエリ最適化
- レスポンスのキャッシュ
- 負荷分散(ロードバランサー)
キャッシュの仕組み
sequenceDiagram
participant B as ブラウザ
participant C as キャッシュ
participant S as サーバー
B->>C: ファイルある?
alt キャッシュヒット
C-->>B: あるよ!(超高速)
else キャッシュミス
B->>S: ファイルください
S-->>B: どうぞ
B->>C: 保存しとく
end
2回目以降の訪問が劇的に速くなる
スケーリング
アクセス増加への対応
flowchart TD
LB[ロードバランサー] --> A1[Appコンテナ1]
LB --> A2[Appコンテナ2]
LB --> A3[Appコンテナ3]
A1 --> DB[(データベース)]
A2 --> DB
A3 --> DB
style LB fill:#fff4e1
style A1 fill:#ffe1e1
style A2 fill:#ffe1e1
style A3 fill:#ffe1e1
style DB fill:#e1ffe1
Dockerなら簡単にコンテナを増やせる
セキュリティの重要性
HTTPSの必要性
- 盗聴防止 - 通信内容の暗号化
- 改ざん防止 - データの完全性保証
- なりすまし防止 - サーバーの正当性確認
HTTP → 平文(危険)
HTTPS → 暗号化(安全)
パスワードやクレジットカード情報を扱うなら必須
まとめ: URLからブラウザ表示まで
- URL入力 - ブラウザがURLを解析
- DNS解決 - ドメイン名をIPアドレスに変換
- TCP接続 - サーバーとの通信路確立
- HTTPリクエスト - サーバーにデータを要求
- サーバー処理 - データベースから情報取得
- HTTPレスポンス - HTMLなどを返却
- レンダリング - ブラウザが画面に表示
すべてが1秒以内に!
Dockerの役割
- 開発環境の統一 - チーム全員が同じ環境
- 本番環境の再現 - 本番と同じ構成でテスト
- スケーラビリティ - 簡単にサーバー増設
- マイクロサービス - 各機能を独立したコンテナに
「どこでも、同じように動く」を実現
ありがとうございました!
質問はありますか?
次回: Dockerの実践的な使い方
- Dockerfileの書き方
- docker-composeの活用
- 実際のアプリケーションのコンテナ化
00:00