nikkie-ftnextの日記

イベントレポートや読書メモを発信

Django Girls Tutorial修了者が投票アプリチュートリアルでDjangoの理解を深めました(その1, 2編)

はじめに

いつも心は虹色に! nikkieです。
先日の #pyhack で、Django公式ドキュメントのチュートリアル(投票アプリ)に取り組みました。
手を動かしてみて気づいたことをアウトプットしていきます。
今回はその1(最初のビュー)とその2(モデルの作成)です。

チュートリアルの概要

はじめての Django アプリ作成、その 1 | Django documentation | Django から始まる7回構成のチュートリアルです。
作るアプリの名前をとって「投票アプリチュートリアル」と呼ぶことにします。
なお、私のDjangoレベルは「Django Girls Tutorial修了」です。
Django Girls Tutorialを終えてから投票アプリチュートリアルに取り組んだことで、Djangoへの理解が深まったと感じています。

それでは早速アウトプットしていきましょう。
最後までお付き合いいただけますと幸いです。(長めなので拾い読みも推奨します)

その1:プロジェクトとアプリケーション作成

はじめての Django アプリ作成、その 1 | Django documentation | Django

動作環境

以下の環境でチュートリアルを進めました。

(env) $ python -m django --version
2.1.1
(env) $

仮想環境のディレクトリenv/と同じ階層でdjango-admin startproject mysiteを実行したところ、env/と同じ階層に「外側のmysiteディレクトリ」ができました。

  • ├ env/
  • └ mysite/
    • ├ manage.py
    • └ mysite/
      • ├ __init__.py
      • ├ settings.py
      • ├ urls.py
      • wsgi.py

django-admin startproject mysiteは、現在のディレクトリ内にmysiteディレクトリを作り、その中にmanage.pyとmysiteディレクトリを作るようです。
Django Girls Tutorialではdjango-admin startproject mysite .1と現在のディレクトリを指定しているため、フォルダ構成が異なります(外側のmysiteディレクトリがありません)。

プロジェクトとアプリケーション

mysiteプロジェクトの中にpollsアプリケーションを作成して進めていきます。

違いについて、チュートリアルより引用。

  • 「プロジェクトとは、あるウェブサイト向けに設定とアプリケーションを集めたもの」
  • 「アプリケーションとは、実際に何らかの処理を行う Web アプリケーション」

mysite/urls.pyとpolls/urls.py

以下の例から、mysite/urls.pyは確かに「目次」だと納得しました。

URLをpolls/からfun_polls/にしたければmysite/urls.pyを変える。

urlpatterns = [
    path('fun_polls/', include('polls.urls')), # 変更
    path('admin/', admin.site.urls),
]

f:id:nikkie-ftnext:20180929171501p:plain:w400
path('content/polls/', include('polls.urls')),に変えると。。 f:id:nikkie-ftnext:20180929171502p:plain:w400

その1についての疑問点

  • mysite/settings.pyのINSTALLED_APPSのリストにpollsを書き加えていないが、Djangoの動作に支障はないのか?
    • Django Girls Tutorialではblogアプリ作成後に書き加えている2
    • 最初のビューは問題なく表示できている
    • その2に進んだら解決した
  • アプリケーションを複数のプロジェクトで使う例が知りたい

その2:モデル(QuestionとChoice)

はじめての Django アプリ作成、その2 | Django documentation | Django

データベースはデフォルトのsqliteを使っていきます。
mysite/settings.pyのTIME_ZONE にはDjango Girls TutorialにならってAsia/Tokyoを指定。3

