GCP（GCE）でNuxt.js + Rustで作ったウェブアプリを公開する

# 概要
去年開設したAWSのアカウントが1年経って無料枠を利用できなくなったので、GCP（Google Cloud Platform）に移行することにしました。AWSのEC2に相当するGCE（Google Compute Engine）では、一番低いスペックのインスタンスを**無期限で利用できること**が乗り換えのきっかけです。
この記事ではGCPのインスタンスの作成やドメイン設定などを簡単に説明します。それぞれの詳しい内容は改めて記事にしたいと考えています。

ソースコードや公開したウェブアプリのURL:

- https://github.com/pyama2000/musa
- [Musa](https://pyama2000.tk)

# GCPでインスタンスの作成
本章ではGCPの簡単な説明と仮想マシンの利用方法などについて述べます。

### Google Cloud Platform（GCP）
GCPはGoogleが提供するクラウドサービスで、ウェブアプリケーションの開発とホスティングが行えるGoogle App EngineやAWSのEC2にあたる、仮想マシンを利用できるGoogle Cloud Engineなどがあります。他にもデータストレージやデータ分析、機械学習などのサービスがあります。
[Google Cloud Platform の無料枠](https://cloud.google.com/free/docs/gcp-free-tier?hl=ja)にあるように、GCPには12ヶ月$300分の無料クレジットと使用上限内であればいつでも無料で利用できるAlways Freeがあります。AWSでもLambdaなどは上限内であれば無料のサービスを提供していますが、GCPは仮想マシンであるGCEに関してもAlways Freeの対象となっています。

### 無料でサーバを作成
Google Compute Engineでインスタンスを作成します。
**メニュー > Compute Engine > インスタンスを作成**と進むと以下のような画面が表示されます。

![gce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227668/1941022b-7a75-2fb2-91c8-2aa96cd59cf5.png)

インスタンスを作成する際に以下のことに注意して入力しましょう。

1. インスタンス名
2. リージョン（インスタンスの場所）とゾーン選択
    - 無料で利用できるリージョンはオレゴン(us-west1)、アイオワ（us-central1）、サウスカロライナ（us-east1）の3つ
3. マシン構成を決定
    - 無料利用できるのはN1シリーズのf1-micro
4. OSとディスクサイズを決定
    - デフォルトのディスクサイズは10GBですが30GBまで無料で利用可能
5. 月々の課金額を確認

画像では$5.08の月間予算と表示されていますが、下の方に744時間分が無料で利用できると書かれています。これはf1-microインスタンスの起動時間が月に744時間以内であれば無料でインスタンスを使用できるという意味です。つまり、GCEの無料枠はインスタンス数ではなく時間に基づくということなので、毎日1台で24時間稼働していようと、2台構成で12時間のみ起動していようと課金されないということです（たぶん）。

今回は外部にウェブアプリを公開するので「ファイアウォール」の「HTTPトラフィックを許可する」「HTTPSトラフィックを許可する」にチェックします。

以上のことを確認できたら、最後に**作成**ボタンをクリックしてインスタンスを作成してください。

# ドメイン取得
[Freenom](https://www.freenom.com/ja/index.html)でドメインを無料で取得し、DNSの設定について説明します。

### 利用可能なドメインを検索
[Freenom](https://www.freenom.com/ja/index.html)にアクセスして「新しい無料ドメインを探します」に取得したいドメインを入力し、「利用可能状況をチェックします」でドメインが取得できるか検索します。

<img width="891" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227668/0afeef46-44ed-aaf8-ab0d-2fcfcd5aa3c1.png">

取得できるドメインが表示されるので、取得したいドメインの「今すぐ入手！」ボタンを押して「チェックアウト」で取得手続きを行います。

<img width="1180" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227668/fdce755e-3b4b-ed0f-013d-4dcc7bfcd443.png">

ドメインのデフォルトの有効期限が3ヶ月になっているので、必要に応じて「Period」で期限を選択して有効期限を変更できます。有効期限を設定したら「Continue」ボタンを押しましょう。

<img width="1139" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227668/239f0bd8-41ac-0e86-8fdb-2ac065d4668c.png">

最後にメールアドレスか、Google/Facebookでログインして必要な情報を記入したらドメインを取得する手順は完了です。

<img width="1139" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227668/0a292a33-ab5c-82f4-2730-b3e2f0861a19.png">

上部のツールバーの「Services」 → 「My Domains」で取得したドメインを確認できます。

<img width="1139" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227668/eaf003dc-ff8b-5df6-9a11-cfbbe7ec13c8.png">

### DNSの設定
取得したドメインとインスタンスのIPアドレスを紐付けます。
さきほどの取得ドメイン一覧画面から「Manage Domain」 → 「Manage Freenom DNS」と移動して、「Target」にインスタンスの外部IPアドレスを入力しましょう。必要であれば「Name」にホスト名を入力して「Save Changes」ボタンを押しましょう。
設定が反映されるまで少し時間がかかります。

<img width="1606" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227668/91b43402-f634-15ad-f15d-4364a76a177c.png">

インスタンスのIPアドレスはGCEの「外部IP」で確認できます。

<img width="793" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227668/93ba2737-9afc-297a-d3b7-70bb926e4791.png">


# HTTP/HTTPSで公開する
取得したドメインでウェブアプリを公開できるようにNginxとSSL証明書の発行などを行います。

## Nginx
下の構成図のようにNginxを使ってローカルで実行しているNuxt.js（クライアント）とRust(APIサーバ）を外部に公開します。

![nginx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227668/d3775286-f67c-b3ea-25d3-e8fbc20e1f3d.png)

Nginxをインストールとサービスを起動するためにSSHなどでインスタンスに接続し、以下のコマンドを実行してください。

```shell
$ sudo apt install -y nginx
$ sudo systemctl start nginx
```

無事にNginxが起動したか確認するために、ブラウザで取得したドメインかインスタンスのIPアドレスにHTTPでアクセスしてみましょう。「Welcome to nginx」と表示されたらインストールと起動の作業は完了です。

## SSL証明書の発行
HTTPSでのアクセスを許可するためにSSL証明書をLet's Encryptで発行したいと思います。
`certbot-auto`をインストールし、必要事項を入力してSSL証明書を発行しましょう。

```shell
$ wget https://dl.eff.org/certbot-auto
$ chmod a+x certbot-auto
$ ./certbot-auto
```

`certbot-auto`は自動的にNginxの設定も変更してくれるので、特に設定することなくHTTPSでアクセスできるようになっていると思います。

## ウェブアプリをNginxで公開する
HTTP/HTTPSでNginxのデフォルトページを表示することができたので、ローカルで実行しているアプリを公開します。

### アプリケーションの起動
Nuxtでアプリケーションを作成したので、まずは実行しましょう。

```shell
# 開発環境として実行する場合
$ npm run dev
# 本番環境として実行する場合
$ npm run build
$ npm run start
```

アプリケーションを実行すると、デフォルトではローカルホストの3000番ポートでアプリケーションが実行されていると思います。

### Nginxの設定を変更
Nginxの設定(/etc/nginx/site-available/default)を編集してHTTP/HTTPSでアプリケーションにアクセスできるようにします。編集するのは下の方にあるSSL設定の方なので注意しましょう。

```conf:変更前
server {

    # SSL configuration
    #
    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;

    # 省略

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }
}
```

```conf:変更後
server {

    # SSL configuration
    #
    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;

    # 省略

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        proxy_pass    http://localhost:3000;
    }
}
```

設定を変更できたらNginxを再起動しましょう。

```shell
$ sudo systemctl restart nginx
```

設定が適用されたら「https://[ドメイン名]/」にアクセスして、ウェブアプリの画面が表示されていると思います。

## APIを公開する
Rustで作成したAPIサーバも同様に起動し、Nginxの設定ファイルを編集することで外部に公開することができます。
ウェブアプリを公開する手順とほとんど一緒ですが、Nginxの設定ファイルのみ違うので以下を参考にして編集してみてください。

```conf
server {

    # SSL configuration
    #
    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;

    # 省略

    # ウェブアプリ
    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        proxy_pass    http://localhost:3000;
    }

    # APIサーバ
    location /api {
        proxy_pass    http://localhost:8000;
    }
}
```

# まとめ
GCEでウェブアプリケーションとAPIを公開する方法を説明しました。
アプリケーションやプログラムはサービスとして登録することでシェルを抜けたり再起動したりしても自動で実行できるようになるので設定することをおすすめします。

> [これから始めるGCP（GCE）　安全に無料枠を使い倒せ - Qiita](https://qiita.com/Brutus/items/22dfd31a681b67837a74)
> [GCP(GCE)にNode.jsアプリケーションをデプロイする - Qiita](https://qiita.com/yfujii01/items/41c15d885830deea8ed1)
> [GCE の無料枠のサーバを立るときに、初見でハマりそうなところ - Qiita](https://qiita.com/ndxbn/items/7ef0a96e409a5b5837bd)