Game Server (Sunshine + Steam)

Docker-конфигурация для запуска до четырёх игровых сессий через Moonlight. Каждый контейнер стримит виртуальный рабочий стол 1920×1080 с Steam Big Picture и отдельным профилем Steam на выделенном GPU.

Архитектура

Moonlight → Sunshine → Xorg dummy (:99) → fluxbox + Steam (CEF)
                ↑
              tini (PID 1, перезапуск дочерних процессов)
  • Sunshine v0.20.0 — стриминг и захват экрана
  • Xorg dummy — виртуальный дисплей 1920×1080 (корректный ввод из Moonlight)
  • fluxbox — панель задач внизу экрана
  • Steam — запускается от пользователя steam через start-steam.sh
  • tini — init-процесс контейнера, предотвращает zombie-процессы fluxbox

Структура проекта

.
├── Dockerfile              # Образ: Sunshine, Steam, Xorg, fluxbox, tini, xdotool
├── docker-compose.yml      # 4 сервиса player1player4
├── scripts/
│   ├── entrypoint.sh       # Запуск DBus, Xorg, fluxbox, Sunshine
│   └── fluxbox/init        # Конфиг панели задач (в образе)
├── players/
│   ├── p1_config/          # Конфиг Sunshine для player1 (монтируется в контейнер)
│   │   ├── apps.json
│   │   ├── start-steam.sh  # Сценарий запуска Steam
│   │   └── keep-steam-window.sh
│   ├── p2_config/ … p4_config/
│   └── p1_steam/ … p4_steam/   # Данные Steam (не в git, создаются на сервере)
├── .env.example            # Опциональный APT-прокси для сборки
└── рекомендации.md         # Проверенные практики эксплуатации

Файлы players/pX_config/ монтируются в /root/.config/sunshine/ — изменения скриптов применяются без пересборки образа. Изменения Dockerfile и scripts/ требуют docker compose build.

Требования

  • Docker и Docker Compose v2
  • NVIDIA драйверы и NVIDIA Container Toolkit
  • 2× Tesla K80 (4 GPU-чипа) или аналогичная конфигурация
  • На хосте: sysctl kernel.unprivileged_userns_clone=1 (нужно для Steam runtime)

Установка

  1. Склонируйте репозиторий на сервер:

    git clone https://git.core.com.ru/bilal/game-server.git /DATA/AppData/game-server
    cd /DATA/AppData/game-server
    
  2. Создайте каталоги данных Steam (если их ещё нет):

    mkdir -p players/p{1,2,3,4}_steam
    
  3. При необходимости измените пути volume в docker-compose.yml (по умолчанию /DATA/AppData/game-server/players/...).

  4. Назначение GPU (NVIDIA_VISIBLE_DEVICES):

    Сервис GPU
    player1 1
    player2 2
    player3 3
    player4 4

    GPU 0 обычно занят отдельной видеокартой хоста и не используется игровыми контейнерами.

  5. Соберите и запустите:

    docker compose up -d --build
    

APT-прокси (опционально)

Для ускорения сборки через apt-cacher-ng:

cp .env.example .env
# отредактируйте APT_PROXY при необходимости
docker compose up -d --build

Подключение Moonlight

В Moonlight добавьте хост вручную: IP:base_port.

Сервис base_port Web UI Sunshine
player1 47989 https://IP:47990
player2 48019 https://IP:48019
player3 48049 https://IP:48049
player4 48079 https://IP:48079

Запускайте приложение Steam Big Picture, не Desktop.

Порты (host → container)

Сервис TCP TCP/UDP UDP
player1 4798447990 48010 4799848000
player2 4801448020 48040 4802848030
player3 4804448050 48070 4805848060
player4 4807448080 48100 4808848090

Конфигурация

Sunshine

  • players/pX_config/apps.json — список приложений Moonlight
  • players/pX_config/credentials/ — TLS-сертификаты (генерируются при первом запуске, не в git)
  • sunshine.conf — создаётся автоматически при первом запуске, не хранится в репозитории

Запуск Steam

start-steam.sh вызывается из apps.json при выборе Steam Big Picture:

  1. Проверяет и поднимает system DBus и fluxbox
  2. Если Steam уже работает и UI виден — не перезапускает процесс
  3. Иначе: чистый старт -silent -no-cef-sandbox, затем однократно steam://open/gamepadui
  4. keep-steam-window.sh удерживает окно входа на экране и центрирует его

Steam работает от пользователя steam; данные сохраняются в players/pX_steam/.

Shared memory

В docker-compose.yml задано shm_size: "2gb". Стандартные 64 MB Docker недостаточны для CEF (Steam UI) — окно входа начинает мигать и пропадать. После изменения shm_size контейнер нужно пересоздать:

docker compose up -d --force-recreate player1

Первичная загрузка Steam

При первом запуске Steam скачивает клиент (~500 MB, 1020 минут). Прогресс:

docker exec -it game-player-1 bash -lc \
  'tail -f /home/steam/.local/share/Steam/debian-installation/logs/bootstrap_log.txt'

После завершения снова откройте Steam Big Picture в Moonlight.

Отладка

Быстрая проверка

docker compose ps
docker compose logs --tail=100 player1

docker exec -it game-player-1 bash -lc '
  echo "PID1: $(cat /proc/1/comm)"          # должно быть tini
  pgrep -a sunshine
  pgrep -a "steam -srt" || echo "steam not running"
  df -h /dev/shm                             # должно быть ~2G, занято <20%
  DISPLAY=:99 xwininfo -root -tree | grep -iE "Sign in|Big Picture|1918x"
'

Логи Steam

docker exec -it game-player-1 bash -lc 'tail -f /home/steam/steam-app.log'
docker exec -it game-player-1 bash -lc \
  'tail -50 /home/steam/.local/share/Steam/debian-installation/logs/cef_log.txt'

Типичные проблемы

Симптом Причина Решение
Окно входа мигает / пропадает /dev/shm переполнен shm_size: "2gb" + --force-recreate
Нет панели задач внизу fluxbox zombie или -tenfoot fullscreen Пересоздать контейнер; не использовать -tenfoot
Чёрный экран, Steam не виден Bootstrap ещё идёт или webhelper упал Смотреть bootstrap_log.txt, webhelper-linux.txt
Steam перезапускается при каждом клике Старый inline-скрипт в apps.json Использовать start-steam.sh из репозитория

Пересборка после изменений

Что изменили Команда
start-steam.sh, apps.json Достаточно перезапустить Steam в Moonlight
Dockerfile, scripts/ docker compose up -d --build --force-recreate player1
docker-compose.yml (shm, GPU, порты) docker compose up -d --force-recreate

Обновление из репозитория

cd /DATA/AppData/game-server
git pull
docker compose up -d --build

Скрипты в players/pX_config/ обновятся автоматически через bind-mount. Если git pull перезаписал локальные правки на сервере — проверьте diff перед перезапуском.

Дополнительно

Подробные рекомендации по эксплуатации — в файле рекомендации.md.

Description
No description provided
Readme 104 KiB
Languages
Shell 85.1%
Dockerfile 14.9%