モデル作成

  • モデルのフィールドの最初の引数は「人間可読な名前を与え」るために用いる
    • 例:pub_date = models.DateTimeField('date published')
  • mysite/settings.pyのINSTALLED_APPSに追加してアプリケーションをプロジェクトに含める(=マイグレーション対象にする
    • 指定の仕方:polls.apps.PollsConfig4
    • polls/(アプリケーション)の下のapps.pyの中のPollsConfigクラスを指定している
class PollsConfig(AppConfig):
    name = 'polls'
  • モデル変更実施の3ステップ
    1. models.py変更
    2. マイグレーション作成(makemigrations)
    3. データベースに変更適用(migrate)
  • 覚えておきたいmanage.py関連コマンド
    • python manage.py sqlmigrate polls 0001: migrateで適用されるSQLの確認
    • python manage.py check:プロジェクトに問題がないかの確認

データベースAPI

インタラクティブシェルで遊んでORMに慣れる。

  • 存在しないidを指定したとき、getはError(DoesNotExist)を上げるが、filterでは[](空のリスト)が返る
  • get(id=1)の代わりにget(pk=1)がよく使われる
  • ForeignKeyはChoiceに設定しただけ(polls/models.py)だが、Question側からも結びつくChoiceを確認できる(choice_set)

管理画面

polls/admin.pyにadmin.site.register(Question)を追加したところ、管理画面からPollsが操作できるようになった。
f:id:nikkie-ftnext:20180929171629p:plain

その2についての疑問点

  • 内省機能とは?(原文確認する)
    • 「このフィールド名(引用者注:モデルのフィールドの最初の引数のこと)は Django の二つの内省機能で使う他、ドキュメントとしての役割も果たします。」
  • DjangoRailsとは思想が違うという点をもっと詳しく知りたい。
  • インタラクティブシェルで遊ぶ中で日時がUTCのところがあった
    • 管理画面で見たDate publishedは日本時間で一致した(レコード作成時はJSTに合わせなくてもいいということ?)
>>> q.pub_date
datetime.datetime(2018, 9, 29, 4, 44, 5, 602909, tzinfo=<UTC>)

今回はここまでです。
次回、その3(ビュー)からのアウトプットでお会いしましょう。
最後までお読みいただきありがとうございました。


  1. プロジェクトを作成しよう! · Django Girls Tutorial より。「コマンドの最後にピリオド . を入力したことを確認してくださいね。」

  2. Djangoモデル · Django Girls Tutorial より。「アプリケーションを作ったら、Djangoにそれを使うように伝えないといけません。 」

  3. プロジェクトを作成しよう! · Django Girls Tutorial

  4. Django Girls Tutorialではblogアプリケーションをblogとして指定しています(Djangoモデル · Django Girls Tutorial )。ここはblog.apps.BlogConfigとも指定できると理解しました。

  5. 例: rails generate model User name:string email:stringRuby on Rails チュートリアル:実例を使って Rails を学ぼう より)

イベントレポート | 第92回 #pyhack にてDjango投票アプリチュートリアルを進めました

はじめに

いつも心は虹色に! nikkieです。
定期的に参加している #pyhack で、Django公式ドキュメントのチュートリアル(投票アプリ)に取り組んできました。

勉強会の概要

(第92回)Python mini Hack-a-thon - connpass

スプリントのゆるい版みたいな感じで各自自分でやりたいことを持ってきて、勝手に開発を進めています。参加費は無料です。 初めての方も常連さんもぜひご参加ください。

pyhackのイメージは「猛者の集まるもくもく会」です。
Pythonの経験豊富な方ばかりで、聞こえてくる会話に耳を傾けていると学びがあります。

取り組んだこと

朝の時点での目標は「Django公式ドキュメントのチュートリアル(その1〜その7)を通してやる」でした。
はじめての Django アプリ作成、その 1 | Django documentation | Django から始まる7回構成のチュートリアルです。
1日でその1〜その4まで進めることができました。
なお、私のDjangoレベルは「Django Girls Tutorial修了」です。

作った投票アプリはこんな感じです。

  • 質問(Question)の一覧画面
    f:id:nikkie-ftnext:20180929170927p:plain:w400
  • 質問には選択肢(Choice)が結びついています。質問詳細画面で確認し、選択肢に投票できます f:id:nikkie-ftnext:20180929170938p:plain:w400
  • 投票結果の表示画面
    f:id:nikkie-ftnext:20180929170948p:plain:w400

感想

Djangoがはじめての人には、投票アプリチュートリアルよりもDjango Girls Tutorialがオススメ」という意見をよく目にするのですが、そのとおりだと感じました。

逆の見方をすると、Django Girls Tutorialを終えた後に取り組むと、深いところが説明されているために「こういうことだったのか!」という気づきが多々ある内容だと思います。
Django Girls Tutorialは初めてプログラミングをする方が対象者なので突っ込んだ説明ができないのでしょう。 投票アプリチュートリアルはプログラミング経験者向けに説明がされています。(例えば、mysite/urls.pyとpolls/urls.pyの違い、ビューはHttpResponseか例外を返す、など)

