Phoenix で Welcome ページを表示するまで

最近、Phoenix なる Web フレームワークの存在を知って厨二心をくすぐられ、少しずつ触っています。
なんでも開発言語は Elixir なる言語だとか。こちらもなんとも厨二心をくすぐるネーミングです。
この投稿では、Docker を利用した CentOS 7 環境で Phoenix の Welcome ページを表示したところまでを紹介します。

## Docker コンテナの起動およびコンテナ環境へログイン

```
$ docker run --hostname phoenix --privileged --name phoenix -td centos:latest /sbin/init
a649f7f4c29a5a23c4b7fba15722d9581b6f7824b980775a0bec88adb9b1cc09

$ docker exec -ti phoenix su -
```

## 環境の事前準備
### timezone の設定

```
[root@phoenix ~]# ln -sf  /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
```

### 開発用のユーザとディレクトリを作成

```
[root@phoenix ~]# useradd homulilly
[root@phoenix ~]# mkdir /apl
[root@phoenix ~]# chown homulilly:homulilly /apl
```

### 基本 & 前提パッケージをインストール

```
[root@phoenix ~]# yum -y update
[root@phoenix ~]# yum install -y epel-release
[root@phoenix ~]# yum install -y rsyslog vim wget gcc-c++ make git openssl openssl-devel readline-devel bzip2 bzip2-devel sqlite-devel curl-devel sudo tree lsof autoconf java-1.8.0-openjdk-devel
```

## Elixir をインストール
> Elixir は Erlang の仮想マシン (BEAM) 上で動作するコンピュータプログラミング言語である。

