heroku container:push でエラー
先日からherokuCLIをアップデートしたあたりからherokuにデプロイしようとする度に以下のエラーが出るようになってしまいました。
(node:26614) Error Plugin: heroku-container-tools: files attribute must be specified in /Users/username/.local/share/heroku/node_modules/heroku-container-tools/package.json module: @oclif/config@1.6.27 plugin: heroku-container-tools root: /Users/username/.local/share/heroku/node_modules/heroku-container-tools See more details with DEBUG=* (node:26614) Error Plugin: heroku-container-tools: files attribute must be specified in /Users/username/.local/share/heroku/node_modules/heroku-container-tools/package.json module: @oclif/plugin-legacy@1.0.15 plugin: heroku-container-tools root: /Users/username/.local/share/heroku/node_modules/heroku-container-tools See more details with DEBUG=* Uninstalling heroku-container-tools... done
エラーメッセージを読んでもよくわからなかったのでいろいろ検索したところ以下の記事がヒットしました。
Latest Docker update broken Heroku cli?
症状は違いますがheroku-container-tools
が悪さをしているようだったので、以下コマンドでアンインストールし、heroku-container-registry
をインストールし直したところ、エラーは出なくなりました。
$ heroku plugins:uninstall heroku-container-tools $ heroku plugins:install heroku-container-registry
Node.jsの環境をDockerで構築&herokuにデプロイ
はじめに
それぞれ他サイトを参照して作ったのみですが、自身の備忘までに。
会社でSkyway使うかも?という話が出てきたため、検証環境を作るのが目的です。 * 他にもいろいろパッケージ入れて検証するかもーついでにnodejsとかの勉強もしなきゃ * 最近Docker触ってないしDockerで環境つくりたい * というかherokuにDockerのコンテナをデプロイできるようになったみたいだし使ってみたい ということで、node.jsの環境をDocker上に構築し、それをHerokuにデプロイするまでを試してみたいと思います。
Skywayとは?
NTT Comunicationsが開発している、WebRTCのためのプラットフォームです。
公式サイト
Enterprise Cloud Skyway
SkyWayとは
ビデオ会議やコンタクトセンター、遠隔作業支援、オンライン教育、ライブ配信など、さまざまな機会において、オンラインでのリアルタイムコミュニケーションのニーズが高まっています。 ビデオ・音声通話、データ通信といったリアルタイムコミュニケーションの標準技術である「WebRTC」が登場し、リアルタイムコミュニケーションがより実現しやすくなってきました。 SkyWayを利用すれば、WebRTCに必要なサーバを構築・運用することなく、手軽にビデオ・音声通話、データ通信を利用できます。 自社サービスの開発・提供に専念して、イノベーションに集中することができます。
要は、Skywayを使えばWebRTCのアプリが簡単に開発できるというものです。
WebRTCはクライアント間で直接通信する方法ですが、そのためにはシグナリングサーバーと呼ばれる、クライアント間の接続する仲介をするサーバーを準備する必要があるのですが(これがまた複雑、らしい)、Skywayではそういったシグナリング等の、WebRTCに必要なサーバサイドの機能をPFとして公開してくれているため、我々開発者はクライアント側の実装に集中できるのです。
自分もまだそんなに詳しくないのでこの辺で。。
Node.jsのDocker環境
まずはDocker上の環境を作っていきます。
とはいえこれまでほとんどNode.jsなんて触ったことがなく全く知識が無いため、 とりあえず先人の行いに習って作ってみます。
以下を参考にしました。
【初心者向け】Dockerで手軽にNode.js開発環境構築 (2)
参考というかほとんど完コピだけど。。
以下のDockerfile
とdocker-compose.yml
を作成
FROM node:8.9.4-alpine ENV NODE_ENV=development RUN npm install -g express-generator@4.15.0 WORKDIR /app EXPOSE 3000
version: '3' services: webserver: build: ./ image: node-express-dev:1.0 container_name: node tty: true volumes: - ./:/app ports: - "8080:3000"
ファイルの配置は記事とは変えてすべて同じディレクトリにしています。
MyApp ├─ Dockerfile └─ docker-compose.yml
そしてビルドと起動
$ docker-compose build $ docker-compose up -d
コンテナに接続し、express-generator
でアプリの雛形を作成します。
参照先サイトでは、オプションにpug
を指定しています。
pug
はテンプレートエンジンですが、構文が馴染めなそうだったので、今回はhtmlライクに書けそうなejs
を指定しました。
$ docker exec -it node /bin/sh # express -f --view=ejs /app # npm install
雛形が生成され、こんな構成になりました。
MyApp ├── Dockerfile ├── app.js ├── bin │ └── www ├── docker-compose.yml ├── node_modules ├── package-lock.json ├── package.json ├── public │ ├── images │ ├── javascripts │ └── stylesheets ├── routes │ ├── index.js │ └── users.js └── views ├── error.ejs └── index.ejs
以下コマンドで開発用サーバを起動します。
# npm start
http://localhost:8080
をブラウザで開いてExpressのスタートページが表示されれば成功です。
Dockerコンテナ上ではポート3000番で立ち上がっていますが、ブラウザの8080番ポートが3000番に転送されています。
Skywayのチュートリアル
さて、とりあえずnode.jsとWebサーバが立ち上がる環境はDocker上に構築出来たので、次はいよいよskywayのチュートリアルアプリを立ち上げていきます。
Javascript SDKの概要は以下公式ページに記載があります。
Skyway JavaScript SDK チュートリアル
とりあえず、今回はまず動くものを動作させたいので、チュートリアルのコードをそのまま使います。
Github上に公開されているサンプルコードを使用します。
今回はP2Pの1対多通信のものを使用しました。
github : skyway/skyway-js-sdk/examples/p2p-broadcast
先程構築したnode環境ではview/index.ejs
がホームにて表示されるページのテンプレートになっています。
↑のgithubに上がっていたindex.html
の内容をそのままvies/index.ejs
に貼り付けます。
script.js
、style.css
はそれぞれ、public/javascripts/script.js
、pubic/stylesheets/style.css
に配置します。
また、APIキーをSkywayのダッシュボードから取得し、public/javascripts/key.js
に記載します。
javascript
window.__SKYWAY_KEY__ = '<YOUR_KEY_HERE>'
index.ejsの読み込み先のパスも変更
<head> <meta charset="utf-8"> <title>SkyWay - Broadcast example</title> <link rel="stylesheet" href="/stylesheets/style.css"> <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script type="text/javascript" src="//cdn.webrtc.ecl.ntt.com/skyway-latest.js"></script> <script type="text/javascript" src="/javascripts/key.js"></script> <script type="text/javascript" src="/javascripts/script.js"></script> </head>
ここまで出来れば、http://localhost:8080
にてSkywayのサンプルが動作するはずです。
browserifyの導入
一旦ここまでで、Skywayの動作確認は出来ますが、jQueryやSkywayのJavascript SDKをCDNから読み込んでいます。
ここままでも問題ないのですが、後々いろんなパッケージを導入することを考えると、(今回もWebRTCでの配信→音声認識とかを試したいなーと思ってるので)
パッケージのバージョン管理が大変になったり、何よりも今回はnode.jsの環境構築の勉強も兼ねていたので、
* npmでパッケージインストール
* browserifyでコンパイル
という流れでパッケージ管理ができるよう変更したいと思います。
まずはnpmでjQueryとskyway-jsをインストールします。
# npm install jquery --save # npm install -D browserify
パッケージをインストールしたら、script.js
内でそれらのライブラリをrequire
する分を記載します。
'use strict'; // Imports jQuery const $ = require('jQuery'); $(function() { // Imports the skyway library const Peer = require('skyway-js');
読み込みも簡単ですね。
ただしこれだけだとrequire
をブラウザが解釈できないので、動作しません。
browserify
でコンパイルする必要があります。
一旦上記script.js
はscript/
ディレクトリを作成し、その配下で管理、開発、コンパイルしたらpublic/javascripts/script.js
が生成されるようにします。
コマンドは以下。
# $(npm bin)/browserify script/script.js -o public/javascripts/script.js
これでpublic/javascripts/script.js
がコンパイルされた形で生成されました。
再びnpm start
コマンドでサーバを立ち上げ、http://localhost:8080
をブラウザで開いてExpressのスタートページが表示されれば成功です。
Herokuへのデプロイ
ひとまず、Docker上に環境を作ることができたので、いよいよHerokuの環境にデプロイをしていきます。
以下のサイトを参考にしました。 * Container Registry & Runtime (Docker Deploys) * Heroku で Docker を使う場合の諸注意
herokuにDockerコンテナをデプロイするためには以下の注意点があるみたいです。
- PORT 環境変数で Listen する Webアプリケーションであること
- Network link は未サポート
- Default working directory = '/'。変更するときは WORKDIR を指定する。
- CMDが必須。ENTRYPOINTはオプション。
- VOLUME、EXPOSE、STOPSIGNAL、SHELL、HEALTHCHECKは未サポート
今回のサンプルはPORT
が3000で動作し、起動コマンドはnpm start
なので、以下をDockerfileに追記します。
ENV PORT 3000 CMD ["npm", "start"]
あとは以下コマンドでHerokuにデプロイします。
$ heroku login # herokuにログイン $ heroku container:login # Heroku 上の Container Registry へログイン $ heroku create # Heorkuアプリの作成 $ heroku container:push web # コンテナをにContainer RegistryにPush # 2018/5/15の変更にて以下のコマンドが必要になった $ heroku container:release web # heroku アプリをデプロイ
heroku open
でherokuアプリがブラウザで開けば成功です。
※5/15時点で変更があり、heroku container:push web
だけではherokuアプリにはデプロイされなくなったようです。実際にアプリにデプロイするにはheroku container:release web
を実行する必要があります。
Pushing images to Container Registry, either via the heroku container:push CLI command or using docker push, no longer releases those images to your application. To create a new release using the images pushed to Container Registry, run heroku container:release (specifying the process types you would like to release). Separating push and release allows you to:
- Push several images and then release them all at the same time.
- Use the release phase feature (run tasks before a new release of your app is deployed).
- Push one image and release it to multiple process types with different CMDs, via heroku.yml or API.
Pushing images to Container Registry no longer creates a release
まとめ
Herokuはこれまでもとても便利だったので大変重宝しておりましたが、自分自身余りgitを使わないし、グローバル環境で動作試験をしたいときもわざわざgit commit
してログに残るのが嫌だったので、Dockerコンテナを気軽にデプロイ出来るのはとても便利だなーと思いました。
参考サイト
プライバシーポリシー
こんにちは管理人のti_takaです。
下記、「プライバシーポリシー」に関して記載致しましたので、ご一読願います。
当サイトに掲載されている広告について
当サイトでは、第三者配信の広告サービス(Googleアドセンス、もしもアフィリエイト)を利用しています。 このような広告配信事業者は、ユーザーの興味に応じた商品やサービスの広告を表示するため、当サイトや他サイトへのアクセスに関する情報 『Cookie』(氏名、住所、メール アドレス、電話番号は含まれません) を使用することがあります。 またGoogleアドセンスに関して、このプロセスの詳細やこのような情報が広告配信事業者に使用されないようにする方法については、こちらをクリックしてください。
当サイトが使用しているアクセス解析ツールについて
当サイトでは、Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています。
このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています。
このトラフィックデータは匿名で収集されており、個人を特定するものではありません。
この機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。
この規約に関して、詳しくはこちら、またはこちらをクリックしてください。
当サイトへのコメントについて
当サイトでは、スパム・荒らしへの対応として、コメントの際に使用されたIPアドレスを記録しています。
これはブログの標準機能としてサポートされている機能で、スパム・荒らしへの対応以外にこのIPアドレスを使用することはありません。
また、メールアドレスとURLの入力に関しては、任意となっております。
全てのコメントは管理人であるti_takaが事前にその内容を確認し、承認した上での掲載となりますことをあらかじめご了承下さい。
加えて、次の各号に掲げる内容を含むコメントは管理人の裁量によって承認せず、削除する事があります。
- 特定の自然人または法人を誹謗し、中傷するもの。
- 極度にわいせつな内容を含むもの。
- 禁制品の取引に関するものや、他者を害する行為の依頼など、法律によって禁止されている物品、行為の依頼や斡旋などに関するもの。
- その他、公序良俗に反し、または管理人によって承認すべきでないと認められるもの。
免責事項
当サイトで掲載している画像の著作権・肖像権等は各権利所有者に帰属致します。
権利を侵害する目的ではございません。
記事の内容や掲載画像等に問題がございましたら、各権利所有者様本人が直接メールでご連絡下さい。
確認後、対応させて頂きます。
当サイトからリンクやバナーなどによって他のサイトに移動された場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。
当サイトのコンテンツ・情報につきまして、可能な限り正確な情報を掲載するよう努めておりますが、誤情報が入り込んだり、情報が古くなっていることもございます。
当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。
プライバシーポリシーの変更について
当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。
修正された最新のプライバシーポリシーは常に本ページにて開示されます。
運営者:ti_taka
[Python]Apache + Gunicorn + hug で簡単APIサーバ
先日、Apacheとmod_wsgiでPythonを動かし、APIサーバを作成してみました。
しかし、hugに備わっているBasic認証を追加することは出来ませんでした。
その後Gunicornを試してみたら、驚くほど簡単に実現できてしまいました。。
最初からこっちにすればよかった。。
前提
Pythonの環境とアプリケーションは前回のものを使います。
import sys,json,os import hug import util from dotenv import load_dotenv dotenv_path = join(dirname(__file__), '.env') load_dotenv(dotenv_path) HUG_USER_NAME = os.environ.get("HUG_USER_NAME") HUG_PASSWORD = os.environ.get("HUG_PASSWORD") authentication = hug.authentication.basic(hug.authentication.verify(HUG_USER_NAME, HUG_PASSWORD)) @hug.get("/hoge",,requires=authentication) def hoge(text): hoge_list = util.getHogeList(text) return json.dumps({"hoge":hoge_list})
前回記述したsys.path.append('/var/www/app')
はなくても今回は正常に動作しました。
また、動作させるアプリケーションは、gunicornを起動する際にパラメータとして渡すので、application = __hug_wsgi__
も不要です。
Gunicornのインストール
pipでインストールします。
$ pip3.6 install gunicorn
これで完了です。
$ cd /var/www/app/ # gunicornの起動 $ gunicorn app:__hug_wsgi__ [2017-09-12 22:54:04 +0000] [3994] [INFO] Starting gunicorn 19.7.1 [2017-09-12 22:54:04 +0000] [3994] [INFO] Listening at: http://127.0.0.1:8000 (3994) [2017-09-12 22:54:04 +0000] [3994] [INFO] Using worker: sync [2017-09-12 22:54:04 +0000] [3997] [INFO] Booting worker with pid: 3997
アプリがポート8000で起動します。
$ curl http://localhost:8000/hoge?text=hoge
結果が帰ってくればOKです。(Basic認証をかけているので認証エラーとなりますが。)
Apacheの設定
次にApacheの設定をします。
/etc/httpd/confd/httpd.conf
に以下の1行を記述し、リクエストをすべてgunicornに流すよう設定します。
ProxyPass / http://localhost:8000/
gunicornを起動した状態で、ブラウザからhttp://192.168.33.10/hoge?text=hoge
にアクセスして認証画面がでて認証できればOK!なのですが、なにやらまた、「Internal Server Error」が。。。
前回とまた同じです。
SELinuxの無効化
Apacheのエラーログを見ると、
[Tue Sep 12 12:03:36.233033 2017] [proxy:error] [pid 5746] (13)Permission denied: AH00957: HTTP: attempt to connect to 127.0.0.1:8000 (localhost) failed [Tue Sep 12 12:03:36.233187 2017] [proxy:error] [pid 5746] AH00959: ap_proxy_connect_backend disabling worker for (localhost) for 60s [Tue Sep 12 12:03:36.233202 2017] [proxy_http:error] [pid 5746] [client 192.168.33.1:62957] AH01114: HTTP: failed to make connection to backend: localhost
proxyがうまくいっていないみたいです。
エラーログを調べてみると色々情報がありました。
SELinuxが原因で、どうやらよくあることらしいです。
こちらを参考にしました。
/var/log/audit/audit.log
を見てみると、たしかに以下のエラーが。
type=AVC msg=audit(1505218092.201:865): avc: denied { name_connect } for pid=5745 comm="httpd" dest=8000 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:soundd_port_t:s0 tclass=tcp_socket
/etc/sysconfig/selinux
を修正して、SELINUX=disabled
とします。
OSを再起動して、再度gunicornを立ち上げると、無事動作しました。
Basic認証も問題なく、きちんと認証できます。
gunicornの自動起動設定
OSを立ち上げたときにApacheは自動起動するよう設定しましたが、gunicornも自動起動するように設定しないとアプリをWebサーバで動作させられません。
ここに記載されているとおりに実行すればOKです。
$ cd /etc/systemd/system/ $ vim app.service
今回gunicornのパスは/bin/gunicorn
で、アプリケーションのディレクトリは/var/www/app
なのでapp.service
の中身は以下のようになりました。
[Unit] Description=gunicorn daemon After=network.target [Service] User=apache Group=apache WorkingDirectory=/var/www/app ExecStart=/bin/gunicorn schedule:__hug_wsgi__ [Install] WantedBy=multi-user.target
自動起動するように設定します。
$ systemctl enable app $ systemctl start app
OSを再起動し、ブラウザからhttp://192.168.33.10/hoge?text=hoge
にアクセスして結果が出ればOKです。
まとめ
前回mod_wsgiでアプリケーションを動作させたよりももっと簡単に実現できました。
また、前回躓いたBasic認証も正常に動作させることが出来ました。
今回はgunicornを運用していこうと思います。
参考ページ
[Python]CnetOS7 + Apache + mod_wsgi + hug で簡単APIサーバ作成
簡単なAPIサーバを作りたいなーと思い、やってみました。
以前はPHPを少ししか書けなかったけど、もう少し色々な言語を使いたいと思いPythonで実装してみることにしました。
色々と調べてみるとPythonにもフレームワークは色々とあるようで、DjangoとかFlaskとかありましたが、簡単に実装できそうなhugを使うことにしました。
PHPだとWebサーバ上で動かすのは簡単だったのですが、Pythonだと割と大変だったので備忘録として残しておきます。
wsgiサーバはpythonだとgunicornとかuwsgiとかがポピュラーみたいでしたが、何やら設定が難しそうな印象を受けたので、なんとなく簡単そうなmod_wsgiを使うことにしました。
最終的にやりたかったBASIC認証までを追加することは出来ませんでしたが。。。
知っている方がいたら教えてほしいです。。
※20170914 追記 gunicorn使った方が簡単でした。
Vagrantを使ってCentOSのVMを作成
Vagrantfileはこんな感じです。
Vagrant.configure("2") do |config| config.vm.box = "centos/7" config.vm.network "private_network", ip: "192.168.33.10" "192.168.0.100" , :bridge => "en0: Wi-Fi (AirPort)" config.vm.synced_folder "./", "/vagrant", type: "virtualbox", :owner => "vagrant", :groupe => "vagrant", :mount_options => ['dmode=755', 'fmode=655'] config.vm.provision "shell", run: "always", inline: "systemctl restart network.service" end
「Vagrant+Laravelでパーミッションで詰まった」とか、「vagrant + centos7 でprivate_networkで設定したIPに接続ができない」とかで躓いた経緯があったから、
config.vm.synced_folder "./", "/vagrant", type: "virtualbox", :owner => "vagrant", :groupe => "vagrant", :mount_options => ['dmode=755', 'fmode=655'] config.vm.provision "shell", run: "always", inline: "systemctl restart network.service"
とかを記載しています。
Python3系とApacheのインストール
hugはPython3系でしか動かないので、まずはPython3系をインストールします。
Apacheはyumでインストールすればいいのですが、Pythonに関してはソースからコンパイルしたりyumで入れたりとか色々やり方はあったのですが、最終的に「Python 3 を CentOS 7 に yum でインストールする手順」のやり方を参考にしたら上手くいきました。
[Python] mod_wsgiを使ってPython3.6をApacheで動かす(CentOS6系)
このあたりを参考にソースからコンパイルする方法も試してみましたが、何故かpipでmod_wsgiをインストールするところでつまずいてしまいました。Cent0S6系と7系の違い?
とりあえず下記コマンドでインストールします。
# 色々インストール $ yum groupinstall -y "Development tools" $ yum install -y zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel # Apacheのインストール $ yum install -y httpd httpd-devel # OS起動時にApacheの起動を有効化 $ systemctl enable httpd.service # Apacheの起動 $ systemctl start httpd.service # Pyton3.6.xのインストール $ yum install -y https://centos7.iuscommunity.org/ius-release.rpm $ yum install -y python36u python36u-libs python36u-devel python36u-pip $ python3.6 -V Python 3.6.2
無事Python3.6とApacheがインストール出来ました。
mod_wsgiのインストール
こちらもソースからインストールしたりpip経由でのインストールがあるみたいですが、あえてソースからインストールするメリットも分からなかったので、pip経由でインストールすることにしました。
先程の[Python] mod_wsgiを使ってPython3.6をApacheで動かす(CentOS6系)の後半辺りを参考にしています。
$ pip3.6 install mod_wsgi $ python3.6 -c "import sys; print(sys.path)" ['', '/usr/lib64/python36.zip', '/usr/lib64/python3.6', '/usr/lib64/python3.6/lib-dynload', '/usr/lib64/python3.6/site-packages', '/usr/lib/python3.6/site-packages']
インストールが完了し、パケージのインストール先が/usr/lib64/python3.6/site-packages
だと分かります。
$ cd /usr/lib64/python3.6/site-packages $ ll total 8 drwxr-xr-x. 6 root root 4096 Sep 5 13:19 lxml drwxr-xr-x. 2 root root 131 Sep 5 13:19 lxml-3.8.0.dist-info drwxr-xr-x. 6 root root 84 Sep 5 09:15 mod_wsgi drwxr-xr-x. 2 root root 141 Sep 5 09:15 mod_wsgi-4.5.18-py3.6.egg-info drwxr-xr-x. 2 root root 6 Jul 19 04:01 __pycache__ -rw-r--r--. 1 root root 119 Jul 8 03:33 README.txt $ cd mod_wsgi/server $ ll total 1048 -rw-r--r--. 1 root root 1558 Sep 5 09:15 apxs_config.py -rw-r--r--. 1 root root 3563 Mar 31 2016 environ.py -rw-r--r--. 1 root root 128159 Aug 29 09:28 __init__.py drwxr-xr-x. 4 root root 60 Sep 5 09:15 management -rwxr-xr-x. 1 root root 932872 Sep 5 09:15 mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so drwxr-xr-x. 2 root root 101 Sep 5 09:15 __pycache__
ここにある、mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
を使います。
パスは/usr/lib64/python3.6/site-packages/mod_wsgi/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.soserver
です。
Apacheの設定
これで必要なものはインストール出来たので、Apacheの設定をしていきます。
/etc/httpd/conf.d/
配下にwsgi.conf
設定ファイルを配置し、wsgiの設定を記述します。
LoadModule wsgi_module /usr/lib64/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so WSGIDaemonProcess myapp user=apache group=apache WSGIProcessGroup myapp WSGISocketPrefix /var/run/wsgi WSGIScriptAlias / /var/www/app/app.py <Directory /var/www/app/> Options ExecCGI MultiViews Indexes MultiViewsMatch Handlers AddHandler wsgi-script .py AddHandler wsgi-script .wsgi DirectoryIndex index.html index.py app.py Order allow,deny Allow from all </Directory>
これを記述したらApacheを再起動しておきます。
$ apachectl restart
これで、ルートディレクトリ/
を開いたときに、/var/www/app/app.py
を動作させるという設定になりました。
hugでapp.pyの作成
とりあえずこんな感じで書きました。
import sys,json,os import hug import util @hug.get("/hoge") def hoge(text): hoge_list = util.getHogeList(text) return json.dumps({"hoge":hoge_list})
今回はGETで受け取ったパラメータを他の関数に渡して処理してもらい、その結果を返すAPIを想定しているので、この様な書き方にしています。
実際に処理する関数はutil.pyに記載しています。
以下コマンドで、開発用サーバを起動します。
$ hug -f app.py /#######################################################################\ `.----``..-------..``.----. :/:::::--:---------:--::::://. .+::::----##/-/oo+:-##----::::// `//::-------/oosoo-------::://. ## ## ## ## ##### .-:------./++o/o-.------::-` ``` ## ## ## ## ## `----.-./+o+:..----. `.:///. ######## ## ## ## ``` `----.-::::::------ `.-:::://. ## ## ## ## ## #### ://::--.``` -:``...-----...` `:--::::::-.` ## ## ## ## ## ## :/:::::::::-:- ````` .:::::-.` ## ## #### ###### ``.--:::::::. .:::.` ``..::. .:: EMBRACE THE APIs OF THE FUTURE ::- .:- -::` ::- VERSION 2.3.1 `::- -::` -::-` -::- \########################################################################/ Copyright (C) 2016 Timothy Edmund Crosley Under the MIT License Serving on port 8000...
開発用のサーバがポート8000番で立ち上がるので、
$ curl http://localhost:8000/hoge?text=hoge
で結果が帰ってくればOKです。
また、http://192.168.33.10:8000/hoge?text=hoge
にアクセスでも見れます。
開発用サーバではなく、mod_wsgi
経由でApacheでも動作しているか確認したいので、mod_wsgiでも動くようにします。
mod_wsgiで動作させるには、mod_wsgiに対応したapplicationを作る必要があります。
mod_wsgiでhugを使い、APIを作るやPython hug with apache mod_wsgiを参照。
app.py
の最下部に以下の一文を追記します。
application = __hug_wsgi__
ブラウザで、http://192.168.33.10/hoge?text=hoge
にアクセスして同じ結果が帰ってくればOK。
・・・なのですが、何やら「Internal Server Error」のエラーが。
Apacheのエラーログを見てみると、
[Sat Sep 09 13:28:00.511142 2017] [wsgi:error] [pid 7361] [remote 192.168.33.1:57939] mod_wsgi (pid=7361): Target WSGI script '/var/www/app/app.py' cannot be loaded as Python module. [Sat Sep 09 13:28:00.511233 2017] [wsgi:error] [pid 7361] [remote 192.168.33.1:57939] mod_wsgi (pid=7361): Exception occurred processing WSGI script '/var/www/app/app.py'. [Sat Sep 09 13:28:00.511368 2017] [wsgi:error] [pid 7361] [remote 192.168.33.1:57939] Traceback (most recent call last): [Sat Sep 09 13:28:00.511434 2017] [wsgi:error] [pid 7361] [remote 192.168.33.1:57939] File "/var/www/app/app.py", line 4, in <module> [Sat Sep 09 13:28:00.511441 2017] [wsgi:error] [pid 7361] [remote 192.168.33.1:57939] import util [Sat Sep 09 13:28:00.511469 2017] [wsgi:error] [pid 7361] [remote 192.168.33.1:57939] ModuleNotFoundError: No module named 'util'
なにやらutil.pyが読み込めていない模様。
Pythonで「ImportError: No module named …」が出た時の3つの対処法を参考に、sys.path.append('/path/to/dir')
をapp.py
に追記すると直りました。
mod_wsgiでは若干挙動が違う?
Basic認証を追加
The guiding thought behind the architectureを参照すると、getの引数にhug.authentication.verify("userid","password")
を与えるとBasic認証が出来るようになるみたいです。
そのままユーザーID、パスワードを記述するのも良くないので、.env
ファイルを作成してそこに環境変数を書くとします。
【GitHub】に載せたくない環境変数の書き方 Python
こちらにdotenv
の使い方が載っています。
$ pip3.6 install python-dotenv
.env
の中身は↓にしました。
HUG_USER_NAME=uname HUG_PASSWORD=pass
この中の環境変数は、以下のように取り出します。
import os from os.path import join, dirname from dotenv import load_dotenv dotenv_path = join(dirname(__file__), '.env') load_dotenv(dotenv_path) HUG_USER_NAME = os.environ.get("HUG_USER_NAME") HUG_PASSWORD = os.environ.get("HUG_PASSWORD")
これらの変数を用いて以下のようにBasic認証の設定を記述します。
import sys,json,os sys.path.append('/var/www/app') import hug import util from dotenv import load_dotenv dotenv_path = join(dirname(__file__), '.env') load_dotenv(dotenv_path) HUG_USER_NAME = os.environ.get("HUG_USER_NAME") HUG_PASSWORD = os.environ.get("HUG_PASSWORD") authentication = hug.authentication.basic(hug.authentication.verify(HUG_USER_NAME, HUG_PASSWORD)) @hug.get("/hoge",,requires=authentication) def hoge(text): hoge_list = util.getHogeList(text) return json.dumps({"hoge":hoge_list}) application = __hug_wsgi__
開発用サーバを立ち上げて、ブラウザからhttp://192.168.33.10:8000/hoge?text=hoge
に認証画面が出て認証できればOKです。
Apacheからの接続はどうかというと、http://192.168.33.10/hoge?text=hoge
に接続すると、無事認証画面が出ました!!!
が、、IDとパスワードを入れても認証出来ません。。。。
いくら調べても原因が分からない。。なんでなんだ~。。。。
今回はここで断念しました。。。
まとめ
mod_wsgiとhugを使って、簡単なAPIサーバを立ち上げることが出来ました。
ただ、最終的にやりたかったBasic認証はなぜかmod_wsgiだと正常に動作しませんでした。
hugに組み込まれている開発用のサーバとmod_wsgiとでは若干挙動が違うようです。
解決策を知っている方が居ましたら教えて下さい。
参考ページ
- hug:Embrace the APIs of the future
- Vagrant+Laravelでパーミッションで詰まった
- vagrant + centos7 でprivate_networkで設定したIPに接続ができない
- Python 3 を CentOS 7 に yum でインストールする手順
- [Python] mod_wsgiを使ってPython3.6をApacheで動かす(CentOS6系)
- mod_wsgiでhugを使い、APIを作る
- Python hug with apache mod_wsgi
- Pythonで「ImportError: No module named …」が出た時の3つの対処法
- The guiding thought behind the architecture
- 【GitHub】に載せたくない環境変数の書き方 Python
銭湯で痴漢された話
僕は昔からホモにモテる。何故かわからないけど。 昔は運動もしていたし、体を使うバイトもしていたので割りと筋肉質でムチムチした体をしていたからかも。
ちょっと前こんな記事を見て、昔銭湯で痴漢されそうになったことを思い出しました。 しかもスーパー銭湯の系列店も同じだし。。。。
犯行現場はやはり泡風呂
先の記事でも泡風呂について言及されてましたが、自分が被害にあったのも泡風呂でした。
友人三人でスーパー銭湯に行き、泡風呂に↓のように座っていました。
┌────────────────┐
│ │
│ │
│ 他 友 友 自 他 │
└────────────────┘
友人三人で並んでお湯に浸かり、自分が端でした。
ゆっくりと他愛もない会話をしながらお湯に浸かっていると、前に伸ばしている自分の膝周りちょいちょい触れるものが。。。
銭湯でたまに体が当たってしまうのはよくあることなので、その時点では何も思わず、「なんか当たんだけど〜、狭いわ〜」と友達にもぼやきながら、足を動かして跳ね除け?たりしていました。
しかし、跳ね除けても跳ね除けても何かが足に触れてきます。自分と隣の人との間には十分なスペースがあり、普通にじっとしていれば体が触れ合うような距離ではなかったのです。
しかも、触れてくる場所が少しずつ上に来て、太もも周りを触られている感触が。
気付いても何も出来ない
「隣のおっさんがこっちに手伸ばして触ろうとしてきてね?!」
そう気づいてしまったときに僕は恐怖に陥りました。
隣のおっさんは普通の何食わぬ顔で前を向きお湯に浸かっているように見えるけど、お湯の中をちらっと見ると不自然な体勢になりながらも手をこちらに伸ばしてきている!!!
恐怖を感じながらも抵抗する?ことも出来ないので、隣の友人に「サウナ行こうぜ!」と言って逃げました。
その後友人に恐怖を語ったものの、笑いものにされたのは言うまでもありません。。。
まとめ
銭湯コワイ ホモコワイ いや、痴漢コワイ
電車で痴漢されて助けを呼べない女性の気持ちが分かったなぁ〜。。