投票アプリチュートリアルでは、リスト内包表記(その3の質問一覧ビュー)や、try ... except ... else ... (その4の投票機能ビュー)といった文法を説明なく使っています。
このあたりはわかっている(または自力で調べられる)方が対象なのでしょう。
Django Girls Tutorialからスムーズに接続するには一工夫必要そうです。

チュートリアルのポイント

気づきを記事に盛り込んでいたら長くなってきたので、気づきは別の記事としてアウトプットします。

  • その1:プロジェクトとアプリケーション作成
    • プロジェクトとアプリケーションの違い、mysite/urls.py と polls/urls.py の違いについて理解が深まった
  • その2:QuestionとChoice、2つのモデルを作成(インタラクティブシェルでORMをみっちり練習)
  • その3:ビューとテンプレート
    • ビューはHttpResponseなるものが肝。これはDjango Girls Tutorialでは意識してこなかった。
  • その4:汎用ビューに書き直し
    • その3までに作成したビューのコードをほとんど書き直した。polls/views.pyのメソッド定義がなくなり、コードが削減されたのは衝撃。「Djangoにこんなの用意されていたのか!」

今回手を動かして、Django Girls Tutorialの知識が補完されたと感じています。
10/6にワークショップのコーチで活かしてみます。

他の方の取り組みから

感想

毎回言っている気がしますが、非常に楽しい時間でした。
今回懇親会は泣く泣く諦めたので、次回リベンジ狙います。
何人かの方には来週のPyLadiesのパーティー(LT会)でお会いできそうで楽しみです^ ^
1日ありがとうございました!

登壇報告 | #stapy にて機械学習モデルをDockerでデプロイする方法について話しました

はじめに

いつも心は虹色に! nikkieです。
9月の「みんなのPython勉強会」(参加者100人規模)に登壇しました。
機械学習モデルをDockerでデプロイする方法について10分で話しました。
このエントリで登壇報告をします。

勉強会の概要

みんなのPython勉強会#38 - connpass

「Stapy秋祭り第1弾:秋の夜長のショートトーク会」
9/15~18にPyCon JP 2018が開催されます。年に一度のPythonのお祭りに合わせて、Stapyでも秋祭りを開催します!第1弾として、「秋の夜長のショートトーク会」と題し、Python好きなGeekのみなさんに、自分の好きなテーマについて自由に語ってもらうショートトークをしていただきます。LTよりは長いけど、通常の講演(GT: General Talk)より短いトークを7件、ご用意しました。秋の夜長の季節です。Pythonの楽しい話で盛り上がりましょう。

2月くらいから「LT駆動学習」に勤しんでいたところ、大変ありがたいことに、今回登壇の機会をいただきました。

登壇:Entrance of Docker for Pythonista 〜Dockerではじめる機械学習モデルのデプロイ〜

「好きなテーマで」と言っていただけたので、「大好きなDockerを他の方にも知ってもらおう」というモチベーションで登壇しました。
聞いた方にDockerを使ってみていただきたかったので、機械学習モデルをDockerでデプロイする流れを紹介しました。

伝えたかったこと

開発環境と本番環境の双方でDockerを用いることで、動作するアプリケーションを本番環境へ持ち運べるようになります。

Dockerを使って機械学習モデルをAPIとしてデプロイする流れは、次の通りです。

  1. モデルを用意する
  2. FlaskでAPI
  3. アプリケーションをコンテナ化(Dockerfileを書いてビルド)
  4. VM(またはPaaS)にデプロイ

あやめの分類器をGCPの仮装マシンにデプロイし、この手順(仮説)を得ました。
今後他のモデルでも検証し、必要に応じてアップデートします。

テーマに至った経緯

当初は環境構築の話をしようとしていたのですが、参加者の方が聞きたいトークにするため、機械学習を絡めました。
詳しくはこちらにあります:イベントレポート | Pythonもくもく自習室 #13 あやめの分類器をAPIに組み込み、Dockerイメージ作成 #rettypy - nikkie-ftnextの日記

テーマを決める上で、こんな図を作って整理しました。
f:id:nikkie-ftnext:20180921072300j:plain

質疑より

1週間ほど前の出来事を記憶ベースで書いているので、認識違いにはご容赦ください。

Dockerのメリットの体験談

私がDockerのメリットを体験したのは、環境構築のしやすさです。
協調フィルタリングをPySparkで行う際、Dockerを使ったところ、PySparkの環境構築が手短に済みました。1
他にもデータ分析環境構築に役立つノートブックが公開されています:https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html:html