との説明が [wiki](https://ja.wikipedia.org/wiki/Elixir_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E)) にありますが、今はよく理解できていません。
Ubuntu だともう少し手軽にインストールできるようです。
### Erlang をインストール

```
[root@phoenix ~]# rpm -Uvh http://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm
[root@phoenix ~]# yum install -y esl-erlang
[root@phoenix ~]# erl
Erlang/OTP 21 [erts-10.0.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

Eshell V10.0.5  (abort with ^G)
1> 
-> Ctrl + C を 2 回押下。
```

## Elixir をインストール

```
[root@phoenix ~]# cd /usr/local/lib
[root@phoenix lib]# git clone https://github.com/elixir-lang/elixir.git
[root@phoenix lib]# cd elixir/
[root@phoenix elixir]# export LANG=en_US.UTF-8
[root@phoenix elixir]# make clean test
[root@phoenix elixir]# ln -s /usr/local/lib/elixir/bin/iex /usr/bin/iex
[root@phoenix elixir]# ln -s /usr/local/lib/elixir/bin/elixir /usr/bin/elixir
[root@phoenix elixir]# ln -s /usr/local/lib/elixir/bin/elixirc /usr/bin/elixirc
[root@phoenix elixir]# ln -s /usr/local/lib/elixir/bin/mix /usr/bin/mix
[root@phoenix elixir]# iex -v
Erlang/OTP 21 [erts-10.0.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

IEx 1.8.0-dev (c76c5d6) (compiled with Erlang/OTP 21)
```

## PostgreSQL のインストール
Phoenix が利用する DB は PostgreSQL がデフォルトになっています。
EPEL リポジトリからもインストールできますが、以下ではより新しいバージョンがインストールできるはずです。

### パッケージのインストールおよびサービス自動起動設定

```
[root@phoenix ~]# yum localinstall -y https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-centos10-10-2.noarch.rpm
[root@phoenix ~]# yum install -y postgresql10-server
[root@phoenix ~]# /usr/pgsql-10/bin/postgres --version
postgres (PostgreSQL) 10.5

[root@phoenix ~]# /usr/pgsql-10/bin/postgresql-10-setup initdb
Initializing database ... OK

[root@phoenix ~]# systemctl enable postgresql-10
Created symlink from /etc/systemd/system/multi-user.target.wants/postgresql-10.service to /usr/lib/systemd/system/postgresql-10.service.
```

### DB のセットアップ

#### サービス起動および CLI 起動

```
[root@phoenix ~]# systemctl start postgresql-10
[root@phoenix ~]# sudo -u postgres psql
could not change directory to "/root": Permission denied
psql (10.5)
Type "help" for help.
```

#### UTF-8 エンコーディングの Database テンプレートを作成
デフォルトでは Database テンプレートに UTF-8 エンコーディングのものがありません。
そのため、Phoenix が UTF-8 エンコーディングの Database を自動作成できない可能性があります。

```
postgres=# UPDATE pg_database SET datistemplate = FALSE WHERE datname = 'template1';
UPDATE 1
postgres=# DROP DATABASE template1;
DROP DATABASE
postgres=# CREATE DATABASE template1 WITH TEMPLATE = template0 ENCODING = 'UTF8';
CREATE DATABASE
postgres=# UPDATE pg_database SET datistemplate = TRUE WHERE datname = 'template1';
UPDATE 1
postgres=# \l
                             List of databases
   Name    |  Owner   | Encoding  | Collate | Ctype |   Access privileges   
-----------+----------+-----------+---------+-------+-----------------------
 postgres  | postgres | SQL_ASCII | C       | C     | 
 template0 | postgres | SQL_ASCII | C       | C     | =c/postgres          +
           |          |           |         |       | postgres=CTc/postgres
 template1 | postgres | UTF8      | C       | C     | 
(3 rows)
```

#### 開発用のユーザを登録

```
postgres=# CREATE USER homulilly WITH PASSWORD '********';
CREATE ROLE
postgres=# ALTER ROLE homulilly SET client_encoding TO 'utf8';
ALTER ROLE
postgres=# ALTER ROLE homulilly SET default_transaction_isolation TO 'read committed';
ALTER ROLE
postgres=# ALTER ROLE homulilly SET timezone TO 'Asia/Tokyo';
ALTER ROLE
postgres=# ALTER ROLE homulilly CREATEDB;
ALTER ROLE
postgres=# \q
```

#### アクセス制限の変更
DB に Phoenix からアクセスできるようにします。とは言っても、パラメータの意味や設定可能な値については理解不足です。

```
[root@phoenix ~]# cp -p /var/lib/pgsql/10/data/pg_hba.conf /var/lib/pgsql/10/data/pg_hba.conf.org
[root@phoenix ~]# vim /var/lib/pgsql/10/data/pg_hba.conf
[root@phoenix ~]# diff -u /var/lib/pgsql/10/data/pg_hba.conf.org /var/lib/pgsql/10/data/pg_hba.conf     
--- /var/lib/pgsql/10/data/pg_hba.conf.org      2018-08-27 18:21:39.820300638 +0900
+++ /var/lib/pgsql/10/data/pg_hba.conf  2018-08-27 19:12:54.176123698 +0900
@@ -77,9 +77,9 @@
 # TYPE  DATABASE        USER            ADDRESS                 METHOD
 
 # "local" is for Unix domain socket connections only
-local   all             all                                     peer
+local   all             all                                     md5
 # IPv4 local connections:
-host    all             all             127.0.0.1/32            ident
+host    all             all             127.0.0.1/32            md5
 # IPv6 local connections:
 host    all             all             ::1/128                 ident
 # Allow replication connections from localhost, by a user with the
```

#### サービス再起動
これで DB に必要なセットアップは完了したので、最後にサービス再起動を行います。

```
[root@phoenix ~]# systemctl restart postgresql-10
```

## Phoenix のインストール
ようやく本題です。Phoenix の開発には Ruby on Rails の開発者も携わっているようで、インターフェースは近しいものがあります。

### Elixir の vim 設定
Elixir の vim 用の設定ツールが公開されていますので利用します。Elixir を書き始めるまでは不要ですが。

```
[root@phoenix ~]# yum install -y inotify-tools
[root@phoenix ~]# su - homulilly
[homulilly@phoenix ~]$ export LANG=en_US.UTF-8
[homulilly@phoenix ~]$ git clone https://github.com/elixir-lang/vim-elixir.git ~/.vim/bundle/vim-elixir
[homulilly@phoenix ~]$ cd .vim/bundle/vim-elixir/
[homulilly@phoenix vim-elixir]$ ./manual_install.sh 
[homulilly@phoenix vim-elixir]$ cd /apl
```

### Node.js のインストール
Phoenix はフロント側の処理で Node.js を利用するという理由だったか、単に便利になるという理由だったか、Node.js が必要そうなのでインストールします。

```
[homulilly@phoenix apl]# curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash
[homulilly@phoenix apl]# source ~/.nvm/nvm.sh
[homulilly@phoenix apl]# nvm install --lts
Installing latest LTS version.
Downloading and installing node v8.11.4...
Downloading https://nodejs.org/dist/v8.11.4/node-v8.11.4-linux-x64.tar.xz...
######################################################################## 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v8.11.4 (npm v5.6.0)
Creating default alias: default -> lts/* (-> v8.11.4)

[homulilly@phoenix apl]# nvm use --lts
Now using node v8.11.4 (npm v5.6.0)

[homulilly@phoenix apl]# node -v
v8.11.4

[homulilly@phoenix apl]# npm -v
5.6.0
```

### Phoenix のインストール
Ruby でいうところの Bundler & RubyGems & Rake に相当する Mix で Phoenix フレームワークをインストールします。Hex はパッケージマネージャーで RubyGems に相当するものとのこと。

```
[homulilly@phoenix apl]$ mix local.hex
Are you sure you want to install "https://repo.hex.pm/installs/1.6.0/hex-0.18.1.ez"? [Yn] Y
* creating /home/homulilly/.mix/archives/hex-0.18.1

[homulilly@phoenix apl]$ mix archive.install https://github.com/phoenixframework/archives/raw/master/phx_new.ez
Are you sure you want to install "https://github.com/phoenixframework/archives/raw/master/phx_new.ez"? [Yn] Y
* creating /home/homulilly/.mix/archives/phx_new

[homulilly@phoenix apl]$ mix phx.new -v
Phoenix v1.3.4
```

## 動作確認
### テストプロジェクトの作成
Phoenix に関するコマンドは `mix phoenix.XXX` と `mix phx.XXX` が利用できますが、前者は旧バージョンの名残のようです。以下のコマンドを前者で実行すると、ディレクトリ構造が結構変わります。

```
[homulilly@phoenix apl]$ mix phx.new test
```

### 開発用環境の DB 設定

```
[homulilly@phoenix apl]$ cd test
[homulilly@phoenix test]$ cp -p config/dev.exs config/dev.exs.org 
[homulilly@phoenix test]$ vim config/dev.exs
[fhomulillyjse@phoenix test]$ diff -u config/dev.exs.org config/dev.exs
--- config/dev.exs.org  2018-08-27 18:52:34.093193918 +0900
+++ config/dev.exs      2018-08-27 18:57:18.198177567 +0900
@@ -49,8 +49,8 @@
 # Configure your database
 config :test, Test.Repo,
   adapter: Ecto.Adapters.Postgres,
-  username: "postgres",
-  password: "postgres",
+  username: "homulilly",
+  password: "********",
   database: "test_dev",
   hostname: "localhost",
   pool_size: 10
```

### DB の migrate
テーブルは作成していませんが、PostgreSQL に test_dev という Database が作成されるはずです。
ちなみに以下の 1 行目のファイル編集は、構文エラーが発生し DB への migrate が失敗したために行ったのですが、よくわかっていないままとりあえず動くようにしたものなので、将来的にどこかで想定外の動作になる可能性があります。

```
[homulilly@phoenix test]$ vim deps/phoenix/lib/phoenix/presence.ex 
l.110 の ":: :ignore" を "| :ignore" に書き換える。

[homulilly@phoenix test]$ mix ecto.create
warning: found quoted keyword "test" but the quotes are not required. Note that keywords are always atoms, even when quoted, and quotes should only be used to introduce keywords with foreign characters in them mix.exs:57

The database for Test.Repo has already been created
```

### Phoenix サーバの起動
Phoenix サーバを起動します。`Rails s` に相当するコマンドです。デフォルトでは 4000 番ポートで listen しているはずです。

```
[homulilly@phoenix test]$ mix phoenix.server
```

以上で、ブラウザで Welcome ページが閲覧できました。今後は production 環境も構築していきます。