22
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

kintoneクローン? OSSWebDBのExmentをLightsail+Dockerで立ち上げたら結構ハマったのでメモしておく

Last updated at Posted at 2020-09-08

Exment is 何?

2020-09-08_11h46_18.png
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に目を通しておきますか。

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部構成になっていて、

  1. 言語とタイムゾーンの指定
  2. DB設定
  3. 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で修正/追記します。

.env
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の部分だけ書き出します。

docker-compose.yml
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して中に入ってください。

/var/www/exment/.env
APP_ENV=production
/var/www/exment/app/Providers/AppProvider.php
class AppServiceProvider extends ServiceProvider
    public function boot()
    {
    if (config('app.env') === 'production') {
       \URL::forceScheme('https'); //Schemaじゃなくて、Scheme!!!(ハマりポイント6)
    }
    }
/var/www/exment/config/admin.php
    /*
    |--------------------------------------------------------------------------
    | 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の素敵なところをほめまくる記事とか書きたいですね!

22
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?