量子プログラミング入門→量子コンピューティングサービス構築入門

量子コンピューター初心者の筆者が日々学びながら、量子コンピュータ上で量子プログラミングできるようなるまでの学習日記を記録していきます。 内容は量子コンピューター入門者向けで、専門家の方からするとおかしな内容があるかもしれません。その際はコメント等でお知らせください!

カテゴリ: サイト構築

無料プロキシサーバ公開

自分の勉強もかねてプロキシサーバを立ち上げてみた。 自分の実験などいろいろ行いたいが、大半は使ってない状態で、ただずっと立ち上がってるので一般公開します。 それでも無差別にアクセスされるのは嫌なので、IDとPassword認証だけは入れておきます。 でも入力しやすいようにパスワードは簡単なのにします。

パスワードは定期的に更新するので、この記事で最新のパスワードを公開していきます。

プロキシサーバの性能

すごく小さなサーバーを使っていますが、自分一人で使っている状態だとそれなりの速度は出ています。80Mbpsなら動画視聴などにも十分性能がでるので悪くないと思います。ただシングルCPUのインスタンスなので、利用者が複数になってくると極端に性能が落ちるかもしれません。利用者がどれぐらい増えるかわかりませんが、無償なのでとりあえずベストエフォートということでご容赦ください。
proxy_speedtest






プロキシアクセス情報

情報更新日2022-10-18 03:28:41.225904 (JST)
アドレスhttp://proxy.northshorequantum.com
ポート番号3128
場所日本・東京
User IDuser
Passwordfujitsu2011!

不正利用防止のためパスワードは24時間に1回程度の頻度で更新しますので、定期的にこのページを見に来てください。

iOSでのプロキシ設定方法について

iPhoneでプロキシの設定を行う方法を説明しておきます。
1) 設定からWi-Fiを選択します IMG_4855

2) 接続しているWi-Fiの(i)マークをタップします。 IMG_4856

3) 一番下にプロキシ設定があるので、プロキシ設定を選択します。
IMG_4857
4) 下記の画像のように認証(Authentication)を有効にして、Server, Port, Username, Passwordを設定します。
IMG_4858






Proxyサーバを使っていろいろ実験をしたいと思ったのでAWSのEC2 Ubuntuのインスタンス上でSquidでProxyを立てた時のメモ

Docker環境構築

EC2のインスタンスを立ち上げるところは省略します。
Ubuntuのインスタンスを立ち上げた後にこちらを参考にDockerをインストールします。

一連のコマンドは下記
sudo apt update

sudo apt upgrade

sudo apt-get install -y\
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -


sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \                 
   $(lsb_release -cs) \                                                         
   stable"

sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io -y

sudo usermod -aG docker ubuntu

squidのdocker imageをとってくる

こちらのdocker imageを使います。下記のコマンドでdocker imageをとってきます。
sudo docker pull sameersbn/squid:3.5.27-2

squidの設定変更

アクセスコントロール

下記の部分は自分のアクセス元に合わせて設定してください。
acl mynet src 192.168.0.10

てっとり早く動かしたい方はhttp_access allow mynetを
http_access allow all

とすれば動きます。

匿名化設定

こちらのサイトを参考に設定変更を加えていくが、squidがversionアップされているので、ディレクティブ名が変更になっているので要注意。header_accessとなっているところは、request_header_accessに変更する。
匿名化設定として追加したのは下記5つ
visible_hostname none
forwarded_for off
request_header_access X-FORWARDED-FOR deny all request_header_access VIA deny all request_header_access CACHE-CONTROL deny all

最終版

squid.confはとてつもなく巨大なので、コメント以外の部分を抽出するとこんな感じです
acl SSL_ports port 443
acl Safe_ports port 80		# http
acl Safe_ports port 21		# ftp
acl Safe_ports port 443		# https
acl Safe_ports port 70		# gopher
acl Safe_ports port 210		# wais
acl Safe_ports port 1025-65535	# unregistered ports
acl Safe_ports port 280		# http-mgmt
acl Safe_ports port 488		# gss-http
acl Safe_ports port 591		# filemaker
acl Safe_ports port 777		# multiling http
acl CONNECT method CONNECT
http_access deny !Safe_ports
acl mynet src 192.168.0.10
http_access allow localhost
http_access allow mynet
visible_hostname none
forwarded_for off
http_port 3128
coredump_dir /var/spool/squid
refresh_pattern ^ftp:		1440	20%	10080
refresh_pattern ^gopher:	1440	0%	1440
refresh_pattern -i (/cgi-bin/|\?) 0	0%	0
refresh_pattern (Release|Packages(.gz)*)$      0       20%     2880
refresh_pattern .		0	20%	4320
request_header_access X-FORWARDED-FOR deny all
request_header_access VIA deny all
request_header_access CACHE-CONTROL deny all

