- はじめに
- 環境
- 方針
- 構築手順
- 動作確認
- ついでにsystemdでサービス化
- メモ: 永続データの配置場所のまとめ
- メモ: データベースの配置場所
- メモ: 添付ファイルの配置場所
- メモ: プラグインの配置場所
- メモ: テーマの配置場所
- メモ: ディレクトリのオーナー
- 参考
はじめに
バグの管理などは通常ITS (Issue Tracking System)を利用するが、どういう形態のITSを使うかは状況によって異なる。 GitHubのIssues機能などSaaSで提供されているITSは手軽に使い始められるものの、センシティブな情報はクラウドへの配置が許されない事も多いので、そういった場合はオンプレで運用できるRedmineが重宝する。 そこで、RedmineをDocker Composeで構築して、ライトに運用してみることにしたので、その手順を記しておく。
環境
$ cat /etc/os-release | grep PRETTY_NAME PRETTY_NAME="Ubuntu 18.04.4 LTS" $ docker --version Docker version 19.03.5, build 633a0ea838 $ docker-compose --version docker-compose version 1.25.4, build 8d51620a
方針
- 運用
- 簡易な運用にする。サービスレベルは気にしない。落ちたら上げる、ぐらいで。
- Docker Composeを利用
- 可読性を保ったままパラメータの記述ができて便利。コンテナを起動するためのスクリプトを書かずにすむ。
- 永続データ (DB)
- DBサーバの運用はしない。SQLiteを利用して永続化する。
- 永続データ (ファイル)
- 特別なストレージは準備せずに、ホストのファイルシステムをマウントする。
構築手順
以下に構築手順を示す。 永続データについては色々調べまくったが、ここでは触れずに後続の節でメモを残しておく。
(1) Composeファイルの作成
以下の内容でComposeファイルを作成する。
Composeファイルのパスは任意だが、ここでは/opt/docker-compose-service/docker-compose.yml
として説明をすすめる。
version: '3.7' services: redmine: image: redmine:4.1 container_name: redmine volumes: - /var/lib/docker-compose-service/redmine/files:/usr/src/redmine/files - /var/lib/docker-compose-service/redmine/plugins:/usr/src/redmine/plugins - /var/lib/docker-compose-service/redmine/public/themes:/usr/src/redmine/public/themes - /var/lib/docker-compose-service/redmine/sqlite:/usr/src/redmine/sqlite ports: - 10080:3000 environment: - TZ=Asia/Tokyo
RedmineのイメージはRedmine公式のものを利用する。
Webサーバはコンテナ内部ではポート番号3000で立ち上がるが、コンテナ外部にはポート番号10080で公開する。
環境変数TZ
でタイムゾーンを指定して、表示時刻を日本標準時にしておく。
SQLiteを利用する場合は、以下のDockerHubのRedmineのサイトからの引用のとおり、単にDBの設定(環境変数の定義)をしないでおけばよい。
そうすれば、自動的にSQLiteにフォールバックされる。
If neither variable is set, the image will fall back to using SQLite.
(2) 永続データ用のディレクトリを作成
ホスト側に、docker-compise.yml
のvolumes
の項目で指定する、永続データ用のディレクトリを作成する。
$ sudo mkdir -p /var/lib/docker-compose-service/redmine/files $ sudo mkdir -p /var/lib/docker-compose-service/redmine/plugins $ sudo mkdir -p /var/lib/docker-compose-service/redmine/public/themes $ sudo mkdir -p /var/lib/docker-compose-service/redmine/sqlite
コンテナ内で動作するRedmineのプロセスのuidとgidは、それぞれ999である。 そのため、これらディレクトリのオーナーのuidとgidも、それぞれ999にする。
$ sudo chown -R 999:999 /var/lib/docker-compose-service/redmine
(3) デフォルトデータのロード
コンテナを立ち上げて、デフォルトデータをロードする。
$ docker-compose -f /opt/docker-compose-service/docker-compose.yml up $ docker exec -it redmine bundle exec rake redmine:load_default_data RAILS_ENV=production REDMINE_LANG=ja W, [2020-02-16T17:59:24.731200 #32] WARN -- : Creating scope :system. Overwriting existing method Enumeration.system. Default configuration data loaded.
警告が気になるが、メッセージ的に環境の問題ではないように見える。
Rubyのことは詳しくないのだが、おそらくRedmineのコードの中で意図的にEnumeration.system
を再定義(?)しているのだと思われる。
動作確認
詳細は割愛するが、以下の手順を実施した後でも期待通りの状態でRedmineが利用できるなら、永続データが欠落しておらず動作確認が取れたと言える。
docker-compose up
を実行し、コンテナを開始- チケットの作成、プラグインの追加、テーマの追加など、永続データの変更を伴う作業を実施
docker-compose down
を実行し、コンテナを停止docker rm redmine
を実行し、コンテナを削除docker-compose up
を実行し、コンテナを再び開始
ついでにsystemdでサービス化
以下の過去の記事で説明したように、Docker Composeをsystemdでサービス化しておくと、ライフサイクル(起動/停止など)の管理が容易になる。
構築は以上で終了。 以降は今回の構築にあたっての調査メモ。
メモ: 永続データの配置場所のまとめ
DockerHubのRedmineのサイトには、永続データを保存しておくためには、どのディレクトリに外部のストレージをマウントすればよいかが明記されていない。 そのため、Redmineのドキュメントを元に永続データが配置されているディレクトリを以下の通りに特定した。 ドキュメントは全部は読めていないので、抜け漏れはあるかもしれない。
項目 | 永続データの配置場所 | 参考ドキュメント |
---|---|---|
データベース | /usr/src/redmine/sqlite |
Backing up and restoring Redmine |
添付ファイル | /usr/src/redmine/files |
Backing up and restoring Redmine |
プラグイン | /usr/src/redmine/plugins |
Plugin Tutorial |
テーマ | /usr/src/redmine/public/themes |
HowTo create a custom Redmine theme |
以下、永続データの配置場所の詳細を説明する。
メモ: データベースの配置場所
データベース(SQLite)について、ドキュメント「Backing up and restoring Redmine」には、以下の記述がある。
SQLite databases are all contained in a single file, so you can back them up by copying the file to another location. You can determine the file name of SQLite database by looking at config/database.yml.
日本語訳すると、以下になる。
SQLiteデータベースは単一のファイルに必要なものがすべてが含まれているため、そのファイルを他の場所にコピーすることによりバックアップを取ることができます。 SQLiteデータベースのファイル名はconfig/database.ymlの中を確認することで特定できます。
そこで確認のために、ボリュームの設定を行わずに直接DockerからRedmineを起動し、config/database.yml
の中身を表示してみる。
$ docker run -it --rm --name redmine redmine:4.1 $ docker exec -it redmine /bin/cat /usr/src/redmine/config/database.yml production: adapter: "sqlite3" host: "localhost" username: "redmine" database: "sqlite/redmine.db" encoding: "utf8"
表示結果には、database: "sqlite/redmine.db"
とあるので、ディレクトリ/usr/src/redmine/sqlite
に永続用のストレージをマウントすればよい。
メモ: 添付ファイルの配置場所
添付ファイルについて、ドキュメント「Backing up and restoring Redmine」には、以下の記述がある。
All file uploads are stored in attachments_storage_path (defaults to the files/ directory). You can copy the contents of this directory to another location to easily back it up.
WARNING: attachments_storage_path may point to a different directory other than files/. Be sure to check the setting in config/configuration.yml to avoid making a useless backup.
言葉を補いつつ日本語訳すると、以下になる。
すべてのファイルは、設定項目attachments_storage_pathで指定された場所(デフォルトはディレクトリfiles/)に保存されます。 このディレクトリの内容を他の場所にコピーすることで、簡単にバックアップすることができます。
警告: 設定項目attachments_storage_pathはfiles/以外の場所を指している場合があります。 無効なバックアップを防ぐために、config/configuration.ymlの中の設定を必ず確認してください。
ということで、config/configuration.yml
の中を確認する必要がありそうだ。
しかしながら、ドキュメント「Installing Redmine」には、以下の記述がある。
If you need to override default application settings, simply copy config/configuration.yml.example to config/configuration.yml and edit the new file; the file is well commented by itself, so you should have a look at it.
言葉を補いつつ日本語訳すると、以下になる。
アプリケーション(=Redmine)のデフォルトの設定をオーバーライドする必要がある場合、config/configuration.yml.exampleをconfig/configuration.ymlにコピーして編集するだけでよいです。 そのファイルのコメントには十分な説明が書かれているので、よく読んでください。
言い換えると「すべてデフォルト値でよければconfig/configuration.yml
は不要」ということだと理解した。
Redmineの公式イメージの中を確認したがconfig/configuration.yml
は存在しなかったので、全てデフォルト値が利用されていることになる。
結局のところ、デフォルトであるディレクトリfiles
、つまりフルパスではディレクトリ/usr/src/redmine/files
に永続用のストレージをマウントすればよい。
メモ: プラグインの配置場所
プラグインについては、ドキュメント「Backing up and restoring Redmine」では何故か言及がない。
そこで、プラグイン開発のドキュメント「Plugin Tutorial」を確認すると、プラグインに必要なファイルはディレクトリplugins/[プラグイン名]
に集約しているようだ。
そのため、ディレクトリplugins
、つまりフルパスではディレクトリ/usr/src/redmine/plugins
に永続用のストレージをマウントすればよい。
ちなみに、公式のRedmineのイメージではプリインストールされているプラグインはないが、もしプラグインがプリインストールされているイメージを利用する場合は、アタッチするボリュームに事前にディレクトリplugins
の内容をコピーするなどの追加の手順が必要になる。
メモ: テーマの配置場所
テーマについても、ドキュメント「Backing up and restoring Redmine」では何故か言及がない。
そこで、テーマのカスタマイズのドキュメント「HowTo create a custom Redmine theme」を確認すると、テーマに必要なファイルはディレクトリpublic/themes/[テーマ名]
に集約しているようだ。
そのため、ディレクトリpublic/themes
、つまりフルパスではディレクトリ/usr/src/redmine/public/themes
に永続用のストレージをマウントすればよい。
ここで注意点がひとつある。
ディレクトリ/usr/src/redmine/public/themes
にはプリインストールのテーマの「Alternate」と「Classic」が含まれている。
そのため、単に永続用のストレージをマウントするとこれらのテーマが見えなくなってしまう。
必要であれば、事前にこれらのテーマを永続用のストレージにコピーするなどの追加の手順が必要になる。
ちなみに、デフォルトのテーマは/usr/src/redmine/public/stylesheets/application.css
なので、/usr/src/redmine/public/themes
の内容に関わらず利用できる。
メモ: ディレクトリのオーナー
コンテナにマウントするホスト側のディレクトリは、単に作成するだけではRedmineから書き込みが出来ず、以下のようにSQLiteのファイルの作成に失敗する。
$ docker-compose up Creating redmine ... done Attaching to redmine (略) redmine | SQLite3::CantOpenException: unable to open database file (略) redmine exited with code 1
原因は、ホスト側のディレクトリのオーナーとRedmineのプロセスのオーナーが異なるからである。
以下のようにコンテナに入ってRedmineのプロセスの情報を確認すると、ユーザはredmine
(uidは999)で、グループもredmine
(gidは999)で動作していることが分かる。
$ docker run -it --rm --name redmine redmine:4.1 $ docker exec -it redmine /bin/ps -e -o user,uid,group,gid,cmd USER UID GROUP GID CMD redmine 999 redmine 999 /usr/local/bin/ruby bin/rails server -b 0.0.0.0 root 0 root 0 /bin/ps -e -o user,uid,group,gid,cmd
念のため、/etc/passwd
と/etc/group
を確認してみると、以下のように確かにredmine
のエントリがある。
$ docker exec -it redmine /bin/cat /etc/passwd | grep redmine redmine:x:999:999::/home/redmine:/bin/sh $ docker exec -it redmine /bin/cat /etc/group | grep redmine redmine:x:999:
そのため、以下のようにホスト側で/var/lib/docker-compose-service/redmine
とそのサブディレクトリの所有ユーザーと所有グループを、それぞれ999に変更する。
$ sudo chown -R 999:999 /var/lib/docker-compose-service/redmine
ただし、ホスト側ではuid 999とgid 999は別の目的で利用されている可能性がある。
セキュリティの観点では、コンテナの都合に無理やり合わせてchown
するのはあまり良くないので、理想的にはユーザーネームスペースのリマッピングなど、何らかの対策が必要になる。