2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RedmineをAWS App Runnerで動かす方法 (S3連携)

Last updated at Posted at 2025-12-11

RedmineAWSのマネージドサービスである App Runner+RDS+S3のシンプルな構成で動かす方法です。

概要

  • コンテナのベースイメージは Redmine公式のredmine:6.1.0-alpine3.22を使用
  • AWSコンテナサービス: App Runner を使用
  • データベース(RDS): Aurora MySQL 8.0 を使用 (Serverlessも対応)
  • 添付ファイルの格納先: Amazon S3 を使用

特徴

  • シンプルな構成、簡単構築/設定/運用 (Auto Scaling対応)
    • ALBECS Fargateの構成に比べてシンプルで、コストも安価(一時停止も可能)
    • AWS App RunnerEFSマウントできないため、代わりに Amazon S3を使う
  • セキュリティ関連
    • Redmine公式イメージを使用。ベースイメージはAlpine Linuxを使用
    • S3アクセスはIAMロールを使うため、アクセスキーは不要
    • マルチステージビルドで実行時のパッケージを最小化
    • CRITICAL/HIGHの脆弱性に対応(検証時点)

構成例

  • AWS App Runner (プライベート接続の構成)
    • 受信ネットワークトラフィック: プライベートエンドポイント
      • VPC経由からは AWS PrivateLink 経由でApp Runnerへアクセス(https)
    • 送信ネットワークトラフィック: カスタム 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コンテナのファイル構成(例)

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.rbconfig/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:-} ※設定不要

アクセスキーとシークレットは必須と書いているが、IAMロールを使うことで S3_ACCESS_KEY_IDS3_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.rbconfig.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

機密情報は、SSMパラメータストアで設定すること(ARNを指定する)

App Runnerのインスタンスロール (IAMロール)

  • SSMパラメータストアから値を取得する
  • Amazon S3のバケット内のオブジェクト操作

App Runner > 設定 > セキュリティ > インスタンスロール

  • 例) AppRunnerForSSMParameterStore+S3

  • 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 部分は環境に合わせて修正
    • 許可ポリシー: 例) 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.173.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)

コンテナイメージを作成したら脆弱性スキャンしよう
(スキャンツール: trivy、AWS ECR/Inspectorなど)

参考

Redmine_JP

Redmine公式イメージ (Docker Hub)

RedMica S3プラグイン (GitHub: redmica/redmica_s3)

App Runner > デベロッパーガイド

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?