会場では話していませんが、デプロイのしやすさもあります。
VPSにDockerをインストールして、docker-compose up -dでデプロイしたところ、手動デプロイに要していた時間が劇的に短縮されました。2

Dockerの普及について

主催の @akucchan_world さんから。
アカデミックな領域ではDockerの普及が進んでいないという情報共有がありました。

私の知っている以下の情報を共有しました。

  1. DockerはGUIで使えるようにアップデート予定
  2. Kubernetesは意識しなくてよくなる方向へ向かっている(Knative)

1点目は以下の情報をベースにしています。
[速報]次期Docker for Win/Mac、GUIの数クリックで簡単にアプリケーションのコンテナ化と実行が可能に。DockerCon 2018 - Publickey
3ヶ月毎にリリースされるので、10月リリース版からはGUIで使えると期待しています。

2点目ですが、Kubernetesとは本番環境でコンテナを動かす際に使う「オーケストレーションツール」のデファクトスタンダードです。
これがクラウドで抽象化されていき、デプロイする側はKubernetesを意識しなくてよくなると理解しています。

なお、Dockerの普及が進んでいないという点に関しては、時間的な制約もあるそうです。

宿題事項

興味を持った方向けに詳細な説明を用意したいと思っています。

また、Dockerfileやソースコードについては正常系で最低限動作する状態です。
以下のアップデート項目があります。

  • アプリケーション実行ユーザを用意する(現状rootユーザ)
  • POSTしたJSONにwidth, height両方のキーがないと、FlaskのAPIは実行中にエラーを吐き、500を返す点の修正
  • APIの動作確認ができるビューがあるとよかった
  • WebAppsで動かない件のデバッグ3

アウトプットしたことの周りを固めていくことが、PyCon登壇という目標につながるんじゃないかと、今の時点では考えています。

感想

ショートトークは、懇親会のLTと景色が違いました(皆さん着席されていてまさに「講義」という感じでした)。
登壇の機会を与えてくださった、@akucchan_world さんをはじめとするstapyスタッフの皆さまに感謝します。
また、聞いていただいた参加者の方、懇親会でフィードバックをくださった方々、ありがとうございました。

stapy LT王子4代目の称号をいただいたので、引き続きLT駆動で取り組んでいきます。

実は、今回の準備は全部Dockerでやりました。4
ここまでいくとやりすぎ感もありますが、さまざまな環境を立てられるDockerは本当に便利です。
皆さまがDockerで幸せになれることをお祈りしつつ、筆を置かせていただきます。
Happy Docker Life!

脚注


  1. HadoopやMesosなどDockerを使わずに環境構築できたか、あまり自信がありません。

  2. 手順に慣れる目的なのでdocker-composeを使いました。本番環境では、Kubernetesなどのオーケストレーションツールを使うべきである点にご注意ください

  3. ENTRYPOINTやCMDの組合せが問題ではないかとご指摘いただきました。ありがとうございます。ご指摘参考に切り分けてみます。

  4. あやめの分類器作成のjupyter環境、ローカルでのFlaskアプリ作成、本番環境(GCPVM)へのデプロイ、いずれもDockerを使っています。Dockerという金槌を気に入ったことで、なんでも釘に見えている状態かもしれません。持ち歩かないちょっとした環境なら、仮想環境を使ったほうがベターだと思います。(pypro3によると、仮想環境はファイルサイズが小さいそうです)

イベントレポート | #pyconjp 2日目、まさしくひろがるPythonでした

はじめに

いつも心は虹色に! nikkieです。
PyConカンファレンス2日目も盛況のうちに幕を閉じました。
後で手を動かす際に参照できるよう、自分のツイートやスライドリンクをまとめます。

基調講演:「Pythonでやってみた」:広がるプログラミングの愉しみ

niconicoにおけるコンテンツレコメンドの取り組み

Djangoだってカンバンつくれるもん(Django Channels + Vue)

ASGIを知れたのが大きいです。
でんぞうさんの記事や、Django Channelsのチュートリアルでキャッチアップしていきます。

Notebook as Web API: Turn your notebook into Web API

デモはローカルホストでしたが、クラウド上のマシンでjupyterが使えるよう設定してnotebookを置けば、APIとして動作させられるそうです。
オープンソース化が待たれますね。
Jupyter Kernel Extensionは試してみようと思ってます。(発表したDockerでのデプロイと比較したい)

