Nginx 入門:軽量・高速なWebサーバ / リバースプロキシを動かして理解する

WebサイトやAPIを公開するとき、ほぼ確実に候補に上がるのが Nginx(エンジンエックス) です。
「とりあえず動く」だけなら簡単ですが、いざ本番運用に近づくと、

  • どこに何を書くの?
  • location の優先順位って?
  • 静的配信とアプリの中継(リバースプロキシ)って何が違うの?
  • なんでNginxが速いって言われるの?
  • どこを触ると落ちる(危ない)?

…みたいな壁にぶつかりがちです。

この記事では、Nginxの位置づけを「理解の言葉」で説明しつつ、手を動かすハンズオンで納得できるように構成しています。Dockerで再現性も高いので、ローカルで気軽に試せます。


Nginxとは?何を担当するソフト?

Nginxは一言でいうと 「Webの入口(エッジ)になれる万能サーバ」 です。主な用途は次のとおり。

1) Webサーバ(静的ファイル配信)

HTML/CSS/JavaScript/画像など、アプリ処理を介さずにそのまま返せるものを配信します。
静的配信は「速くて軽い」だけでなく、アプリの負荷を減らし、構成をシンプルにできます。

2) リバースプロキシ(バックエンド中継)

裏側で動くアプリ(Node.js / Python / Go / Java など)を直接インターネットに晒さず、Nginxを入口にして中継します。

  • ブラウザ → Nginx → アプリ
    の流れにすることで、アプリは「内側」で動くだけでOKになります。

3) ロードバランサ(振り分け)

アプリを複数台(複数コンテナ)に増やして、アクセスを分散します。
ここは入門の次のステップですが、Nginxがよく使われる理由のひとつです。

4) TLS終端(HTTPSの担当)

Let’s Encryptなどの証明書をNginxで扱い、アプリ側はHTTPのまま運用するパターンも多いです。
運用上は「証明書の更新」「暗号設定」「HTTP→HTTPSリダイレクト」などの責務を入口に寄せられます。


なぜNginxは速いと言われる?

「速い」の理由は一つではありませんが、入門として押さえると良いポイントは次の2つです。

  • イベント駆動(イベントループ的な処理モデル)
    たくさんの接続を効率よく扱いやすい。
  • 静的配信が得意
    ファイルを返すだけの処理が非常に強い。アプリを起動してテンプレを作るより圧倒的に軽い。

とはいえ、最初は「速い仕組み」を深掘りしすぎなくてOKです。
まずは Webの入口として整理されている ことと、設定が強力で実務に直結することを押さえるのが重要です。


Nginx設定の基本構造:入れ子を理解すれば読める

Nginxの設定ファイルは、ブロック構造を理解すればかなり読みやすくなります。

  • http { ... }:HTTP全体の設定(大枠)
  • server { ... }:1サイト(1ホスト/1ポート)単位の設定
  • location { ... }:URLパス単位のルール

イメージとしては、

  • server は「このポートで待ち受け」「このホスト名のサイト」
  • location は「このパスに来たらどうする」

です。

よくある誤解は、「serverが複数あると何が起きるの?」です。
答えはシンプルで、listenserver_name の条件に応じて、どの server が応答するかが決まります。


よく使うディレクティブ(まずはこれだけ)

入門では「全部覚える」より、「使う順に覚える」方が失敗しません。
まずは以下のセットを押さえれば十分です。

静的配信に必要

  • listen 80;:待ち受けポート
  • root /path;:配信するファイルのディレクトリ
  • index index.html;:デフォルトで返すファイル
  • try_files ...;:ファイルの存在チェック(ない場合の挙動)

リバースプロキシに必要

  • proxy_pass http://...;:転送先(裏のアプリ)
  • proxy_set_header ...;:転送時のヘッダ(実務で重要)

ハンズオンの前提(Docker推奨)

ローカル環境を汚さず、確実に再現するためにDockerで進めます。

  • Windows / macOS / Linux どれでもOK
  • Docker Desktop(またはDocker Engine)が入っていればOK
  • コマンドは docker compose を使います

ハンズオン1:Nginxで「静的サイト」を配信してみる(最小構成)

まずは「Webサーバとして使う」を最短で体験します。
この段階で理解したいのは、Nginx=設定とファイルがあれば即配信できる という感覚です。

1. ディレクトリ構成

nginx-static/
  ├─ index.html
  └─ docker-compose.yml

2. index.html を作成

index.html

<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <title>Nginx 入門</title>
  </head>
  <body>
    <h1>Nginxで静的サイト配信できた!</h1>
    <p>Docker + Nginx の最小構成です。</p>
  </body>
</html>

3. docker-compose.yml を作成

docker-compose.yml

services:
  nginx:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./index.html:/usr/share/nginx/html/index.html:ro

ポイント:

  • nginx:alpine は軽量で手早い
  • ports でホスト8080→コンテナ80に接続
  • volumes でindex.htmlを配信ディレクトリにマウント
  • :ro で読み取り専用(安全)

