Help us understand the problem. What is going on with this article?

CentOS7上でnginxとDockerとLetsEncryptでSSLをごにょごにょする話

More than 3 years have passed since last update.

LetsEncryptを使ってみたかった。
nginxでHTTPリクエストを受けてリバースプロキシでコンテナのHTTPサーバにproxy_passしている状態からLetsEncryptのSSL証明書を利用したい。

前提

CentOS 7.2(host)
docker 1.8
nginx 1.9
コンテナはFROM centos:centos7でDockerfileを使って立てたもの。

課題

すでに立てているコンテナは80/tcpしか空けていない。
コンテナを作り直すのは嫌だなあ、と考えた。

実現方法

フォルダを共有する方法で、コンテナの鍵フォルダをホスト側に共有し、ホスト側で見えた鍵をnginxで利用する。

ホスト側の操作

共有用のフォルダを作成する

$ sudo mkdir /etc/nginx/cert

まあ、どこでもいいのだが、nginxのところに作った。

コンテナのエクスポートとインポート

$ sudo docker stop <container_id>
$ sudo docker export <container_id> > container_name.tar
$ sudo cat container_name.tar | docker import - <repository>:<tag>

一旦止めてファイルに書き出して、イメージとしてインポートする必要がある。

コンテナの起動

$ sudo docker run --privileged -v /etc/nginx/cert:/etc/letsencrypt/ -d --name <new_container_name> -it -p 20080:80 <repository>:<tag>

-vオプションでコンテナの/etc/letsencrypt/をホストの/etc/nginx/certと共有するように設置した。

nginxの設定と再起動

すでにインストールされている前提なので、インストールは省略。

/etc/nginx/conf.d/virtual.conf
server {
    listen 80;
    server_name www.hogehoge.com;
    location / {
        proxy_pass http://127.0.0.1:20080;
    }
}

nginxを再起動する。

$ sudo systemctl reload nginx

コンテナの操作

コンテナでLetsEncryptをインストールする

すでにコンテナでHTTPサーバが起動している前提。

$ sudo su -
$ cd ~
# git clone https://github.com/letsencrypt/letsencrypt
# cd letsencrypt/
# ./letsencrypt-auto --help
# ./letsencrypt-auto certonly --webroot --webroot-path /var/www/html -d www.hogehoge.com
# exit

大体うまくゆく。

コンテナで証明書を更新するためのcronを設定する

$ sudo crontab -e
00 03 01 * * /root/letsencrypt/letsencrypt-auto certonly --webroot --webroot-path /var/www/html -d www.hogehoge.com --renew-by-default

毎月1日の午前3時にcronが動いて、証明書を更新する。

再度ホスト側の操作

証明書があることを確認する

$ sudo ls -l /etc/nginx/cert/live/www.hogehoge.com/
合計 0
lrwxrwxrwx 1 root root 34  3月  6 00:10 cert.pem -> ../../archive/www.hogehoge.com/cert1.pem
lrwxrwxrwx 1 root root 35  3月  6 00:10 chain.pem -> ../../archive/www.hogehoge.com/chain1.pem
lrwxrwxrwx 1 root root 39  3月  6 00:10 fullchain.pem -> ../../archive/www.hogehoge.com/fullchain1.pem
lrwxrwxrwx 1 root root 37  3月  6 00:10 privkey.pem -> ../../archive/www.hogehoge.com/privkey1.pem

ホストでnginxの再設定と再起動

confを編集する。

/etc/nginx/conf.d/virtual.conf
server {
    listen 80;
    server_name www.hogehoge.com;
    location / {
        return 301 https://$host$request_uri;
    }
}
server {
    listen 443;
    server_name www.hogehoge.com;

    ssl on;
    ssl_certificate     /etc/nginx/cert/live/www.hogehoge.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/cert/live/www.hogehoge.com/privkey.pem;

    ssl_session_timeout  5m;
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers  ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256;
    ssl_prefer_server_ciphers   on;
    add_header Strict-Transport-Security 'max-age=31536000;includeSubDomains;';

    location / {
        proxy_pass http://127.0.0.1:20080;
    }
}

nginxを再起動する。

$ sudo systemctl reload nginx

ホスト側でもcronを走らせる

$ sudo crontab -e
00 04 01 * * /usr/bin/systemctl reload nginx

毎月1日の午前4時にcronが動いて、nginxを再起動する。

これで作業完了

補足

コンテナのDockerfileでは、以下のようにhttpdとcrondのサービスを起動する設定にしておくのがコツ。

Dockerfile
FROM centos:centos7
RUN systemctl enable httpd
RUN systemctl enable crond
EXPOSE 80
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away