EC2にDockerでElixir-Phoenixをデプロイする
EC2にDockerを使ってデータを表示するPhoenixアプリをデプロイする。
Phoenixのconfig設定
Producrion用のconfigを書き換える。
ポート4000にロードし、nginxでリバースプロシキさせる。
config/prod.exs
が以下。
config :stock_scraping, StockScraping.Endpoint, http: [port: 4000], url: [host: "example.com", port: 4000]
Dockerfile作成
Phoenixを起動するDockerfileを作成する。
さっそく中身。
FROM elixir MAINTAINER yuki-toida RUN apt-get update # hex RUN mix local.hex --force && \ mix local.rebar --force && \ mix hex.info # phoenix RUN mix archive.install https://github.com/phoenixframework/archives/raw/master/phoenix_new.ez # node npm RUN apt-get install -y nodejs npm RUN npm cache clean && npm install n -g RUN n stable && ln -sf /usr/local/bin/node /usr/bin/node RUN apt-get purge -y nodejs npm # inotify-tools RUN apt-get install -y inotify-tools EXPOSE 4000 # git repository RUN git clone https://github.com/yuki-toida/stock_scraping.git root/stock_scraping WORKDIR /root/stock_scraping RUN chmod +x run.sh ENTRYPOINT ["./run.sh"] CMD ["dev"]
Elixirの公式イメージを使って公式サイトの手順でPhoenixをインストール。
node.jsとnpmをインストールし、古いパッケージをパージ。
エントリーポイントをrun.sh
とする。以下。
#!/bin/bash git reset --hard HEAD git pull origin master mix deps.get npm install MIX_ENV=$1 mix compile MIX_ENV=$1 mix phoenix.server
環境変数にprodを設定すると、mix compile
が必須になるのがポイント。
EC2にログインしDockerイメージをプルする
docker pull yukitoida/stock_scraping
Dockerコンテナを起動させる
docker run --net="host" yukitoida/stock_scraping prod
これでlocalhost:4000にPhoenixアプリがロードされてるはず。
前回、nginxの設定は終わってるので、リバースプロシキされるはず。
実際のURLがこちら。株カレンダー
なんというクソUI、気が向いたらUIをちゃんと作る。
AWS EC2 に nginx をインストールしリバースプロシキさせる
EC2でPhoenixアプリをグローバルに公開するための設定。
port80を公開する
EC2に適用しているセキュリティグループのインバウンドルールに下記を追加。
タイプ | プロトコル | ポート範囲 | 送信元 |
---|---|---|---|
HTTP | TCP | 80 | 0.0.0.0/0 |
これでポート80をグローバルに公開できる。
nginxのインストール
パッケージ情報確認。
sudo yum info nginx 読み込んだプラグイン:priorities, update-motd, upgrade-helper 利用可能なパッケージ 名前 : nginx アーキテクチャー : x86_64 エポック : 1 バージョン : 1.10.2 リリース : 1.30.amzn1 容量 : 534 k リポジトリー : amzn-main/latest 要約 : A high performance web server and reverse proxy server URL : http://nginx.org/ ライセンス : BSD 説明 : Nginx is a web server and a reverse proxy server for HTTP, SMTP, POP3 and : IMAP protocols, with a strong focus on high concurrency, performance and low : memory usage.
↑のように表示されていれば利用可能なので、インストール。
sudo yum install nginx
インストールされたか確認。
nginx -V built by gcc 4.8.3 20140911 (Red Hat 4.8.3-9) (GCC) built with OpenSSL 1.0.1k-fips 8 Jan 2015
nginx を起動する
sudo nginx
プロセスを確認。
ps -ef | grep nginx root 9069 1 0 17:43 ? 00:00:00 nginx: master process nginx nginx 9070 9069 0 17:43 ? 00:00:00 nginx: worker process ec2-user 9072 8991 0 17:43 pts/0 00:00:00 grep --color=auto nginx
起動している。
EC2のパブリックIPでアクセスできるか確認する。
nginxのデフォルトページが表示されたらおk。
nginx 自動起動設定
sudo service nginx start sudo chkconfig nginx on sudo chkconfig --list nginx nginx 0:off 1:off 2:on 3:on 4:on 5:on 6:off
これで自動起動設定完了。
nginx config 設定
Phoenix はlocalhost:4000をリッスンしている。
それを[パブリックIP]:80でリバースプロシキ。
/etc/nginx/conf.d/local.conf
が以下。
upstream phoenix { server localhost:4000 max_fails=5 fail_timeout=5s; } server { listen 80; server_name [パブリックIP] location / { allow all; # Proxy Headers proxy_http_version 1.1; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-Cluster-Client-Ip $remote_addr; # The Important Websocket Bits! proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass http://phoenix; } }
パブリックIP文字列が長すぎてハッシュ化出来ないと nginx に怒られたので、
/etc/nginx/nginx.conf
に下記追加。
server_names_hash_bucket_size 128;
これで準備完了。
あとはPhoenixをデプロイして、Dockerコンテナ内でlocalhost:4000でアプリをホストすればいけるはず。
次回やる。
AWS EC2 にcronを設定し定期的にDockerコンテナを実行する
東京株式市場は15時大引けなので毎日18時に実行するよう設定する。
EC2にDockerをインストール
# パッケージ更新 sudo yum update -y # dockerインストール sudo yum install -y docker # dockerサービス起動 sudo service docker start # ec2-user を dockerグループに追加しsudoなしで実行できるように sudo usermod -a -G docker ec2-user
Dockerイメージをプル
イメージをプルして、コンテナ実行ファイルを作成する。
docker pull yukitoida/stock_scraping_batch
以下実行ファイル/home/ec2-user/docker/run-batch.sh
。
#!/bin/sh/ docker run --rm --net="host" yukitoida/stock_scraping_batch prod
cron を設定する
crontab -e
コマンドを実行する。
MAILTO="" DIR="/home/ec2-user/docker" 00 18 * * 1-5 /bin/bash $DIR/run-batch.sh > $DIR/logs/`date +\%Y\%m\%d_\%H\%M\%S`.log
MAILTO=""
にすることで実行後メールを無効化する。
その代わりに、ファイル名を日付にしログを残す。
crontab -l
で登録内容を確認する。
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にデプロイする。