0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JPiereをDockerComposeでインストールしてみた【日本企業向けオープンソースERP】

Last updated at Posted at 2025-05-22

オープンソースERPの「iDempiere」を日本の商習慣に対応させた「JPiere」を、DockerComposeで構築してみました。企業級ERPシステムのDocker化は想像以上に複雑で、特にJetty設定の動的生成やデータベース初期化の自動化などめちゃムズかったです

JPiereとは何か

JPiereは、世界的に利用されているオープンソースERP「iDempiere」を日本の商習慣に適応させたERPシステムです。消費税計算、日本の会計基準、商取引慣行などに対応しており、中小企業から大企業まで幅広く利用されているそうです。

主な特徴

  • 販売管理、購買管理、在庫管理、財務会計の統合システム
  • 日本の消費税法に完全対応
  • Webベースのユーザーインターフェース
  • 多言語対応(日本語、英語など)
  • プラグインによる機能拡張

今回構築する環境

システム構成

アプリケーションサーバー

  • JPiere 11(iDempiere 11ベース)
  • Java 17(Eclipse Temurin)
  • Jetty Webサーバー

データベース

  • PostgreSQL 13
  • 日本語対応設定(UTF-8、Locale C)

プロジェクト構成

実際のファイル構成は以下の通りです。

jpieredocker/
├── Dockerfile                               # JPiereアプリケーション用イメージ
├── docker-compose.yaml                      # サービス構成定義
├── docker-entrypoint.sh                     # 起動時スクリプト
└── files/
    ├── JPiereServer11.gtk.linux.x86_64.zip  # JPiereサーバー本体
    └── ExpDat.jar                           # データベース初期データ

files/ディレクトリにダウンロードしたJPiereファイルを配置しました。

Docker Composeの詳細設定

本当は環境変数を使うべきでしょうが簡易的に…

PostgreSQLサービス

postgres:
  image: postgres:13
  platform: linux/amd64
  hostname: "postgres"
  environment:
    - POSTGRES_DB=postgres
    - POSTGRES_USER=postgres
    - POSTGRES_PASSWORD=postgres
    - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C
  volumes:
    - postgres_data:/var/lib/postgresql/data
    - ./init-postgres.sql:/docker-entrypoint-initdb.d/init-postgres.sql
  ports:
    - "5432:5432"
  networks:
    - jpiere_network
  healthcheck:
    test: ["CMD-SHELL", "pg_isready -U postgres"]
    interval: 10s
    timeout: 5s
    retries: 5

重要なポイント:

JPiereサービス

jpiere:
  build:
    context: .
    dockerfile: Dockerfile
  platform: linux/amd64
  image: jpiere:11
  hostname: "jpiere"
  ports:
    - "8080:8080"    # Web UI
    - "12612:12612"  # Telnet管理コンソール
  environment:
    - TZ=Asia/Tokyo
    - DB_NAME=idempiere
    - DB_HOST=postgres
    - DB_PORT=5432
    - DB_USER=adempiere
    - DB_PASS=adempiere
    - DB_ADMIN_PASS=postgres
    - JAVA_OPTS=-Xms256M -Xmx2048M
    - MIGRATE_EXISTING_DATABASE=false
    - DISABLE_SSL=true
  volumes:
    - jpiere_config:/opt/idempiere/configuration
    - jpiere_plugins:/opt/idempiere/plugins
    - jpiere_log:/opt/idempiere/log
  depends_on:
    postgres:
      condition: service_healthy
  networks:
    - jpiere_network

重要なポイント:

SSL無効化: 開発環境での簡単な接続のため

Dockerfileの詳細解析

基盤イメージとパッケージ

FROM --platform=linux/amd64 eclipse-temurin:17-jdk-jammy

ENV IDEMPIERE_VERSION 11
ENV IDEMPIERE_HOME /opt/idempiere
ENV IDEMPIERE_PLUGINS_HOME $IDEMPIERE_HOME/plugins
ENV IDEMPIERE_LOGS_HOME $IDEMPIERE_HOME/log