Docker立ち上げ

Dockerを立ち上げる時に下記のコマンドのように自分の作成したsquid.confを指定して立ち上げます。ローカルのsquid.confの置き場所は自分の環境に合わせて変更してください。
sudo docker run --name squid -d --rm --publish 3128:3128 -v /srv/docker/squid/cache:/var/spool/squid -v $(pwd)/etc/squid.conf:/etc/squid/squid.conf sameersbn/squid:3.5.27-2

Proxy匿名度診断

診断君で診断した結果はAまたは生IP、CACHE-CONTROLまで設定しましたが、20%の確率でプロキシかもとのこと。

ちなみに、このプロキシを使ってDAZNにアクセスすると下記のようにDAZN IS NOT AVAILABLE IN THIS COUNTRYとなります。つまりDAZNにはProxy認定(?)されています(笑) 
(日本国内から日本国内に立てたProxyを経由してアクセスしています)
DAZNなどのコンテンツサイトはIPアドレスでNGとしている場合が多いので、AWSのIPアドレスでNGを食らってるのかもしれません。

dazn_deny


ちなみに、先日紹介したAblenetのVPS経由だとDAZNはきちんと表示されました。(2020年10月時点)
一方で、AWSに立てたインスタンスからだとDAZNは上記のProxy経由と同じように、NOT AVAILBLEになります。DAZNはProxyかどうかの判断もしているのと、アクセス元がAWSのIPアドレスの場合などに対してもガードしているようです。





こちらの記事で WindowsのVPSを使ってリモートデスクトップ接続する記事を書いたが、AWSのUbuntu Desktopでリモートデスクトップ接続できないか実験してみた。

PuTTYのインストール

PuTTYは検索すればすぐに出てくるが、ダウンロード先のリンクはこちら

AWSでインスタンス立ち上げ

イメージの種類はUbuntu20.04を選択
AWS_Instance_Ubuntu


インスタンスの種類はt2.mediumにする。(t2.microだとChromeがほとんど動かないくらい重い)
AWS_Instance_Type


基本的にはデフォルトの設定で問題ないが、気を付けるのはセキュリティ設定でSSHの22番ポートがきちんと開いていることを確認しておく。(デフォルトから変更しなければ問題ない)

インスタンス生成時にSSHの鍵ファイルをダウンロードする。(あらかじめ生成しておいたものでもよい)
AWSの鍵ファイルはpem形式だが、PuTTYが受け付けるのはppk形式なので変換が必要だこちらの情報を参考にpemファイルを ppkに変換する。自分の場合はWSLからputtygenを使って変換した。(WSLのインストールの仕方はこちら)

PuTTYの設定

Ubuntu側のリモートデスクトップ設定が終わったら、PuTTY側でクライアントからのSSH接続の設定を行う。
  1. Host NameにインスタンスのパブリックIPアドレスを入力する
  2. 設定を保存しておいたほうが便利なので、Saved Sessionsに名前を入力しSaveを押す
  3. SSHメニューの中のAuthを開き、先ほど生成したppkファイルを設定する
PuTTY Configuration 2020_10_18 19_02_52

PuTTY Configuration 2020_10_18 19_03_01

Ubuntuのリモートデスクトップのインストールおよび設定

以下のコマンドを実行し、Ubuntuのリモートデスクトップのインストールおよび設定を行う
sudo apt update && sudo apt upgrade
sudo sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
sudo /etc/init.d/ssh restart
sudo passwd ubuntu
sudo apt install xrdp xfce4 xfce4-goodies tightvncserver
echo xfce4-session> /home/ubuntu/.xsession
sudo cp /home/ubuntu/.xsession /etc/skel
sudo sed -i '0,/-1/s//ask-1/' /etc/xrdp/xrdp.ini

AWSのUbuntuのインスタンスはデフォルト設定ではパスワード認証でログインできないようになっているが、途中で認証の設定を変更し、パスワード認証でログインできるようにするとともにパスワード設定を行っている。
新しいパスワードを入力するように聞かれるので、新しいパスワードを設定する。

Puttyでトンネリング設定

