Docker上で、HTTPS対応のnginxサーバを構築する

# はじめに

Docker上で、HTTPS対応のnginxサーバを構築する方法を解説します。なお利用したソフトウェアのバージョンは以下の通りです。

```
$ openssl version
OpenSSL 1.1.1f  31 Mar 2020
```

```
$ docker version
Client: Docker Engine - Community
 Cloud integration: v1.0.35+desktop.5
 Version:           24.0.7
 API version:       1.43
 Go version:        go1.20.10
 Git commit:        afdd53b
 Built:             Thu Oct 26 09:08:17 2023
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Desktop
 Engine:
  Version:          24.0.7
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.10
  Git commit:       311b9ff
  Built:            Thu Oct 26 09:08:02 2023
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.25
  GitCommit:        d8f198a4ed8892c764191ef7b3b06d8a2eeb5c7f
 runc:
  Version:          1.1.10
  GitCommit:        v1.1.10-0-g18a0cb0
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
```


# 手順

事前準備として、秘密鍵用のパスフレーズを決めておきます。このパスフレーズは繰り返し利用するので、かならず控えておくこと。

## 手順1. 秘密鍵の作成

秘密鍵ファイルを作成する。パスフレーズは事前に決めておいたものを入力する。

```
openssl genrsa -des3 2048 > server.key
```

実行例:

```
$ openssl genrsa -des3 2048 > server.key
Generating RSA private key, 2048 bit long modulus (2 primes)
.....................................+++++
...............................................................................+++++
e is 65537 (0x010001)
Enter pass phrase:
Verifying - Enter pass phrase:
```

## 手順2. サーバ証明書の作成

以下のコマンドを実行し、必要な情報を入力することで、サーバ証明書を作成する。パスフレーズは事前に決めておいたものを入力する。

```
openssl req -new -key server.key -out server.csr
```

実行例:

```
$ openssl req -new -key server.key -out server.csr
Enter pass phrase for server.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Kanagawa-Ken
Locality Name (eg, city) []:Kawasaki-Shi
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example Corp.
Organizational Unit Name (eg, section) []:Web Technology
Common Name (e.g. server FQDN or YOUR name) []:www.example.jp
Email Address []:foo@example.jp

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
```

## 手順3. 自己署名

作成したサーバ証明書に対して自己署名を行う。パスフレーズは事前に決めておいたものを入力する。

```
openssl x509 -req -in server.csr -days 365 -signkey server.key -out server.crt
```

実行例:

```
$ openssl x509 -req -in server.csr -days 365 -signkey server.key -out server.crt
Signature ok
subject=C = JP, ST = Kanagawa-Ken, L = Kawasaki-Shi, O = Example Corp., OU = Web Technology, CN = www.example.jp, emailAddress = foo@example.jp
Getting Private key
Enter pass phrase for server.key:
```

## 手順4. パスワードファイルの作成

パスワードファイルを作成する。このファイルにはパスフレーズが記載されている。

```
echo [パスフレーズ] > server.password
```

## 手順5. default.confの作成

nginxの設定ファイルであるdefault.confを作成する。内容は以下の通り。

```default.conf
server {
    listen       80 default_server;
    listen  [::]:80 default_server;
    return 301 https://$host$request_uri;
}
server {
    listen       443 ssl;
    listen  [::]:443 ssl;
    http2 on;
    
    ssl_certificate     server.crt;
    ssl_certificate_key server.key;
    ssl_password_file   server.password;
    
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}
```

## 手順6. nginxの起動

Dockerを利用してnginxを起動する。コンテナ名は任意。ここではnginx2024とする。

```
docker run --name nginx2024 \
           -d \
           --restart unless-stopped \
           -p 80:80 \
           -p 443:443 \
           nginx:1.25.3
```

## 手順7. 作成したファイルの移送

以下のコマンドを順次実行し、nginxコンテナに作成したファイルを移送する。このとき、所有者や権限についても同時に設定する。

```
docker cp server.key      nginx2024:/etc/nginx
docker cp server.crt      nginx2024:/etc/nginx
docker cp server.password nginx2024:/etc/nginx
docker cp default.conf    nginx2024:/etc/nginx/conf.d
docker exec -it nginx2024 chown nginx:nginx /etc/nginx/server.key
docker exec -it nginx2024 chown nginx:nginx /etc/nginx/server.crt
docker exec -it nginx2024 chown nginx:nginx /etc/nginx/server.password
docker exec -it nginx2024 chown nginx:nginx /etc/nginx/conf.d/default.conf
docker exec -it nginx2024 chmod 700 /etc/nginx/server.key
docker exec -it nginx2024 chmod 700 /etc/nginx/server.crt
docker exec -it nginx2024 chmod 700 /etc/nginx/server.password
docker exec -it nginx2024 chown 700 /etc/nginx/conf.d/default.conf
```

## 手順8. nginxの再起動

コンテナを再起動することで、nginxの再起動を行う。

```
docker restart nginx2024
```
# 稼働確認

Chromeで`http://localhost/`にアクセスすると、自動的に`https://localhost/`へリダイレクトされることがわかる (常時SSL化対応の確認)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105859/311e0afa-fdb9-48e6-349e-e513abadad32.png)

自己署名のため、Chromeが警告を発しているが、これを無視して進める。まず「詳細設定」を押下して、確認画面を表示する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105859/fcd45528-f8e2-27ae-57ea-5961fda77e0e.png)

「localhostにアクセスする(安全ではありません)」を押下し、nginxのインデックスページに遷移できれば、https対応のnginxサーバが構築できたとわかる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105859/7fd348bb-05e3-6dbf-947d-401998bf00d3.png)