4. 起動して確認

docker compose up -d
docker compose ps

ブラウザで
http://localhost:8080
を開いてページが表示されれば成功です。

5. 何が起きているか(短く整理)

  • Nginxはコンテナ内の /usr/share/nginx/html を「静的配信のルート」として使う
  • そこに index.html があるので返せる
  • つまり「設定が最小でも動く」

ハンズオン2:設定ファイルを自作して server / location を理解する

次は「設定を変えたら挙動が変わる」体験をします。
location を使えるようになると、Nginxの理解が一気に進みます。

1. 構成

nginx-conf/
  ├─ html/
  │   ├─ index.html
  │   └─ health.html
  ├─ nginx/
  │   └─ default.conf
  └─ docker-compose.yml

2. HTMLを作成

html/index.html

<h1>Top Page</h1>
<p>/ で表示されます</p>

html/health.html

OK

3. Nginx設定を作成

nginx/default.conf

server {
  listen 80;
  server_name _;

  root /usr/share/nginx/html;
  index index.html;

  # /health は health.html を返す(完全一致)
  location = /health {
    default_type text/plain;
    try_files /health.html =404;
  }

  # それ以外は静的配信(無ければ404)
  location / {
    try_files $uri $uri/ =404;
  }
}

ここで理解したいのは2つです。

location = /health の意味

= は「完全一致」。
/health にだけ反応し、/health//healthcheck には反応しません。

try_files の意味

指定した順で「存在確認」して、見つかったらそれを返します。
見つからなければ最後の =404 が採用されます。

4. docker-compose.yml を作成

docker-compose.yml

services:
  nginx:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro

5. 起動して確認

docker compose up -d
  • http://localhost:8080/ → Top Page
  • http://localhost:8080/health → OK

6. 設定テスト(本番級に大事)

設定を変えたら必ずテストします。

docker compose exec nginx nginx -t

syntax is ok / test is successful が出ればOKです。
これを習慣化すると事故が激減します。


ハンズオン3:リバースプロキシ(Nginx → Node.js)を作る

ここが「実務で一番使う形」です。
アプリを直接外に出さず、Nginxを入口にして裏へ流します。

1. 構成

nginx-reverse-proxy/
  ├─ app/
  │   ├─ server.js
  │   └─ package.json
  ├─ nginx/
  │   └─ default.conf
  └─ docker-compose.yml

2. Node.jsアプリ

app/package.json

{
  "name": "app",
  "version": "1.0.0",
  "type": "module",
  "dependencies": {
    "express": "^4.18.2"
  }
}

app/server.js

import express from "express";
const app = express();

app.get("/", (req, res) => {
  res.send("Hello from Node.js behind Nginx!");
});

app.get("/api", (req, res) => {
  res.json({ message: "API OK", time: new Date().toISOString() });
});

app.listen(3000, () => console.log("app listening on 3000"));

3. Nginx設定(proxy_pass)

nginx/default.conf

upstream backend {
  server app:3000;
}

server {
  listen 80;
  server_name _;

  location / {
    proxy_pass http://backend;

    # 実務でよく入れるヘッダ
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}

upstream を作っておくと、後で「複数台に増やす」拡張がしやすいです。

4. docker-compose.yml

docker-compose.yml

services:
  nginx:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - app

  app:
    image: node:20-alpine
    working_dir: /app
    volumes:
      - ./app:/app
    command: sh -c "npm install && node server.js"

5. 起動 & 確認

docker compose up -d
docker compose logs -f app
  • http://localhost:8080/Hello from Node.js behind Nginx!
  • http://localhost:8080/api → JSONが返る

ここで体感してほしいのは、クライアント(ブラウザ)からはNginxしか見えていないのに、裏のアプリが動いていることです。
つまり、アプリ側を入れ替えたり増やしたりしても、入口のURLは変えずに運用できます。


よくある落とし穴(入門でつまずきやすい)

1) localhost の罠

Dockerの世界では localhost は「そのコンテナ自身」です。
つまりNginxコンテナから見た localhost:3000 は「Nginxコンテナの3000番」で、Nodeコンテナには届きません。

コンテナ間通信は サービス名 を使います。
今回なら app:3000 が正解です。

2) 設定反映されない

設定ファイルを編集したのに挙動が変わらない場合は、まず確認:

docker compose exec nginx nginx -T | head -n 80

nginx -T は読み込んだ全設定を出力します。
「思っているファイルが読み込まれているか」を確認できるので強いです。

3) 404になる

roottry_files の組み合わせミスが多いです。
マウントしているディレクトリが合っているかを確認:

docker compose exec nginx ls -la /usr/share/nginx/html

ここまでできたら、Nginxはもう「入口」として使える

入門として重要なのは、Nginxを「単なるWebサーバ」ではなく、

  • 静的配信ができる
  • location でパスごとに処理を分けられる
  • proxy_pass で裏のアプリへ中継できる

という「入口の設計」に使えることです。


投稿日

カテゴリー:

投稿者:

タグ:

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です