今回はUbuntu側でリモートデスクトップのポートを開いて接続するのではなく、すでに開いているSSHの22番のポートを利用してSSHの中にRDPのプロトコルをトンネリングさせる。少しわかりにくいが下記の図のように、SSH接続が土管(トンネル)となってその中をリモートデスクトップのプロトコルが流れるイメージだ。
ubuntu_tunneling
PuTTYの設定は
  • Source Portに8888
  • Destinationに (Local IP Adressを172.31.3.223とした場合) 172.31.3.223:3389
と入力しAddボタンを押す。
PuTTY Configuration 2020_10_18 20_07_28

この設定をした後に再度PuTTYでUbuntuのインスタンスにSSH接続する。

リモートデスクトップ接続

次にWindowsの端末からリモートデスクトップ接続する。この際に先ほどPuTTYで設定したように接続先を「loclahost:8888」とする。
rdp_client


下記のような画面が現れここでUbuntuで設定したパスワードを入力しログインする。
localhost_8888 - リモート デスクトップ接続 2020_10_18 16_43_48

Google Chromeのインストール

Ubuntuにログインできたらブラウザをインストールする。ここではGoogle Chromeのインストール方法を紹介しておく。Ubuntu上でのGoogle Chromeのインストールは下記のコマンド2つで実行
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome-stable_current_amd64.deb

インストール出来たら左上のメニューからGoogle Chromeが起動できるようになっている。
localhost_8888 - リモート デスクトップ接続 2020_10_18 17_39_44

所感

UbuntuなのでWindowsと比べてサクサク動くことを期待していたが、Ubuntuのリモートデスクトップ環境はかなり重たく、4GBメモリではGoogle Chromeを動かすのでさえもカクカクして実用レベルになかった。AWS上のUbuntuはデスクトップ用途には向いていないので、デスクトップを使いたいのであればおとなしくWindowsのインスタンスを使うほうが良いと思う。
EC2でインスタンスを立ち上げるのも久しぶりにやるとけっこう複雑で、こちらで紹介したAblenetのWindows VPSのほうが楽ちんで初心者にも使いやすいと思いました。


Windows Server 2012をリモートデスクトップで使ってみる

コロナの影響でテレワークがより普及されてきて、いろいろな場所から作業する機会が増えてきた。ノートパソコン1つで作業できるならよいが、データがたくさん詰まったラップトップを持ち歩くのに気が引ける場合もあるので、常にリモートで同じ環境にアクセスできるようにWindowsのVPSを試してみた。
今回試してみたのはAblenet(エイブルネット)のWindows Desktop環境を使ってみた。一番安いプランだと月々1981円で今ならキャンペーン価格でさらに安く、メモリも1.5GBに増量されておりお得になっている。
OSはWindows Serverの2012になっており、通常のデスクトップOSと異なる部分もあるので、最初に実施した設定をまとめてみた。

接続

通常のリモートデスクトップアクセスと変わりません。リモートデスクトップのアプリを起動します。この際に念のため音声の設定を確認しておきます。
login2

リモートデスクトップで音声が再生できるようになっているのと、テレワークなどでマイクも使用したい場合は、リモートオーディオ録音も「このコンピュータから録音」にしておきます。

login3

IEのセキュリティ設定の解除

「Internet Explorerセキュリティ強化の構成」でほぼほぼすべてのアドレスにアクセスするたびに警告メッセージが出ます。
IE_Warning
「Internet Explorerセキュリティ強化の構成」を解除するにはサーバーマネージャーを開き、ローカルサーバーを選択します。サーバーマネージャーはWindowsメニューの中から選択できます。
IE_Security_Disable
左メニューから「ローカルサーバー」を選択し、右側から「IEセキュリティ強化の構成」の「有効」をクリックすると設定変更画面がでるので、ここで設定を「無効」にします。

Chromeのインストール

さすがにIEだけでは、いろいろ不自由があるのでGoogle Chromeなどの新しい目のブラウザをインストールしておきます。

VPS側のサウンドの設定

端末側のサウンド設定は接続時に設定してありますが、VPS(Windows Server 2012)側はデフォルトでオーディオデバイスが無効になっています。このままでは音声を再生できないのでオーディオデバイスを有効にします。
まずコントロールパネルを開き、ハードウェアを選択します。

audio

次にサウンドを選択するとオーディオサービスを有効にするか聞かれますので、「はい」を押して有効にします。

audio2


これで接続元の端末からも音声が使えるようになり、テレワークでのリモート会議や動画視聴が可能になります。


使用した感想

一番下の最低構成(2 core, 1.5GBメモリ)の詳細は下記 (あくまで自分に割り当てられた構成で、Ablenet側が保証している仕様ではないのでご注意を)


