Exment is 何?
Exmentは、Laravel製(ということは、LAMPですね。ということは、レンタルサーバーでも動きますね。)のWeb DBシステムです。リレーショナルなデータベースをGUI管理画面から操作できます。
ExmentはOSSで、GPLライセンスです。開発は株式会社カジトリが中心となって行っています。詳細は開発者の方の記事をご覧ください。
GUIのWeb DBというと、なんとなくサイボウズ社のkintoneを連想する方もいるのではないでしょうか。
開発元からはキントーンのキの字も聞こえてきませんが、筆者はひそかにkintoneクローンだと思っていて、かなり可能性を秘めているOSSプロダクトだと考えています。
正直、かなりほれ込んでいるのですが、この記事ではお気に入りポイントは解説しません。また別の機会に。
クラウドでなるべくお安くExmentを運用したい!
ローカルでは、Dockerを使ってExmentを試すことができます。作ってくれた人ありがとう!
ローカルで実際やってみたところ(macOS Mojave、Windows 10 Home WSL2で確認)、あっさり出来ました。すごいですね。
そうしたら、クラウドでホスティングして、外出先などからもアクセスしたくなるというのが人情ですよね。
ホスティング先をいろいろ考えてみました。フロントエンドだけなら、NetlifyやVercelといった無料のサービスもあるのですが、残念ながらこれはバックエンドのシステムです…
先述していますが、Exmentはレンタルサーバーでも運用できます。
Exment公式サイトには、さくらやエックスサーバーといったレンサバでのインストール手順が公開されていますが、残念ながら、さくらやエックスサーバーのアカウントを私は持ち合わせておりません。つまり、筆者はレンサバの契約をしていないのですね。(フロント寄りの作りかけ個人プロダクトがNetlifyやVercelにはわんさかあるんですけど)
Exmentのためだけにレンサバ借りるのもなんだかなあ、だったらVPSのほうが良くない? と色々調べた結果、AmazonのLightsailが私の用途にぴったりだと気付きました。
(なお、筆者はこの時点でVPS、AWS童貞です)
ではさっそくLightsailのアカウントを取得して、始めるぞ!
Lightsailにログインしてからインスタンスの作成あたりまでは、下記記事が詳しいです。
今回は、一番安い$3.5/月の512MBRAMのインスタンスにしました。なるべくお安く、というテーマなので。どうしてもスペック足りなかったら、その時にスケールアップなりなんなり対応を考えようというスタンスです。
Lightsailには、WordPressなどのWebアプリケーションがセットになったインスタンスひな形があるのですが、当然知名度まだまだのExmentひな形というのはありません。
そこで、OSのみのインスタンスを選択します。今回は、CentoOS7を選択しました。
CentOSにフツーにインストールする? それとも…?
Exment公式には、CentOS7にインストールする手順も公開されており、またそれを補強する記事もあります。(下記参照)
が、公式を見ていただければわかる通り、結構な手順があります。で、実際1度やりました。何度か環境を捨てたりやり直したりする過程で「この手順毎回やってられんわ!」となり、他の方法を考えることに至ります。
せや、Dockerそのまま載せたったらええやん?
Lightsail+DockerでExmentを動かす(httpsもあるよ!)
ここからは、ハマりポイントを踏まえた回避策も含めて手順を記します。ここを守れば、最短でExment on Lightsail+Dockerが実現できます。
CentOS7でインスタンス作成後、Docker、Docker-composeとgitをインストールする
では、もろもろインストールしていきます。
毎回、sudo つけるの大変なので、rootになります。
Lightsailでrootになるには、こちらの記事を参考にしました。
$ sudo su -
Dockerをインストールします。こちらの記事が詳しいです。
[root@ip-172-xx-xx-x ~]# yum install -y docker # dockerのインストール
[root@ip-172-xx-xx-x ~]# service docker start # dockerの起動
[root@ip-172-xx-xx-x ~]# groupadd docker # ユーザー権限で実行できるようにしておく
[root@ip-172-xx-xx-x ~]# usermod -g docker centos # 作成したグループにcentosユーザを追加
[root@ip-172-xx-xx-x ~]# sudo /bin/systemctl restart docker.service
[root@ip-172-xx-xx-x ~]# docker info
これでDockerはインストールできました。
続いて、Docker-composeです。
[root@ip-172-xx-xx-x ~]# curl -L https://github.com/docker/compose/releases/download/1.21.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
[root@ip-172-xx-xx-x ~]# chmod +x /usr/local/bin/docker-compose
[root@ip-172-xx-xx-x ~]# docker-compose --version
最後に、Gitをインストールします。CentOS7のyumで入るGitは、1.8.2と古いバージョンのものです。気になる人は、下記記事を参考に新しいのを入れてみてください。今回は、git cloneしたいだけなので、そのままyumでインストールします。
[root@ip-172-xx-xx-x ~]# yum install -y git
これで、Gitもインストールできました。
スワップ領域を作る
RAM512MBのインスタンスなので、DockerでMySQLまで動かすとメモリ不足になりました。(ハマりポイント1)なので、先んじてスワップ領域を作っておきましょう。
スワップの作り方は下記記事を参考にしました。
[root@ip-172-xx-xx-x ~]# dd if=/dev/zero of=/swapfile bs=1M count=4096 status=progress
コマンドの書き方をミスってたため、結構ハマりました(ハマりポイント2)
あれこれ試行錯誤した過程で、/dev/zeroが何のファイルかわかっておらず、rm -rfしちゃったのはいい思い出です。
/dev/zeroを復活させるのは、こちらの記事を参考にしました。
[root@ip-172-xx-xx-x ~]# mknod -m 666 /dev/zero c 1 5
[root@ip-172-xx-xx-x ~]# chown root:mem /dev/zero
status=progress
オプションですが、今回はスワップ領域が4Gと大きめなので、しばらくターミナルが沈黙しちゃうと心配です。なので、ddコマンドの進捗をお知らせしてくれるオプションをつけました。下記記事を参考にしています。
ddでスワップ領域が作成されたら、粛々と残りの作業を進めます。
[root@ip-172-xx-xx-x ~]# chmod 600 /swapfile #パーミッションの変更
[root@ip-172-xx-xx-x ~]# mkswap /swapfile #スワップの作成
Setting up swapspace version 1, size = 1048572 KiB
no label, UUID=d0519bf6-8abf-4c0d-9375-8068c9e5e9a1
[root@ip-172-xx-xx-x ~]# swapon /swapfile #スワップの有効化
[root@ip-172-xx-xx-x ~]# free -m #スワップの確認
最後に、スワップの永続化をします。
viで/etc/fstabを開き、
/swapfile swap swap defaults 0 0
でおしまいです。
git cloneで、docker-compose.ymlとDockerfileを拾ってくる。
先述ご紹介した、ExmentのDockerを作ってくれた方のGithubから拾います。
[root@ip-172-xx-xx-x /home/centos/]# git clone https://github.com/yamada28go/docker-exment.git
場所はどこでもいいと思うんですけど、デフォルトユーザーディレクトリ直下にしました。
httpsは?
Dockerでhttpsというと、https-portalが有名なようです。
結論から先にいうと、https-portalを先に設定した状態でExmentをインストールしたら、上手くいきませんでした!!!(ハマりポイント3)
なので、SSLを設定する前に非SSLの状態でExmentのインストールを進めます。
一応、docker-compose.ymlに目を通しておきますか。
version: '3'
services:
nginx:
image: nginx:latest
ports:
- 8080:80
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- www-data:/var/www
depends_on:
- php
php:
build: ./php
volumes:
- www-data:/var/www
depends_on:
- db
db:
image: mysql:5.7
ports:
- 13306:3306
volumes:
- mysql-data:/var/lib/mysql
environment:
MYSQL_DATABASE: exment_database
MYSQL_ROOT_PASSWORD: secret
MYSQL_USER: exment_user
MYSQL_PASSWORD: secret
phpmyadmin:
image: phpmyadmin/phpmyadmin:latest
ports:
- 8888:80
depends_on:
- db
# volumes を定義する
volumes:
# volume の名前を指定
# Exmentのインストールパス
www-data:
# Compose の外ですでに作成済みの volume を指定する場合は ture を設定する。
# そうすると、 docker-compose up 時に Compose は volume を作成しようとしません。
# かつ、指定した volume が存在しないとエラーを raise します。
#external: true
# mysql dbのインストールパス
mysql-data:
あとでhttps-portalが80番ポートを使うので、nginxが8080になっているのは逆に都合がいいです。特にこのまま何も編集しません。
docker-compose.ymlとDockerfileは何もさわりませんが、php.iniだけは1行だけ追記します。
最後の行に
memory_limit=-1
を追記しておきます(ハマりポイント4、詳細は後述)
ではいよいよ…
[root@ip-172-xx-xx-x /home/centos/]# docker-compose up -d
初回なので、イメージの取得とビルド、ボリュームの作成をやってくれます。
起動が完了したら、docker-comopse ps
で、全コンテナがUpしていることを確認します。(スワップを作っていなかった時は、ここでMySQLがExitしてました)
無事起動したら、IPアドレスでアクセスしてみよう
Lightsail側で以下の手順を済ませておきます。
- 静的IPのアタッチ
- ポート8080番の開放
xx.xx.xx.xx:8080にブラウザでアクセスしてみて、Laravelの初期画面が表示されていれば成功です。
xx.xx.xx.xx:8080/adminにアクセスすると、Exmentの初期設定画面になります。
画面は3部構成になっていて、
- 言語とタイムゾーンの指定
- DB設定
- DB設定開始ボタン
の3画面です。何か入力するのは2画面目のDB設定です。
Dockerを使っていますので「ExmentのDocker環境を作ってみた」の記事を参考に、設定を埋めます。
- ホスト名 → db
- データベース名 → exment_database
- ユーザー名 → exment_user
- パスワード → secret
この後、無事インストールが完了すれば、Exmentの初期画面となります。
添付ファイルとかはS3に保存したいじゃんね!
今回のLightsailインスタンスは、保存領域が20GBと、まあ何か動かすのはいいけど、バイナリデータ突っ込んでいったらすぐパンパンになるよね、って容量です。
Exmentには、外部のストレージサービスに各種ファイルを保存するオプションがあります。
せっかくですので、AWSでそろえて、S3に保存させるようにしてみましょう。
S3も童貞でしたので、下記記事を参考にバケットを作成してみました。
Exment側でも設定が必要です。既にdocker-compose exec php bash
で立ち上がっているコンテナの中に入ります。
[root@ip-172-xx-xx-x /home/centos/]# docker-compose exec php bash
これで、Exmentが動いているphpコンテナの中に入れます。プロンプトの表示がこんな感じに変われば成功です。
root@f54bef27801a:/var/www#
つまり、クラウド上にあるLightsailの中にあるDockerコンテナphpの中にいるという二重構造なわけですね。
引き続き、「(上級者向け)ファイルの保存先変更」を読み解きながら、Exment(Laravel)のファイルを修正していきます。
Exmentルートフォルダにある、.envファイルをvimで修正/追記します。
EXMENT_DRIVER_EXMENT=s3
EXMENT_DRIVER_BACKUP=s3
EXMENT_DRIVER_TEMPLATE=s3
EXMENT_DRIVER_PLUGIN=s3
AWS_ACCESS_KEY_ID=(AWS S3のアクセスキー)
AWS_SECRET_ACCESS_KEY=(AWS S3のシークレットアクセスキー)
AWS_DEFAULT_REGION=(AWS S3のリージョン)
AWS_BUCKET_EXMENT=(添付ファイルで使用するAWS S3のバケット)
AWS_BUCKET_BACKUP=(バックアップで使用するAWS S3のバケット)
AWS_BUCKET_TEMPLATE=(テンプレートで使用するAWS S3のバケット)
AWS_BUCKET_PLUGIN=(プラグインで使用するAWS S3のバケット)
なお、EXMENT_DRIVER_xxx
はすべて設定する必要はなく、必要があるものだけ設定します。それに紐づくAWS_BUCKET_xxx
も必要なものだけでOKです。
私は添付ファイルとバックアップデータはS3に保存したかったので、
EXMENT_DRIVER_EXMENT
EXMENT_DRIVER_BACKUP
AWS_BUCKET_EXMENT
AWS_BUCKET_BACKUP
の4つのみ設定しました。
最後に、composerでライブラリをインストールします。
先ほど、docker-compose up -d
の前にphp.iniを編集しましたが、Composerはメモリ食いで、すぐPHPのメモリ利用可能上限に達してしまうので、この上限を解除する設定をしたのでした。
Composerはインストールに時間がかかるので、時間かかった結果失敗した、って辛いですよね…(筆者はとても悲しかったです。)なので、この設定はcomposer require
をする前にもう一度確認しておきましょう。
root@f54bef27801a:/var/www# php -i | grep memory_limit
memory_limit => -1 => -1
-1になっていればOKです。(メモリ上限なし、の意味)
では、いよいよライブラリのインストールです
root@f54bef27801a:/var/www# composer require league/flysystem-aws-s3-v3 ~1.0 -vvv
-vvv
オプションは、もっとも粒度細かくログを出す、という意味の指示です。composerはインストールにとても時間がかかるので、長い時間ターミナルが沈黙していると心配になります。
なので、逐次ログを出してくれるようにします。このオプションをして長いこと沈黙があれば、それは本当に何かしらの理由で止まっているか、めちゃくちゃ重い処理をしている、ということになります…
S3に添付ファイルをアップするオプションの設定は以上です。適当な画像でもアップして、バケットの中にファイルがあることを確認しましょう。
最後に呪いのhttpsです…
いや、httpsに何の悪いところもないのですが、かなりハマって悩まされたので…
色々やり方が悪かったのかと思い、Docker環境全捨てからの再インストールを何度も行ったので、かなり時間を食ってしまいました。
さっきも言いましたが、docker-composeにhttps-portalも混ぜて書いてしまうと、初回インストールに失敗します。結局はよくわからんエラーに遭遇して詰みました。
インストールは3画面あるといいましたが、最後の3画面目のインストールボタンを押したら、あのLaravelのグレーみの強いエラー画面で
Use of undefined constant STDIN - assumed 'STDIN' (this will throw an Error in a future version of PHP)
って出てきて、DBにデータが差し込めないことに。PHPやLaravelに明るくない筆者であるため、ここで断念しました。
httpならちゃんとうまくいったので、結局このエラーをつぶすことはあきらめ、httpでインストール完了させ、その後httpsにするという作戦に切り替えた次第です。
https-portalをdocker-compose.ymlに追記する
https-portalの部分だけ書き出します。
https-portal:
image: steveltn/https-portal:1
ports:
- '80:80'
- '443:443'
links:
- nginx
restart: always
volumes:
- ./certs:/var/lib/https-portal
environment:
STAGE: 'production'
DOMAINS: >-
example.com -> http://nginx:8080
depends_on:
- php
特に難しいことはありません。公式のサンプルとそんなに変わりませんし。ポイントとしては、enviroment:
のSTAGE:
が、'production'
か'staging'
でないと、Let's Encryptの本チャンの証明書はもらえないということです。ここがlocalとか指定なしだと、ローカル開発ってことで、なんちゃって証明書が発行されます。ここも地味にハマりポイントでした(ハマりポイント5)
さて、最後に https://example.com/ にアクセスして、Laravelの初期画面が表示されれば晴れて成功です…
と言いたいのですが、まだあります。
https://example.com/admin にアクセスすると、盛大に画面崩れを起こしているじゃないですか!
ブラウザコンソールを見ると、mixed contentでhttpがソースのCSS/JS類が全部ブロッキングされています。
これの対処が最初全然わからなかったのですが、試行錯誤の結果、LaravelおよびLaravel-adminが犯人と断定されました! asset('/css/hoge.css')みたいな記述のところで、http付のパスを出力しちゃってるようです…
以下、この件についての対策です。またdocker-compose exec php bash
して中に入ってください。
APP_ENV=production
class AppServiceProvider extends ServiceProvider
public function boot()
{
if (config('app.env') === 'production') {
\URL::forceScheme('https'); //Schemaじゃなくて、Scheme!!!(ハマりポイント6)
}
}
/*
|--------------------------------------------------------------------------
| Access via `https`
|--------------------------------------------------------------------------
|
| If your page is going to be accessed via https, set it to `true`.
|
*/
'https' => env('ADMIN_HTTPS', true), // ←デフォはfalseなので、trueに!
これで、すべてのアセットがhttpsから配信され画面崩れなく表示されるようになりました。
正直、これが本当の意味で正解かどうかわかりません。もしかしたら、AppProvider.phpは不要かもしれません… Laravelのバージョンによってコードの書き方が微妙に違うようでした。これは、本当にたくさんの参考ソースを読みまくって、なんとか動くコードに落ち着いたというのが実情です。
もし、もっと良い方法があるよ、という方はぜひコメント欄で教えてください。
以上、無事動くようになりました!
今のところ、機嫌よく動いてくれています。
セキュリティ等
本記事は検証目的の環境づくりのため、セキュリティ等については触れておりません。詳しい方は補足いただけると助かります。
今後
Exmentの素敵なところをほめまくる記事とか書きたいですね!