こんにちは、テクマトリックスの村上です。
社内利用しているRedmineを自社のオンプレサーバーからEC2のDockerコンテナへ移行する機会があったので記載します。

EC2に移行するきっかけ

12月に本社を移転する予定で、オンプレサーバーも引っ越しを行います。このタイミングで社内サーバーのアプリをEC2に移行することになりました。

Redmineの移行内容と構築の要件

移行するRedmineについては、以下の要件がありました。

項目内容状況
Redmineのデータ移行の対象・DBの情報
・添付ファイル
社内の共有サーバーに保存されているため、それらを移行します。
データベースはPostgreSQLを利用しています。
利用しているプラグインの移行移行できるものは全て移行するが、代替えの方法がある場合は不要
また、必要に応じてプラグインのアップデートを実施
以下のOSSプラグインを利用中。
・Redmine Lightbox 2
・Redmine Startpage plugin
・View Customize plugin
メールサーバーの設定の移行既存の設定を移行/var/lib/redmine/config/configuration.ymlに設定されています。
ログイン認証の移行現在利用しているLDAP認証を継続して利用DBにLDAP認証の設定が保存されています。
構築する環境Dockerコンテナ新規サーバーにDockerをインストール済みです。
既存環境はDockerを未使用。
バックアップの取得以下を指定のディレクトリに保存
・DBの情報
・添付ファイル
新規作成する必要があります。
リバースプロキシの利用有無apacheのリバースプロキシを利用新規設定する必要があります。
ネットワークDirect Connectでオンプレミスと同様にAWSから社内ネットワークに接続が可能メールサーバーや認証サーバーは設定を変える必要がないです。

新規環境で環境構築

①Redmineのコンテナ作成

Redmineのコンテナを構築するために、docker-compose.ymlとDockerfileを作成します。
volumeに添付ファイルとpluginファイルを設定しました。
設定しておくことで、コンテナが停止した場合も永続化されEC2上に残ります。また、pluginのアップデート時にコンテナ内へファイルを移動する必要がなくなり、少し楽になります。

以下は作成したファイル例になります。

services:
  redmine:
    build: .
    environment:
      REDMINE_DB_POSTGRES: db
      REDMINE_DB_PASSWORD: パスワード
      REDMINE_DB_DATABASE: データベース名
      REDMINE_DB_USERNAME: ユーザー名
      REDMINE_PLUGINS_MIGRATE: 1
      TZ: Asia/Tokyo
    ports:
            - ポート番号:3000
    privileged: true
    volumes:
      - ./data/plugins:/usr/src/redmine/plugins
      - ./data/files:/usr/src/redmine/files
    restart: always
  db:
    image: postgres:14.5
    environment:
      POSTGRES_ROOT_PASSWORD: パスワード
      POSTGRES_USER: ユーザー名
      POSTGRES_PASSWORD: パスワード
      POSTGRES_DATABASE: データベース名
      TZ: Asia/Tokyo
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=C"
    restart: always
FROM redmica/redmica:2.0.0

# システム設定
ENV LANG=ja_JP.UTF-8 \
    LC_ALL=ja_JP.UTF-8
RUN apt-get -y update
RUN apt-get -y install -y libjpeg62 libfontconfig-dev unzip wget libxrender1 make g++

RUN bundle install --without development test