From Data to Web Application: Anime Character Image Recognition with Transfer Learning

非常に楽しませていただきました。

人間の顔を検出するモデルがアニメキャラクターの顔を検出してくれない
→調整したらアニメキャラクターの顔を検出してくれるようになった!
(副作用として人間の顔は検出できなくなっちゃったけどね)爆

データセットdanbooruは触ってみたいですね。

AltJSとしてのPython - フロントエンドをPythonで書こう

LT

興味深かったものをピックアップ。

Webサービスpoke2vec
【poke2vec】word2vecをポケモンのパーティに適用してみた | ぽよのーと

深層学習モデルのサイズが大きく、アプリでのロードに時間がかかるために、heroku無料枠だと辛かったそうです。

終わりに

たくさんインプットさせていただき、間違いなく私のPythonの世界は広がりました。
見聞きしたことに知識が追いついていないので、手を動かして知識を積んでいきます。
ただし、あれもこれもと手を出す前に、判断の強制機構として、優先度を整理するのがよさそうです。

来年はスタッフ参加、そして登壇が目標です。
CFPへの準備期間は始まっていると思うので、コツコツ準備していきます!

スピーカーの方々、スタッフの方々、そして参加者の皆さま、最高に楽しいお祭りをどうもありがとうございました。
お疲れさまでした!

イベントレポート | #pyconjp 1日目、手を動かす時間を確保することが大事とわかりました

はじめに

いつも心は虹色に! nikkieです。
PyConカンファレンス1日目めちゃくちゃ楽しかったです。
後で手を動かす際に参照できるよう、自分のツイートやスライドリンクをまとめます。

基調講演:Argentina in Python: community, dreams, travels and learning

Django Girls Tutorial翻訳という共通点があり、非常に力をいただいた講演でした。 Kaufmannさんの具体例から抽出し、自分のプロジェクトに当てはめるという宿題をもらったと考えています。
(「コーディング、コーディング、コーディングでは、現実のHello Worldには足りないよ」というメッセージが頭に残っています)

招待講演:東大松尾研流 実践的AI人材育成法

ありがたいことに松尾研は学習リソースを公開しています。
Deep Learning基礎講座演習コンテンツ 公開ページ | 東京大学松尾研究室 - Matsuo Lab
今回松尾研の育成方針が聞けて、やはり手を動かすことが肝と再認識しました。

以下のトークは現時点では短いまとめにとどめ、手を動かした後にまとめたいと考えています。

Why you should care about types

PyCon-JP-2018/slides.pdf at master · Sterbic/PyCon-JP-2018 · GitHub

typingという標準モジュールの存在を、恥ずかしながら今回知りました。
26.1. typing — 型ヒントのサポート — Python 3.6.5 ドキュメント
公式ドキュメントを確認した上で手を動かしてみたいと思います。

Building Maintainable Python Web App using Flask

