python×Cloud Functions×FirestoreでAPIを簡単に作ってみる Pt3 デプロイ編

## 概要
毎回GCPのコンソールからデプロイするのも面倒なので、ローカルからコマンドで関数をデプロイできるようにします。


 - 前回までの記事はこちら
   - [python×Cloud Functions×FirestoreでAPIを簡単に作ってみる Pt1](https://qiita.com/ny7760/items/9cdc3407dfda99c21ae1)
   - [python×Cloud Functions×FirestoreでAPIを簡単に作ってみる Pt2 テスト編（要約）](https://qiita.com/ny7760/items/5519dd3988ceb2326d38)
   - [python×Cloud Functions×FirestoreでAPIを簡単に作ってみる Pt2 テスト編（詳細）](https://qiita.com/ny7760/items/01dacd4df434f4a5be25)

## 開発環境
- 開発環境
  - MacOS
  - python3.7
  - pycharm

## gcloudツールのインストール
ローカルからデプロイするには、gcloudコマンドが使えるようになる必要があります。Macの場合brewでインストールします。

```console
$ brew cask install google-cloud-sdk
```

インストールが終わったらinitでSDKを初期化します。以下のコマンドを実行するとgoogleアカウントやプロジェクトIDが質問されるので、適宜答えていくと初期化が完了します。

```console
$ gcloud init
```

## デプロイの準備
### ソースの準備

ローカルからデプロイする場合、対象のソースファイルは```main.py```という名前にする必要があります。今まで作成してきたソースを別ファイル名にしたり、あるいは複数の関数をデプロイするために```main.py```に追加していくのは、少し残念な感じです。

そこでファイルを分けてソースの管理を楽にします。以下の記事が非常に参考になります。
[Cloud Functions(Python)でコードファイルを分割する](https://qiita.com/kai_kou/items/a07872db77193f130b9a)

記事の通り、外部ソースからデプロイ対象の関数を```main.py```にimportします。

```python:main.py
from functions.getFilteredUser import get_filtered_user
```

ソースの内容はPt1やPt2の記事を参照してください。
別関数をデプロイしたい場合、以下のようにimport文を増やすだけOKです。

```python:main.py
from functions.getFilteredUser import get_filtered_user
from functions.getUser import get_user  # 追加関数
```

### requirements.txtの準備

コンソールからのデプロイ時と同様に、外部パッケージは指定する必要があります。ローカルでmain.pyと同じパスにrequirements.txtを作成します。

```:requirements.txt
# Function dependencies, for example:
# package>=version
google-cloud-firestore==1.2.0
```

### フォルダの最終形
以下のようなフォルダ構成になっていると思います。「.auth」はデプロイ時には不要です。
<img width="313" alt="スクリーンショット 2019-08-05 0.11.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451175/d1b5db0b-73cb-618a-80dd-102e5b41b826.png">


## デプロイ
というわけでようやく本題のデプロイです。venvなど```main.py```があるディレクトリで以下コマンドを実行します。

```console
$ gcloud functions deploy get_filtered_user --runtime python37 --trigger-http
```

コマンドでは```main.py```に含まれる関数を```get_filtered_user```という名前でデプロイします。2分くらい待つとデプロイが完了します。

```console:deployコマンドの結果
Deploying function (may take a while - up to 2 minutes)...done.                                                                                                             
availableMemoryMb: 256
entryPoint: get_filtered_user
httpsTrigger:
  url: https://<リージョン>-<プロジェクトID>.cloudfunctions.net/get_filtered_user
labels:
  deployment-tool: cli-gcloud
name: projects/<プロジェクトID>/locations/<リージョン>/functions/get_filtered_user
runtime: python37
(以下省略)
```

エンドポイントのURLは指定が無ければ関数名と同じになります。変更する場合や、```main.py```内の別関数をデプロイする場合は、```--entry-point```のオプションを付けてデプロイします。

```console
$ gcloud functions deploy get-user --runtime python37 --trigger-http --entry-point get_user
```
このコマンドでは、```main.py```にimportしたget_user関数がデプロイされます。また、URLはget-userになります。

その他オプションの使い方は公式に書かれています。
[Deploying from Your Local Machine](https://cloud.google.com/functions/docs/deploying/filesystem)

## おわりに
Pt1〜Pt3を通じて、GCP, Firebaseを使うと、ローカルで作成した関数を簡単にAPIとしてデプロイすることができます。ハッカソンなどで簡単なアプリケーションを作りたい場合には便利だと思いますので、ぜひ試してみてください。


## 参考
 - [Google Cloud FunctionsでPythonを利用してみた(Beta利用)](https://qiita.com/kai_kou/items/dca21cdfd8375a247c2f)
 - [MacでCloud Machine Learning Engineを利用してみる](https://qiita.com/kai_kou/items/0952c9b28efe19f2f680)
 - [Cloud Functions(Python)でコードファイルを分割する](https://qiita.com/kai_kou/items/a07872db77193f130b9a)