Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

Docker で最速で nginxサーバーを立てる

サンプルリポジトリ

記事で紹介した内容をリポジトリにあげてあります。よろしければ参考にしてください。

github.com

nginx イメージを使う

たったこれだけでカレントディレクトリのpublicフォルダを公開するウェブサーバーを建てられます。

$ docker run -d -p 8080:80 -v $PWD/public:/usr/share/nginx/html:ro nginx

しかし、単にサーバーを立てるだけならわざわざ docker を使わずにもっと短くできます((python -m http.server 8080 ./public で代用できます))。せっかく Nginx を使うのですから、設定ファイルを使いたいですよね。設定ファイルをマウントするには次のようにします。

$ docker run -d -p 8080:80 -v $PWD/public:/usr/share/nginx/html:ro \
  -v $PWD/nginx.conf:/etc/nginx/nginx.conf:ro \
  -v $PWD/conf.d:/etc/nginx/conf.d:ro nginx

しかし、これだけでは立ち上がる Nginx の prefix が /etc/nginx になってしまうので、prefix を /usr/share/nginx にして起動します。

$ docker run -d -p 8080:80 -v $PWD/public:/usr/share/nginx/html:ro \
  -v $PWD/nginx.conf:/etc/nginx/nginx.conf:ro \
  -v $PWD/conf.d:/etc/nginx/conf.d:ro nginx nginx -p /usr/share/nginx -g 'daemon off;'

さらに --restart=always を付ければ再起動後も自動で立ち上がるようになります。

docker-compose を使う

上のコマンドを docker-compose.yml で書くと次のようになります。

version: '3'
services:
  web:
    image: nginx:alpine
    ports:
      - 8080:80
    volumes:
      - ./public:/usr/share/nginx/html:ro
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./conf.d:/etc/nginx/conf.d:ro
    command: nginx -p /usr/share/nginx -g 'daemon off;'

これなら restart: always をつけることで再起動後も自動で立ち上がるようにできます。

あとは docker-compose.yml と同階層でdocker-compose up -dを実行するとサーバーが立ち上がります。

リバースプロキシ

ネットワークをたててその中で完結させたい場合は以下のようにすると簡潔です。

$ docker create network -d bridge my-network
$ docker run -d -p 8080:80 -v $PWD/public:/usr/share/nginx/html:ro \
  --net my-network \
  -v $PWD/nginx.conf:/etc/nginx/nginx.conf:ro \
  -v $PWD/conf.d:/etc/nginx/conf.d:ro nginx \
  nginx -p /usr/share/nginx -g 'daemon off;'

docker-compose.yml を使うと以下になります。

version: '3'
services:
  web:
    image: nginx:alpine
    ports:
      - 8080:80
    volumes:
      - ./public:/usr/share/nginx/html:ro
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./conf.d:/etc/nginx/conf.d:ro
    command: nginx -p /usr/share/nginx -g 'daemon off;'

networks:
  default:
    external:
      name: my-network

external で指定してあるのは、このコンテナでネットワークを立ててしまうと、このコンテナを起点に依存関係ができてしまうためです。ネットワークを作るかわりに external で既存のネットワークを使えば、このコンテナは他のコンテナの起動状況に関わらず立ち上げることができます。また、他のコンテナもこのコンテナの起動状況に依存せずに済みます。

他のコンテナは、外部とはこのリバースプロキシを介して通信できるので、portsの代わりにexposeでポートをネットワーク内に公開するだけで良いです。