スライドに沿って手を動かしたいのですが、まだ公開されていないようです。
Maintainable=Unit-Testableということで、decouple(切り離す)とよいという主張でした。

  • 外部との連携を切り離す(DB、ファイルシステム
  • Presenter(モデルとビューの間にAdapterを入れる)
  • configはFlask提供のものを使う

Jupyterで広がるPythonの可能性(どりらんさん)

pyconjp2018/slides.ipynb at master · drillan/pyconjp2018 · GitHub

Pythonistaの選球眼(せんきゅうがん)

  • エンジニアの選球眼:選択と決断の繰り返しの中で選択と集中ができること
  • イシューからはじめる=作るものを言語化する→物事を決断するルールとなる
    • 決断ルールの外は決してやらない(SREにある「判断の強制機構」を思い出す)
  • ゴロではなくフライを打つ(ホームランを狙うなら)
    • 宿題:Pythonistaの「フライ」って何だろう? イシューに集中した取り組みということかな?

終わりに

1日目は招待講演で手を動かす話からはじまり、選球眼の話で手を動かす時間を確保する重要性を認識しました。

もくもく会やLTに積極的に参加してきたこともあって、いろいろな方とお会いし、「いつの間にかPython界隈では顔が広くなっていたんだな」と実感しました。
久々の出会い、新しい出会いがあるのはカンファレンスの醍醐味なんでしょうね。
お会いした方々、ありがとうございました。

nikkie流PyConトークの歩き方 #pyconjp

はじめに

いつも心は虹色に! nikkieです。
いよいよカンファレンスですね。
Pythonを通じて新しい知識や人とどんな出会いがあるかワクワクしています。
今回はPyConでトークを聞いて知りたいことを整理するために書き出しました。

アクセス

実は16日に会場に行っている1のですが、京急でのアクセスは、以下の「アクセス方法」がわかりやすかったです。
交通アクセス|大田区産業プラザPiO

PyCon履修決め

カンファレンス - PyCon JP 2018
自分の取り組みに関係が深そうなトークを生で聞くという方針で選択しました。
もくもく会で面識のある方のトークが重なっていたりして、どちらを聞くか非常に悩みました。
公開されたYouTubeは可能な限り消化しようと思っています。(むしろYouTube公開されてからが本番ですね)

基調講演など複数トラック並行でないところは省きました。
現地で関心を引かれて、聞くトークが変わる可能性があります。

17日 13:30-

Why you should care about types: Python Typing in the Facebook Backend
@小展示ホール

  • 普段Pythonで型を意識することはあまりないのですが、型を意識するとどんなメリットがあるか知って、コーティングに取り入れたいです
  • TypeScriptを触ったことがあるので、型の導入は期待してます
  • FBのエンジニアがどんな働き方しているかというのも知られたら嬉しいです(キラキラしている企業に弱い)

17日 14:30-

Building Maintainable Python Web App using Flask @A+B会議室

  • Flaskは独学から業務で利用したのですが、コードの保守性には課題を感じました
  • ユニットテストやDDDの話をされるそうなので、Flaskのコードを書く上で実践できそうなことを知るために聞きます

17日 15:45-

Jupyterで広がるPythonの可能性(どりらんさん)
@コンベンションホール

  • これまでのもくもく会での準備を見て、Jupyterの機能を全然知らなかったと思い知り、トークを聞きたくなりました
  • 先日stapyでトークした機械学習モデルのデプロイにもう少し取り組むので、Jupyterの知識はモデル作成時に活かせそうです
  • スライドをGitPitchからJupyterに切り替えるかも迷っているので情報収集したいです

17日 16:30-

Pythonistaの選球眼(せんきゅうがん) - エンジニアリングと野球の目利きになる技術(shinyorkeさん) @A+B会議室

  • 『イシューからはじめよ』は最近読んだので、エンジニアとどう結びつけるのか気になっています
  • 1年弱の自分の取り組みを振り返る観点を見つけられるんじゃないかと期待しています

18日 11:15-

niconicoにおけるコンテンツレコメンドの取り組み
@コンベンションホール

  • レコメンドはAzure Machine LearningやPySparkで経験のある身なので、大規模なレコメンドの事例として興味があります
  • レコメンドを実装する上で使うパッケージの情報が知られたら嬉しいです

18日 13:30-

Djangoだってカンバンつくれるもん(Django Channels + Vue)
@特別会議室

  • 業務でフロントエンドも必要になってくるので、簡単なものを1つ作ってみたいと思っています。トークで扱っている題材の写経が1つの候補です

18日 14:30-

Notebook as Web API: Turn your notebook into Web API
@D会議室

  • この拡張でどこまでできるのか興味があります
  • 機械学習モデルをDockerでデプロイするよりも使いやすそうなら乗り換えも検討したいです

18日 15:45-

From Data to Web Application: Anime Character Image Recognition with Transfer Learning
@A+B会議室

  • アニメ題材なので即決でした
  • トークをもとに手を動かしてみようと思っています(転移学習)

18日 16:30-

AltJSとしてのPython - フロントエンドをPythonで書こう
@D会議室

  • フロントエンドを学習するまでの繋ぎとしてPythonで書く方法に興味があります
  • どこまでできるのか、限界やデメリットはあるのかというところを知りたいです

マークダウンでとったメモを休憩時間にHackMDに上げていく予定です。

トークの他にブース回りも予定しています。
LTは落ちた身なので、どんな題材が通ったのか研究して、普段のネタ決めに取り入れるつもりです。
本当にワクワクしますね。

よーし、楽しむぞ!


  1. 先日の転職と関係があります。後ほどブログで状況報告しようと思います。

イベントレポート | #モグモグDjango にてDockerでDjango+MySQLの環境構築の知見を得ました

はじめに

いつも心は虹色に! nikkieです。
#モグモグDjango にお邪魔してDockerでDjango+MySQLの環境を構築するノウハウをつかみました。

勉強会の概要

第2回 モグモグDjango - connpass

Djangoもくもく会 モグモグDjango を開催します. Django初心者の方から,上級者の方までどなたでもご参加下さい(^^)
この会では,しーーっんとしているもくもく会ではなく,質問や分からないところがあったら,その場で聞くことができる環境にしたい!と思っています.

7月に続いて2回目開催の#モグモグDjango
『現場で使える基礎Django』や加筆版(Kindle版ペーパーバック版)の著者akiyokoさんが今回もいらっしゃり、Djangoユーザにとって充実のもくもく環境でした。

休憩の王道ドーナツ(mamixさん持参)もあり、上質な甘さを堪能していました。(本当に美味しかった。。ごちそうさまでした)

取り組んだこと

Django Girls Tutorial翻訳でお世話になっているkaizumakiさんが、前回からDockerでDjango+MySQLの環境を構築するのに取り組まれていたので、一緒に調べていました。

本当はやりたいことを用意していたのですが、業務がオーバーフローしてしまい、何をするかが詰められないままの参加でした。1(ここは要反省です。。)

Django+MySQLの環境構築で得られた知見

以下のブログをベースに取り組みました。2

以下の2つの点が収穫です。

  • PyMySQLが必要
  • db-datadirというディレクトリをホスト側に作って、MySQLのデータを永続化する

わかったことをまとめていきます。

実行環境

  • macOS 10.13.6
  • Docker Client/Server 18.06.1-ce

Dockerfile

Dockerの公式ドキュメントの書き方が納得できないので、以下のように修正しました。

FROM python:3.6
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/
  • Python3.6系を使うためベースイメージを変更(FROM命令)
  • ファイルやフォルダの単なるコピーであれば、ADD命令よりCOPY命令のほうが好ましいと認識しているので、COPY命令を使用

requirements.txt

Django~=2.0.6
PyMySQL
  • Django Girls Tutorialと同様に2.0系の最新を指定
  • Dockerの公式ドキュメントにあるpsycopg2PostgreSQL接続用3

docker-compose.yml

version: '3'

services:

  # https://hub.docker.com/r/mysql/mysql-server/
  db:
    image: mysql/mysql-server:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=P@ssw0rd
      - MYSQL_ROOT_HOST=%
    volumes:
      - ./db-datadir:/var/lib/mysql
      - ./sql:/docker-entrypoint-initdb.d

  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db
  • ホストからdbコンテナの3306ポートにアクセスしないだろうとdbにportsは設定していません(コンテナ間はDockerのネットワークで通信できる認識)
  • webコンテナにdepends_on設定しているので、webの方がdbより先に立ち上がることはないと考え、commandのsleep 3;は削除しました
  • volumesの./db-datadir:/var/lib/mysqlという書き方でMySQLのデータが永続化できることを初めて知りました。ホスト側にdb-datadirディレクトリができて、データが永続化されます。
    • これまでは以下のように宣言したdb-volumeを指定してきました。(関連箇所を抜粋)
services:
  db:
    volumes:
      - db-volume:/var/lib/mysql
volumes:
  db-volume:

参考記事ではsqlファイルを作成しているのですが、よくわからなかった私はスキップして先に進みました(注意: ハマりたくなければ、スキップしないでください)。

フォルダ構成

  • Dockerfile
  • requirements.txt
  • docker-compose.yml

プロジェクト作成

$ docker-compose up -d db
$ docker-compose run web django-admin startproject mysite .
$

フォルダ構成

  • db-datadir/
  • mysite/
  • manage.py
  • Dockerfile
  • requirements.txt
  • docker-compose.yml

[ハマった] DBの接続設定をして、migrationを実施

mysite/settings.pyを以下のように変更

import pymysql
pymysql.install_as_MySQLdb()
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django',
        'USER': 'django',
        'PASSWORD': 'P@ssw0rd_django',
        'HOST': 'db',
        'OPTIONS': {
            'charset': 'utf8mb4',
        },
    }
}
  • PORTは指定不要の認識です(デフォルトで3306ポートと通信している認識です)

