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に下記の内容でインスタンスを立てます。

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

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

静的IPアドレスの設定

VPCネットワーク > 外部IPアドレスを選択し、静的アドレスを予約します。

名前はなんでも大丈夫です。
リージョンには、GCEと同じオレゴンを選んでいます。
予約ボタンを押し、VMインスタンスとの設定を入力します。
VMインスタンスの詳細画面から、編集を選択し、「ネットワーク インターフェース」を設定します。
外部IPのセレクトボックスから、先ほど登録した静的IPアドレスを選択します。

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

Cloud DNSの設定

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

ネットワークサービス > Cloud DNSからゾーンを作成します。

ゾーン名は任意で、DNS名は「お名前.com」で取得したドメインを入力します。
ゾーンを作成したら次は、今作成したゾーンの詳細画面を開き、レコードセットを作成します。

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

お名前.comの設定

お名前.comとCloud DNSの連携は、ゾーンの詳細画面のNSに書かれたデータという項目のxxxxx.googledomains.com.と書かれた4つをお名前.comのネームサーバに指定する必要があります。

上記の赤枠の値を下記のお名前.comのネームサーバに設定します。

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

VMインスタンスの設定

作成したVMインスタンスにSSH接続します。
作成したVMインスタンスの詳細画面からSSH接続できます。

接続出来たら、下記のコマンドを上から順番に実行して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のバージョン確認

# バイナリから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を利用すると、自動的に更新してくれるみたいです。素晴らしい。