Docker+Python環境からGoogleドライブへアクセスする

## やりたいこと
Docker+Python環境でGoogleドライブへアクセスすること

## 前準備
今回、GoogleドライブへのアクセスにはPyDrive2を利用した。PyDrive2は、Google Drive APIのPython Wrapper。開発が止まっているPyDriveをforkして作られており、現在進行形でメンテナンスされている。
> 参考：[PyDrive2 · PyPI](https://pypi.org/project/PyDrive2/)

```Dockerfile
FROM python:3.8.2

ENV HOME /home
WORKDIR $HOME

RUN apt-get update && apt-get upgrade -y
RUN pip install --upgrade pip \
    && pip install PyDrive2
```

```docker-compose.yml
version: '3'

services:
  app:
    build: .
    volumes:
      - type: bind
        source: ./
        target: /home/
    tty: true
```

## Google Drive APIの有効化
Google Drive APIを有効化し、OAuthクライアントを作成する。

手順は次の記事のとおり。ただし、以下の点は記事と異なる。

- OAuth同意画面を作成する際、テストユーザに自身のGoogleアカウントを追加する
- OAuthクライアントを作成する際、アプリケーションの種類は「デスクトップアプリ」にする

> 手順：[PythonからGoogleDriveに接続する方法を画像付きで説明 | たかけのブログ](https://takake-blog.com/python-driveapi/)

OAuthクライアント作成後、その認証情報のJSONファイル（ `client_secret_xxx~~~xxx.json` ）をダウンロードし、 `client_secrets.json` という名前に変更して作業ディレクトリに入れる。

## Googleドライブへアクセスする
作成したOAuthクライアントを用いてGoogleドライブへアクセスする。

まず、作業ディレクトリ内が次の構成になっているか確認する。
```
<working_dir>/
|- Dockerfile
|- docker-compose.yml
|- client_secrets.json
|- access_gdrive.py
```

`access_gdrive.py` には次のコードを入力しておく（コードには、Googleドライブにアクセスしてドライブのルートディレクトリのファイル・ディレクトリ情報を取得する処理が書かれている）。

```access_gdrive.py
from pydrive2.auth import GoogleAuth
from pydrive2.drive import GoogleDrive

gauth = GoogleAuth()
gauth.CommandLineAuth()

drive = GoogleDrive(gauth)

file_list = drive.ListFile({'q': "'root' in parents and trashed=false"}).GetList()
for file1 in file_list:
    print('title: %s, id: %s' % (file1['title'], file1['id']))
```

※ PyDrive2公式は `gauth.LocalWebserverAuth()` を既定の認証方法としているが、Docker環境からだとうまくいかなかったため `gauth.CommandLineAuth()` を使用している。その関係でOAuthクライアントもアプリケーションの種類を「ウェブアプリケーション」ではなく「デスクトップアプリ」としている

> 参考：[Google DriveをUbuntu Dockerから読み書きする(pyDrive編) : 量子プログラミング入門→量子コンピューティングサービス構築入門](https://northshorequantum.com/archives/pydrive_ubuntu_docker)

Pythonスクリプトを実行する。実行後、表示されたURLにアクセスして認証コードをコピーし、 `Enter verification code:` の部分に貼り付ける。認証に成功すると、Googleドライブのルートディレクトリのファイル・ディレクトリが表示される。

```
root@66b4fc33004c:~# python access_gdrive.py 
Go to the following link in your browser:

    https://accounts.google.com/o/oauth2/auth?client_id=（中略）&response_type=code

Enter verification code: xxxxxxxxxx
Authentication successful.
title: 新しいフォルダ, id: xxxxxxxxxx
root@66b4fc33004c:~# 
```

## 次回以降の認証を省略する

`settings.yml` に次のように記述することで、次回以降の認証を省略することができる。

```settings.yml
client_config_backend: settings   # クライアント構成をsettingsから読み取る
client_config:
  client_id: xxxxx.apps.googleusercontent.com   # クライアントID
  client_secret: XXXXxXXXxXXXX                  # クライアントシークレット

save_credentials: True                    # 認証情報を保存する
save_credentials_backend: file            # 認証情報の保存はファイルに行う
save_credentials_file: credentials.json   # 認証情報を保存するファイルの名前

get_refresh_token: True   # Refresh Tokenを利用する
```

> 参考：
> - [Google DriveをUbuntu Dockerから読み書きする(pyDrive編) : 量子プログラミング入門→量子コンピューティングサービス構築入門](https://northshorequantum.com/archives/pydrive_ubuntu_docker)
> - [Refresh Tokenってなに？〜JWTと絡めて〜](https://zenn.dev/ayumukob/articles/640cbf4a1ff3ed)

## 参考記事
- [Google DriveをUbuntu Dockerから読み書きする(pyDrive編) : 量子プログラミング入門→量子コンピューティングサービス構築入門](https://northshorequantum.com/archives/pydrive_ubuntu_docker)
- [OAuth made easy - PyDrive2 1.10.0 documentation](https://docs.iterative.ai/PyDrive2/oauth/?highlight=credentials%20json)
- [PythonでGoogle Driveの自分のファイルを操作する方法](https://zenn.dev/karaage0703/articles/9e92e077ad2725)