Swiftで始めるWeb開発(3) Swiftで書かれたWebページをデプロイする

前回の[Swiftで始めるWeb開発(2) 静的サイトジェネレータIgniteを用いてWebページを構築する](https://qiita.com/gdate/items/241e5b76b009c584e901)に続き今回はSwiftからジェネレートされたWebページをデプロイしてみたいと思います。

Google Cloud Runにデプロイできる設定をしたサンプルプロジェクトを用意していますので、簡単に試してみたい方は見てみてください。
https://github.com/gdate/SwiftServerDemo

# Google Cloud Runとは
Google Cloud RunとはDockerコンテナを使用して、任意の言語やフレームワークで記述されたWebアプリケーションやAPIをパッケージ化し、Googleのインフラストラクチャー上で実行するためのサービスです。
今回WebページのデプロイにGoogle Cloud Runを選択した理由は、上述の通りプログラミング言語の制限がないからです。例えば Google Cloud Functions を使用する場合、使用できるランタイムは Node.js、Python、Go、Java、Ruby、PHP、.Net Core です。つまり、Cloud Functions では Swift で実装することができません。

また、今回はサーバサイドのWebアプリケーション開発フレームワークであるVaporをつかってSwiftで書いたバックエンドコードをGoogle Cloud Runにデプロイします。

# プロジェクトを作成
以下を参考にGoogle Cloudコンソールからプロジェクトを作成
https://cloud.google.com/resource-manager/docs/creating-managing-projects?hl=ja#console

# コマンドラインツールをインストールする
macユーザーであれば以下リンクからコマンドラインツールを入手

https://cloud.google.com/sdk/docs/install?hl=ja#mac

インストールディレクトリに移動してインストールスクリプトを実行

```
$ ./install.sh
```
途中でPATHを通すか聞いてくるので通す
```
Modify profile to update your $PATH and enable shell command completion?

Do you want to continue (Y/n)?  y
```

# コマンドラインツールを初期化
```
$ gcloud init
```
ログインを求められるので、出力されたURLをブラウザに貼り付けてログイン
```
You must log in to continue. Would you like to log in (Y/n)?  y

Your browser has been opened to visit:

    https://accounts.google.com/o/oauth2/auth?response_type=code&xxxxxxxx
```

# プロジェクトを設定
```
$ gcloud config set project {PROJECT_ID}
```
確認
```
$ gcloud config list
[core]
account = xxx
disable_usage_reporting = True
project = xxx
```

# Google Cloud Run にデプロイ
今回はソースから直接デプロイをします。この方法ではソースコードからコンテナイメージが自動的にビルドされて、デプロイされます。
```
// プロジェクトのルートディレクトリ
$ gcloud run deploy
```
ビルドに足りないAPIを有効にするか聞いてくるので、有効にする
```
Service name (xxx):
The following APIs are not enabled on project {PROJECT_ID}:
        artifactregistry.googleapis.com
        cloudbuild.googleapis.com
        run.googleapis.com

Do you want enable these APIs to continue (this will take a few minutes)? (y/N)?
  y
```
続いてCloud Runを稼働させるリージョンが聞かれるのでasia-northeast1などを選択
```
Please specify a region:
 [1] africa-south1
 [2] asia-east1
 [3] asia-east2
 [4] asia-northeast1
 [5] asia-northeast2
 [6] asia-northeast3
 ...
Please enter numeric choice or text value (must exactly match list item):  4
```
最後にサービスを公開するかを聞かれるのでYes
```
Allow unauthenticated invocations to [swiftserverdemo] (y/N)?  y
```
サービスのURLが発行するのでアクセスする
```
Done.
Service [xxx] revision [xxx] has been deployed and is serving 100 percent of traffic.
Service URL: https://xxx.a.run.app
```

# Tips
### .gitignoreに注意
google cloud runでソースコードをアップロードする際にIgniteから生成されたフォルダだけアップロードされないという不具合に遭遇しました。
```
---> Running in xxx
cp: cannot stat '/build/Build': No such file or directory
The command '/bin/sh -c cp -r /build/Build ./' returned a non-zero code: 1
```
gcloud run deployのドキュメントをよく読んでみたところ、
**.gcloudignoreファイルが存在しない場合は.gitignoreから.gcloudignoreを生成し、そこにリストされているものはアップロードされない** ということでした。

>If a .gcloudignore file is absent and a .gitignore file is present in the local source directory, gcloud will use a generated Git-compatible .gcloudignore file that respects your .gitignored files.

https://cloud.google.com/sdk/gcloud/reference/run/deploy

そのため、.gcloudignoreを作ってアップロード対象の指定をしてあげる必要があるようでした。
.gcloudignoreを作成する際には、一旦全ファイルを無視して、必要なものだけ指定するというのが必要最低限のものをアップロードできてよさそうでした。
そこで以下のように設定しました。
```
* ←全ファイル無視
!Sources/**
!Sources/WebServer/**
Sources/WebSiteGenerator/**　←IgniteのSwiftコードはビルド時に必要ないので除外
!Assets/**
!Content/**
!Public/**　←Igniteによって生成されるWebページの表示に必要なものが入ったフォルダは含める
!CloudRun/**
!docker-compose.yml
!Dockerfile
```

# 参考
https://cloud.google.com/sdk/gcloud/reference/topic/gcloudignore
https://blog.pokutuna.com/entry/allowlist-gcloudignore