6/18に北海道のオープンソースカンファレンスでDjangoの紹介をしてきました。 www.ospn.jp 説明が急ぎ足になったり、デモが中途半端に終わってしまって申し訳ない感じですが、聞きに来てくださった方はありがとうございました。
いくつか面白いセミナーもあったし、ビールとジンギスカン良かったので、また来年も参加できればいいなーと思います。
スライドとサンプルコード
www.slideshare.net github.com
6/18に北海道のオープンソースカンファレンスでDjangoの紹介をしてきました。 www.ospn.jp 説明が急ぎ足になったり、デモが中途半端に終わってしまって申し訳ない感じですが、聞きに来てくださった方はありがとうございました。
いくつか面白いセミナーもあったし、ビールとジンギスカン良かったので、また来年も参加できればいいなーと思います。
www.slideshare.net github.com
プライベートで使ってるVPSの環境をdocker-composeで動かしたのだけど、忘れてもいいようにメモを残す。
ホストOSは、Ubuntu16.04。
dockerは手順通りaptでインストールすればよい。
Installation on Ubuntu
docker-composeは、dockerとは別途インストールが必要(1ファイルのコマンドをダウンロードして配置するだけ)
Install Compose
dockerコマンドを実行するユーザーはdockerグループに属している必要があるので、インストール後にusermodで設定しておく(usermodで設定したグループは再ログインで反映される)
DockerHubからpullしてくるか、Dockerfileを作成してビルド(docker build)する。
ビルドの際に、名前の指定をしとかないと、無名になりハッシュ値で指定することになる。
なるべくオフィシャルのイメージを使って、自前ビルドや野良ビルドのイメージは避けたほうがよさそう。メンテが面倒。
野良のイメージを使う場合は、セキュリティに注意する。バックドアが仕込まれたイメージなどもあるらしい。
docker runコマンドで起動されるが、これはコンテナ作成+プロセス実行であって、実行が終わってもコンテナが消えないで残るので注意。
コンテナ一覧はdocker psで見れる。-aオプションを指定すると、実行中以外のコンテナも表示される。
docker ps -a
終了したプロセスの再実行はdocker startでできる。
runの際にポートマッピングやvolumeのマウントなど、全部指定する。コンテナ名をちゃんと指定したほうがよい。
「-d」 (detouch) オプションを指定しないとforegroundで実行される(systemdやsupervisorなどから監視させるならdetouchしなくていい)
docker-composeで管理するなら、docker-compose.ymlにrunのオプションを書いてしまう。
docker stopで停止できる。停止してもコンテナは消えないので、startで再度実行できる。
docker restartでプロセスを再起動できる。runで指定したオプションを変更するならコンテナの再生成が必要かも?
設定ファイルが入ったディレクトリをVOLUMEでマウントさせとけば、restartでプロセスに読み込ませるのも可能か。
docker runで実行するときに --restart オプションでalwaysを指定しておくと、プロセスが死んでもdocker-engineが自動で再起動してくれる。
また、alwaysの場合は、OSを再起動したときも自動で起動される。
Docker run reference -- Restart policies (--restart)
例:
$ docker run -d -v /tmp/ftp/:/srv/soloftpd/ \ -p 21:21 -p 50000-50009:50000-50009 \ --env OPTIONS="--masquerade-address=192.168.0.2" \ --name=soloftpd --restart=always tokibito/soloftpd
docker-composeを使って依存を記述すればいい。
docker-compose.ymlにdocker runのオプションなどを書いといて、複数のイメージをまとめてビルド、コンテナを作って実行するところまでやってくれるラッパーツール。
docker-compose up
でイメージをビルドしてコンテナを生成して起動までやってくれる。 -dオプションを指定すればバックグラウンドで実行できる。
docker-compose down
でコンテナを停止して破棄してくれる。
前回の計算以降、プランの見直しや通信回線の解約、契約を行ったので、メモを残す。
前回から5000円近く下がった。乗り換えに伴い、解約手数料や端末購入代金が発生したので、ペイするのは半年後ぐらいから。
ガラケーを辞めればもう少し下げれるけど、頑丈な通話用の端末をどうするかに悩む。
自宅のインターネット回線は、マンション一括契約のもので1,500円/月ぐらいなので、計算には入れてない。
Djangoフレームワークでは、APIが変更、廃止される場合には、次のバージョンですぐに変わってしまうのではなく、警告を上げた上で2つ先のバージョンで削除されることになっています。
Deprecation policy
Pythonの組み込み例外であるDeprecationWarningを継承したクラスがDjangoでは定義されており、必要に応じてこれを確認できます。
Pythonの実行オプションとして -Wd のように指定するとDeprecationWarningを表示できるので、これを「manage.py test」や「manage.py check」の実行時に指定すればよいです。
試したバージョンはPython3.5, Django1.9.5です。
$ python -Wd manage.py test
実行結果:
$ python -Wd manage.py test Creating test database for alias 'default'... /home/tokibito/sandbox/django_dep/myproject/myapp/urls.py:5: RemovedInDjango110Warning: Support for string view arguments to url() is deprecated and will be removed in Django 1.10 (got index). Pass the callable instead. url('^$', 'index'), /home/tokibito/sandbox/django_dep/myproject/myapp/urls.py:5: RemovedInDjango110Warning: django.conf.urls.patterns() is deprecated and will be removed in Django 1.10. Update your urlpatterns to be a list of django.conf.urls.url() instances instead. url('^$', 'index'), /home/tokibito/sandbox/django_dep/myproject/myproject/urls.py:20: RemovedInDjango20Warning: Passing a 3-tuple to django.conf.urls.include() is deprecated. Pass a 2-tuple containing the list of patterns and app_name, and provide the namespace argument to include() instead. url(r'^admin/', include(admin.site.urls)), . ---------------------------------------------------------------------- Ran 1 test in 0.021s OK
RemovedInDjango110WarningとRemovedInDjango20Warningの両方が表示されますが、20が不要な場合は、-Wオプションに指定する文字列を変更すれば除外できます。
$ python -W::DeprecationWarning manage.py test
これはRemovedInDjango20WarningがPendingDeprecationWarningを継承しているからです。
Pythonの実行オプションについては、ドキュメントを参照してください。
110を表示せずに20のみを表示したい場合は、PendingDeprecationWarningを指定するとできます。
$ python -W::PendingDeprecationWarning manage.py test
今、使っているバージョンでのDeprecationWarningを解消してからアップグレードすると、コードを大きく変更しなくても1つ次のバージョンでなら動作します。
先にDjangoのバージョンを上げてしまうと、アプリケーションは「修正しないと動かない」です。
アプリケーションが「動いてる状態」で警告を解消するほうが、手間は少ないです。
そのため、DeprecationWarningを修正しつつ、1つずつバージョンを上げていくのが結果的には楽なのかもしれないなと思いました。
もちろんテストコードは必須です。
PythonでOracle Databaseに接続するには、cx_Oracleを使う。
マルチスレッド環境下でcx_Oracleを使う場合にハマったのでメモを残す。
Oracleのクライアントライブラリは、マルチスレッドで使う際には、OCI_THREADEDというモードで使わないといけないらしい。
cx_OracleをOCI_THREADEDモードで使うには、connect関数のthreadedオプションにTrueを指定する。
>>> import cx_Oracle >>> connection = cx_Oracle.connect( ... "testuser", ... "testpassword", ... "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=oracledb.example.com) (PORT=1521))(CONNECT_DATA=(SID=ORCL)))", ... threaded=True)
cx_Oracleのドキュメントにも説明があった。
The threaded argument is expected to be a boolean expression which indicates whether or not Oracle should use the mode OCI_THREADED to wrap accesses to connections with a mutex.
Module Interface — cx_Oracle 5.2.1 documentation
Doing so in single threaded applications imposes a performance penalty of about 10-15% which is why the default is False.
DjangoでOracleを使っていて、マルチスレッドで動作させる場合だと、settingsのデータベース設定に指定すればよい。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.oracle', 'NAME': 'oracledb.example.com:1521/orcl', 'USER': 'testuser', 'PASSWORD': 'testpassword', 'OPTIONS': { 'threaded': True, } } }
この指定をしない状態で、gunicornのThreadWorkerで動かしていた際に、低頻度でワーカープロセスがログを出力せずに死ぬ、という現象が発生していた。
シングルスレッドの場合は、threaded=Falseのほうがパフォーマンスが良いそうなので、使いどころに気をつけたい。