CentOS7にJupyter NotebookをインストールしてローカルPCから接続

はじめに

最近データ加工などのためにローカルPCでJupyter Notebookを使っています。

でも、時間のかかる処理が必要なこともあるため、そういうときはサーバ側で実行したいです。

そこで、CentOS7にJupyter Notebookをインストールして、ローカルPCから接続するまでの方法を調べてまとめました。

環境

さくらのvpsに新規でCentOS7を立ち上げた状態からJupyter Notebookをインストールして、ローカルPCから接続する想定です。

セキュリティの設定

まずはOS再インストール後すぐに、さくらVPSのCentOS7のセキュリティ設定を見て対応していきました。

(参考サイト:チュートリアル:CentOS 7(さくらのVPS)サーバ作成直後に設定しておくべき初期セキュリティ設定 – さくらのVPSニュース

上記サイトが分かりやすかったのでそのまま設定をします。

  • 一般ユーザの作成
  • 公開鍵認証の設定
  • sudo 設定
  • SSH 接続時、root でのログインを禁止
  • SSH 接続時、パスワード認証を禁止

ここで作成した秘密鍵パスフレーズは後のサーバ接続のために利用します。

公開鍵認証でのローカルからのSSH接続のコマンドをよく忘れるのでメモします。 上記設定の後だと一般ユーザで公開鍵認証でしかログインできなくなります。

ssh -i ~/.ssh/id_rsa ユーザ名@IPアドレス

Jupyter Notebookのインストール

色々インストール方法はありますが、本記事ではpyenvをインストールしてからAnacondaをインストールします。 Anacondaを入れるとpython本体に加えてデータ分析等のよく使われるライブラリも同時にインストールできます。 その中にjupyter notebookも含まれます。

自分が過去に書いたPythonインストール記事を参考にします。
以下を実行してインストールからjupyter notebook起動までを行います。

(参考サイト:CentOSにPython環境を作ってみたまとめ - 薮蛇なエンジニアの開発備忘録

yum update -y
yum install -y gcc gcc-c++ make git openssl-devel bzip2-devel zlib-devel readline-devel sqlite-devel bzip2 sqlite git
cd /usr/local/src/
git clone https://github.com/yyuu/pyenv.git
echo 'export PYENV_ROOT="/usr/local/src/pyenv"' >> /etc/profile.d/pyenv.sh
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> /etc/profile.d/pyenv.sh
echo 'eval "$(pyenv init -)"' >> /etc/profile.d/pyenv.sh
exec $SHELL -l
pyenv --version

pyenv install --list
pyenv install anaconda3-4.3.1
pyenv global anaconda3-4.3.1
pyenv rehash
python --version
cd ~
mkdir workspace
cd workspace
jupyter notebook

これでjupyter notebookを起動できます!
(でも、まだローカルPCからはアクセスできません)

notebook起動後、以下のようなメッセージが出力されるので token=以下の文字列をあとで利用します。

[NotebookApp] 
    
    Copy/paste this URL into your browser when you connect for the first time,
    to login with a token:
        http://localhost:8888/?token=xxxxxxxxx(毎回異なるトークンが入る)

注意
自分が過去にpyenvを使ったので今回も利用しましたが、 改めてPython環境周りを調べると構成を再検討した方が良さそうでした。
でも、今回は取り急ぎjupyter notebookをインストールする一例としてこのまま進めます。

SSHポートフォワーディングについて

サーバにインストールしたnotebookにアクセスする方法を調べたところ次の2つが見つかりました。 個人的な利用を想定しているため(2)を採用しました。

(1) notebookを公開してパスワードをつける
(2) SSHポートフォワーディングでサーバに接続する

ポートフォワーディングについては次のように理解しています。

SSHコマンドに-L オプションをつけるとポートフォワーディングできる

 例:ssh -L 7777:localhost:8888 ユーザ名@IPアドレス

■ローカル指定ポートにアクセスで、サーバ上から指定場所にアクセスできる

 例:上記のコマンドのあとローカルPCでlocalhost:7777にアクセスするとサーバ側から繋いだlocalhst:8888にアクセスできる(つまり、jupyternotebookがサーバ内部でしか見れなかったとしてもポートフォワーディングすればローカルPCから閲覧可能)

(ポートフォワーディングの参考サイト:サーバー上の Jupyter Notebook を SSH Port Forwarding を通して使う | kuune.org

ローカルPCからの接続

ssh -L 7777:localhost:8888 ユーザ名@IPアドレス -i ~/.ssh/id_rsa

jupyterを起動したのとは別のターミナルを立ち上げて、
公開鍵認証でポートフォワーディングする上記のコマンドを実行します。

その後ブラウザでlocalhost:7777に接続すると、次のような画面が出てきます。

f:id:h2shiki:20170817225406p:plain

「Passsword or token:」の部分に、jupyter起動時のtoken=以下の文字列をコピペして「Log in」ボタンを押します。

これでローカルPCからサーバのjupyter notebookにアクセスできます!

使いやすくする工夫

■jupyter notebookがターミナルを閉じると止まる

これまでの方法だと、jupyter notebookを起動したターミナルを閉じるとjupyterも停止してしまいます。

ターミナルを閉じた後も停止させないようにするためにはnohupをつけると良いようです。

(参考サイト1:Jupyter Notebook を永続的に起動させる方法 - 約束の地

(参考サイト2:プロセス管理: nohup, disown, kill - Heavy Watal

nohup jupyter notebook >~/jupyter_out.txt 2>~/jupyter_err.txt &

上記のコマンドを打つとターミナルを閉じた後も、ポートフォワーディングさえできていればローカルPCからjupyterに接続できました。

バックグラウンド実行中でtokenを確認したくなったときはjupyter notebook listで見れます。

SSH接続がタイムアウトする

ターミナルをしばらく操作しないでいるとタイムアウトされるため、頻繁に接続しなおすことになり面倒です。

なるべくタイムアウトを引き伸ばす方法を調べました。

(参考サイト:ターミナルのSSH接続が切れすぎるので設定いじった話 - helen's blog

以下のようにsshd_configを修正して再起動しました。

sudo vim /etc/ssh/sshd_config
sudo systemctl restart sshd

変更前

# ClientAliveInterval
# ClientAliveCountMax

変更後

ClientAliveInterval 60
ClientAliveCountMax 12

これでだいぶ切断頻度が下がりました!

まとめ

CentOS7のサーバにJupyter Notebookをインストールし、ローカルPCから接続する方法をまとめました。

これで時間のかかる処理を実行したときにファンの音などPCを気にせずにすみそうです。また、iPadSafariからでもサーバで起動したnotebookを表示できたので、くつろぎながら進捗確認をしたり色々捗りそうです。

PythonでPostgreSQLに接続してみた

概要

前回の記事ではPostgreSQLのインストールを行いました。今回はPythonからPostgreSQLへの接続を行う方法をまとめます。

(前回のPostgreSQLのインストール記事:PostgreSQLをyumでインストール(yumとrpmの復習込み) - 薮蛇なエンジニアの開発備忘録

PythonからDB接続するためにはドライバというモジュールをインストールする必要があるようです。

psycopg2というドライバが2016/1時点で一番DLされているようなので、そちらを利用しました。

(参考サイト:PythonからPostgreSQLに接続する方法 | アシスト

psycopg2のインストール

シンプルにpipでインストールしたところエラーが出てしまいました。

pip install psycopg2

エラー内容から一部抜粋

 Error: pg_config executable not found.
    
    Please add the directory containing pg_config to the PATH
    or specify the full executable path with the option:
    
        python setup.py build_ext --pg-config /path/to/pg_config build ...
    
    or with the pg_config option in 'setup.cfg'.

エラーをgoogleで検索したところ既に解決している方がいたので、その方法を使わせて頂きました。

(参考サイト:Python / PostgreSQL on Heroku でpsycopg2がない & pg_configがないと怒られる時 - 木木木

pg_configへのPATHを追加してください的な内容のエラーなので、pg_configの場所を調べてPATHに追加してやれば良いようです。

以下は解決方法の引用です。

locate pg_config

これで私の場合は/usr/pgsql-9.4/bin/pg_configが出てきたので次のようにしました。

2016.05.20追記:別の環境で構築したところ、locateコマンドを叩いても何も表示されませんでした。updatedbというコマンドを叩くとlocate用ファイルが更新されてパスが表示されるようになりました。

export PATH="/usr/pgsql-9.4/bin:$PATH"

再度インストール

pip install psycopg2
python
>>>  import psycopg2
>>>
>>> exit()

無事インストールできて、実際にimportして確認してもエラーは出ませんでした。

2016.05.20追記:何故かbottle環境からpsycopg2を利用しようとするとインポートエラーになりました。yum -y install psycopg2を実行したところ直りました。yumとpipの関係が分かっていないので今後調べます。

今回の私の原因とは違うので余談ですが、postgresql-develをインストールしていない場合でも Error: pg_config executable not found. のエラーが起きるようです。

(参考サイト:(Djangoメモ)データベースにPostgreSQLを設定 - Qiita

pythonからPostgreSQLに接続

DBユーザの作成、DBの作成は済ませているものとします。

以下のサイトを参考にしてまずはDB接続を行いました。

(参考サイト:PythonからPostgreSQLに接続する方法 | アシスト

【】で括った部分は既に作成済みのDB情報に合わせるものとします。

python
>>> import psycopg2
>>> connection = psycopg2.connect("host=【IPアドレス】 port=5432 dbname=【DB名】 user=【ユーザ名】 password=【パスワード】")

これで繋がると思ったらエラーが出てしまいました。

エラー内容から一部抜粋

psycopg2.OperationalError: could not connect to server: Connection refused

接続が拒否されているようなので、外部から接続できるように設定します。以下のサイトを参考に試みました。

(参考サイト1:http://rina.jpn.ph/~rance/linux/postgresql/connect.html

(参考サイト2:PostgreSQLのポート番号を変更する - (=゜ω゜)ノぃょぅ にっき

(参考サイト3:PostgreSQLエラー「FATAL: no pg_hba.conf entry for host "127.0.0.1", user "postgres", database "データベース名", SSL off」の原因と解決方法 - r_nobuホームページ

まずは受け入れポート等の設定変更

locate postgresql.conf
vim /var/lib/pgsql/9.4/data/postgresql.conf

postgresql.confの中身からlisten_addressとportのコメントを外して書き換え

listen_addresses = 'localhost, 【IPアドレス】'
port = 5432 

接続できるクライアントの指定

locate pg_hba.conf
vim /var/lib/pgsql/9.4/data/pg_hba.conf

pg_hba.confに以下内容を追加

host all all 【IPアドレス】/32 trust
service postgresql-9.4 restart

設定を変更してpostgresqlを再起動した後、再びpsycopg2.connect(引数は省略)を実行したところ、正常に接続することができました。

注意:pg_hba.confで接続できるクライアントのIPアドレスに、自身のIPアドレスを指定して追加しただけなのでセキュリティ的に大丈夫と思いますが、この設定内容を利用する方がいましたら各自で再度問題ないかご確認ください。

INSERTとSELECTの実行

データベースに接続できたので、INSERTとSELECTを実行してみます。

(参考サイト:psycopg2によるPython2.7からのAmazon Redshiftアクセスサンプル | Developers.IO

python
>>> import psycopg2
>>> conn = psycopg2.connect(
...   host="【IPアドレス】",
...   database="【DB名】",
...   port="5432",
...   user="【ユーザ名】",
...   password="【パスワード】"
... )
>>> cursor = conn.cursor()
>>> cursor.execute("INSERT INTO table_name (column1) VALUES ('hoge')")
>>> cursor.execute("INSERT INTO table_name (column1) VALUES ('fuga')")
>>> cursor.execute("SELECT * FROM table_name")
>>> results = cursor.fetchall()
>>> for row in results:
...   print(row[0])
...
hoge
fuga
>>> conn.commit()
>>> cursor.close()
>>> conn.close()

【】で括った項目とtable名とカラム名は事前に作成しておいた名前を入力するものとします。

insertしたhogeとfugaをselectの結果として表示することができました。

ここでは全件取得でcursor.fetchall()を用いましたが、1レコードだけ取り出すときはcursor.fetchone()を利用するようです。

プレースホルダの利用

以下のサイトを見ながらプレースホルダを使用してみました。

(参考サイト:PostgreSQLをPythonからpsycopg2を使っていじる — そこはかとなく書くよん。

一つ前に書いたコード中のINSERT文を次のように置き換えできました。

cursor.execute("INSERT INTO table_name (column1) VALUES (%s)", ["hoge"])

値の渡し方に癖があるらしく、("hoge")にすると受け付けないらしいです。

あとINT型でも%sを使うようです。

明示的なCOMMIT/ROLLBACKの必要性

以下のサイトによりますと、参照の処理だけでもトランザクション開始されるようなので、明示的にCOMMIT/ROLLBACKする必要性があるとのことです。

(参考サイト:PythonからPostgreSQLに接続する方法 | アシスト

自動COMMITさせるためには次のように属性を変更すると可能なようです。

>>> connection.autocommit = True

まとめ

PythonPostgreSQLに接続する方法について調べて、基本的なDB操作ができるようになりました。

PostgreSQLのインストールさえできていればPythonから簡単に呼び出せるかと思っていましたが、意外と設定に苦戦してしまいました。

もっとスマートな環境構築方法やPostgreSQLの設定等についてはおいおい詳細を勉強していきたいです。

PostgreSQLをyumでインストール(yumとrpmの復習込み)

概要

PostgreSQLCentOSにインストールしようと思って調べたところ、yumを使った方法が何種類か見つかりました。 どれも根本は同じ事をしているように見えますが、コマンドが微妙に違っています。 yumrpmについて自分の理解度が低かったせいで混乱しかけたので、改めてyumrpmの関係を復習しつつPostgreSQLのインストールを実践してみようと思います。

続きを読む

Python用フレームワークbottleを使ってみた

概要

ちょっとしたプログラムをPythonで作ってWebに公開したかったので、bottleという軽量フレームワークについて基本的な使い方を調べました。

続きを読む

ApacheでPythonを動かしてみた(bottle利用)

概要

前の記事ではPythonプログラムをサーバに公開するためにApacheを利用しました。

(前の記事→ApacheでPythonを動かしてみた(mod_wsgiをソースからインストール) - 薮蛇なエンジニアの開発備忘録

しかし少し調べてみると、Pythonは自前でWEBサーバ機能を持っているらしくミドルウェア無しでもサーバとして公開できるようでした。またbottleというシンプルなフレームワークを使えばURLルーティングなども分かりやすくできるようです。…そんな簡単にできたなんて!

とはいえサーバ用ミドルウェアを使っておいた方が安定すると思うので、Apacheでbottleフレームワークを利用する方法について調べてみました。

これで、自分がやりたかった「Pythonでプログラム書いてサーバに公開する」ためのインフラがほぼできたと思います。

続きを読む

ApacheでPythonを動かしてみた(mod_wsgiをソースからインストール)

概要

Pythonを使って何かしたかったので、まずはサーバアプリとして公開する方法を調べてみました。 色々実現方法はあると思いますが、自分がイメージしやすいWebサーバのモジュールとして起動することにしました。

続きを読む

CentOSにPython環境を作ってみたまとめ

概要

PythonをCentOS6.7にインストールしようと思ったところ、仮想環境やらパッケージ管理やらについての情報が散らばっていてどうすればいいか最初まったく分かりませんでした。 単純にPythonをインストールしようと思っただけなのに、virtualenvで仮想環境を作るといいとか、pyenvだとかpipやらsetuptoolsなど、関係がよく分からない用語が多すぎです。 自分なりに調べてみて、pyenvとvirtualenvを使ったPythonの基本的な環境を構築できたので情報をまとめてみます。

続きを読む