🌐

URLからブラウザ表示までの流れとDockerの役割

URLからブラウザ表示まで

Webリクエストの裏側とDockerの役割

ブラウザにURLを入力してからページが表示されるまで、何が起きているのかを理解する

今日学ぶこと

  1. URLの仕組み - URLとは何か
  2. ブラウザからサーバーへ - リクエストの送信
  3. サーバーでの処理 - データの準備と生成
  4. ブラウザへの返答 - レスポンスの受信
  5. ブラウザでの表示 - HTMLのレンダリング
  6. 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と入力

ブラウザがすること

  1. URLを解析(プロトコル、ドメイン、パスなど)
  2. キャッシュを確認(前回の訪問データがあるか)
  3. ドメイン名から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

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
  • コンテナ名で通信できる
  • ポートマッピングで外部公開
  • 独立したネットワーク空間

実際の開発フロー 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からブラウザ表示まで

  1. URL入力 - ブラウザがURLを解析
  2. DNS解決 - ドメイン名をIPアドレスに変換
  3. TCP接続 - サーバーとの通信路確立
  4. HTTPリクエスト - サーバーにデータを要求
  5. サーバー処理 - データベースから情報取得
  6. HTTPレスポンス - HTMLなどを返却
  7. レンダリング - ブラウザが画面に表示

すべてが1秒以内に!

Dockerの役割

  • 開発環境の統一 - チーム全員が同じ環境
  • 本番環境の再現 - 本番と同じ構成でテスト
  • スケーラビリティ - 簡単にサーバー増設
  • マイクロサービス - 各機能を独立したコンテナに

「どこでも、同じように動く」を実現

ありがとうございました!

質問はありますか?

次回: Dockerの実践的な使い方

  • Dockerfileの書き方
  • docker-composeの活用
  • 実際のアプリケーションのコンテナ化
00:00