上記を作成後にコンテナを起動することで、Redmine(http://IPアドレス:ポート番号)にアクセスできるかを確認します。
コンテナ起動時のコマンドは以下です。

$ docker-compose build
$ docker-compose up -d

②Redmineをapacheのリバースプロキシでアクセスするように設定

リバースプロキシを利用する場合は、コンテナ内にあるRedmineの設定ファイル(/usr/src/redmine/config.ruと/usr/src/redmine/config/environment.rb)とサーバーにあるapacheファイルを書き換えます。
Redmineの設定ファイルについては、コンテナの永続化(volume)ではなくDockerfileのCOPYを利用しました。COPYは指定したファイルやディレクトリのみをコンテナ作成時に配置し、永続化はコンテナ作成時にサーバー上のファイルを全部コピーします。つまり、永続化を利用する際は指定したディレクトリのファイルを全て配置する必要があります。

今回はconfig.ruをルートディレクトリに配置する必要があるため、COPYを利用しました。永続化すると、Redmine本体のアップデート時にルートディレクトリの全ファイルを更新する必要があり、手間がかかります。今後のアップデートを考慮すると、必要なファイルのみを配置するCOPYの方が良いです。

設定内容は以下になります。

FROM redmica/redmica:2.0.0

# システム設定
ENV LANG=ja_JP.UTF-8 \
    LC_ALL=ja_JP.UTF-8
RUN apt-get -y update
RUN apt-get -y install -y libjpeg62 libfontconfig-dev unzip wget libxrender1 make g++

#設定ファイルをコピーして配置する
COPY ./data/config/environment.rb /usr/src/redmine/config/
COPY ./data/config.ru /usr/src/redmine/

RUN bundle install --without development test
# This file is used by Rack-based servers to start the application.

require ::File.expand_path('../config/environment',  __FILE__)
#run Rails.application
map ENV['RAILS_RELATIVE_URL_ROOT'] || '/' do
  run Rails.application
end
# frozen_string_literal: true
#
# Load the Rails application
require File.expand_path('../application', __FILE__)

# Make sure there's no plugin in vendor/plugin before starting
vendor_plugins_dir = File.join(Rails.root, "vendor", "plugins")
if Dir.glob(File.join(vendor_plugins_dir, "*")).any?
  $stderr.puts "Plugins in vendor/plugins (#{vendor_plugins_dir}) are no longer allowed. " \
    "Please, put your Redmine plugins in the `plugins` directory at the root of your " \
    "Redmine directory (#{File.join(Rails.root, "plugins")})"
  exit 1
end

# Initialize the Rails application
Rails.application.initialize!

ActionController::Base.relative_url_root = RedmineApp::Application.routes.default_scope
Redmine::Utils::relative_url_root = RedmineApp::Application.routes.default_scope

ENV['RAILS_RELATIVE_URL_ROOT'] = "/redmine/"
Redmine::Utils::relative_url_root = ENV['RAILS_RELATIVE_URL_ROOT']

サーバーのapacheの設定ファイルには、以下を追記しました。

...
ProxyRequests Off
AllowEncodedSlashes NoDecode
ProxyPass /redmine/ http://IPアドレス:ポート番号/redmine/
ProxyPassReverse /redmine/ http://IPアドレス:ポート番号/redmine/

apacheを再起動し、Redmine(http://IPアドレス/redmine/)にアクセスできるかを確認します。

③既存のRedmineから移行

既存のRedmineの情報を移行するために以下の内容を実施します。

  • 既存環境のpluginを移行先のサーバー上に配置
  • 既存環境のfilesを移行先のサーバー上に配置
  • メールサーバーの設定
    既存のconfiguration.ymlを移行先のサーバー上に配置し、COPYでコンテナに配置するように設定。
    以下の内容をDockerfileに追記
    COPY ./data/config/configuration.yml /usr/src/redmine/config/
  • DBの移行
    DBコンテナにダンプファイルをコピーし、コンテナにアタッチしてリストアします。
  • コンテナを再起動
    設定ファイルの読み込みやプラグインのマイグレーションを行います。

上記のDBの移行時は以下のコマンドを実行しました。
【EC2上で操作】

#DBコンテナにダンプファイルをコピー
$ docker cp ダンプファイル名 redmica_db_1:/tmp

#Redmineコンテナを停止
$ docker stop redmica_redmine_1

#DBコンテナにアタッチ
$ docker exec -it redmica_db_1 /bin/bash

【DBコンテナ内で操作】

#PostgreSQLにログイン
$ su postgres
$ psql -U redmine

#redmineのデータベースを削除
> \c postgres
> drop database redmine;

#redmineのデータベースを作成
> CREATE DATABASE redmine WITH ENCODING='UTF8' OWNER=redmine;
> \q

#redmineのデータベースをリストア
$ psql -U redmine -d redmine < /tmp/ダンプファイル名

#パスワードの設定
$ psql -U redmine
> ALTER USER redmine WITH PASSWORD 'パスワード';


④Redmineにログインして以下の確認をします。

  • LDAP認証でログインできるか。
  • 想定していたプラグインがインストールされているか
  • 動作に問題がないかなど

バックアップの設定

サーバー上のfilesディレクトリ(添付ファイル)とDBコンテナのPostgreSQLのダンプファイルを定期的に取得するようにします。今回はファイルの取得をshellで、定期的な実行をcronで行いました。

作成したshellは以下になります。

#!/bin/sh

#dumpファイルを取得
docker exec redmica_db_1 pg_dump -Uユーザー名 --if-exists -c redmine > /tmp/redmine_`date "+%Y%m%d"`.pgdump
#圧縮して保存場所に配置
tar -zcvf 保存先ディレクトリ/redmine_`date "+%Y%m%d"`.pgdump.tar.gz /tmp/`date "+%Y%m%d"`.pgdump

#不要ファイルの削除
rm  /tmp/redmine_`date "+%Y%m%d"`.pgdump

#filesを圧縮
tar -zcvf 保存先ディレクトリ/redmine_`date "+%Y%m%d"`.file.tar.gz filesディレクトリ


cronは、毎日深夜1時に実行されるように以下の設定を行いました。

1 * * * bash /opt/redmine/backup.sh

まとめ

オンプレのRedmineをEC2のDockerコンテナに移行しました。EC2などの環境はあらかじめ作成されていたため、Dockerコンテナの作成から実施しました。コンテナの再作成やRedmineのバージョンアップ、プラグインのバージョンアップを考慮した作りにしたため、今後のメンテナンスは比較的簡単に行えるかと思います。DockerのRedmineコンテナの構築やコンテナへのデータ移行時に少しでもご参考になれば幸いです。