CPUXeon E5 2667 v3 (2仮想CPU)
メモリ1.5GB
*カタログ上は2coreだが、システム上は2仮想CPUとのこと、2コアなのか2threadなのかはわからなかった

性能的には動画視聴などブラウジング程度ならサクサク動き十分に使える。メールやブラウザ、簡単な資料作成といった軽い作業しかしないのであれば外出先かアクセスできる個人環境として十分である。
(真っ黒な画面だがyoutube視聴中)

spec


気になるのは立ち上げただけで0.6GBのメモリを使用し、Chromeを開いてyoutubeを視聴した時点で1.1GBのメモリを使用となり、たくさんアプリを立ち上げる場合はメモリが不足しそうなので、ライトユーザーには一番下の構成で十分だが、メインの環境として使うには少し物足りないかもしれない。

使い方により構成を適切に選択する必要はあるが、月々2000円以下でリモートのWindows環境を使えるのは非常に便利だと思う。


Google DriveのRate Limit



 ここ最近Google Driveを使ってシステム構築できないかいろいろ試してきたが使っていてなんだか不安定だなと思っていたのだが、プログラムの問題ではなくGoogle Driveのアクセス制限(Rate Limit)であることに気が付いた。

事前にあまり情報がなかったので帯域や通信制限がどのようになっているのか気にはなっていたが、特に制限はないと勘違いしていたが、明確にアクセス回数制限に上限があるようだ。


Google DriveのRate Limitの確認方法


まずGoogle APIのダッシュボード画面に行くDashboard
Google Driveを使っている場合、画像のようにGoogle Drive APIへのリンクが出ている。
ここをクリックしGoogle Drive APIのダッシュボードに移動する。

gd_dashboard

ここで左のメニューから"割り当て"をクリックする。

gd_rate_limit
そうすると、Google Drive APIのRate Limitが表示される。
無料会員の場合、下記のような制限になってると思います。

Queries per day: 1,000,000,000
Queries per 100 seconds per user:  1,000
Queries per 100 seconds: 10,000

100秒間に1000リクエストの制限があるので短時間で大量にファイルをアップロードするような処理をpyDriveで実装しても、Rate Limitに引っかかってしまいプロセスがkillされてしまう。google-drive-ocamlfuseが不安定だったのもこのせいだと思われたが、100秒当たりのコール数を確認しても1000コールにほど遠い状況。1日のコール数も全然少ないので問題ない。


gd_api_rate


何か他にもありそう。
pythonのプログラムが"Killed"のメッセージだけ残して落ちるのでほぼほぼ手掛かりがないが、exceptionに引っかかってるわけではないので、外部(OS)からKillされているっぽい。
topコマンドでメモリ使用量を見てると、流してくとメモリ使用量が徐々に増えているのがわかる。
プログラムはほぼほぼここで公開しているものと同じだが果たしてどこでリークしているのか...






pyDriveを使ってフォルダ丸ごとアップロードするプログラム


はじめに

pyDriveを使うための事前準備はこちらに書いてあるのでご参考にしてください。
今回作成したのはローカルのディレクトリにあるファイルを一括転送するプログラムで、2階層のディレクトリ構造で下記のように2階層目にデータファイルがある構造を想定しています。
この構成でtestディレクトリを丸々アップロードするプログラムです。
/home/static/Data/test
|
|
+- dir1
| |
| +- Data1
| +- Data2
|
+- dir2
|
+- Data3
+- Data4



とりあえずプログラム

実際に使う場合は下記を自分の環境に合わせて設定してください。その他はコピペすれば動くはずです。
    parentid:  Google Drive上のアップロード先フォルダのIDを指定、この下にデータがアップロードされます
    path: ローカルのデータ格納フォルダ

import os
import sys
import datetime

from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

def auth_gd():
    gauth = GoogleAuth()
    gauth.CommandLineAuth()
    drive = GoogleDrive(gauth)
    return drive

def upload2googledrive():
    drive = auth_gd()
    
    parentid = 'xxxxxxxx' #project-root directory
    path = "/home/static/Data/test" #path to local data

    # "test"フォルダをGoogle Drive上に作成
    t_folder = create_dir(parentid, os.path.basename(path), drive)

    # ローカルのディレクトリ一覧取得
    flag = ""
    dir_list=get_dirlist(path)
    for d in dir_list:
        d_folder = create_dir(t_folder['id'], os.path.basename(d), drive)
