RedmineをAWSのマネージドサービスである App Runner+RDS+S3のシンプルな構成で動かす方法です。
概要
- コンテナのベースイメージは
Redmine公式のredmine:6.1.0-alpine3.22を使用 - AWSコンテナサービス:
App Runnerを使用 - データベース(RDS):
Aurora MySQL 8.0を使用 (Serverlessも対応) - 添付ファイルの格納先:
Amazon S3を使用-
RedMica S3 pluginを使う (バージョン 3.0.0)
-
特徴
- シンプルな構成、簡単構築/設定/運用 (Auto Scaling対応)
-
ALB+ECS Fargateの構成に比べてシンプルで、コストも安価(一時停止も可能) -
AWS App RunnerはEFSマウントできないため、代わりにAmazon S3を使う
-
- セキュリティ関連
- Redmine公式イメージを使用。ベースイメージは
Alpine Linuxを使用 - S3アクセスはIAMロールを使うため、アクセスキーは不要
- マルチステージビルドで実行時のパッケージを最小化
-
CRITICAL/HIGHの脆弱性に対応(検証時点)
- Redmine公式イメージを使用。ベースイメージは
構成例
- AWS App Runner (プライベート接続の構成)
- 受信ネットワークトラフィック: プライベートエンドポイント
- VPC経由からは
AWS PrivateLink経由でApp Runnerへアクセス(https)
- VPC経由からは
- 送信ネットワークトラフィック: カスタム VPC
- VPCコネクタ経由でVPC内のRDSへアクセス、S3へアクセス
- 受信ネットワークトラフィック: プライベートエンドポイント
- Amazon Aurora MySQL 8.0 Serverless (RDS)
- パブリックアクセスは無効化
- App RunnerからはVPCコネクタ経由でアクセス (3306/tcp)
- Amazon S3
- パブリックアクセスブロックを有効化
- App RunnerからはVPCコネクタ → VPC S3 Gatewayエンドポイント経由でアクセス(https)
留意事項
本記事では、設定の概要とポイントを解説します。
- 前提スキル:AWS App Runner、RDS、S3などの構築/設定/運用経験
- 具体的な構築手順などは省略しています
- RDSへのDB接続のIAMロール認証は未対応(本記事では触れません)
- メール通知の設定も触れません
App Runnerはプライベートネットワークに構築することを強く推奨します。
パブリックネットワークで構築すると、セキュリティ事故のリスクが高まります。
(WAFの導入、IPアドレス制限、MFAの利用必須など、別途セキュリティ対策が必須)
ファイル構成
Redmineコンテナのファイル構成(例)
- redmine-app: コンテナアプリのフォルダ(任意名称)
-
Dockerfile... Redmineコンテナの設定 -
docker-entrypoint.sh... 起動スクリプト -
Gemfile.local- 個別バージョンアップで使用 (rackの脆弱性対応) -
plugins/redmica_s3-RedMica S3プラグインを置く -
config/database.yml- データベース設定 (環境変数で設定) -
config/additional_environment.rb(オプション設定。サブURLで動かす場合) -
config/config.ru(オプション設定。サブURLで動かす場合)
-
Dockerfile
# Multi-stage build for plugins
FROM redmine:6.1.0-alpine3.22 as plugin-builder
RUN apk update && apk upgrade --no-cache && apk add --no-cache pcre2 --upgrade
WORKDIR /usr/src/redmine
COPY plugins/redmica_s3 /usr/src/redmine/plugins/redmica_s3
COPY Gemfile.local /usr/src/redmine/Gemfile.local
# Remove rack duplicate entries
RUN sed -i "/^gem 'rack'/d" Gemfile && bundle update rack || true
RUN bundle config set without 'development test'
RUN bundle install
# Final stage
FROM redmine:6.1.0-alpine3.22
RUN apk update && apk upgrade --no-cache && \
apk add --no-cache mysql-client pcre2 --upgrade && \
rm -rf /var/cache/apk/*
COPY --from=plugin-builder /usr/src/redmine/plugins /usr/src/redmine/plugins
RUN chown -R redmine:redmine /usr/src/redmine/plugins
COPY --from=plugin-builder /usr/src/redmine/Gemfile.lock /usr/src/redmine/Gemfile.lock
COPY --from=plugin-builder /usr/src/redmine/Gemfile /usr/src/redmine/Gemfile
COPY --from=plugin-builder /usr/src/redmine/Gemfile.local /usr/src/redmine/Gemfile.local
RUN bundle config set without 'development test' && \
bundle config set deployment 'false' && \
bundle config set cache_all 'false' && \
bundle install && \
rm -f /usr/local/bundle/specifications/rack-3.1.17.gemspec || true && \
bundle info rack | grep -E "rack \(3.1.18\)" || (echo 'Unexpected rack version'; exit 1)
COPY config/database.yml /usr/src/redmine/config/
COPY config/additional_environment.rb /usr/src/redmine/config/
COPY config/config.ru /usr/src/redmine/config.ru
RUN chown -R redmine:redmine /usr/src/redmine/config
# Delete gosu (CVE-2025-47912,58183,58186,58187,58188,61724)
RUN rm -f /usr/local/bin/gosu
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
USER redmine
EXPOSE 3000
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
- ベースイメージは
redmine:6.1.0-alpine3.22を使用 - サブURL (
/redmine/など) で動かさない場合は、config/additional_environment.rb、config/config.ruのCOPY行は不要 (コメントアウト または 削除)# COPY config/additional_environment.rb /usr/src/redmine/config/ # COPY config/config.ru /usr/src/redmine/config.ru - Gemfile.local のあたりは、個別に脆弱性対応が不要になったら消す
- /usr/local/bin/gosu は脆弱性があるため削除した (実行時は不要と思う)
docker-entrypoint.sh
#!/bin/sh
set -e
echo "Waiting for MySQL to be ready..."
until mysql --skip-ssl -h "${REDMINE_DB_MYSQL}" -u "${REDMINE_DB_USERNAME}" -p"${REDMINE_DB_PASSWORD}" -e 'SELECT 1' >/dev/null 2>&1; do
echo 'Still waiting for MySQL...'
sleep 2
done
echo 'MySQL is ready!'
if [ -n "$S3_BUCKET" ]; then
echo "Generating S3 configuration from environment variables..."
cat > /usr/src/redmine/config/s3.yml <<EOF
production:
access_key_id: ${S3_ACCESS_KEY_ID:-}
secret_access_key: ${S3_SECRET_ACCESS_KEY:-}
bucket: ${S3_BUCKET}
region: ${S3_REGION:-ap-northeast-1}
folder: ${S3_FOLDER:-}
endpoint: ${S3_ENDPOINT:-}
thumb_folder: ${S3_THUMB_FOLDER:-tmp}
import_folder: ${S3_IMPORT_FOLDER:-tmp}
EOF
fi
bundle exec rake db:migrate RAILS_ENV=production
bundle exec rake redmine:plugins:migrate RAILS_ENV=production
exec bundle exec rails server -b 0.0.0.0 -p 3000 -e production
Gemfile.local (脆弱性対策)
# Security pin for rack (CVE-2025-61919 mitigation)
gem 'rack', '3.1.18'
-
rack-3.1.17は脆弱性(CVE-2025-61919)があるため、個別にバージョンアップしている
plugins/redmica_s3: プラグイン導入
-
RedMica S3プラグインをダウンロードしてplugins/redmica_s3のように置いておく
https://github.com/redmica/redmica_s3例cd plugins git clone https://github.com/redmica/redmica_s3 -
S3連携の設定は、
docker-entrypoint.shで記述している。値は環境変数で設定する- S3バケットを指定:
${S3_BUCKET}※必須 -
access_key_id:${S3_ACCESS_KEY_ID:-}※設定不要 -
secret_access_key:${S3_SECRET_ACCESS_KEY:-}※設定不要
- S3バケットを指定:
アクセスキーとシークレットは必須と書いているが、IAMロールを使うことで S3_ACCESS_KEY_ID と S3_SECRET_ACCESS_KEY は環境変数で設定しない。
config/database.yml: データベース設定
production:
adapter: mysql2
database: <%= ENV['REDMINE_DB_DATABASE'] || 'redmine' %>
host: <%= ENV['REDMINE_DB_MYSQL'] || ENV['REDMINE_DB_HOST'] || 'localhost' %>
port: <%= ENV['REDMINE_DB_PORT'] || 3306 %>
username: <%= ENV['REDMINE_DB_USERNAME'] || 'redmine' %>
password: <%= ENV['REDMINE_DB_PASSWORD'] || '' %>
encoding: <%= ENV['REDMINE_DB_ENCODING'] || 'utf8mb4' %>
collation: utf8mb4_unicode_ci
reconnect: true
- 環境変数で設定するため、内容はそのままでOK
オプション設定(サブURL利用)
参考)URLパスを /redmine/ で動かしたい場合
-
config/にadditional_environment.rbとconfig.ruのファイルを作成する
config/additional_environment.rb
# Redmine additional environment configuration
Rails.application.configure do
config.relative_url_root = '/redmine'
config.action_mailer.default_url_options = {
host: 'localhost',
port: 3000,
script_name: '/redmine'
}
end
ActionController::Base.relative_url_root = '/redmine'
config/config.ru
# Modified for subpath support
require_relative 'config/environment'
map '/redmine' do
run Rails.application
end
# redirect
map '/' do
run lambda { |env|
[302, {'Location' => '/redmine/', 'Content-Type' => 'text/plain'}, ['Redirecting to /redmine/']]
}
end
App Runnerの設定 (ポイントのみ)
- コンテナのポートは
3000※サービス設定>ポートで指定 - 環境変数の設定は必須
- 機密情報は 事前に
SSMパラメータストアで暗号化して設定し、ARNを指定する -
SECRET_KEY_BASEは、セッション生成で使うシークレット。変更するとすべてのセッションを無効化できる。乱数を指定するとよい (SSMパラメータストアで管理)
- 機密情報は 事前に
- セキュリティ > インスタンスロールで
SSMパラメータストアとS3アクセスを許可する
環境変数の設定例
App Runner > 設定 > サービス設定 > 環境変数
| タイプ | 環境変数名 | 値 |
|---|---|---|
| テキスト | TZ | 例) Asia/Tokyo
|
| テキスト | REDMINE_DB_ENCODING | utf8mb4 |
| テキスト | REDMINE_PLUGINS_MIGRATE |
true ※起動時に自動的にマイグレーションを実行 |
| テキスト | REDMINE_DB_MYSQL | RDSのクラスターエンドポイントを指定 |
| パラメータストア | REDMINE_DB_USERNAME | DB接続ユーザー名 (ARN指定) |
| パラメータストア | REDMINE_DB_PASSWORD | DB接続パスワード (ARN指定) |
| テキスト | REDMINE_DB_DATABASE | 例) redmine
|
| テキスト | REDMINE_DB_PORT | 例) 3306
|
| パラメータストア | SECRET_KEY_BASE | セッション生成用の乱数 (ARN指定) |
| テキスト | S3_BUCKET | S3バケット名 例) example-bucket-123456789012
|
| テキスト | S3_REGION | S3のリージョン 例) ap-northeast-1
|
| テキスト | S3_FOLDER | S3のファイル保存先のパス 例) redmine/files
|
- 環境変数については、Redmine公式イメージの説明を参照
https://hub.docker.com/_/redmine#environment-variables
機密情報は、SSMパラメータストアで設定すること(ARNを指定する)
App Runnerのインスタンスロール (IAMロール)
- SSMパラメータストアから値を取得する
- Amazon S3のバケット内のオブジェクト操作
App Runner > 設定 > セキュリティ > インスタンスロール
-
例) AppRunnerForSSMParameterStore+S3
- 参考) ドキュメント > App Runner > デベロッパーガイド > 環境変数の参照
https://docs.aws.amazon.com/ja_jp/apprunner/latest/dg/env-variable.html#env-variable.sensitivedata.permissions
- 参考) ドキュメント > App Runner > デベロッパーガイド > 環境変数の参照
-
IAMロールを作成し、SSMパラメータストアとS3の権限を設定する
-
カスタム信頼ポリシー
カスタム信頼ポリシー{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "tasks.apprunner.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } -
許可ポリシー: 例) AppRunnerForSSMParameterStore
AppRunnerForSSMParameterStore{ "Statement": [ { "Action": [ "secretsmanager:GetSecretValue", "kms:Decrypt*" ], "Effect": "Allow", "Resource": [ "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:*", "arn:aws:kms:ap-northeast-1:123456789012:key/*" ] }, { "Action": [ "ssm:GetParameters" ], "Effect": "Allow", "Resource": [ "arn:aws:ssm:ap-northeast-1:123456789012:parameter/*" ] } ], "Version": "2012-10-17" }- AWSアカウントID
123456789012部分は環境に合わせて修正
- AWSアカウントID
-
許可ポリシー: 例) S3-access
S3-access{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::example-bucket-123456789012", "arn:aws:s3:::example-bucket-123456789012/*" ] } ] }- ※バケット指定
example-bucket-123456789012の部分は環境に合わせて修正
- ※バケット指定
-
脆弱性対応
公式イメージをそのまま使うと、脆弱性が多く含まれている場合がある。
脆弱性対応については、本記事作成時点の情報のため参考まで。
-
OS パッチ適用(apk upgrade) → OS パッケージの脆弱性は解消 (CRITICAL / HIGHもあり)
-
Ruby (gemspec):
rack-3.1.17の脆弱性 (HIGH: CVE-2025-61919)- 個別対応で
rack 3.1.17→3.1.18に更新 (修正版: ~> 3.1.18 または >= 3.2.3)
- 個別対応で
-
usr/local/bin/gosu: HIGH 6件 (CVE-2025-47912, 58183, 58186, 58187, 58188, 61724)
- Dockerfileで
gosuを削除で対応 (rm -f /usr/local/bin/gosu)
- Dockerfileで
コンテナイメージを作成したら脆弱性スキャンしよう
(スキャンツール: trivy、AWS ECR/Inspectorなど)
参考
Redmine_JP
Redmine公式イメージ (Docker Hub)
RedMica S3プラグイン (GitHub: redmica/redmica_s3)
App Runner > デベロッパーガイド