GCP（GCE）のDockerでSSL証明書を利用したデプロイの備忘録

GCEにて、Webサイトを構築するうえで、SSLを利用したhttp通信をしたく、いろいろと試行錯誤して実現できたので、備忘録として記事にします。

#目的
dockerコンテナをGCEに立て、ブラウザにてWebサイトにアクセスする際に、IPアドレスを直打ちして表示するのではなく、ドメイン・SSLを利用したhttpsアクセスを実現する。

#環境等
・GCE：Ubuntu 18.04 LTS
       n1-standard-1（vCPU x 1、メモリ 3.75 GB）
・ドメイン：お名前.comにて取得
・SSL証明書：Let's Encrypt


#ドメインの取得
まずは、ドメインの取得をします。
今回は「お名前.com」を利用しました。
ドメインによって金額は異なりますが、安いので「.work」が1円とか、「.site」で25円とかありましたので、こだわりが無ければ安いので問題ないかと思います。
私は「.com」で1000円のドメインを契約しました。

ドメインの取得が完了したら、次のステップです。

#GCEにVMインスタンスを立てる
GCEに下記の内容でインスタンスを立てます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259123/65eccc96-251c-f498-acc9-50c901744967.png)

マシンタイプは「n1-standard-1（vCPU x 1、メモリ 3.75 GB）」がよさそうです。
OSは使い慣れた「Ubuntu 18.04 LTS」を使用しています。
下部の「HTTPトラフィックを許可する」「HTTPSトラフィックを許可する」にチェックを入れ、作成します。

既にコンテナイメージをDockerHubに上げている場合は、「このVMインスタンスにコンテナイメージをデプロイする」にチェックを入れ、イメージを指定しても問題ないはず。
今回は、新しいUbuntu環境にdocker等を入れていきます。

#静的IPアドレスの設定
VPCネットワーク > 外部IPアドレスを選択し、静的アドレスを予約します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259123/91e4ac65-ad4b-c2a7-655c-98a7b0e33901.png)
名前はなんでも大丈夫です。
リージョンには、GCEと同じオレゴンを選んでいます。
予約ボタンを押し、VMインスタンスとの設定を入力します。
VMインスタンスの詳細画面から、編集を選択し、「ネットワーク インターフェース」を設定します。
外部IPのセレクトボックスから、先ほど登録した静的IPアドレスを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259123/84780397-9fe9-89fa-b49b-c57a0ad115d1.png)

これで、VMインスタンスのIPアドレスの固定が完了しました。

#Cloud DNSの設定
次に、Cloud DNSを設定します。

ネットワークサービス > Cloud DNSからゾーンを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259123/80481963-5d05-f6ec-5e67-cd9a45e7899a.png)


ゾーン名は任意で、DNS名は「お名前.com」で取得したドメインを入力します。
ゾーンを作成したら次は、今作成したゾーンの詳細画面を開き、レコードセットを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259123/a9a888ab-6aef-011d-ae7a-6f685513c61b.png)

DNS名はそのまま何も入力せずに、IPv4アドレスに予約した静的IPアドレスを入力して作成します。
登録後、ゾーンの詳細画面に戻り、お名前.comとの設定をします。

#お名前.comの設定
お名前.comとCloud DNSの連携は、ゾーンの詳細画面のNSに書かれたデータという項目のxxxxx.googledomains.com.と書かれた4つをお名前.comのネームサーバに指定する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259123/107ef170-fc8c-bd53-94cc-dcc0b7cf9d76.png)

上記の赤枠の値を下記のお名前.comのネームサーバに設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259123/0181f82a-48bd-26f8-b270-e9f0f5494e0e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259123/63aa74ee-f2fb-6b86-8c1b-74a8746b642c.png)

この際に、もともと入力されていたネームサーバ情報はすべて消してください。
これで、お名前.com・GCPの設定は完了です。

#VMインスタンスの設定
作成したVMインスタンスにSSH接続します。
作成したVMインスタンスの詳細画面からSSH接続できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259123/334cbdf3-b9f0-5063-159e-9b9fa6329c20.png)

接続出来たら、下記のコマンドを上から順番に実行してdocker関連をインストールします。
※ 「このVMインスタンスにコンテナイメージをデプロイする」にチェックを入れた場合は、「SSLの設定」まで飛ばして下さい。