#ローカルのファイル一覧取得 file_list=get_filelist(d) for f in file_list: upload_file(d_folder['id'], f, drive)
# ディレクトリがGoogle Drive上に存在するかどうかをチェックし、
# 存在しなければ作成、すでに存在すれば既存のフォルダを返す def create_dir(pid, fname, drive=None): if drive == None: drive = auth_gd() ret = check_files(pid, fname, drive) if ret == False: folder = drive.CreateFile({'title': fname, 'mimeType': 'application/vnd.google-apps.folder'}) folder['parents']= [{'id': pid}] folder.Upload() else: folder = ret print(folder['title']+" exists") return folder
#同じ名前のファイルがGoogle Drive上に存在するかチェックし、
#存在しなければアップロード、存在すれば既存のファイルを返す def upload_file(pid, fname, drive=None): if drive == None: drive = auth_gd() ret = check_files(pid, fname, drive) if ret == False: gf = drive.CreateFile() gf['parents']= [{'id': pid}] gf.SetContentFile(fname) gf['title'] = os.path.basename(fname) gf.Upload() else: gf = ret print(gf['title']+" exists") return gf
#Google Drive上にその名前のファイル/フォルダがあるかチェック、なければFalseを、あれば既存のファイル/フォルダを返す def check_files(pid, fname, drive=None): if drive == None: drive = auth_gd() query = '"{}" in parents'.format(pid) query += ' and title = "' + os.path.basename(fname) + '"' list = drive.ListFile({'q': query}).GetList() if len(list)> 0: return list[0] return False def get_dirlist(basedir): ret = [] for path, dirnames, filenames in os.walk(basedir): for dir in sorted(dirnames): d = os.path.join(path, dir) ret.append(d) return ret def get_filelist(basedir): ret = [] for path, dirnames, filenames in os.walk(basedir): for filename in sorted(filenames): fullpath = os.path.join(path, filename) ret.append(fullpath) return ret if __name__ == '__main__': upload2googledrive()


プログラム解説

Google Driveのファイル管理について

初めに、pyDriveでGoogle Driveを取り扱ううえで厄介なのがファイルがファイル名でなくIDで管理されていることです。IDで管理されているということは、同じ名前のファイルを同じフォルダにアップロードできてしまい、別ファイルとして存在できてしまいます。そのためこのプログラムではファイル名(title)でlistを確認し、同じファイル名のファイルが存在すればそれを返すようにすることで二重生成を防いでいます。毎回フォルダ作成やファイルアップロードのたびにこのチェックが入るので、けっこうなやり取りが発生します。

ファイルのアップロード

        gf = drive.CreateFile()
        gf['parents']= [{'id': pid}]
        gf.SetContentFile(fname)
        gf['title'] = os.path.basename(fname)
        gf.Upload()
CreateFileを使用し、google driveのGoogleDriveFileオブジェクトを生成します。
生成したファイルオブジェクトに属性を設定して、最後にアップロードします。

['parents']:格納するディレクトリのIDを指定します。
Google Driveはパス名やファイル名でデータを管理しておらず、IDを使ってデータ構造を管理します。
自分のIDはアップロード後に、gf['id']で参照することができます。
フォルダを作成し、その下にファイルをアップロードする場合は、作成したフォルダの['id']を取得し、アップロードするファイルの['parents']にフォルダの['id']を設定します。

フォルダの生成

        folder = drive.CreateFile({'title': fname,
                                 'mimeType': 'application/vnd.google-apps.folder'})
        folder['parents']= [{'id': pid}]
        folder.Upload()

フォルダの生成もファイルの生成とほぼ同様です。1つだけポイントは
'mimeType': 'application/vnd.google-apps.folder'
とすることです。

Google Drive上の情報取得

    query = '"{}" in parents'.format(pid)
    query += ' and title = "' + os.path.basename(fname) + '"'

    list =  drive.ListFile({'q': query}).GetList()

ListFile()を使用してGoogle Drive上のファイルの一覧を取得することができます。
'q'を使ってQueryで条件を指定することができます。
ここでは、
  • in parentsで親となるフォルダを指定している
  • title=を使ってファイル・フォルダ名を指定している
で、条件を絞り込んでいます。queryの内容はstrで指定でき、条件を"and"でつなぐことで、複数の条件を指定することができます。andでつなぐ場合はきちんと間にスペースが入っていることを確認しましょう。

ローカルファイルの一覧取得

    ret = []
    for path, dirnames, filenames in os.walk(basedir):
        for dir in sorted(dirnames):
            d = os.path.join(path, dir)
            ret.append(d)

os.walkを使用してローカルのディレクトリ・ファイル一覧を取得します。上記ではディレクトリの一覧のみを取得していますが、ファイルに関しても同じように処理できます。


