L2J Mobius High Five — Docker
L2J Mobius (хроники High Five, L2J_Mobius_CT_2.6_HighFive) в Docker Compose.
Три контейнера: mysql, loginserver, gameserver. Исходники сервера лежат
прямо в этом репозитории (src/) и собираются локально через Ant — без
внешних зависимостей от GitLab при каждой пересборке.
Структура проекта
l2j-docker/
├── src/ # Исходники L2J Mobius (java/, build.xml, dist/, launcher/) — редактируешь напрямую
├── Dockerfile.build # Собирает src/ через Ant, кладёт результат в /out
├── scripts/
│ ├── collect-dist.sh # Нормализует результат сборки в /out/login, /out/game, /out/sql
│ └── extract-reference.sh # Выгружает /out на хост в reference/ для просмотра
├── login/
│ ├── Dockerfile # Runtime-образ login-сервера (JRE)
│ └── entrypoint.sh # Ждёт mysql, применяет config_override, стартует jar
├── game/
│ ├── Dockerfile # Runtime-образ game-сервера (JDK — нужен для скриптового движка)
│ └── entrypoint.sh # Ждёт mysql+login, применяет config_override, стартует jar
├── mysql/
│ ├── Dockerfile # MySQL 8.0 + автоимпорт SQL-схем при первом старте
│ └── init/
├── config/
│ ├── login/config/ # Override-конфиги login (применяются при каждом старте контейнера)
│ └── game/config/ # Override-конфиги game
├── reference/ # Сгенерированный полный дефолтный дистрибутив (не в git, см. ниже)
├── geodata/ # .l2j файлы геодаты (не входят в репозиторий, кладутся руками)
├── docker-compose.yml
├── .env # Пароли, порты — реальные значения, не в git
└── .env.example # Шаблон .env с плейсхолдерами
Как это работает
Dockerfile.buildкопируетsrc/в builder-образ и собирает его черезant -f build.xml. Результат —LoginServer.jar,GameServer.jarи SQL-схемы.scripts/collect-dist.shраскладывает собранный архив в/out/login,/out/game,/out/sql— единую структуру для runtime-образов.login/Dockerfileиgame/Dockerfileберут готовый/out/*из builder-образа и кладут в финальный контейнер с JRE/JDK.config/login/config/иconfig/game/config/— это единственное место, где нужно редактировать конфиги. При каждом старте контейнераentrypoint.shкопирует всё из этой папки поверх дефолтных файлов внутри контейнера. Правки здесь переживают любойdocker compose build/--force-recreate. Редактировать конфиги внутри уже запущенного контейнера (docker exec) — не сохранится после пересборки.
Запуск с нуля
1. Собрать builder-образ
docker build -f Dockerfile.build -t l2j-build:latest .
2. Геодата
Скачай геодату для High Five отдельно. (Можно тут)
Распакуй все .l2j файлы (и geo_index.txt) прямо в ./geodata/, без
вложенных подпапок.
3. Настроить .env
cp .env.example .env # если только клонировал репозиторий
nano .env
Задай MYSQL_ROOT_PASSWORD и остальные значения. Важно: пароль здесь
должен совпадать с паролем в config/login/config/Database.ini и
config/game/config/Database.ini (см. ниже).
⚠️ Обязательно смени перед первым запуском
Репозиторий содержит рабочие сетевые настройки (mysql, loginserver
вместо localhost), но пароль и IP — от конкретной машины, на которой
это разворачивалось изначально. Смени их в трёх местах, иначе:
подключение к БД будет использовать чужой пароль, а клиенты будут
пытаться попасть на чужой IP.
config/login/config/Database.iniиconfig/game/config/Database.ini— строкаPassword = .... Должна совпадать сMYSQL_ROOT_PASSWORDв.env.config/game/config/ipconfig.xml— атрибутaddress="..."в корневом теге<gameserver>. Это IP/домен, который сервер сообщает клиенту после выбора сервера в списке (свой локальный/публичный IP, не192.168.1.207— это чужая машина).
Всё остальное (mysql, loginserver, 0.0.0.0 в Server.ini) —
универсальные значения, менять не нужно, они завязаны на имена сервисов
в docker-compose.yml, а не на конкретный хост.
4. Настроить сетевые конфиги
Login и game сервера по умолчанию слушают/подключаются на localhost —
внутри Docker-сети это не работает, контейнеры видят друг друга по именам
сервисов (mysql, loginserver, gameserver). Уже настроено в
config/*/config/Database.ini и config/login/config/Server.ini:
Database.ini(оба сервера):URL = jdbc:mysql://mysql/l2jmobiush5?...login/config/Server.ini:LoginHostname = 0.0.0.0,LoginHostnameдля приёма game-сервера —LoginHost = 0.0.0.0(не127.0.0.1, иначе gameserver не сможет подключиться из своего контейнера)game/config/Server.ini:LoginHost = loginserver(имя сервиса, не IP)
5. ipconfig.xml — адрес для клиентов
config/game/config/ipconfig.xml определяет, какой IP-адрес game-сервер
сообщает клиенту после выбора сервера в списке. Если клиент подключается:
- с этого же сервера — оставь
127.0.0.1 - из локальной сети — укажи локальный IP сервера (например,
192.168.1.207) - из интернета — укажи публичный IP или домен
Пример минимального конфига:
<?xml version="1.0" encoding="UTF-8"?>
<gameserver address="192.168.1.207" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../data/xsd/ipconfig.xsd">
</gameserver>
6. Собрать и запустить
docker compose build
docker compose up -d
docker compose logs -f mysql loginserver gameserver
Ожидаемая последовательность в логах:
mysql— выполняет SQL-схемы, проходит healthcheckloginserver—LoginServer: Login client listener started on 0.0.0.0:2106gameserver—LoginServerThread: Registered on login as Server N: <Name>
Если видишь Registered on login as Server — стек полностью поднят.
Просмотр полного дистрибутива сервера (reference)
/out внутри builder-образа (login/, game/, sql/ с jar-файлами,
конфигами и data/) существует только как промежуточный слой между стадиями
Docker-сборки — на хосте его не видно напрямую. Чтобы удобно читать
дефолтные файлы сервера (посмотреть, что там есть, прежде чем что-то
копировать в override), используй скрипт scripts/extract-reference.sh:
./scripts/extract-reference.sh
Это выгружает полный /out из свежего l2j-build:latest образа в
./reference/ — обычную папку на диске:
reference/login/config/...
reference/game/config/...
reference/game/data/...
reference/login/libs/...
Дальше — смотришь нужный файл и копируешь только его в override:
cat reference/game/config/Rates.ini
cp reference/game/config/Rates.ini config/game/config/Rates.ini
nano config/game/config/Rates.ini
docker compose up -d --force-recreate gameserver
reference/ — сгенерированные файлы, не нужно коммитить их в git (см.
.gitignore). После пересборки Java-кода (docker build -f Dockerfile.build ...) перезапусти скрипт, чтобы reference/ отражал актуальную сборку:
docker build -f Dockerfile.build -t l2j-build:latest . && ./scripts/extract-reference.sh
Редактирование конфигов
Все дефолтные конфиги обоих серверов уже скопированы в
config/login/config/ и config/game/config/. Правь их прямо здесь:
nano config/game/config/Rates.ini # рейты экспы/дропа
nano config/game/config/NPC.ini # агрессия, respawn
nano config/game/config/Player.ini # лимиты персонажей
После правки — пересоздать нужный контейнер (без пересборки образа, если менялся только конфиг, а не код):
docker compose up -d --force-recreate gameserver
Важно — не копируй reference/ в config/ массово поверх уже
настроенных файлов. config/login/config/Database.ini,
config/game/config/Database.ini, config/game/config/Server.ini и
config/game/config/ipconfig.xml содержат критичные сетевые правки
(mysql/loginserver вместо localhost/127.0.0.1) — если их затереть
дефолтными значениями из reference/, game-сервер перестанет находить
MySQL или login-сервер (Connection refused, LoginServer not available).
Копируй в override только конкретные файлы, которые собираешься менять,
не весь каталог целиком.
Изменение кода сервера
Исходники лежат в src/java/. После правки:
docker build -f Dockerfile.build -t l2j-build:latest .
docker compose build
docker compose up -d
Первая команда пересобирает Java-код через Ant, вторая — пересобирает runtime-образы login/game с новыми jar-файлами, третья — перезапускает стек.
Память JVM
Размер кучи для game-сервера задан в game/entrypoint.sh:
exec java -Xms1g -Xmx4g -Dfile.encoding=UTF-8 -cp "$CLASSPATH" -jar libs/GameServer.jar
Полная геодата High Five (203 региона) требует заметного объёма памяти при
загрузке — при OutOfMemoryError на этапе [ Geodata ] увеличь -Xmx.
После правки:
docker compose build gameserver
docker compose up -d --force-recreate gameserver
Резервное копирование
Образы и контейнеры полностью воспроизводимы из этого репозитория — бэкапить нужно только:
- Сам репозиторий (
src/, конфиги, override) — обычный git. - Данные MySQL (аккаунты, персонажи) — они живут в Docker-volume
mysql_data, не в файлах проекта. Дамп:
docker exec l2j-mysql mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" l2jmobiush5 > backup_$(date +%Y%m%d_%H%M%S).sql
Восстановление:
docker exec -i l2j-mysql mysql -u root -p"$MYSQL_ROOT_PASSWORD" l2jmobiush5 < backup_ФАЙЛ.sql
Порты
| Сервис | Порт | Назначение |
|---|---|---|
| loginserver | 2106 | Подключение клиента (экран логина) |
| gameserver | 7777 | Подключение клиента (после выбора сервера) |
| gameserver → loginserver | 9014 | Внутренний auth-обмен между серверами |
| mysql | 3306 | БД (не публикуется наружу по умолчанию) |
Меняются в .env.