- 投稿日:2020-05-20T22:12:31+09:00
alpineでC言語依存モジュールを pip install した時の時間を計測してみた
Let's 計測
alpineでC言語依存モジュールを pip install すると激重になる話 のおまけ
素直にpip installした場合に、どれくらい時間がかかるか試してみた。
手元にあった機械学習用のrequirements.txt
で実行してみると以下のようなログがでてきたのでBuilding wheels for collected packages: backcall, h5py, kiwisolver, matplotlib, numpy, pandas, pathspec, Pillow, PyYAML, pyzmq, regex, retrying, scikit-learn, scipy, tornado, typed-ast開発時にも使用頻度高そうなモジュールだけピックアップして計測することにした。
- 実行してみるリスト
- numpy
- pandas
- Pillow
- scipy
- scikit-learn
- h5py
- matplotlib
- regex
実験環境
手元で実行できる環境が二種類あったので両方とも試してみる。
- case1: MacBookAir 2015 13inch intel-corei5 8GB DDR3 ・ docker desktop
- case2: AMD Ryzen9 3900X, M.2 ASM2NE6500GTTD, 8x2GB DDR4 ・ ubuntu18.04(WSL2 integration)
計測方法
timeコマンドを頭につける事で実行時間を計測する。
どちらのケースも同一のdockerfileで実行しており、RUN
命令文中にtime pip install hoge
を埋め込む形を取っている。FROM python:3.8-alpine3.11 RUN apk update \ && apk add --virtual .build --no-cache openblas-dev lapack-dev freetype-dev \ gfortran libxml2 g++ gcc zip unzip cmake make \ libpng-dev openssl-dev musl libffi-dev python3-dev libxslt-dev \ libxml2-dev jpeg-dev \ && apk add --no-cache -X http://dl-cdn.alpinelinux.org/alpine/edge/testing hdf5-dev RUN pip install --upgrade --no-cache-dir pip setuptools wheel && \ time pip install --no-cache-dir Cython && \ ...こんな感じ。
docker build
中に出力されるログをまとめたのが次の表となる。結果
※ Cythonはalpineでもコンパイル不要のモジュールであり、
Cython-0.29.16-py2.py3-none-any.whl
のような.whl
形式で降ってきます。非依存モジュールとの比較としてここに載せています。1
module / time case1 case2 real user sys real user sys Cython 3.07s 2.33s 0.42s 1.52s 0.99s 0.07s numpy 5m 28.27s 7m 6.90s 22.11s 2m 11.15s 3m 23.69s 6.05s pandas 31m 46.58s 30m 36.25s 0m 53.83s 14m 8.24s 13m 53.10s 15.88s Pillow 50.81s 44.09s 5.99s 24.79s 19.88s 1.69s scipy 30m 45.99s 36m 29.33s 1m 45.89s 12m 52.81s 17m 54.87s 42.58s scikit-learn 14m 38.63s 14m 3.37s 28.98s 6m 33.10s 6m 24.84s 10.11s h5py 3m 45.58s 3m 34.79s 9.30s 1m 45.87s 1m 42.42s 4.18s matplotlib 2m 51.50s 2m 35.53s 13.59s 1m 21.77s 1m 13.70s 6.75s regex 30.52s 28.84s 1.24s 13.75s 13.06s 0.34s おっっっっそい
ものっっっっっそい、おっっっっっっそいcase1だとnumpyだけでも5分かかるし、pandas・scipyに至っては30分を超えている。scikit-learnに至ってはnumpy・scipyに依存しているので実際のところ一時間は覚悟しないといけない。
挙げた全部合わせると一時間半超だ。
これがどういう事になるか。一日8時間作業すると仮定すると一日たったの5回程度しかデプロイする事ができないことになる
気軽に開発環境に最新ブランチを充てたり、軽微なバグ修正の確認すら困難になる。作業時間も含めると更に減る。
一応、メモリが倍になると処理速度も倍になるので時間の短縮はできなくもない。
awsを使ったりしているのならメモリ量が多いインスタンスタイプを選択することで時短は可能だ。
しかし、性能的にcase1の二倍以上のcase2だと半分以下の時間で済むとはいえ、全部で40分ほどかかっているのは事実。
一日あたり最高で12回ほどのデプロイしかできない。
ちなみに、表の上から順番に
pip install
していったので一部モジュールの実行時間には依存モジュールのインストール実行時間も含まれる。
kiwisolverもtar.gz
で降ってきているようなのでmatplotlib単体はもう少し早いはず。Successfully built pandas Installing collected packages: six, python-dateutil, pytz, pandas Successfully installed pandas-0.25.3 python-dateutil-2.8.1 pytz-2019.3 six-1.14.0 ------ Successfully built scikit-learn Installing collected packages: joblib, scikit-learn Successfully installed joblib-0.14.1 scikit-learn-0.22.2.post1 ----- Successfully built matplotlib kiwisolver Installing collected packages: cycler, kiwisolver, pyparsing, matplotlib Successfully installed cycler-0.10.0 kiwisolver-1.2.0 matplotlib-3.2.1まとめ
軽いものでも1個あたり1~2分かかるレベルなので、なるべくC言語依存モジュールはビルドしないで済む運用を考える必要がある。
condaを使う、は今無しで余談pip
pip install
時はモジュールのwheel化が完了した直後に、再度whlを展開し直して必要な生成物をまるっとsite-package
直下に移動する。pythonで書かれたコードからビルドされた共有ライブラリ郡*.so
も含めて全てだ。
alpineのようにpython3.8
のバイナリが/usr/local/bin
直下にいるとすると/usr/local/lib/python3.8/site-packages/
に移動する。再展開は手間のように見えるがこれはPEPに則った安全なモジュールの導入法である。PEP491にもそう書かれている2
試しに、ビルド済みのwhlファイルを
unzip
して.so
ファイルを検索してみる。./numpy/linalg/lapack_lite.cpython-38-x86_64-linux-gnu.so ./numpy/linalg/_umath_linalg.cpython-38-x86_64-linux-gnu.so ./numpy/core/_operand_flag_tests.cpython-38-x86_64-linux-gnu.so ...それぞれのwhlファイルを
pip install
で導入後にライブラリパスに対して.so
ファイルを検索してみると、モジュール毎にビルド済みファイルが存在しているのを確認できる。/usr/local/lib/python3.8/site-packages/numpy/linalg/lapack_lite.cpython-38-x86_64-linux-gnu.so /usr/local/lib/python3.8/site-packages/numpy/linalg/_umath_linalg.cpython-38-x86_64-linux-gnu.so /usr/local/lib/python3.8/site-packages/numpy/core/_operand_flag_tests.cpython-38-x86_64-linux-gnu.so ... /usr/local/lib/python3.8/site-packages/pandas/io/sas/_sas.cpython-38-x86_64-linux-gnu.so /usr/local/lib/python3.8/site-packages/pandas/_libs/hashtable.cpython-38-x86_64-linux-gnu.so ...これでようやくpythonでimportできる訳だが、
裏を返せばpythonがモジュールを検索するパスに生成物さえ居れば使用できる。
なので元記事の回避法では、python関連以外は後に入れること前提で/usr/local/
直下をdockerのマルチステージビルドを使ってえいやでコピペしている。参考文献
- Wheel files : What is the meaning of “none-any” in protobuf-3.4.0-py2.py3-none-any.whl
- PEP 425 -- Compatibility Tags for Built Distributions
- PEP 491 -- The Wheel Binary Package Format 1.9
- wheelのありがたさとAnacondaへの要望
- wheel・PEP関連ですごく参考にしました。
- ちなみに現在だと
conda skeleton
でPyPiのwheelを導入できる
- ただし、conda独自にビルドし直して導入している模様。個人的には ソウジャナイ感
- anacondaにsentencepieceをwheelファイル経由でインストールする
- 投稿日:2020-05-20T20:42:59+09:00
Rails6について
前提
Rails6について学んだことを書いていきます。
macOS
Docker・Docker Composeインストール済み本題
仮想環境を使う理由
Railsアプリケーションの開発をしようとするときに問題がある。
それは開発用マシン(作業マシン)と実運用を行うマシン(プロダクションマシン)の環境が異なること。
ここで言う環境とは、OSの種類やバージョン、あるいはOS上で動くソフトウェアやライブラリの種類やバージョンをさす。
Ruby on RailsはWindowsでもMacOSでもLinuxでも動作するように設計されている。
しかし、Railsを拡張するために導入するGemパッケージは必ずしもそうではない。
仮に動いたとしても、特定の環境では振る舞いが微妙に異なったり、不具合が出たりすることがある。この問題の解決方法として、作業マシンとプロダクションマシンの環境を一致させること。
そこで現れるのが仮想環境と言うオプション。
Windows、MacOS、ubuntuなどのデスクトップOSの上に仮想環境を構築し、そこにLinuxベースのServerOSをインストールする。開発中のRailsアプリケーションは仮想環境で動作させる。
デスクトップOS上のWebブラウザからRailsアプリケーションにアクセスして動作を確認。
他方、Railsアプリケーションのソースコードは共有フォルダの機能によって、デスクトップOS上で開いて編集する。
こうすれば、使い慣れたテキストエディタやIDEを使い続けながら、プロダクションマシンと同等の環境下でRailsアプリケーションの開発が行える。Dockerとは
仮想環境を提供するオープンソース・ソフトウェア。
設定の容易さや起動の早さが人気。
個々の仮想環境をコンテナと呼ぶ。
コンテナの内容はDockerfileと呼ばれるテキストファイルで記述される。
このファイルがあれば様々なOS上でコンテナを復元できる。Docker-composeとは
Dockerを用いて、Railsアプリケーションを開発したり、プロダクション環境で動かすとき、Railsアプリケーションとデータベースサーバーを別々のコンテナとして構築するのが一般的。
Docker-composeはこれらの複数のコンテナをまとめて起動・停止するためのツール。
docker-compose up
というコマンドを実行するだけで、Webアプリケーションを構成する全てのコンテナ群が動き出す。Rails開発環境の構築
DockerとDocker Composeを用いてRails開発用コンテナ群を構築。
terminal.$ git clone https://github.com/oiax/rails6-compose.git $ cd rails6-compose $ ./setup.shコンテナ群の起動と停止
コンテナ群を全て起動するにはターミナルで下記のコマンドを実行。
オプション-dはコンテナをデーモン(バックグラウンドプロセス)として動かすためのもの。terminal.$ docker-compose up -dコンテナ群を停止するにはターミナルで下記のコマンドを実行。
terminal.$ docker-compose stopwebコンテナにログイン
terminal.$ docker-compose exec web bashRailsのバージョン確認
bash-4.4$ rails --versionRails6.0.0と結果出力されればOK!
rails newコマンドで新規Railsアプリケーションの作成。
bash-4.4$ rails new アプリ名 -d postgresql --skip-test-unit
--skip-test-unit
はTest::Unit関連のコードの生成を省略するためのオプション。中身の確認
bash-4.4$ ls -a アプリ名/Gemfileの編集
gem "bcrypt" #パスワードの暗号化 gem "rails-i18n" #railsが出力するエラーメッセージ、日付、時刻、通貨単位などの翻訳ファイルを集めたもの gem "kaminari" #ページネーション機能 gem "date_validator" #日付のバリデーションを行う gem "valid_email2" #メールアドレスへのバリデーションを行う gem "nokogiri" #XML/HTMLの解析・生成のため※email_validatorはバージョンアップでバリデーションの基準が緩くなり、実用性が乏しくなった。
例えば、@を2個含むようなメールアドレスを有効と判定してしまう。
- 投稿日:2020-05-20T20:15:44+09:00
Zabbix5.0とZabbix agent2をubuntu18.04とvagrantとdocker-composeで動かしてみたけど自分のDockerをまだ監視できない
はじめに
申し訳ないのですがこれは2020/05/20時点の私の技術力だとうまくいかなかったことを恥を忍んで報告する記事です。目的は私のこの徒労がほかの人のためになるかもしれないからです。この手順から何かすればうまくdocker監視できるかもしれないので、もしできた人はコメントください。
一応Zabbix5.0をubuntu18.04とvagrantとdocker-composeで一から環境をセットアップして動かすことはできたのでとりあえずそこまでやりたい人はこの記事を参考にしていただければ幸いです。
zabbix5.0
zabbix5.0はこの5月にリリースされました。
Zabbix 5.0LTSの新機能 https://www.zabbix.com/jp/whats_new_5_0
特にDockerも監視できるというZabbix agent2が使用できるのがDocker使いには魅力的かと思います。
これの前にZabbix5.0とZabbix agent2をCentOS7のDockerで試したけどダメでした
私も興味があったので自分なりにCentOS7で試してみました。
しかしCentOS7だと、docker-composeによるzabbi5とZabbix agent2でDocker監視はできませんでした。正確に言うとDocker関連のアイテムのみ取得できませんでした。
早い話が、現時点では監視対象がRHEL8系だとDockerを監視することがそもそもできない構造になっています。
順を追って書きますと、まず公式のdocker-compose.ymlにはagent2を使用できるように記述されていませんでした。これは正直盲点でした。まさかDockerで動くのにdocker-compose.ymlに存在すらしないとは思わず......
そこで後述する方法でagent2を書いてもDockerのアイテムは取得できません。ほかのテンプレートを登録するとそれらはごく普通に値を取得できていたのではじめは自分の設定の問題かなあと考えておりました。
しかし調べてみると、Zabbix agent2はCentS7をサポートしてませんでした。RHEL8系からでした。
zabbix Agent 2 https://www.zabbix.com/documentation/current/manual/concepts/agent2
しかし、現在DockerはCentOS8をサポートしていません。
Docker公式 CentOSでのDockerインストール https://docs.docker.com/engine/install/centos/
試しに私も無理やり入れて動かしてみましたがimageのpullすらできませんでした。どうもRHEL系はpodmanというdocker互換のものがいるらしいです。これがzabbixのDocker監視機能で引っかかるかはまったくわかりません。多分ダメだと思いますが。
......
とこんなわけで、現時点では監視対象がRHEL8系だとDockerを監視することがそもそもできない構造になっています。
これらはただ表面のWhats Newとか読んでるだけだと気づけない落とし穴です。まんまと私ははまりました......
でもこのままDockerが監視できるのかどうかわからないのもどうかと思いますので、zabbix公式ページにおいて言及されているubuntu18.04にDockerをインストールし、docker-compose.ymlを編集して実際に動作させてみました。
ですがタイトル通りダメでした。
実際zabbixがどんなことができるかを調べるためにはdocker-composeで試したほうが早いとは思います。ただ今回のように自分のできなさにすぐたどり着いてしまうのがつらいですが......
では本題です。今回は
- VagrantでUbuntu18.04を実行する
- Dockerとdocker-composeをインストールする
- 公式のzabbix用docker-composeをpullして動かす
- zabbix-agent2 imageをdocker-composeで動かす
- Dockerを監視項目に追加して結果を確認する
という感じでやっていきます。
VagrantでUbuntu18.04を実行する
Docker for Desktopはかなり便利ですが少し特殊な挙動をしてコンテナの外の話になると途端に扱いづらくなります。たとえばDockerホストそのものにLinuxのコマンドを実行したいときなどは方法がほぼありません。
そこでVirtualboxとVagrantを使います。vagrantでOSインストールとか設定とかの手間を省きたいためです。
これらを事前にインストールしておきます。Hyper-Vを使っている場合だとVirtualboxを使えない場合があるので共存できるかできないかは適宜調査をお願いします。
virtualbox https://www.virtualbox.org/
vagrant https://www.vagrantup.com/
準備が完了したらCLIの所定のディレクトリでディレクトリを用意し、そのディレクトリに入ってからvagrant initします。
$ mkdir ubuntu18 $ cd ubuntu18 $ vagrant init作成されたvagrantfileを以下のようにします。これでubuntu18.04がインストールされ、zabbix完成後はwebブラウザで192.168.33.10にアクセスすればzabbixのweb画面を見ることができます。
Vagrant.configure("2") do |config| config.vm.box = "bento/ubuntu-18.04" config.vm.network "private_network", ip: "192.168.33.10" end完了したらvagrant upでubuntuのインストールと起動を行います。だいぶ時間がかかります。
$ vagrant up完了したらvagrant sshでubuntu内に入り、root権限に移行します。
$ vagrant ssh$ sudo su - #Dockerとdocker-composeをインストールする
楽をするため、今回はdockerの公式が用意しているというshスクリプトを使います。これもしばらく待つとdockerのバージョンが表示され完了します。
参考:最も簡単なDockerの公式セットアップ方法(CentOS/Ubuntu) https://qiita.com/zembutsu/items/bedb18e1061303e217b8
# curl -fsSL get.docker.com -o get-docker.sh # sudo sh ./get-docker.sh実行結果は以下のようになります。
# Executing docker install script, commit: [中略] + sh -c docker version Client: Docker Engine - Community Version: 19.03.9 API version: 1.40 Go version: go1.13.10 Git commit: 9d988398e7 Built: Fri May 15 00:25:18 2020 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.9 API version: 1.40 (minimum version 1.12) Go version: go1.13.10 Git commit: 9d988398e7 Built: Fri May 15 00:23:50 2020 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.2.13 GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429 runc: Version: 1.0.0-rc10 GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd docker-init: Version: 0.18.0 GitCommit: fec3683 If you would like to use Docker as a non-root user, you should now consider adding your user to the "docker" group with something like: sudo usermod -aG docker your-user Remember that you will have to log out and back in for this to take effect! WARNING: Adding a user to the "docker" group will grant the ability to run containers which can be used to obtain root privileges on the docker host. Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface for more information.次にdocker-composeをcurlでインストールします。
# sudo curl -L https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose実行権限を付与しておきます。
# sudo chmod +x /usr/local/bin/docker-composedocker-comoposeのバージョンを確認します。1.25.5となっていればよいです。
docker-compose --version # docker-compose version 1.25.5, build 8a1c60f6公式のzabbix用docker-composeをpullして動かす
では本題のzabbix公式docker-composeのファイル群をpullします。
github zabbix-docker https://github.com/zabbix/zabbix-docker
# git clone https://github.com/zabbix/zabbix-docker.gitcloneしてできたディレクトリに移動してdocker-compose.yamlを指定して起動します。今回はalpine版postgresDBのものを実行します。latestにしているのはzabbix公式がpushしているイメージをそのまま使えるようにするためです。
# cd zabbix-docker # docker-compose -f docker-compose_v3_alpine_pgsql_latest.yaml up -ddocker-compose psでコンテナが全部起動しているか確認します。db_dataはexit0してますがこれで問題ないそうです。
# docker-compose -f docker-compose_v3_alpine_pgsql_latest.yaml ps WARNING: Some services (zabbix-agent, zabbix-java-gateway, zabbix-proxy-mysql, zabbix-proxy-sqlite3, zabbix-server, zabbix-snmptraps, zabbix-web-apache-pgsql, zabbix-web-nginx-pgsql) use the 'deploy' key, which will be ignored. Compose does not support 'deploy' configuration - use `docker stack deploy` to deploy to a swarm. Name Command State Ports --------------------------------------------------------------- zabbix-docker_ sh Exit 0 db_data_mysql_ 1 zabbix-docker_ sh Exit 0 db_data_pgsql_ 1 zabbix- docker- Up docker_mysql- entrypoint.sh server_1 mysql ... zabbix-docker_ docker- Up postgres- entrypoint.sh server_1 postgres zabbix- /sbin/tini -- Up docker_zabbix- /usr/bin/doc agent_1 ... zabbix- docker- Up docker_zabbix- entrypoint.sh java-gateway_1 /usr/ ... zabbix- /sbin/tini -- Up 0.0.0.0:10071- docker_zabbix- /usr/bin/doc >10051/tcp proxy-mysql_1 ... zabbix- /sbin/tini -- Up 0.0.0.0:10061- docker_zabbix- /usr/bin/doc >10051/tcp proxy- ... sqlite3_1 zabbix- /sbin/tini -- Up 0.0.0.0:10051- docker_zabbix- /usr/bin/doc >10051/tcp server_1 ... zabbix- /usr/bin/super Up 0.0.0.0:162->1 docker_zabbix- visord -c /e 162/udp snmptraps_1 ... zabbix- docker- Up (healthy) 0.0.0.0:80->80 docker_zabbix- entrypoint.sh 80/tcp, 0.0.0. web-apache- /usr/ ... 0:443->8443/tc pgsql_1 p zabbix- docker- Up (healthy) 0.0.0.0:8081-> docker_zabbix- entrypoint.sh 8080/tcp, 0.0. web-nginx- 0.0:8443->8443 pgsql_1 /tcp root@vagrant:~/zabbix-docker#webブラウザにアクセスしてみます。
http://192.168.33.10/web画面が表示できたようです。以下の初期パスワードでログインします。
Username:Admin Password:zabbix完了すると以下の画面にたどり着きます。
Zabbix agent is not available (for 3m)とかでているのでこれだけ解消します。
左側のリボンでConfigrationを押して、hostsを選択します。
Zabbix serverのリンクをクリックします。
DNS nameをzabbix-agentと入力し、Connect toをDNSでボタンを押しておきます。終わったらUpdateボタンを押します。
終わったら2分くらい放置した後で左側リボンのMonitoringのLatest dataを押します。するとデータが入ってきていることが確認できます。これでzabbix agentから情報を取得できるようになりました。
top画面からもエラーは消えました。これで大丈夫です。
とはいえ後述するtemplateの追加でdockerを追加してもこんな感じで何も情報が入ってきません。だからagent2を用意する必要があります。
確認ができたのでいったんコンテナをdownします。downするときもこんな感じでファイル指定がいります。少々面倒ですね。
# docker-compose -f docker-compose_v3_alpine_pgsql_latest.yaml downdocker-compose up -dで動かせるようにする
upとかdownとかのコマンドが大変面倒なことになっているので先ほど使用したファイルをコピーしてそれの名前をdocker-compose.yamlにします。これでだいぶ使いやすくなります。
# cp docker-compose_v3_alpine_pgsql_latest.yaml docker-compose.yamlちゃんとファイルがいることが確認できます。
# ls | grep docker-compose.yaml docker-compose.yamlzabbix-agent2 imageをdocker-composeで動かす
出来上がったdocker-compose.yamlに追記します。
vimでもいいと思いますが私はvscodeのremote developmentを使って直に編集できるようにしています。
追記することは非常に単純で、zabbix-agentの部分をコピペします。
そのあとzabbix-agentの情報のimage:部分をzabbix/zabbix-agent2:alpine-5.0-latest、つまりdocker imageのzabbix agent2に変え、最後にpostsのホスト側を10050から10060にするだけです。
zabbix-agent2: image: zabbix/zabbix-agent2:alpine-5.0-latest ports: - "10060:10050" volumes: - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - ./zbx_env/etc/zabbix/zabbix_agentd.d:/etc/zabbix/zabbix_agentd.d:ro - ./zbx_env/var/lib/zabbix/modules:/var/lib/zabbix/modules:ro - ./zbx_env/var/lib/zabbix/enc:/var/lib/zabbix/enc:ro - ./zbx_env/var/lib/zabbix/ssh_keys:/var/lib/zabbix/ssh_keys:ro links: - zabbix-server:zabbix-server deploy: resources: limits: cpus: '0.2' memory: 128M reservations: cpus: '0.1' memory: 64M mode: global env_file: - .env_agent privileged: true pid: "host" networks: zbx_net_backend: aliases: - zabbix-agent - zabbix-agent-passive - zabbix-agent-alpine stop_grace_period: 5s labels: com.zabbix.description: "Zabbix agent" com.zabbix.company: "Zabbix LLC" com.zabbix.component: "zabbix-agentd" com.zabbix.os: "alpine"そのあとでagent1にあたるものは全部コメントアウトしておいてください。とはいえ一度agent1とagent2をコンテナで動かしていても結果に変化はありませんでした。
# zabbix-agent: # image: zabbix/zabbix-agent:alpine-5.0-latest # ports: # - "10050:10050" [中略] # labels: # com.zabbix.description: "Zabbix agent" # com.zabbix.company: "Zabbix LLC" # com.zabbix.component: "zabbix-agentd" # com.zabbix.os: "alpine"終わったらdocker-compose up -dをします。
# docker-compose up -dDockerを監視項目に追加して結果を確認する
ここからがうまくいかなかった話です。
再びconfigrationのhostsに移動し、create hostをクリックします。
hostnameは適当でよいです。DNS nameをzabbix-agent2と入力し、Connect toをDNSでボタンを押しておきます。
さらにtemplateタブを押して移動してLink new templates
行のselectを押し、Applications → Dockerと選びます。終わったらUpdateボタンを押します。
そうすればうまくいくと思ったのですが、結局ダメでした。こんな感じで待てど暮らせどデータが入ってきません。
topの画面でもこんな感じで表示されます。
にもかかわらずagent2のstatusはenabledになっています。zabbix初心者なのでこんな事象ははじめてで皆目見当がつかないです。
ここからいくらか粘ったのですがどこから情報をあさればいいのかもわからず結局終了しました。つらい。
おわりに
本当はできましたって記事にしたかったのですが結局うまくいきませんでした。申し訳ありません。
冒頭でも書きましたが一応Zabbix5.0を一から環境セットアップしてagent2そのものを動かすことはできたのでそこまでやりたい人はこの記事でお試しください。
この手順から何かすればうまくdocker監視できるかもしれないので、もしできた人がいたらコメントください。
私のこの徒労がほかの人のためになることを願ってます......
- 投稿日:2020-05-20T19:58:05+09:00
DockerでMySQLを簡易的に立ててデータインポート
環境
- Windows 10
- MySQL Workbench 8.0
- Docker Toolbox
- MySQL8.0.16
工程
- docker に MySQL を入れる
- MySQL Workbench で接続できるようにする
- SQLをインポートする
Docker machine の起動
Docker Quickstart Terminal のアプリケーションを起動する
MySQL のイメージを取得
$ docker pull mysql:8.0.16
MySQLコンテナを作成して起動
# docker ps -a で全てのコンテナ一覧 # docker ps で起動しているコンテナ一覧 # docker stop [CONTAINER ID] でコンテナ停止 # docker rm [CONTAINER ID] でコンテナ削除 $ docker run -it --name temp-mysql -e BIND-ADDRESS=0.0.0.0 -e MYSQL_ROOT_PASSWORD=mysql -p 3306:3306 -d mysql:8.0.16 # 一度作成したら docker start temp-mysql で起動できるMySQLコンテナに接続
$ docker exec -it temp-mysql bashMySQLに接続
$ mysql -u root -p -h 127.0.0.1 ※終わったら MySQL を exit、コンテナも exit外部IPを確認
$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS default * virtualbox Running tcp://192.168.99.100:2376 v19.03.5 local-by-flywheel - virtualbox Stopped UnknownMySQL Workbench から MySQL に接続
※MySQL Workbench は新しいバージョンをインストールしておくこと
接続情報
HOST ACCOUNT PASS PORT 192.168.99.100 root mysql 3306 SQLをインポートするデータベースを作成
CREATE DATABASE `{database_name}`;SQLをインポート
- MySQL Workbench を起動して MySQL に接続する
Navigator(左メニュー)
のタブをAdministration
からSchemas
に切り替える- 作成したデータベースを選択
- 上メニューの
Server
でData Import
を選択
Import from Self-Contained File
のラジオボタンを選択- インポートしたいファイルを選択
Default Traget Schema
でインポート先のShema
を選択Start Import
ボタンをクリック
- 投稿日:2020-05-20T19:00:42+09:00
actix-webのホットリロードされるDocker開発環境を作る
はじめに
本記事では表題の通り、actix-webの開発環境について検討します。
actix-webはRust製のweb frameworkで、LL製の有名フレームワークより高速に動作することで知られています。
https://www.techempower.com/benchmarks/一方で、修正を確認するためには都度コンパイルをする必要があり、RubyやPythonのような軽量言語に比べると開発効率が下がるのでは、という懸念があるかと思います。
(実際には型安全でコンパイラのチェックが優秀なRustは結果として開発効率が良い可能性もありますが。)そこで、本記事ではLL製の有名フレームワークと同等の効率でRust製のAPI Serverを開発するための環境を構築する方法を検討します。
理想の開発環境
現代のWebアプリ開発はコンテナベースで行われることが多いかと思います。
そこで、本記事では
docker-compose up
とか打ったら開発環境が動く- 開発用と本番用のDockerfileが共通になっており、本番用のイメージが小さい
- 修正がすぐに確認できる
のような条件を満たす開発環境を目指します。
想定する構成
本記事では、Vue.jsで作られたSPAのフロントエンドからactix-webで作られたAPI Serverへリクエストする構成を考えます。
本記事の主な対象ではないのですが、DBにはPostgreSQLを想定しています。
- フロントエンド:Vue.js
- バックエンド:actix-web
- DB:PostgreSQL
本題
本記事ではRustに関係する部分のみを紹介します。
上記構成を作る全体像が必要であれば、成果物のリポジトリをご参照ください。Dockerfile
Dockerfileの作成にはDockerfileを改善するためのBest Practice 2019年版を非常に参考にしています。
まず、マルチステージビルド機能を使用して開発用のステージとビルド用、本番用のステージを分けています。本番用には開発用に比べて軽量なベースイメージを使用しており、例えばFargateなどにデプロイする際にかかる時間を減らしています。
なお、今回は本番用のベースイメージに
rust:1.43.1-slim-stretch
を使用していますが、開発環境は不要なのでもっと小さなイメージを使用することが可能です。
ベースイメージについては以下のリンクが参考になります。
参考:RustのLinux muslターゲット (その2:極小Dockerイメージを実現)Dockerfile# 開発環境 FROM rust:1.43.1 as develop-stage WORKDIR /app RUN cargo install cargo-watch COPY . . # ビルド環境 FROM develop-stage as build-stage RUN cargo build --release # 本番環境 FROM rust:1.43.1-slim-stretch COPY --from=build-stage /app/target/release/api . EXPOSE 8088 CMD ["/usr/local/bin/api"]ちなみに、このDockerfileと同じパスに
.dockerignoretargetというファイルを置いています。
これは本番用のイメージをビルドする際に、COPY . .
で時間をかけないようにする意図があります。docker-compose.yml
以下のyamlはRust部分のみを抽出したdocker-compose.ymlです。
build
には先ほどのDockerfileを指定し、target
には開発用のステージを指定します。また、中間ファイルのディレクトリをキャッシュすることで
docker-compose up
するたびに不要なビルドが実行されることを回避しています。commandには
cargo watch -x run
を指定しており、これによってホットリローディングを実現しています。
なお、actix-webのドキュメントにはAuto-Reloading Development Serverという項目が存在するのですが、ここで紹介されているsystemfd
がsystemd
を必要としており、docker上で動かすのが難しいと思い断念しています。
cargo watch
では修正するたびにプロセスを再実行するのだと思いますが、ステートレスなAPI Serverを開発する分には影響が少ないと判断しています。docker-compose.ymlversion: '3.7' services: backend: build: context: ./backend target: 'develop-stage' ports: - "8088:8088" depends_on: - db volumes: - ./backend:/app - cargo-cache:/usr/local/cargo/registry - target-cache:/app/target command: /bin/sh -c "cargo watch -x run" volumes: cargo-cache: target-cache:成果物
上記構成で作られた開発環境のサンプルは以下の通りです。
本記事では紹介しなかったフロントエンドのDockerfileなども含まれます。https://gitlab.com/yamamoto_kazumasa/docker-actix-web
まとめ
API Serverの開発には十分なactix-webの開発環境を構築することが出来ました。
修正するたびにコンパイルする状況に比べれば良い環境ではないかと思います。今回は開発時の構成にのみ着目しましたが、実際の開発ではユニットテストの実行やCI/CDの考慮が必要だと思います。
その場合には、本記事で紹介したDockerfileに適切にステージを追加することで必要なイメージを効率よく作ることができると思います。将来的には開発の全体をカバーしたサンプルプロジェクトを作れたらと考えています。
- 投稿日:2020-05-20T17:44:02+09:00
docker-machineコマンドをインストール
ちょいメモです
悩み
PhpStormを使っていて
docker-machine
コマンドへのパスを設定しようと思ったら、
肝心のdocker-machine
コマンドがどこにも無い!原因
最近のバージョンである Docker Desktop インストーラには付属しなくなったそうです。
解決方法
docker-machine
コマンドを単体インストールすればよいそうです。
https://github.com/docker/machine/releasesWindowsの場合
一発インストールコマンドが掲載されていますが、環境によって動かない場合もあるので、手動インストールする方法をば。
exeをダウンロードする。
https://github.com/docker/machine/releases/download/v0.16.2/docker-machine-Windows-x86_64.exe
(URL中の /v0.16.2/ は執筆当時のものです。適宜読み替えてください。)exeをDocker Desktop の bin フォルダにコピーする。
デフォルトだと↓かと思います。
C:\Program Files\Docker\Docker\resources\bin違ったら探してね。
exeの名前を
docker-machine.exe
に変える。以上!
- 投稿日:2020-05-20T13:37:43+09:00
Windows10 に PHP7+Laravel環境をDockerで構築
概要
掲題のとおり「Windows10 に PHP7+Laravel環境をDockerで構築」を、
↓こちらの神記事を参考に、初心者向けに解説していきます。「どうしてそういう設定を施すのか?」といったことは元記事が丁寧に説明して下さっているので、ここではとにかくローカルPC内にLaravelサーバを立ち上げるまでの手続きを駆け足でご紹介すると共に、Windows10でやると行きづまる所を補足しています。
私が試した環境
- Windows10 Pro 64bit版
- Docker Desktop for Windows - 2.3.0.2 (今回の手順中でインストールします)
- Git for Windows - 2.25.0.windows.1 (今回の手順中でインストールします)
- Make for Windows - 3.81 (今回の手順中でインストールします)
下準備編
いくつかのソフトウェアが必要なので、ダウンロード&インストールしましょう。
Docker, docker-compose(Docker Desktop for Windows)
↓こちらをご参考に。
※ ↑の記事内に記載していますが、Windows10のエディションやパソコンのCPUによる条件がありますので、ご注意下さい。
Git, Git-Bash(Git for Windows)
↓こちらからダウンロードしてインストールしましょう。
https://gitforwindows.org/Git for Windows を入れれば Git-Bash も一緒に入ります。
make for Windows
元記事では
make
コマンドを使用されているので必要です。
(複雑なコマンドをショートカットのようにまとめるのに使用されています。)↓こちらからダウンロードしてインストールしましょう。
http://gnuwin32.sourceforge.net/packages/make.htmmakeコマンドがあるフォルダを環境変数
PATH
に追加しておく。どこからでも
make
コマンドを打てるようにしておきましょう。
手順は割愛しますが、代わりに↓こちらの記事を紹介させていただきます。makeコマンドがあるフォルダの場所は、デフォルトのインストール設定では↓です。
C:\Program Files (x86)\GnuWin32\binmake for Windows をインストールするときにインストール先フォルダをカスタマイズした場合は、↑を参考に探してみてください。
一部コマンドをwinpty経由で実行するよう設定する。
Gitインストール時、オプション
Use MinTTY
をONにした場合、この設定作業が必要です。
- Windowsにログオンしているユーザーのホームフォルダ(例:
C:\Users\山田太郎
)の中に.bashrc
という名前のテキストファイルを作ります。(すでに存在する場合は不要です。).bashrc
の中身に↓を追記して保存します。alias docker='winpty docker' alias docker-compose='winpty docker-compose' alias make='winpty make'Git-Bashに慣れている方は、vimコマンドなどで作業してももちろんOKです!
※ winptyは、Windowsへのコマンド指示をLinuxっぽいインターフェースでできるようにするラッパー的なソフトです。
ここでは、docker
、docker-compose
、make
コマンドだけ、自動的にwinpty経由で実行するよう設定をしています。
これをしないと、dockerコンテナの中に入って作業する系のコマンドが↓のようなエラーで失敗します。$ docker-compose exec app composer create-project --prefer-dist laravel/laravel . the input device is not a TTY. If you are using mintty, try prefixing the command with 'winpty'また
make
の中で実行されるコマンドもwinpty経由で実行させるにはmake
自体をwinpty経由で実行しなければダメなので、3行目でそのように設定しています。構築編
こちらは駆け足でザッと参ります。
一通り完了したら、ぜひ元記事も読んでみてください。Git-Bashを起動する。
適当なフォルダを作って移動する。
ソースコードをダウンロードして色々やるので、万が一汚れても大丈夫なフォルダを作ってそこで作業しましょう。
ここでは例として、Cドライブ直下にtempというフォルダを作ってそこに移動してます。cd /c mkdir temp cd temp元記事で公開されているソースコード一式をダウンロードする。
githubに公開されているので、gitコマンドを使ってダウンロードします。
git clone git://github.com/ucan-lab/docker-laravel.gitgithubアカウントを持ってなくてもダウンロードできるはず…
もし途中でkeyがうんたらと英語で質問が表示されたら、yes
と入力してリターンキー押しておけばOK!
make
コマンド向け設定ファイルが存在するフォルダに移動する。cd docker-laravel/infrastructure
LaravelサンプルWEBサイトを新規作成するコマンドを実行する。
make create-project数分かかるかも。
ずらーっと流れるログが↓のようになって止まったらOK。・ ・ ・ Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully. 32 packages you are using are looking for funding. Use the `composer fund` command to find out more! XXXXXX@XXXXX MINGW64 /c/temp/docker-laravel/infrastructure $LaravelサンプルWEBサイトにアクセスしてみる。
↓をWEBブラウザで開いてみてください。
http://127.0.0.1これはLaravelフレームワークを使って作られているサンプルWEBページで、それを動かすためのWEBサーバが自分のPC内で起動している証です。
お疲れ様でした。
この記事では端折った部分もあるので、ぜひ元記事も一読してみてください。
- 投稿日:2020-05-20T12:03:17+09:00
Docker ComposeでWordpressを起動してみた
docker-compose.ymlを作るだけだった。。。
ファイルリファレンスdocker-compose.ymlversion: '3.8' services: db: image: mysql:5.7 volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: somewordpress MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress wordpress: depends_on: - db image: wordpress:latest ports: - "8000:80" volumes: - ./html:/var/www/html restart: always environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_NAME: wordpress volumes: db_data: {}docker-composeコマンド
docker-compose.ymlを作成したディレクトリで実行する。
コマンドリファレンス作成と起動
コンテナの作成と起動。
$ docker-compose up -dブラウザで
http://localhost:8000
を開く停止
コンテナの停止。(削除しない)
$ docker-compose stop
起動
停止しているdbとwordpressコンテナを起動。
$ docker-compose start db wordpress
ブラウザで
http://localhost:8000/wp-admin
を開く停止と削除
コンテナの停止と削除。
$ docker-compose down --volumesコンテナ一覧
コンテナ一覧を表示したいときに。
$ docker-compose ps
イメージ一覧
イメージ一覧を表示したいときに。
$ docker-compose images
コマンド実行
wordpressコンテナで
ls -l
コマンドを実行。$ docker-compose exec wordpress ls -lGithub
- 投稿日:2020-05-20T07:50:10+09:00
Docker × swagger × Basic認証 をherokuにデプロイする
はじめに
関わっているスタートアップではAPIの調整をswaggerを用いて行なっているのですが、swagger uiに毎回ログインするのはめんどくさすぎるので、herokuにデプロイしてそちらを使うことにしました。
その際に認証なしはまずいのでbasic認証をかけていますソースコード
まずは構成から、、、
とは言っても大したことはありません. ├── Dockerfile ├── heroku.yml └── swagger.ymlDockerfileFROM swaggerapi/swagger-ui # ローカルで作成したswagger.ymlをdocker内のsample.yamlにコピー COPY ./swagger.yml /usr/share/nginx/html/sample.yaml # デフォルトで表示する内容をコピーしたものにするように環境変数を修正 ENV API_URL=sample.yaml # Basic認証 # Basic認証を使うためのパッケージをインストール RUN apk add apache2-utils ARG USERNAME=username ARG PASSWORD=password # 暗号化して`/etc/nginx/.htpasswd`に書き出している RUN htpasswd -c -b /etc/nginx/.htpasswd ${USERNAME} ${PASSWORD} && cat /etc/nginx/.htpasswd # `/etc/nginx/nginx.conf` に # auth_basic "Restricted Content"; # auth_basic_user_file /etc/nginx/.htpasswd; # の2行を加筆する RUN sed -i "s|location / {|location / {\n\tauth_basic \"Restricted Content\";\n\tauth_basic_user_file /etc/nginx/.htpasswd;\n|g" /etc/nginx/nginx.confheroku.ymlbuild: docker: web: Dockerfileherokuでdockerを動かすためのファイル
herokuのためのdocker-composeみたいなイメージです
※参考: https://devcenter.heroku.com/articles/build-docker-images-heroku-ymlherokuの設定
ターミナルheroku login heroku container:login heroku create 任意のアプリケーション名 heroku container:push web heroku container:release web heroku open
適切にデプロイされていることを確認
※参考:https://devcenter.heroku.com/articles/container-registry-and-runtimeCI/CD
gitにpushされた時に自動でデプロイさせる
1, herokuダッシュボードにいき該当のアプリケーションの詳細ページへ
2, 「deploy」を選択
4, 自動デプロイするブランチを選択し「Enable Automatic Deploys」を選択
5, masterにpush後herokuの「Activity」内で
Build succeeded
とかって文字があれば設定は完了です。まとめ
個人的に一番辛かったのがどうやってswaggerにbasic認証をかけるか?
ってところです笑
まあ、蓋を開けてみれば別に大したことしなくても動いてくれたのでとりあえずいいかな〜と、、、
なんか本当はもうちょっといいやり方ありそうな気がするので他にやり方知っている方いれば教えてください汗
- 投稿日:2020-05-20T00:00:03+09:00
【初心者向け】Firebaseでチャットアプリを開発(codelabs)
今更感もありますが、、サーバレスアプリ開発の勉強の為にFirebaseを用いて簡単なチャットアプリを作成しました。
Firebaseについて
Firebaseは、高品質のアプリを迅速に開発できるGoogle のmBaaSです。
今回は主要な機能である下記を使用します。
- Firebase Authentication : アプリへのログイン機能を提供
- Cloud Firestore : 構造化データを保存し、変更時に即座に通知を受け取ることが出来る
- Cloud Storage : クラウドにファイルを保存する
- Firebase Hosting : ホスティングする
- Firebase Cloud Messaging :プッシュ通知を送信する
- Firebase Performance Monitoring : アプリのパフォーマンスデータを収集する
開発環境
- Windows10
- Docker (DockerDesktop for windows(2.2.0.5))
完成イメージ
チャットアプリ開発
1. 環境構築
- codelabsのリポジトリから、ローカルへソースをコピーしてくる
- Firebaseのconsoleよりwebアプリを作成
- [プロジェクトの作成]を行う(プロジェクト名とGoogleアナリティクス有効は任意)
- </>(webアプリにFirebaseを追加)を行う(アプリ名は任意、FirebaseHostingの設定はONにする)
- 下記Dockerfileとdocker-compose.ymlをローカルソースのRootへ配置し、
docker-compose up -d --build
コマンドで開発環境コンテナを作成するDockerfileDockerfile FROM node:10.19-alpine WORKDIR /app RUN npm install -g firebase-tools RUN apk add curl ENV HOST 0.0.0.0 EXPOSE 5000 EXPOSE 9005docker-compose.ymlversion: '3' services: node: container_name: node build: ./ tty: true volumes: - ./:/app ports: - 5000:5000 - 9005:90052. FirebaseCLI設定
- 作成したコンテナ内にFirebaseCLIをインストールする
docker exec -it node ash
でコンテナ内へnpm -g install firebase-tools
よりインストール実施firebase --version
が返ってくればインストール成功- FirebaseCLIへユーザー認証する
firebase login
と打つとURL(ttps://accounts.google.com/o/oauth2/auth...)が表示されるので、ブラウザで表示されたURLへ移動- Googleの認証画面が表示されるので、画面に従い認証を通す
cd /app/web-start/
でweb-startディレクトリへ移動firebase use --add
にてアプリとFirebaseを関連付けする(Project IDは前手順のものを選択、aliasは無くてOK)firebase serve -o "0.0.0.0" --only hosting
にてローカル上でのアプリ起動hosting: Local server: http://localhost:5000
と表示されれば起動- ブラウザより http://localhost:5000 を起動し、下記画面が表示されるか確認
3. 機能実装
- Firebaseのconsoleより、下記設定を行う
- 「開発>Authentication」、「sign-in method」からGoogleログインを有効にする
- 「開発>Database」、CloudFirestoreのCreate Databaseを行う([Start in test mode]を選択し、locationは任意選択)
- 「開発>Storage」、「始める」からCloud Storageを作成する(locationは任意選択)
web-start/public/index.html
内にFirebaseSDKとSDK構成用のscriptの記載があるか確認web-start/public/scripts/main.js
内のfunctionを下記記載の通りに書き換える参考)
https://firebase.google.com/docs/reference/js/firebase.auth.Auth
https://firebase.google.com/docs/reference/js/firebase.firestore
https://firebase.google.com/docs/reference/js/firebase.storage
#messagesのデータモデル図
index.html<script src="/__/firebase/X.X.X/firebase-app.js"></script> <script src="/__/firebase/X.X.X/firebase-auth.js"></script> <script src="/__/firebase/X.X.X/firebase-storage.js"></script> <script src="/__/firebase/X.X.X/firebase-messaging.js"></script> <script src="/__/firebase/X.X.X/firebase-firestore.js"></script> <script src="/__/firebase/X.X.X/firebase-performance.js"></script> <script src="/__/firebase/init.js"></script> <script src="scripts/main.js"></script>main.js// Signs-in Friendly Chat. function signIn() { var provider = new firebase.auth.GoogleAuthProvider(); firebase.auth().signInWithPopup(provider); } // Signs-out of Friendly Chat. function signOut() { firebase.auth().signOut(); } // Initiate firebase auth. function initFirebaseAuth() { firebase.auth().onAuthStateChanged(authStateObserver); } // Returns the signed-in user's profile Pic URL. function getProfilePicUrl() { return firebase.auth().currentUser.photoURL || '/image/profile_placeholder.png'; } // Returns the signed-in user's display name. function getUserName() { return firebase.auth().currentUser.displayName; } // Returns true if a user is signed-in. function isUserSignedIn() { return !!firebase.auth().currentUser; } // Saves a new message on the Firebase DB. function saveMessage(messageText) { return firebase.firestore().collection('messages').add({ name: getUserName(), text: messageText, profilePicUrl: getProfilePicUrl(), timestamp: firebase.firestore.FieldValue.serverTimestamp() }).catch(function(error) { console.error('Error writing new message to database', error); }); } // Loads chat messages history and listens for upcoming ones. function loadMessages() { // create the query to load the last 12 messages and listen for new ones. var query = firebase.firestore() .collection('messages') .orderBy('timestamp', 'desc') .limit(12); // start listening to the query. query.onSnapshot(function(snapshot) { snapshot.docChanges().forEach(function(change) { if (change.type === 'removed') { deleteMessage(change.doc.id); } else { var message = change.doc.data(); displayMessage(change.doc.id, message.timestamp, message.name, message.text, message.profilePicUrl, message.imageUrl); } }) }) } // Saves a new message containing an image in Firebase. // This first saves the image in Firebase storage. function saveImageMessage(file) { // 1 - We add a message with a loading icon that will get updated with the shared image. firebase.firestore().collection('messages').add({ name: getUserName(), imageUrl: LOADING_IMAGE_URL, profilePicUrl: getProfilePicUrl(), timestamp: firebase.firestore.FieldValue.serverTimestamp() }).then(function(messageRef) { // 2 - Upload the image to Cloud Storage. var filePath = firebase.auth().currentUser.uid + '/' + messageRef.id + '/' + file.name; return firebase.storage().ref(filePath).put(file).then(function(fileSnapshot) { // 3 - Generate a public URL for the file. return fileSnapshot.ref.getDownloadURL().then((url) => { // 4 - Update the chat message placeholder with the image's URL. return messageRef.update({ imageUrl: url, storageUri: fileSnapshot.metadata.fullPath }); }); }); }).catch(function(error) { console.error('There was as error uploading a file to Cloud Storage:', error); }); }4. 通知の表示
web-start/public/manifest.json
を下記記載の通りに書き換えるweb-start/public/firebase-messaging-sw.js
を作成し、下記内容を記載するweb-start/public/scripts/main.js
のfunctionsaveMessagingDeviceToken
を下記内容で実装する- ここまで出来たら、下記の手順にて通知が表示されることが確認できる
- コンテナ内で
firebase serve -o "0.0.0.0" --only hosting
よりアプリ起動- http://localhost:5000 へアクセスし、通知の許可を求められるので「許可」にする
- ブラウザからjavascriptのconsoleを開き、
Got FCM device token
の値を控える- FirebaseのconsoleよりCloud Messagingを開きサーバーキーを控える
- 下記記載のcurlコマンドの
YOUR_DEVICE_TOKEN
を上記3、YOUR_SERVER_KEY
を上記4で控えた内容に置換る- 作成したcurlコンテナ内で実行することでブラウザに表示中のチャットアプリから通知が表示される
manifest.json{ "name": "Friendly Chat", "short_name": "Friendly Chat", "start_url": "/index.html", "display": "standalone", "orientation": "portrait", "gcm_sender_id": "103953800507" }firebase-messaging-sw.jsimportScripts('/__/firebase/6.0.4/firebase-app.js'); importScripts('/__/firebase/6.0.4/firebase-messaging.js'); importScripts('/__/firebase/init.js'); firebase.messaging();main.js// Saves the messaging device token to the datastore. function saveMessagingDeviceToken() { firebase.messaging().getToken().then(function(currentToken) { if (currentToken) { console.log('Got FCM device token:', currentToken); // Saving the Device Token to the datastore. firebase.firestore().collection('fcmTokens').doc(currentToken) .set({uid: firebase.auth().currentUser.uid}); } else { // Need to request permissions to show notifications. requestNotificationsPermissions(); } }).catch(function(error){ console.error('Unable to get messaging token.', error); }); } // Requests permissions to show notifications. function requestNotificationsPermissions() { console.log('Requesting notifications permission...'); firebase.messaging().requestPermission().then(function() { // Notification permission granted. saveMessagingDeviceToken(); }).catch(function(error) { console.error('Unable to get permission to notify.', error); }); }参考)https://firebase.google.com/docs/reference/js/firebase.messaging
curlcurl -H "Content-Type: application/json" \ -H "Authorization: key=YOUR_SERVER_KEY" \ -d '{ "notification": { "title": "New chat message!", "body": "There is a new message in FriendlyChat", "icon": "/images/profile_placeholder.png", "click_action": "http://localhost:5000" }, "to": "YOUR_DEVICE_TOKEN" }' \ https://fcm.googleapis.com/fcm/send5. セキュリティルール
web-start/firestore.rules
を作成し、下記内容を記載するweb-start/storage.rules
を作成し、下記内容を記載するweb-start/firebase.json
へ、下記追記する- コンテナ内で
firebase deploy --only storage,firestore
コマンドにより作成したセキュリティルールをデプロイするfirestore.rulesservice cloud.firestore { match /databases/{database}/documents { // Messages: // - Anyone can read. // - Authenticated users can add and edit messages. // - Validation: Check name is same as auth token and text length below 300 char or that imageUrl is a URL. // - Deletes are not allowed. match /messages/{messageId} { allow read; allow create, update: if request.auth != null && request.resource.data.name == request.auth.token.name && (request.resource.data.text is string && request.resource.data.text.size() <= 300 || request.resource.data.imageUrl is string && request.resource.data.imageUrl.matches('https?://.*')); allow delete: if false; } // FCM Tokens: // - Anyone can write their token. // - Reading list of tokens is not allowed. match /fcmTokens/{token} { allow read: if false; allow write; } } }参考) https://firebase.google.com/docs/firestore/security/overview
storage.rules// Returns true if the uploaded file is an image and its size is below the given number of MB. function isImageBelowMaxSize(maxSizeMB) { return request.resource.size < maxSizeMB * 1024 * 1024 && request.resource.contentType.matches('image/.*'); } service firebase.storage { match /b/{bucket}/o { match /{userId}/{messageId}/{fileName} { allow write: if request.auth != null && request.auth.uid == userId && isImageBelowMaxSize(5); allow read; } } }参考)https://firebase.google.com/docs/storage/security/start
firebase.json{ //Add this "firestore": { "rules": "firestore.rules" }, //Add this "storage": { "rules": "storage.rules" }, "hosting": { ... } }6. パフォーマンス測定
web-start/public/index.html
に下記内容があるか確認web-start/public/scripts/main.js
に下記を追記- FID計測する場合は、
web-start/public/index.html
へ下記追記- Firebaseのconsoleからパフォーマンスを確認することが可能となる
index.html<script src="/__/firebase/X.X.X/firebase-performance.js"></script> <script src="/__/firebase/init.js"></script>main.jsfirebase.performance();index.html(EnableFID)<script type="text/javascript">!function(n,e){var t,o,i,c=[],f={passive:!0,capture:!0},r=new Date,a="pointerup",u="pointercancel";function p(n,c){t||(t=c,o=n,i=new Date,w(e),s())}function s(){o>=0&&o<i-r&&(c.forEach(function(n){n(o,t)}),c=[])}function l(t){if(t.cancelable){var o=(t.timeStamp>1e12?new Date:performance.now())-t.timeStamp;"pointerdown"==t.type?function(t,o){function i(){p(t,o),r()}function c(){r()}function r(){e(a,i,f),e(u,c,f)}n(a,i,f),n(u,c,f)}(o,t):p(o,t)}}function w(n){["click","mousedown","keydown","touchstart","pointerdown"].forEach(function(e){n(e,l,f)})}w(n),self.perfMetrics=self.perfMetrics||{},self.perfMetrics.onFirstInputDelay=function(n){c.push(n),s()}}(addEventListener,removeEventListener);</script>7. デプロイ
/web-start/firebase.json
へdepoyするローカルファイルを指定するfirebase deploy --except functions
コマンドにてFirebaseHostingへdeployするDeploy complete!
との表示されれば完了(URLはHosting URL: https://xxxx
)firebase.json{ "firestore": { "rules": "firestore.rules" }, "storage": { "rules": "storage.rules" }, "hosting": { "public": "./public" } }最後に
上記はGoogleの提供するcodelabを元に構築しました。
取り敢えずチャットアプリを作成する部分のみを抜粋して記載しております為、より深くFirebaseについて知りたい方は参考元 (Firebase web codelab) をご覧いただければと思います。また、色々と独学で進めている部分が多い為、上記記事でおかしな点あればやさしくコメント頂けると幸いです。