google-drive-ocamlfuse vs pyDrive性能比較


ubuntu上のシステムからGoogle Driveをストレージとして使用したいと考え、google-drive-ocamlfuseを使ってみたが、性能が非常に遅いのと、長時間通信をしているとファイルシステムがおかしくなり途中で通信できなくなるので、pyDriveでのデータ転送を試してみる。

google-drive-ocamlfuseの使い方はこちらを参照
使用したpyDriveコードはこちらを参照


性能測定結果

1MBのファイル 10個のアップロード

モジュール5回測定の平均時間
pyDrive28.60
ocamlfuse32.38

1MBのファイルを10個アップロードする処理を5回実施し、それぞれの平均時間をとってみた。
ばらつきがあるものの、pyDriveのほうが基本的に早く、平均すると13%ほど早い。
ただ、どちらの処理も10MBのデータ転送に30秒程度かかるのでけっこうな遅さだ。

10MBのファイル 1個のアップロード

モジュール5回測定の平均時間
pyDrive5.89
ocamlfuse4.81

こちらのテストではocamlfuseのほうが早かった。おそらくファイル1個の転送に対してpyDriveでは1回の認証処理が入っているので祖分部分のオーバーヘッドが大きいと思われる。

100MBのファイル 1個のアップロード

モジュール5回測定の平均時間
pyDrive8.29
ocamlfuse8.90

ファイルのサイズを10倍にしてみた。こちらのテストではpyDriveのほうが若干早かった。
転送時間自体は、それぞれ3秒程度伸びだだけで、処理時間の大部分が転送以外の部分に使われていることがわかる。
よくわからない動きをしたのが、ocamlfuseの場合、最初の2回は10秒程度かかっていたが、後半の3回は7秒台にまで短縮され、キャッシュの処理か何かあるのか突然加速した。

その他気になったこと

ocamlfuseはファイルシステムで、おそらくキャッシュを持っている。ubuntuからファイルをGoogle Driveにファイルを作成し、作成したファイルをブラウザで開いたGoogle Driveで削除といった処理をすると、削除が反映されるまでに時間がかかる。syncコマンドも効かず、キャッシュ更新のトリガーはよくわからなかった。

まとめ

基本的にネットワーク越しのストレージなのでベースとなる性能はよくない。いずれのモジュールを使っても性能的には大きな差は出ない。
ただ、小さなファイルを大量にいくつもアップロードする必要がある場合は、pyDriveで独自の処理を書いたほうが良いと思われる。ocamlfuseの場合はそのような処理をしていると途中でエラーがでたりおかしくなる。業務で利用するならocamlfuseは避けたいと思う。

少ない数のファイルを置いたり、軽めの参照をしたりするぐらいだとocamlfuseが便利だ。
pyDriveの難点は簡単なファイル操作でもそれなりのコードが必要で、その点でocamlfuseは通常のファイルシステムとして見えるので非常に便利である。


pyDriveでUbuntuのDockerからGoogle Driveのファイル操作を行う


google-drive-ocamlfuseの問題

google-drive-ocamlfuseを使ってUbuntuのDockerからGoogle Driveをマウントする方法を試してみたのだが、google-drive-ocamlfuseは特別な手続きなしでファイルを操作できる反面、使ってみるとめちゃめちゃ遅くて、小さなファイルのやり取りならなんとかなるが、数十MBのデータの移動などをするとなると実用レベルにないくらい遅い。別の方法も試してみようと思い、pyDriveに行き着く。

pyDriveとは

pyDriveはGoogleのGoogle Drive APIのpython wrapperで、直接APIを呼び出すよりはpythonから呼び出したほうが便利かと思ってこれを試してみる。


Dockerを立ち上げる前に下記のファイルを用意しておく
  • Dockerfile
  • Google APIのClient ID / Client Secret (デスクトップアプリ用のID/Secretを用意)
  • settings.yaml (Google Driveの認証情報などの設定の定義ファイル)
  • gd_pydrive.py (pyDriveのお試しプログラム)

デスクトップアプリ用のClient ID/Client Secretについては作り方をこちらで紹介しています。今回は認証にCommandLineAuth()を使うので"デスクトップアプリ"用のID/Secretを用意してください。

それぞれのファイルは下記。

Dockerfile
FROM ubuntu:latest

RUN apt-get update
RUN apt-get install python3 python3-pip -y
RUN pip3 install pydrive

COPY . /work
WORKDIR /work

とりあえず最低限の構成。ローカルディレクトリに設定ファイル(settings.yaml)とテストプログラム(gd_pydrive.py)を配備しておき、Docker上の/workにコピーする


