個人プロジェクト開発メモ その3

Debian8 Jessie on VirtualBox(Windows 10 Pro)

  1. 初期インストール時にミスったおかげでHOMEPATHに日本語が含まれていてVagrantがまともに機能してくれない
  2. 開発用のユーザアカウントを新規に追加するも、追加アカウントはバグ(たぶんWin10のバグ)っていてほとんど何もできない

という状況からスタートしました。
Win10に上げればChocolateyを入れずともパッケージ管理が標準で使えるため、この機会にとWin8.1から上げたのが一ついけなかった。バグの情報など見ておけば危ないからと上げなかったところでしょう。

何を言っても仕方がないので、いったん直にVirtualBox上にDebianをインストールして環境を構築します。

が、そもそもHyper-Vが有効になっているせいでVirtualBoxがまともに動作せず、Hyper-Vの機能を無効化しようにも無効化中に「構成に失敗しました」とか出て巻き戻ってしまうという状況。

色々と試した末、Hyper-VとVMwareを共存させるを参考にHyper-Vを無効化することができました。

bcdedit /set hypervisorlaunchtype off
shutdown /r /t 0

Hyper-V無効化後、VirtualBoxを立ち上げてDebian仮想マシンを作ります。
VirtualBoxのバージョンを最新(5.0.4)に上げたらエラーで仮想マシンが起動できなかったため、5.0.2にダウングレード。VirtualBoxにはよくある話ですが、本当に毎度毎度きつい。
HOMEPATHに日本語が入っている影響でVirtualBox拡張機能ダウンロード、インストールの流れがコケます。ExtensionPackを直にダウンロードし、日本語を含まないパスに置いてロードします。

Vagrantを使わずに開発するため、とりあえずGUIも入れます。GNOMEはもうアレなのでMATEで。

プロジェクトのセットアップ

YesodなどHaskellの環境はStackで整えていきます。

Stackについての日本語情報は以下あたりを参照。

qiita.com

tune.hateblo.jp

1. Stackのインストール

GitHubリポジトリのインストール手順に従います。

stack/install_and_upgrade.md at master · commercialhaskell/stack · GitHub

$ wget -q -O- https://s3.amazonaws.com/download.fpcomplete.com/debian/fpco.key | sudo apt-key add -
OK
$ echo 'deb http://download.fpcomplete.com/debian/jessie stable main'|sudo tee /etc/apt/sources.list.d/fpco.list
deb http://download.fpcomplete.com/debian/jessie stable main
$ sudo apt-get update && sudo apt-get install stack -y

2. Yesodプロジェクトの作成

stack new PACKAGE_NAMEでプロジェクトを作成できますが、その際プロジェクトテンプレートを指定できます。
stack templatesでテンプレートの一覧を取得することができます。今回はPostgreSQLを利用するためyesod-postgresを選択します。

h2@debian:~/works$ stack new lcdeckbuilder yesod-postgres
Downloading template "yesod-postgres" to create project "lcdeckbuilder" in lcdeckbuilder/ ...
Writing default config file to: /home/h2/works/lcdeckbuilder/stack.yaml
Basing on cabal files:
- /home/h2/works/lcdeckbuilder/lcdeckbuilder.cabal

Checking against build plan lts-3.7
Selected resolver: lts-3.7
Wrote project config to: /home/h2/works/lcdeckbuilder/stack.yaml

成功すると以下のようなファイルやディレクトリができています。