webコンテナで プロジェクトを作成しよう! · Django Girls Tutorial にならってコマンドを実行させました。

$ docker-compose run web python manage.py migrate
 :
django.db.utils.OperationalError: (1045, "Access denied for user 'django'@'172.19.0.3' (using password: YES)")
$

djangoユーザでMySQLに接続できず落ちます。

現状の問題4

  • MySQLdjangoデータベースが作成されていない
  • MySQLdjangoユーザが作成されていない

これはsqlを作成して実行していないことが原因です。
必要なsqlを作成していきます。

DB初期化用SQLファイル作成 + 初期化実施

sql/001_setup_application_database.sql

CREATE DATABASE IF NOT EXISTS django CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER IF NOT EXISTS 'django'@'%' IDENTIFIED BY 'P@ssw0rd_django';
GRANT ALL PRIVILEGES ON django.* TO 'django'@'%';

フォルダ構成

  • db-datadir/
  • mysite/
  • sql/
  • manage.py
  • Dockerfile
  • requirements.txt
  • docker-compose.yml

sqlファイル作成後にdocker-compose up -d dbをしても、初期化は実施されません。
データを永続化しているdb-datadirディレクトリを削除する必要がありました。5
(参考記事中の「DBを作成し直す場合の手順」をもとにしました)