settings.yaml
client_config_backend: settings
client_config:
  client_id: xxxxx.apps.googleusercontent.com
  client_secret: XXXXxXXXxXXXX

save_credentials: True
save_credentials_backend: file
save_credentials_file: credentials.json

get_refresh_token: True

詳細なオプションは公式マニュアルを参照してもらうとして、
ポイントを説明すると、
  • client_id, client_secretをこのファイルで指定しておく。
  • save_credentialsをTrueにして、ファイルに保存するようにしておくことで次回以降の認証手続きを簡素化させる。
  • get_refresh_tokenをTrueにすることでアクセスするごとにtokenをリフレッシュさせる


gd_pydrive.py
from pydrive.auth import GoogleAuth

gauth = GoogleAuth()
gauth.CommandLineAuth()

調べていると、gauth.LocalWebserverAuth()を使うやり方が多く紹介されているが、ホストのUbuntuからだとうまく行くが、Docker上からだと認証後のリダイレクトがうまく行かず断念。
公式のマニュアルもLocalWebserverAuth()が第一候補だが、 CommandLineAuth() も紹介されており、こちらを使ってみる

You can also use CommandLineAuth() which manually takes code from user at command line.

Docker Image作成+実行


下記コマンドを実行し、Dockerイメージを作成+Dockerを実行
sudo docker build -t gdrive .
sudo docker run  -it gdrive /bin/bash

Docker上でpyDriveをお試し(初回認証)
root@2385921abe7d:/work# python3 gd_pydrive.py
/usr/local/lib/python3.8/dist-packages/oauth2client/_helpers.py:255: UserWarning: Cannot access credentials.json: No such file or directory
  warnings.warn(_MISSING_FILE_MESSAGE.format(filename))
Go to the following link in your browser:

    https://accounts.google.com/o/oauth2/auth?client_id=xxxxxxxxxxxx.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive&access_type=offline&response_type=code&approval_prompt=force

Enter verification code: xxxxxxxxxxxxxxxxxxxxxxxx
Authentication successful.



同じディレクトリにcredentials.jsonが生成され、次回からブラウザによる認証なしで行ける
root@536122a820a4:/work# ls -l
-rw------- 1 root root 1286 Sep 20 13:38  credentials.json
-rw-rw-r-- 1 root root  306 Sep 20 12:57  gd_pydrive.py
-rw-rw-r-- 1 root root  296 Sep 20 12:57  settings.yaml

認証は通るようになったので次回はファイル操作をしてみて性能を見てみることとする。

Ubuntu DockerからGoogle Driveをマウント

0) はじめに

LightsailでWebサイトを運用していてストレージが不足してきたので、ストレージを追加しようと計画していていろいろ調べていましたが、Lightsailのstorageは割高感があり、S3も調べましたが、料金体系が複雑で、試算しているとけっこういい値段になります。Google Driveは100GBで200円程度で、トラフィック量など複雑なことを考えずにすむので、とりあえず試してみようと思いました。

ここで問題はグラフィックコンソールがあるUbuntu DesktopからGoogle Driveをマウントする方法はたくさん紹介されていますが、Lightsailはheadless(グラフィックコンソル / X端末がない状態)で運用しておりそれらの方法が使えません。ここではheadless(グラフィックコンソル / X端末がない状態)でubuntuからGoogle Driveをマウントする方法を紹介します。
さらに、WebサイトはDockerを使って立ち上げているので、UbuntuのDocker ImageからGoogle Driveをマウントする方法を紹介します。

1) Google API設定  Client ID / Client Secretの取得

UbuntuからGoogle Driveをマウントするには"google-drive-ocamlfuse"を使用しますが、"google-drive-ocamlfuse"をheadless/グラフィック端末無しで使用するには通常のGoogle Accountによる認証ではなく、Google APIのclient ID/client secretを用意する必要があり、これらを初めて使う人には少し複雑な作業です。

Google APIのclient ID / client secretはGoogle Developer Consoleから取得可能で、このページにGoogleアカウントを使用してログインします。

a) プロジェクトの作成

no title

まず最初にプロジェクトを作成します。(既存のプロジェクトを使うのでも問題ないです)
Google APIコンソールの左上にあるプロジェクトをクリックすると新しいプロジェクトを作成するボタンがでますので、プロジェクト名を決めて新しいプロジェクトを作成します。

b) 認証情報の作成 → oauth同意画面を設定