h2@debian:~/works$ cd lcdeckbuilder
h2@debian:~/works/lcdeckbuilder$ ls -l
total 76
drwxr-xr-x 2 h2 h2 4096 Sep 28 04:58 app
-rw-r--r-- 1 h2 h2 6799 Sep 28 03:33 Application.hs
drwxr-xr-x 2 h2 h2 4096 Sep 28 05:08 config
-rw-r--r-- 1 h2 h2 6062 Sep 28 03:33 Foundation.hs
drwxr-xr-x 2 h2 h2 4096 Sep 28 05:00 Handler
drwxr-xr-x 2 h2 h2 4096 Sep 28 03:33 Import
-rw-r--r-- 1 h2 h2  125 Sep 28 03:33 Import.hs
-rw-r--r-- 1 h2 h2 4905 Sep 28 03:33 lcdeckbuilder.cabal
-rw-r--r-- 1 h2 h2  385 Sep 28 03:33 Model.hs
drwxr-xr-x 2 h2 h2 4096 Sep 28 03:44 Settings
-rw-r--r-- 1 h2 h2 5365 Sep 28 03:33 Settings.hs
-rw-r--r-- 1 h2 h2  982 Sep 28 03:33 stack.yaml
drwxr-xr-x 5 h2 h2 4096 Sep 28 04:45 static
drwxr-xr-x 2 h2 h2 4096 Sep 28 05:00 templates
drwxr-xr-x 3 h2 h2 4096 Sep 28 03:33 test

3. ビルド

プロジェクトのビルド時はstack buildを実行します。

h2@debian:~/works/lcdeckbuilder$ stack build
[1 of 1] Compiling Main             ( /tmp/stack9633/Setup.hs, /tmp/stack9633/Setup.o )
Linking /home/h2/.stack/setup-exe-cache/tmp-setup-Simple-Cabal-1.22.4.0-x86_64-linux-ghc-7.10.2 ...
hex-0.1.2: download
hex-0.1.2: configure
hex-0.1.2: build
hex-0.1.2: install
Progress: 22/181
--  While building package entropy-0.3.7 using:
      /home/h2/.stack/programs/x86_64-linux/ghc-7.10.2/bin/runhaskell -clear-package-db -global-package-db -package-db=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/pkgdb/ -package-db=/home/h2/works/lcdeckbuilder/.stack-work/install/x86_64-linux/lts-3.7/7.10.2/pkgdb/ -hide-all-packages -package=Cabal-1.22.4.0 -package-id=array-0.5.1.0-d4206b835b96b5079d918fa1eab1a9a8 -package-id=base-4.8.1.0-4f7206fd964c629946bb89db72c80011 -package-id=bin-package-db-0.0.0.0-b04c253694f93767af4f641e39a406a0 -package-id=binary-0.7.5.0-07214b304bb0a2c4cbf50d9dc7914ee6 -package-id=bytestring-0.10.6.0-2362d1f36f1255e85478e7793e15b170 -package-id=containers-0.5.6.2-2de75421d746ab474b330e43191bb31b -package-id=deepseq-1.4.1.1-8fb9688ae42216e388cee132aef3d148 -package-id=directory-1.2.2.0-258f6e56fc0799f4b45f149644b75783 -package-id=filepath-1.4.0.0-8fee9c13b5e42926cc01f6aa7c403c4b -package-id=ghc-prim-0.4.0.0-af16264bc80979d06e37ac63e3ba9a21 -package-id=haskeline-0.7.2.1-0a475c6a6a7de67d5fce6186e9d8d81a -package-id=hoopl-3.10.0.2-c84778769b61752ff34e979bbbebdb63 -package-id=hpc-0.6.0.2-567a296524cbf417c57abd674ccf4f5e -package-id=integer-gmp-1.0.0.0-8e0f14d0262184533b417ca1f8b44482 -package-id=pretty-1.1.2.0-2932d0905cc17ca1d9638eb9cca0a227 -package-id=process-1.2.3.0-f0287ac288afc0705be775d1adda59ee -package-id=template-haskell-2.10.0.0-90e8393d65f4ae44cb2026177a257f28 -package-id=terminfo-0.4.0.1-c72a7d139b97f9299867b81ab34b8dde -package-id=time-1.5.0.1-c208e8fcb3277879fd30f1140654d53e -package-id=transformers-0.4.2.0-21dcbf13c43f5d8cf6a1f54dee6c5bff -package-id=unix-2.7.1.0-6436007ffcf967b9823833b48295b586 -package-id=xhtml-3000.2.1-5a3d6f023f8af89b9c3e60e732c4b723 /tmp/stack9633/entropy-0.3.7/Setup.hs --builddir=.stack-work/dist/x86_64-linux/Cabal-1.22.4.0/ configure --user --package-db=clear --package-db=global --package-db=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/pkgdb/ --libdir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/lib --bindir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/bin --datadir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/share --libexecdir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/libexec --sysconfdir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/etc --docdir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/doc/entropy-0.3.7 --htmldir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/doc/entropy-0.3.7 --haddockdir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/doc/entropy-0.3.7 --dependency=base=base-4.8.1.0-4f7206fd964c629946bb89db72c80011 --dependency=bytestring=bytestring-0.10.6.0-2362d1f36f1255e85478e7793e15b170 --dependency=unix=unix-2.7.1.0-6436007ffcf967b9823833b48295b586
    Process exited with code: ExitFailure 1
    Logs have been written to: /home/h2/works/lcdeckbuilder/.stack-work/logs/entropy-0.3.7.log

    <command line>: can't load .so/.DLL for: libtinfo.so (libtinfo.so: cannot open shared object file: No such file or directory)

