LoginSignup
5
2

More than 1 year has passed since last update.

Dockerでnginxを使ってみた

Last updated at Posted at 2021-09-11

この記事の内容

Dockerでnginxを使用する際に気をつけたポイントについて書いてみた。
他コンテナとの連携方法や、nginxの設定などについて触れる。

サンプルコード

本記事で解説したコードを公開しています。
https://github.com/fukky21/nginx-sample

全体の構成

今回は以下のような構成を考えてみる。
全体構成

環境構築

docker-compose.yml
version: '3.9'
services:
  proxy:
    image: nginx:1.21.0
    container_name: nginx-sample_proxy
    volumes:
      - ./proxy/nginx.conf:/etc/nginx/nginx.conf
      - ./proxy/html:/etc/nginx/html
      - ./proxy/log:/var/log/nginx
    ports:
      - '80:80'
    depends_on:
      - api
      - web

  api:
    build:
      context: ./api
      dockerfile: Dockerfile
    container_name: nginx-sample_api
    command: yarn dev
    volumes:
      - ./api:/app
    tty: true

  web:
    build:
      context: ./web
      dockerfile: Dockerfile
    container_name: nginx-sample_web
    command: yarn dev
    volumes:
      - ./web:/app
    tty: true
    environment:
      PORT: 3000
      HOST: 0.0.0.0

いくつかポイントがあるので解説する。
Dockerfileの内容については、サンプルコードをご覧ください。

proxyの起動を最後にする

depends_onでwebとapiを指定することで、proxyよりも先にその2つが起動する。
nginx.confで、プロキシの転送先にnginx-sample_apinginx-sample_webを指定するので、最後に起動する必要がある。

webとapiのポートをホスト側に公開しない

webとapiにはportsを指定しない。こうすることで、ホストから直接webとapiにアクセスすることはできず、必ずproxyを経由することになる。

webの環境変数にPORTとHOSTを指定する

webのenvironmentPORTHOSTを指定している。
これを指定しないと502 Bad Gatewayと表示され、Webサイト(Nuxt.js)に接続できない。
原因に関しては、この記事に分かりやすくまとめられている。
https://qiita.com/amuyikam/items/01a8c16e3ddbcc734a46

container_nameを指定する

後ほど紹介するnginx.confで、ここで指定したcontainer_nameを使用する。

nginxの設定

nginx.conf
worker_processes auto;

events {
  worker_connections 16;
}

http {
  server {
    listen 80 default_server;
    server_name _;
    return 444;
  }

  server {
    listen 80;
    server_name localhost;

    proxy_redirect off;

    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Connection '';

    error_page 404 /404.html;
    location = /404.html {
      root /etc/nginx/html;
      internal;
    }

    location /app/ {
      allow 172.24.0.1;
      deny all;
      proxy_pass http://nginx-sample_web:3000;
    }
    location /api/ {
      proxy_pass http://nginx-sample_api:3080;
    }
  }
}

worker_processesとworker_connections

こちらの記事によると、

nginxにおける同時クライアントの最大数は、worker_processes × worker_connectionsの数で決まる。

ということらしい。
worker_processes autoとすると、ワーカープロセス数はCPUのコア数と同じになる。
Macの場合、CPUコア数は下のコマンドで確認できる。

$ system_profiler SPHardwareDataType | awk '/Total Number of Cores/ { print $NF }'

worker_connectionsの値を色々いじってみると、接続できるクライアント数が変わることを確認できる。

IPの直打ちアクセスを弾く

server {
  listen 80 default_server;
  server_name _;
  return 444;
}

http://127.0.0.1/app のように、IPアドレスを直打ちしてアクセスしてきた場合に接続を切ることで、攻撃を防ぐことができる。
444は、接続を閉じるためのnginxの特別な標準外コードで、詳しくはこちらを参照。

ヘッダーを書き換える

proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Connection '';

ヘッダーの書き換えを行わない場合、webやapi側にはプロキシからリクエストが来たことしか伝わらない。ヘッダー情報を、プロキシにアクセスしてきたクライアントの情報に書き換えることで、webやapi側でもクライアントの情報を扱えるようになる。

エラーページをカスタマイズする

error_page 404 /404.html;
location = /404.html {
  root /etc/nginx/html;
  internal;
}

デフォルトのエラーページでは以下のように表示される。

デフォルトエラーページ

nginxを使用していることがクライアントにバレてしまうのが嫌な場合は、エラーページを独自に設定すると良い。
今回の例では、404(Not Found)のときだけオリジナルのエラーページが表示されるようにしてあるが、403(Forbidden)500(Internal Server Error)のときも個別に指定できる。
internalを指定することで、内部からのリクエストのためだけに使用されることになり、外部からは直接アクセスできなくなる。

IPアドレス制限をかける

allow 172.24.0.1;
deny all;

管理者サイトなど、特定のIPアドレスからのアクセスのみ許可したい場合はallowで指定する。その後ろにdeny allを記述することで、allowで指定したIPアドレス以外のアクセスを弾くことができる。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2