```
# インストール可能なパッケージの「一覧」を更新
$ sudo apt update

# HTTPS経由でrepositoryをやりとり出来るようにするためのパッケージをインストール
$ sudo apt install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common

# Dockerの公式GPG keyを追加
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# repository( stable ) を追加
$ sudo add-apt-repository \
     "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
     $(lsb_release -cs) \
     stable"

# 再度 apt パッケージのアップデート
$ sudo apt update

# docker をインストール
$ sudo apt install -y docker-ce

# dockerの起動確認
$ sudo systemctl status docker

```

次に指定の一般ユーザでも sudo 無しでdockerを使えるようにします。
※ 下記のuserNameは環境のユーザ名に合わせて修正して下さい。

```
# 自分のユーザー名を表示
$ whoami
userName

# userNameをDockerグループに追加
$ sudo gpasswd -a userName docker

# dockerグループの確認
$ cat /etc/group | grep docker
docker:x:999:userName 

# dockerが使用するソケットを一般ユーザでも読み込み出来るようにする
$ sudo chmod 666 /var/run/docker.sock

```

docker-composeをインストールします

[docker-composeのバージョン確認](https://github.com/docker/compose/releases/)

```
# バイナリからdocker-composeをインストール
# インストールするバージョンを設定
$ export compose='1.24.0'
※ バージョンは都度確認が必要です。
2019/6/10時点で最新：1.24.0

# docker-composeをダウンロード
$ sudo curl -L https://github.com/docker/compose/releases/download/${compose}/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

# 実行権限の付与
$ sudo chmod 0755 /usr/local/bin/docker-compose

#バージョン確認
$ docker-compose -v

```

ここまででVMインスタンスの設定は完了です。

# Dockerイメージを取得
デプロイするDockerイメージをDocker Hubからpullします。
pullした後に、docker runコマンドによって、コンテナーを作成・起動します。

```
# docker hubから任意のDockerイメージを取得する
$ docker pull Dockerイメージ名

# docker runコマンドより、コンテナを作成・起動します。
$ docker run --name web -d Dockerイメージ名

```

コンテナの起動を確認したら、コンテナに入り、hostnameを確認します。

```
# 立ち上がっているコンテナに入る
$ docker exec -it web sh

# コンテナのIPアドレスを確認する
$ hostname -i

```

コンテナのIPアドレスを確認したら、どこかに控えておきましょう。
私の場合は「172.17.0.3」でした。

#SSLの設定
やっとSSLの設定に入ります。
ここまでが事前準備といったところでしょうか・・・長い・・・

今回、SSL証明書は「Let’s Encrypt」を使用します。
既に、Webサーバにnginx, 証明書にlet’s encryptベースのリバースプロキシとして動作する. 自動で証明書の更新もしてくれるDockerイメージの「https-portal」がありますので、こちらをpullします。

```
# steveltn/https-portalをpull
$ docker pull steveltn/https-portal

```

イメージをpullできたら、次はdocker runコマンドでコンテナの作成・起動します。
※ webコンテナは私の場合ポート8080で起動するようにあらかじめ設定していますので、環境に合わせて変更してください。

```
docker run --name reverse-proxy -p 80:80 -p 443:443 -e STAGE='production' -e DOMAINS='ドメイン名 -> http://webコンテナのIPアドレス:8080' steveltn/https-portal -d
```
上記で大事なのは「-e DOMAINS='ドメイン名 -> http://webコンテナのIPアドレス:8080'」ですね。今回の環境でいうと「-e DOMAINS='ssl-site.com -> http://172.17.0.3:8080'」となります。
ドメイン名の紐づけに、VMインスタンスのIPアドレスではなく、先に作成したWebコンテナのIPアドレスを入力しないと、動いてくれません。

ここまでくると、あとはブラウザにてドメインをhttpsで接続するだけです。
お名前.comの反映に時間がかかる場合がありますので、接続がうまくいかなくても2日程度待てば、つながることもあります。

これで、GCEのDocker環境でSSL証明書を利用したデプロイが完了しました。
let’s encryptの証明書には90日の期限がありますが、steveltn/https-portalを利用すると、自動的に更新してくれるみたいです。素晴らしい。