Elixir Mix.Configで環境毎にConfigを使い分ける
開発環境により使用するConfigを使い分ける。
流れとしては、Mix.Configにimport宣言を追加し環境ごとのConfigファイルを作成する。
コンパイル時、環境変数を設定しConfigを使い分ける。
Mix.Configの修正
Mix.Config – Mix v1.4.5
import_config "#{Mix.env}.exs"
宣言を追加する。
以下config/config.exs
。
use Mix.Config import_config "#{Mix.env}.exs" config :stock_scraping, ecto_repos: [StockScrapingBatch.Repo]
Configファイル追加
dev.exs
prod.exs
を追加する。
以下config/dev.exs
。
use Mix.Config config :stock_scraping_batch, StockScrapingBatch.Repo, adapter: Ecto.Adapters.MySQL, database: "stock_scraping", username: "ytoida", password: "", hostname: "127.0.0.1", port: 3306
環境変数を設定しコンパイルする
DockerfileにENTRYPOINTを定義し、引数で環境変数を渡すようにした。
以下Dockerfile
。
FROM elixir MAINTAINER yuki-toida RUN git clone https://github.com/yuki-toida/stock_scraping_batch.git root/stock_scraping_batch WORKDIR /root/stock_scraping_batch RUN mix local.hex --force && \ mix local.rebar --force && \ mix hex.info RUN chmod +x run.sh ENTRYPOINT ["./run.sh"] CMD ["dev"]
以下run.sh
。
#!/bin/bash # git pull git pull origin master # create executable shell script mix deps.get MIX_ENV=$1 mix escript.build # execute ./stock_scraping_batch
これで引数無しでdocker run
した場合はdev環境。
prod環境にしたい場合は、docker run --net="host" [イメージ名] prod
で引数に指定する。
DockerコンテナからDockerホストMySQLに接続する
スッとMySQLに繋げなかったのでちょっと調べた。
- Dockerネットワークの種類
- Dockerコンテナ起動時にオプションでネットワークを指定する
- MySQLユーザーのHostを書き換える
- アプリケーションからのMySQL接続ホストを127.0.0.1にする
- Dockerコンテナ起動
Dockerネットワークの種類
Docker コンテナ・ネットワークの理解 — Docker-docs-ja 1.13.RC ドキュメント
ここを見ながら概要をつかむ。
Dockerインストール時、3つのネットワークが作成される。
$ docker network ls NETWORK ID NAME DRIVER SCOPE d1dbc2003e68 bridge bridge local c16c847feff0 host host local 27dc4c232fed none null local
Dockerコンテナ起動時にオプションでネットワークを指定する
指定しないとデフォルトのbridge
が適用される。
それだと、Dockerコンテナに割り当てられたIPをMySQLがリッスンする必要があり、
my.cnf
にbind-address=<DockerコンテナIP>
を指定する必要がある。
めんどくさいので、host
を指定する。
ホストネットワークは、DockerコンテナにDockerホストのネットワークスタックを共有する設定。
MySQLユーザーのHostを書き換える
Dockerコンテナからlocalhostへの接続は出来ないため、127.0.0.1
でアクセスする。
よって、MySQLユーザーのHostを変更する。
rename user 'ytoida'@'localhost' to 'ytoida'@'127.0.0.1';
変更されたか確認する。
select User, Host from mysql.user;
アプリケーションからのMySQL接続ホストを127.0.0.1にする
config/config.exs
を修正する。
config :stock_scraping_batch, StockScrapingBatch.Repo, adapter: Ecto.Adapters.MySQL, database: "stock_scraping", username: "ytoida", password: "", hostname: "127.0.0.1", port: 3306
Dockerコンテナ起動
ネットワークオプションをhost
にして起動する。
docker run --rm --net="host" yukitoida/stock_scraping_batch
実際のDockerfile
の中身は以下。
FROM elixir MAINTAINER yuki-toida RUN git clone https://github.com/yuki-toida/stock_scraping_batch.git root/stock_scraping_batch WORKDIR /root/stock_scraping_batch RUN mix local.hex --force && \ mix local.rebar --force && \ mix hex.info RUN chmod +x run.sh CMD ["./run.sh"]
run.sh
の中身は以下。
#!/bin/bash # git pull git pull origin master # create executable shell script mix deps.get mix escript.build # execute ./stock_scraping_batch
Dockerfileを作成し、DockerHubで自動ビルドを行う
早速Dockerfileを作成していく。
公式 elixir Dockerイメージを使う
https://hub.docker.com/_/elixir/
OSは、16.04.1-Ubuntu だった、サイズが大きいので最適化したほうがいい。
FROM elixir MAINTAINER yuki-toida RUN git clone https://github.com/yuki-toida/stock_scraping_batch.git root/stock_scraping_batch WORKDIR /root/stock_scraping_batch RUN mix local.hex --force && \ mix local.rebar --force && \ mix hex.info RUN chmod +x run.sh CMD ["./run.sh"]
この数行に何時間かかったんだろうか。。。
Dockerfileの文法を学ぶのと、デバッグ(build)に時間がかかることで手間取った。
Dockerfile リファレンス — Docker-docs-ja 1.13.RC ドキュメント
DockerHub 自動ビルド
githubにプッシュすると、DockerHub検知してが自動でビルドをしてくれる。
Build Detail タブに現在のステータスが表示される(動作確認済み)。
前回記事参照。
こちらがGitHubリポジトリ。
GitHub - yuki-toida/stock_scraping_batch
こちらがDockerHubリポジトリ。
https://hub.docker.com/r/yukitoida/stock_scraping_batch/
DockerHub からイメージをプルし実行
DockerHubからプルしてくる。
docker pull yukitoida/stock_scraping_batch
実行する。
docker run --rm -it yukitoida/stock_scraping_batch
Tips
dockerコンテナ全削除コマンド。
docker rm -f `docker ps -a -q`
dockerイメージ全削除コマンド。
docker rmi -f `docker images -q`
Dockerをインストール(Ubuntu)しGitHubと連携
パッケージインストール
apt-getでDockerのインストールに必要なパッケージをインストール。
sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ software-properties-common
Docker公式GPG鍵追加
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
DockerのPPA追加
sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable"
Docker CE インストール
sudo apt-get update sudo apt-get install docker-ce
sudo docker version
でversion確認すると↓のような出力。
Client: Version: 17.03.1-ce API version: 1.27 Go version: go1.7.5 Git commit: c6d412e Built: Mon Mar 27 17:14:09 2017 OS/Arch: linux/amd64 Server: Version: 17.03.1-ce API version: 1.27 (minimum version 1.12) Go version: go1.7.5 Git commit: c6d412e Built: Mon Mar 27 17:14:09 2017 OS/Arch: linux/amd64 Experimental: false
sudo 無しで docker を実行する
docker グループにユーザーを追加すればいい。
docker グループ存在確認。
cat /etc/group | grep docker
存在しなければ、作成。
sudo groupadd docker
現在のユーザーをdockerグループに追加する。
sudo gpasswd -a $USER docker
docker 再起動すればsudoなしでdockerコマンドを実行できる。
もし、permission deniedという警告が出たら下記実行。
sudo chown "$USER":"$USER" /home/"$USER"/.docker -R sudo chmod g+rwx "/home/$USER/.docker" -R
docker-compose インストール
Releases · docker/compose · GitHub
ここで最新バージョンを確認し、下記実行。
sudo -i curl -L "https://github.com/docker/compose/releases/download/1.14.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
バージョンを確認して完了。
docker-compose version
Docker Hub に登録して GitHubと連携させる
https://hub.docker.com/
Docker Hubにアカウントを新規作成し、DockerfileのAutomated Buildを設定する。
Automated Buildとは、Dockerイメージの元となるDockerfileをDocker Hubのビルドクラスターに読み込ませ、
Dockerイメージを作成、Docker Hubリポジトリで公開する仕組み。
これで対象のGitHubリポジトリが更新されたら自動でDockerイメージが作成される。
いまさら聞けないDocker入門(終):Docker Hubの使い方とGitHubからのDockerイメージ自動ビルド (2/2) - @IT
Dockerfile
力尽きたので次回。
Dockerでの環境構築が整ったら、EC2にデプロイする。
UbuntuでgitをセットアップしGitHubにプッシュする
さくっとGitHubにプッシュする。
最新のGitを使えるようにする
Ubuntuで最新のGitを使用できるようにするために、
git ppa
をリポジトリに追加する。
$ sudo add-apt-repository ppa:git-core/ppa $ sudo apt-get update $ sudo apt-get upgrade
これで最新のGitを使えるようになる。
Git Config設定
Gitの初期設定を行う。
git config --global user.name "YukiToida" git config --global user.email "y.toidax@gmail.com"
Config確認。
git config --list
user.name=YukiToida user.email=y.toidax@gmail.com
と表示されればおk。
SSH Key 作成
ssh-keygen
./ssh/id_rsa.pub
が作成されるので github に登録する。
GitHubへプッシュ
いつも先にブラウザからリポジトリを作成してcloneする方法をとっている。
.gitignore の追加とか楽なので。
対象フォルダにcloneする。
git clone git@github.com:yuki-toida/stock_scraping.git
add して commit して push する。
git add . git commit -m "initial commit" git push -u origin master
Elixir - Phoenixで株価を表示する(後編)
前回の続き。
今回は、Volume(日別出来高ランキング)
ページを実装する。
VolumeController
引数に受けた文字列をDate
にキャストする。
その値を使いDBからデータを取得する。
ポイントは where句ではピン演算子
を使うこと。
んでそのままテンプレートに@items
として渡す。
web/controllers/volume_controller.ex
が以下。
defmodule StockScraping.VolumeController do use StockScraping.Web, :controller def index(conn, %{"date" => date}) do target_date = case Date.from_iso8601(date) do {:ok, value} -> value end items = StockScraping.YahooVolume |> where(date: ^target_date) |> Repo.all render conn, "index.html", items: items end end
VolumeView
ヘルパーは今のところ使用していないので、デフォルトのまま。
web/views/volume_view.ex
が以下。
defmodule StockScraping.VolumeView do use StockScraping.Web, :view end
VolumeTemplate
コントローラーから受け取った@items
をレンダリングする。
web/templates/volume/index.html.eex
が以下。
<h3>出来高増加率ランキング</h3> <ul> <%= for item <- @items do %> <li> <%= item.ranking %> - <%= item.name %> </li> <% end %> </ui>
これで一旦表示出来た。
この時点で月別カレンダーと日別出来高ランキングが表示されるようになった。
Elixir - Phoenixで株価を表示する(前編)
MySQLに入っている株価データを表示する。
ページ構成としてはHome
(月別カレンダー)とVolume
(日別出来高ランキング)の2つ。
今回はHomeだけ。
Routing
ルーティングでのポイントは、HomeControllerへのルートは引数有り無しのに種類用意すること。
web/router.ex
が以下。
defmodule StockScraping.Router do use StockScraping.Web, :router pipeline :browser do plug :accepts, ["html"] plug :fetch_session plug :fetch_flash plug :protect_from_forgery plug :put_secure_browser_headers end scope "/", StockScraping do pipe_through :browser get "/", HomeController, :index get "/:date", HomeController, :index get "/volume/:date", VolumeController, :index end end
HomeController
ここでは引数で受けた文字列をDate
にキャストしている。
引数がない場合は、現在時刻を使用する。
(キャスト方法は本当にこれであってるんだろうか…)
render conn, "index.html", items: items
とすることでテンプレートで@items
を参照可能になる。
web/controllers/home_controller.ex
の最終形が以下。
defmodule StockScraping.HomeController do use StockScraping.Web, :controller def index(conn, params) do target_date = case params do %{"date" => date} -> case Date.from_iso8601(date) do {:ok, value} -> value end _ -> now() end items = Repo.all(StockScraping.YahooVolumeDate) |> Enum.filter(fn(x) -> x.date.year == target_date.year && x.date.month == target_date.month end) render conn, "index.html", items: items end end
HomeView
ViewへはDateをstringに変換する関数を作成し、テンプレートから呼び出す。
あえてパターンマッチングで実装してみた。
web/views/home_view.ex
が以下。
defmodule StockScraping.HomeView do use StockScraping.Web, :view def convert(date) do case Timex.format(date, "{YYYY}-{0M}-{D}") do {:ok, value} -> value end end end
HomeTemplete
UIおいといてとりあえず表示させる。
ポイントはvolume_path(@conn, :index, convert(item.date))
VolumeControllerのIndexアクションへのURLをクエスパラメータ付きでレンダリングする処理。
Routingのget "/volume/:date", VolumeController, :index
でルートを追加しないと例外でる。
<h3>カレンダー</h3> <ul> <%= for item <- @items do %> <li> <a href="<%= volume_path(@conn, :index, convert(item.date)) %>"><%= item.date %></a> </li> <% end %> </ul>
これで一旦株価を更新した日付の一覧を表示できた。