# 必要なパッケージのインストール
RUN apt-get update && \
  apt-get install -y --no-install-recommends nano postgresql-client unzip && \
  rm -rf /var/lib/apt/lists/*

Eclipse Temurin 17を使用することで、Oracle JDKのライセンス問題を回避しています。

JPiereサーバーの展開処理

# ローカルファイルをコンテナにコピー
COPY files/JPiereServer11.gtk.linux.x86_64.zip /tmp/jpiere-server.zip
COPY files/ExpDat.jar /tmp/ExpDat.jar

# JPiereサーバーのセットアップ
RUN echo "=== JPiere Server Setup Start ===" && \
  echo "Hash: $(md5sum /tmp/jpiere-server.zip)" > $IDEMPIERE_HOME/MD5SUMS && \
  echo "Date: $(date)" >> $IDEMPIERE_HOME/MD5SUMS && \
  echo "=== Extracting JPiere Server ===" && \
  cd /tmp && \
  unzip -q jpiere-server.zip && \
  echo "=== Finding jpiere-server directory ===" && \
  JPIERE_DIR=$(find /tmp -maxdepth 1 -name "jpiere-server*" -type d | head -1) && \
  echo "Found JPiere directory: $JPIERE_DIR" && \
  if [ -n "$JPIERE_DIR" ] && [ -d "$JPIERE_DIR" ]; then \
    cp -r "$JPIERE_DIR"/* "$IDEMPIERE_HOME"/ && \
    rm -rf "$JPIERE_DIR" && \
    rm -f /tmp/jpiere-server.zip; \
  else \
    echo "ERROR: JPiere server directory not found!" && \
    exit 1; \
  fi

この部分で重要なのは:

  1. MD5ハッシュ記録: ビルド時のファイル整合性を記録
  2. 動的ディレクトリ検索: ZIPファイル内のディレクトリ名を自動検出
  3. エラーハンドリング: 展開に失敗した場合はビルド停止

データベース初期データの処理

# ExpDat.jarの解凍(JPiere用PostgreSQLダンプファイル)
RUN echo "=== ExpDat.jar Processing Start ===" && \
  cd /tmp && \
  if [ -f ExpDat.jar ]; then \
    unzip ExpDat.jar && \
    ls -la ExpDat.dmp && \
    echo "ExpDat.dmpファイルを/tmp/に配置完了" && \
    rm ExpDat.jar; \
  else \
    echo "ERROR: ExpDat.jar not found!" && \
    exit 1; \
  fi

ExpDat.jarには、JPiere用のPostgreSQLダンプファイル(ExpDat.dmp)が含まれています。これがJPiereのマスターデータと初期設定データです。

環境設定ファイルの生成

# myEnvironment.shの作成と必要ファイルの確認
RUN echo "=== Environment Setup ===" && \
  if [ ! -d "$IDEMPIERE_HOME/utils" ]; then \
    mkdir -p "$IDEMPIERE_HOME/utils"; \
  fi && \
  if [ ! -f "$IDEMPIERE_HOME/utils/myEnvironment.sh" ]; then \
    echo "#!/bin/bash" > "$IDEMPIERE_HOME/utils/myEnvironment.sh" && \
    echo "export JAVA_HOME=${JAVA_HOME}" >> "$IDEMPIERE_HOME/utils/myEnvironment.sh" && \
    echo "export IDEMPIERE_HOME=${IDEMPIERE_HOME}" >> "$IDEMPIERE_HOME/utils/myEnvironment.sh" && \
    echo "export PATH=\$PATH:\$JAVA_HOME/bin" >> "$IDEMPIERE_HOME/utils/myEnvironment.sh" && \
    chmod +x "$IDEMPIERE_HOME/utils/myEnvironment.sh"; \
  fi

iDempiereが期待する環境設定ファイルを動的に生成しています。

エントリーポイントスクリプトの複雑さ

docker-entrypoint.shは、このプロジェクトで最も複雑で重要な部分です。この部分の実装に最も時間がかかりました。

環境変数の設定

# 環境変数設定
JAVA_OPTIONS=${JAVA_OPTIONS:-""}
KEY_STORE_PASS=${KEY_STORE_PASS:-myPassword}
KEY_STORE_ON=${KEY_STORE_ON:-idempiere.org}
KEY_STORE_OU=${KEY_STORE_OU:-"JPiere Docker"}
HOST=${HOST:-0.0.0.0}
IDEMPIERE_PORT=${IDEMPIERE_PORT:-8080}
IDEMPIERE_SSL_PORT=${IDEMPIERE_SSL_PORT:-8443}
TELNET_PORT=${TELNET_PORT:-12612}
DB_HOST=${DB_HOST:-postgres}
DB_PORT=${DB_PORT:-5432}
DB_NAME=${DB_NAME:-idempiere}
DB_USER=${DB_USER:-adempiere}
DB_PASS=${DB_PASS:-adempiere}
DB_ADMIN_PASS=${DB_ADMIN_PASS:-postgres}
MIGRATE_EXISTING_DATABASE=${MIGRATE_EXISTING_DATABASE:-false}
DISABLE_SSL=${DISABLE_SSL:-false}

これらの環境変数は、iDempiereのconsole-setup.shに自動入力するために使用されます。

PostgreSQL接続待機

Postgresとの接続に何度も失敗したので接続確認するようにしました

# PostgreSQL接続待機
RETRIES=30
until PGPASSWORD=$DB_ADMIN_PASS psql -h $DB_HOST -U postgres -c "\q" > /dev/null 2>&1 || [[ $RETRIES == 0 ]]; do
    echo "Waiting for postgres server, $((RETRIES--)) remaining attempts..."
    sleep 1
done

if [[ $RETRIES == 0 ]]; then
    echo "PostgreSQL connection failed. Shutting down..."
    exit 1
fi

Jetty設定の動的生成(最難関部分)

Jettyサーバー設定ファイルの動的生成もめちゃくちゃややこしかったです。

setup_jetty_config() {
    echo "=== Setting up Jetty configuration files ==="
    
    local jetty_etc_dir="$IDEMPIERE_HOME/jettyhome/etc"
    local template_dir="$IDEMPIERE_HOME/org.adempiere.server-feature/jettyhome/etc"
    
    # テンプレートディレクトリが存在しない場合は、現在のディレクトリをテンプレートとして使用
    if [[ ! -d "$template_dir" ]]; then
        template_dir="$jetty_etc_dir"
    fi
    
    # テンプレートファイルの処理
    for template_file in "$template_dir"/*-template.xml; do
        if [[ -f "$template_file" ]]; then
            local basename=$(basename "$template_file")
            local target_file="$jetty_etc_dir/${basename/-template/}"
            
            # プレースホルダーの置換
            sed -e "s|@ADEMPIERE_SSL_PORT@|$IDEMPIERE_SSL_PORT|g" \
                -e "s|@ADEMPIERE_PORT@|$IDEMPIERE_PORT|g" \
                -e "s|@ADEMPIERE_WEB_PORT@|$IDEMPIERE_PORT|g" \
                -e "s|@ADEMPIERE_WEB_SSL_PORT@|$IDEMPIERE_SSL_PORT|g" \
                -e "s|@ADEMPIERE_HOST@|$HOST|g" \
                -e "s|@ADEMPIERE_KEYSTORE@|$jetty_etc_dir/keystore|g" \
                -e "s|@ADEMPIERE_KEYSTOREPASS@|$KEY_STORE_PASS|g" \
                -e "s|@ADEMPIERE_KEYPASS@|$KEY_STORE_PASS|g" \
                "$template_file" > "$target_file"
        fi
    done
}
  1. テンプレートファイルの場所: JPiereのディレクトリ構造が複雑で、テンプレートファイルの場所を特定するのに時間がかかりました
  2. プレースホルダー置換: 一つでも置換し忘れるとJettyが起動しません
  3. SSL設定の処理: 最近はゲートウェイを使うのが普通だと思う。SSLを無効化したい

SSL無効化の処理

# SSL設定の無効化(オプション)
if [[ "${DISABLE_SSL:-false}" == "true" ]]; then
    echo "=== Disabling SSL configuration (DISABLE_SSL=true) ==="
    
    # SSL設定ファイルを削除するのではなく、最小限の設定ファイルを作成
    if [[ -f "$jetty_etc_dir/jetty-ssl.xml" ]]; then
        cat > "$jetty_etc_dir/jetty-ssl.xml" << 'EOF'
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
<!-- SSL disabled configuration -->
<Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory$Server">
  <Set name="Provider"><Property name="jetty.sslContext.provider"/></Set>
</Configure>
EOF
    fi
fi

SSL設定ファイルを単純に削除するとJettyが起動しないため、最小限の内容で上書きする必要がありました。

console-setup.shの自動実行

# コンソールセットアップ実行
echo "Executing console-setup..."
echo -e "$JAVA_HOME\n$JAVA_OPTIONS\n$IDEMPIERE_HOME\n$KEY_STORE_PASS\n$KEY_STORE_ON\n$KEY_STORE_OU\n$KEY_STORE_O\n$KEY_STORE_L\n$KEY_STORE_S\n$KEY_STORE_C\n$HOST\n$IDEMPIERE_PORT\n$IDEMPIERE_SSL_PORT\nN\n2\n$DB_HOST\n$DB_PORT\n$DB_NAME\n$DB_USER\n$DB_PASS\n$DB_ADMIN_PASS\n$MAIL_HOST\n$MAIL_USER\n$MAIL_PASS\n$MAIL_ADMIN\nY\n" | ./console-setup.sh

iDempiereの対話式セットアップを自動化するため、改行区切りで全ての入力値を事前に用意してecho -eでパイプしています。

データベース初期化の自動判定

# データベース初期化チェック
if ! PGPASSWORD=$DB_PASS psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c "\q" > /dev/null 2>&1 ; then
    echo "Database '$DB_NAME' not found or user '$DB_USER' doesn't exist, initializing..."
    
    # PostgreSQLユーザー作成
    PGPASSWORD=$DB_ADMIN_PASS psql -h $DB_HOST -U postgres -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASS';" 2>/dev/null
    
    # データベース作成
    PGPASSWORD=$DB_ADMIN_PASS psql -h $DB_HOST -U postgres -c "CREATE DATABASE $DB_NAME OWNER $DB_USER;" 2>/dev/null
    
    # JPiere固有: ExpDat.dmpでデータベース初期化
    echo "Importing JPiere database from ExpDat.dmp..."
    PGPASSWORD=$DB_ADMIN_PASS psql -h $DB_HOST -U postgres -d $DB_NAME -f /tmp/ExpDat.dmp
    
    # データベース同期
    cd utils
    ./RUN_SyncDB.sh
    cd ..
    
    # データベース署名
    ./sign-database-build.sh
fi

この部分では、データベースとユーザーの存在確認、作成、ExpDat.dmpからの初期化、スキーマ同期、署名という一連の処理を自動化しています。

まとめ

JPiereのDockerCompose環境構築を通じて学んだことを率直に共有します。

苦労した点

1. 企業級ERPの複雑さ

単純なWebアプリケーションとは次元の違う複雑さでした。特に:

  • Jetty設定ファイルの動的生成
  • データベース初期化の自動化
  • SSL設定の適切な無効化
  • iDempiereのconsole-setup.shの自動化

これらの実装に、予想以上の時間がかかりました。

2. ドキュメントの不足

JPiereやiDempiereのDocker化に関する情報は非常に限られており、エラーメッセージもJavaスタックトレース中心で根本原因の特定が困難でした。

3. Apple Siliconでの性能問題

DockerでRosettaを有効にしてx86_64エミュレーションしています。

あとがき

本当にこんなにインストール大変なんでしょうか

正しい方法をご存知でしたらご教示ください

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?