$ docker-compose down
$ rm -rf db-datadir
$ docker-compose up -d db
$ docker-compose run web python manage.py migrate
$

dbコンテナが立ち上がるまで少し時間を置く必要がありましたが、これでデータベースとユーザが作られ、マイグレーションが実行できました。
sqlファイルにより、手動でデータベースやユーザを作る作業をなくしているんだなと気づきました。

superuser作成

$ docker-compose run web python manage.py createsuperuser
 :
$

以上で設定が終わったのでdocker-compose up -dしてから、http://127.0.0.1:8000/adminにアクセスすると。。

f:id:nikkie-ftnext:20180908205552p:plain

管理画面にログインできました^ ^

他に情報提供したこと

  • Docker関連でもう1件サポート: ポートの設定が食い違っていました
    • runでポート設定を8000:8000と指定
    • コンテナに接続してから0.0.0.0:8080でrunserver
  • k8sでデプロイされる方がいらっしゃったので、知っている情報を提供
    • 無事デプロイできたそうでおめでとうございます!

成果発表から

興味深かった情報を挙げていきます。

  • 男性OKのPyLadies Event PyLadies Tokyo - 4周年記念パーティ - connpass
    • 10/8の技術書典と重なるのですが、LTドリブンでなにかやりたかったので申し込んでみました
  • 年内いっぱい応募期間だそうで、力試ししてもいいかも Urban Data Challengeアーバンデータチャレンジ
  • どりらんさんのPyConトーク「Jupyterで広がるPythonの可能性」の頭出し。Jupyterのマジックコマンドすごかった
  • akiyokoさんの新刊応用編はすごくほしい内容でした。技術書典全体で見ると3冊程度Django本があるらしい?
  • 懇親タイムで OSS Gate | Doorkeeper 教えていただきました。ありがとうございます。駆け出しの身でも、コードでなくて翻訳でも、貢献できるそうなので、飛び込んでみよう!

感想

独学してきたDockerでお役に立てて嬉しく思います。
人に教えると自分の学びにもなるんですよね(データ永続化の理解が進みました!)。
一緒に考えるスタンスで、たまった知見を引き続き共有していきます。

今回「Pythonもくもく会でAzureでハマっている人」という通り名を得ました。
言い得て妙ですね。笑
まだまだハマる日々は続きそうですので、温かい目で見守っていただけると幸いです。

次回も予定されているそうで非常に楽しみです(akiyokoさんの新刊でもくもく予定です)。
皆さん、どうもありがとうございました!

脚注


  1. 月曜日から5営業日、勤務先のブログをVPSWordPressで構築していました。7日(金)の夜に設定漏れが見つかり、もくもくの時間の一部を使って対応させていただきました。。

  2. Dockerの公式ドキュメント Quickstart: Compose and Django | Docker DocumentationMySQL版とのことです。助かりました。ありがとうございます!

  3. ここはkaizumakiさんの疑問で調べたため、つまずかずに済みました(私は書いてあっても問題ないだろうと先走っていました)。ありがとうございました。

  4. docker exec -it <dbコンテナ> bashしてからrootユーザでmysqlに接続し、突き止めました

  5. docker-compose build dbで再ビルドしてもデータベースとユーザが作られず、同様のエラーでした