1
次に左のメニューの"認証情報"を選択し、"+認証情報を作成"をクリック、"OAuthクライアントID"を選択
  1. 左のメニューの"認証情報"を選択
  2. +認証情報を作成"をクリック
  3. OAuthクライアントID
2
初回は"OAuth同意画面"の設定に行くことになります。
3
この画面が出たら、"外部"を選択します。

c) OAuth同意画面の設定

4
アプリケーション名を入力し、スコープでGoogle Driveを追加する
5

Google Drive APIをスコープに追加
6



  • Google Drive内のすべてのファイルの表示
  • Google Drive内のファイルのメタデータの表示
  • Google Driveのファイルのメタデータの表示
をチェックし、Scopeに追加します。

d) 認証情報の作成 

7
次に認証情報を作成します。もう一度"+認証情報を作成"をクリックします。

8
"デスクトップアプリ"を指定します。

e) client ID/ client secret取得

これでClient ID/ Client Secretが取得できました。

9

2) "google-drive-ocamlfuse"でマウント

a) google-drive-ocamlfuseのインストール

まず最初に下記コマンドを実施し、必要なモジュールをインストールします。
sudo apt-get -y install software-properties-common
sudo add-apt-repository ppa:alessandro-strada/ppa
sudo apt update
sudo apt -y install google-drive-ocamlfuse

b) google-drive-ocamlfuseの実行

インストールができたら下記のようにコマンドを実行しGoogle Driveをマウントします。
google-drive-ocamlfuse /MOUNTPOINT -headless -id YOURID.apps.googleusercontent.com -secret YOURSECRET
MOUNTPOINTはマウントしたいディレクトリを指定、-idと-secretは先ほど取得したclient IDとclient secretを指定します。

初回は下記のようにURLが表示されて、verification codeを入力するように求められます。
10
このURLをコピーし、PCのブラウザからURLを開き認証を実施します。コードが表示されるのでコピーし、入力します。認証がうまく通らない場合はAPIコンソールで登録したアプリケーションの種類などを見直してください。"デスクトップアプリケーション"になっていることが前提です。
11

3) DockerからGoogle Driveをマウント

通常のUbuntuでGoogle Driveをマウントできるようになったので、次にDockerからGoogle Driveをマウントさせてみます。下記のDockerfileでDockerを生成します。
Dockerfile
FROM ubuntu:latest

RUN apt-get update
RUN apt-get install python3 python3-pip -y


ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN apt-get -y install software-properties-common
RUN add-apt-repository ppa:alessandro-strada/ppa
RUN apt update
RUN apt -y install google-drive-ocamlfuse
RUN mkdir /googledrive
ここでのポイントはDockerfileないでTime Zone設定を実施しておくこと、これをやってないとこの問題にはまります。マウントポイントのディレクトリは/googledriveとしていますが、ここは自由に変更できます。

次にDockerを起動させます。
sudo docker run  -it --rm --privileged -v $(pwd)/vol:/root/.gdfuse google-drive /bin/bash
google-drive-ocamlfuseはホームディレクトリの.gdfuseにクレデンシャル情報を書き出します。このディレクトリがDocker停止のたびに消えてしまうと毎回ブラウザの認証が必要になってしまい不便ですので、ホスト側のディレクトリをマウントしておき消えないようにしておきます。

またdocker runに"--privileged"を入れておく必要があります。これがないと"fuse: device not found, try 'modprobe fuse' first"のエラーが出てしまいます。

これでUbuntu上からGoogle Driveがマウントできアクセスできるようになっているはずです。
12

13



Docker Build中に Configuring tzdataでハング


Docker build中に下記の状態でハングした場合の対策メモ
この状態におちいると、数字を入力しても先に進まなくなってしまう。


Configuring tzdata ------------------ Please select the geographic area in which you live. Subsequent configuration questions will narrow this down by presenting a list of cities, representing the time zones in which they are located. 1. Africa 4. Australia 7. Atlantic 10. Pacific 13. Etc 2. America 5. Arctic 8. Europe 11. SystemV 3. Antarctica 6. Asia 9. Indian 12. US Geographic area:
対策は、このTime Zone設定状態に入らないようにDockerfileで先にtime zone設定をしてしまう。
問題となる箇所の手前に下記のTime Zone設定を入れておくことでTime Zone設定を聞かれなくなる。
ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

例えばこんな感じです。

Dockerfile
FROM ubuntu:latest

ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN apt-get -y install software-properties-common
RUN add-apt-repository ppa:alessandro-strada/ppa
RUN apt update
RUN apt -y install google-drive-ocamlfuse
RUN mkdir /mnt/googledrive

↑このページのトップヘ