上記エラーが発生したため、sudo apt-get install -y libtinfo-devでライブラリを追加。

再度stack buildすると、別のエラーが発生しました。

prelude-extras-0.4.0.2: download
prelude-extras-0.4.0.2: configure
prelude-extras-0.4.0.2: build
prelude-extras-0.4.0.2: install
Progress: 22/160
--  While building package postgresql-libpq-0.9.1.1 using:
      /home/h2/.stack/programs/x86_64-linux/ghc-7.10.2/bin/runhaskell -clear-package-db -global-package-db -package-db=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/pkgdb/ -package-db=/home/h2/works/lcdeckbuilder/.stack-work/install/x86_64-linux/lts-3.7/7.10.2/pkgdb/ -hide-all-packages -package=Cabal-1.22.4.0 -package-id=array-0.5.1.0-d4206b835b96b5079d918fa1eab1a9a8 -package-id=base-4.8.1.0-4f7206fd964c629946bb89db72c80011 -package-id=bin-package-db-0.0.0.0-b04c253694f93767af4f641e39a406a0 -package-id=binary-0.7.5.0-07214b304bb0a2c4cbf50d9dc7914ee6 -package-id=bytestring-0.10.6.0-2362d1f36f1255e85478e7793e15b170 -package-id=containers-0.5.6.2-2de75421d746ab474b330e43191bb31b -package-id=deepseq-1.4.1.1-8fb9688ae42216e388cee132aef3d148 -package-id=directory-1.2.2.0-258f6e56fc0799f4b45f149644b75783 -package-id=filepath-1.4.0.0-8fee9c13b5e42926cc01f6aa7c403c4b -package-id=ghc-prim-0.4.0.0-af16264bc80979d06e37ac63e3ba9a21 -package-id=haskeline-0.7.2.1-0a475c6a6a7de67d5fce6186e9d8d81a -package-id=hoopl-3.10.0.2-c84778769b61752ff34e979bbbebdb63 -package-id=hpc-0.6.0.2-567a296524cbf417c57abd674ccf4f5e -package-id=integer-gmp-1.0.0.0-8e0f14d0262184533b417ca1f8b44482 -package-id=pretty-1.1.2.0-2932d0905cc17ca1d9638eb9cca0a227 -package-id=process-1.2.3.0-f0287ac288afc0705be775d1adda59ee -package-id=template-haskell-2.10.0.0-90e8393d65f4ae44cb2026177a257f28 -package-id=terminfo-0.4.0.1-c72a7d139b97f9299867b81ab34b8dde -package-id=time-1.5.0.1-c208e8fcb3277879fd30f1140654d53e -package-id=transformers-0.4.2.0-21dcbf13c43f5d8cf6a1f54dee6c5bff -package-id=unix-2.7.1.0-6436007ffcf967b9823833b48295b586 -package-id=xhtml-3000.2.1-5a3d6f023f8af89b9c3e60e732c4b723 /tmp/stack11844/postgresql-libpq-0.9.1.1/Setup.hs --builddir=.stack-work/dist/x86_64-linux/Cabal-1.22.4.0/ configure --user --package-db=clear --package-db=global --package-db=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/pkgdb/ --libdir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/lib --bindir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/bin --datadir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/share --libexecdir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/libexec --sysconfdir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/etc --docdir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/doc/postgresql-libpq-0.9.1.1 --htmldir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/doc/postgresql-libpq-0.9.1.1 --haddockdir=/home/h2/.stack/snapshots/x86_64-linux/lts-3.7/7.10.2/doc/postgresql-libpq-0.9.1.1 --dependency=base=base-4.8.1.0-4f7206fd964c629946bb89db72c80011 --dependency=bytestring=bytestring-0.10.6.0-2362d1f36f1255e85478e7793e15b170
    Process exited with code: ExitFailure 1
    Logs have been written to: /home/h2/works/lcdeckbuilder/.stack-work/logs/postgresql-libpq-0.9.1.1.log

    Configuring postgresql-libpq-0.9.1.1...
    Setup.hs: The program 'pg_config' is required but it could not be found.

単純にPostgreSQLをインストールしていなかったため、インストールします。

$ sudo apt-get install postgresql postgresql-client postgresql-server-dev-9.4

これでビルドが通りました。

h2@debian:~/works/lcdeckbuilder$ stack build
...
lcdeckbuilder-0.0.0: configure
Configuring lcdeckbuilder-0.0.0...
lcdeckbuilder-0.0.0: build
Preprocessing library lcdeckbuilder-0.0.0...
[1 of 9] Compiling Model            ( Model.hs, .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/Model.o )
[2 of 9] Compiling Settings         ( Settings.hs, .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/Settings.o )
[3 of 9] Compiling Settings.StaticFiles ( Settings/StaticFiles.hs, .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/Settings/StaticFiles.o )
[4 of 9] Compiling Import.NoFoundation ( Import/NoFoundation.hs, .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/Import/NoFoundation.o )
[5 of 9] Compiling Foundation       ( Foundation.hs, .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/Foundation.o )
[6 of 9] Compiling Import           ( Import.hs, .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/Import.o )
[7 of 9] Compiling Handler.Common   ( Handler/Common.hs, .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/Handler/Common.o )
[8 of 9] Compiling Handler.Home     ( Handler/Home.hs, .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/Handler/Home.o )
[9 of 9] Compiling Application      ( Application.hs, .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/Application.o )
In-place registering lcdeckbuilder-0.0.0...
Preprocessing executable 'lcdeckbuilder' for lcdeckbuilder-0.0.0...
[1 of 1] Compiling Main             ( app/main.hs, .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/lcdeckbuilder/lcdeckbuilder-tmp/Main.o )
Linking .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/lcdeckbuilder/lcdeckbuilder ...
lcdeckbuilder-0.0.0: install
Installing library in
/home/h2/works/lcdeckbuilder/.stack-work/install/x86_64-linux/lts-3.7/7.10.2/lib/x86_64-linux-ghc-7.10.2/lcdeckbuilder-0.0.0-2eA3tELX9HzADeaH532x5G
Installing executable(s) in
/home/h2/works/lcdeckbuilder/.stack-work/install/x86_64-linux/lts-3.7/7.10.2/bin
Registering lcdeckbuilder-0.0.0...
Completed all 138 actions.

4. 起動

とりあえずbuildで出力されたバイナリをパス指定で実行します。

h2@debian:~/works/lcdeckbuilder$ .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/lcdeckbuilder/lcdeckbuilder
lcdeckbuilder: libpq: failed (FATAL:  password authentication failed for user "lcdeckbuilder"
FATAL:  password authentication failed for user "lcdeckbuilder"
)

エラーは単純に設定ファイルに書かれたDBユーザが存在しないということですね。
config/settings.ymlにDBユーザやパスワードなどの設定が記載されています。
とりあえず今は開発するだけなので、特に設定はいじらず、デフォルト設定どおりのパスワードを持ったユーザとデータベースを作成します。

h2@debian:~/works/lcdeckbuilder$ su -
root@debian:~# su - postgres
postgres@debian:~$ psql
psql (9.4.4)
Type "help" for help.

postgres=# CREATE USER lcdeckbuilder WITH PASSWORD 'lcdeckbuilder';
CREATE ROLE
postgres=# CREATE DATABASE lcdeckbuilder OWNER lcdeckbuilder;
CREATE DATABASE

再度実行すると、DBのマイグレーション処理が走ります。

h2@debian:~/works/lcdeckbuilder$ .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/lcdeckbuilder/lcdeckbuilder
Migrating: CREATe TABLE "user"("id" SERIAL  PRIMARY KEY UNIQUE,"ident" VARCHAR NOT NULL,"password" VARCHAR NULL)
Migrating: CREATe TABLE "email"("id" SERIAL  PRIMARY KEY UNIQUE,"email" VARCHAR NOT NULL,"user" INT8 NULL,"verkey" VARCHAR NULL)
Migrating: ALTER TABLE "user" ADD CONSTRAINT "unique_user" UNIQUE("ident")
Migrating: ALTER TABLE "email" ADD CONSTRAINT "unique_email" UNIQUE("email")
Migrating: ALTER TABLE "email" ADD CONSTRAINT "email_user_fkey" FOREIGN KEY("user") REFERENCES "user"("id")

特にスタートしたとか出ず、localhost:3000にアクセスするとページが表示されます。

127.0.0.1 - - [28/Sep/2015:04:45:13 -0400] "GET / HTTP/1.1" 200 - "" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.3.0"
127.0.0.1 - - [28/Sep/2015:04:45:13 -0400] "GET /static/tmp/autogen-SWBGXCgb.js HTTP/1.1" 200 - "http://localhost:3000/" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.3.0"
127.0.0.1 - - [28/Sep/2015:04:45:13 -0400] "GET /favicon.ico HTTP/1.1" 200 1342 "" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.3.0"
127.0.0.1 - - [28/Sep/2015:04:45:13 -0400] "GET /static/css/bootstrap.css HTTP/1.1" 200 - "http://localhost:3000/" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.3.0"
127.0.0.1 - - [28/Sep/2015:04:45:13 -0400] "GET /static/tmp/autogen-pGIQ-osA.css HTTP/1.1" 200 - "http://localhost:3000/" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.3.0"
127.0.0.1 - - [28/Sep/2015:04:45:13 -0400] "GET /static/fonts/glyphicons-halflings-regular.woff HTTP/1.1" 200 - "http://localhost:3000/static/css/bootstrap.css?etag=QRP3qj9r" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.3.0"
127.0.0.1 - - [28/Sep/2015:04:45:13 -0400] "GET /favicon.ico HTTP/1.1" 200 1342 "" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.3.0"
127.0.0.1 - - [28/Sep/2015:04:48:42 -0400] "GET /favicon.ico HTTP/1.1" 200 1342 "" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.3.0"

表示はできていますが、開発用設定になっていないためログが少ない、ホットリロードが行われないなど不便です。

config/settings.ymlを開き、開発設定を有効にします。開発時はinverseってことなので全部trueにしています。

h2@debian:~/works/lcdeckbuilder$ vim config/settings.yml
# Optional values with the following production defaults.
# In development, they default to the inverse.
#
# development: false
# detailed-logging: false
# should-log-all: false
# reload-templates: false
# mutable-static: false
# skip-combining: false

+ development: true
+ detailed-logging: true
+ should-log-all: true
+ reload-templates: true
+ mutable-static: true
+ skip-combining: true

最後にもう一度ビルドして実行します。

h2@debian:~/works/lcdeckbuilder$ .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/lcdeckbuilder/lcdeckbuilder
GET /
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  Status: 200 OK 0.002523s
GET /static/css/bootstrap.css
  Params: [("etag","QRP3qj9r")]
  Accept: text/css,*/*;q=0.1
  Status: 304 Not Modified 0.000101s
GET /static/tmp/autogen-pGIQ-osA.css
  Accept: text/css,*/*;q=0.1
  Status: 304 Not Modified 0.000059s
GET /static/tmp/autogen-SWBGXCgb.js
  Accept: */*
  Status: 304 Not Modified 0.000046s
GET /favicon.ico
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  Status: 200 OK 0.000136s

詳細なログが出るようになりました。

とりあえず動くところまでいったので、これをベースに開発していけば良さそうですね。