Comments 17
докер это конечно хорошо.
Но вместо того чтобы создать нормальный примитивный сервис (как раз systemd с этим очень хорошо справляется), пляски с бубном с докером
в случае с OxideMod, установленном поверх RustDedicated, предполагается, что папка oxide должна быть в корне. Сервис, который вы предлагаете создать, позволяет создать изолированную папку oxide, которая не будет перезаписана другим таким же сервисом ?
как это примерно будет выглядеть, можете, пожалуйста, показать ?
Можно создать два сервиса, и каждому прописать свою WorkingDirectory.
[werwolf@power] ~
❯ systemctl cat valheim-server@.service
# /usr/lib/systemd/system/valheim-server@.service
[Unit]
Description=Valheim dedicated server
Wants=network-online.target
After=multi-user.target network.target network-online.target
[Service]
Type=simple
User=valheim
Group=valheim
Environment="LD_LIBRARY_PATH=/var/lib/valheim/%i/linux64"
EnvironmentFile=/etc/valheim-%i.conf
WorkingDirectory=/var/lib/valheim/%i
ExecStartPre=+/usr/bin/steamcmd +login $STEAM_LOGIN +force_install_dir /var/lib/valheim/%i +app_update 896660 validate +exit
ExecStartPre=+/usr/bin/chown -R valheim:valheim /var/lib/valheim
ExecStart=/var/lib/valheim/%i/valheim_server.x86_64 -name $SERVER_NAME -port $PORT -world $WORLD_NAME -password $PASSWORD
Restart=always
RestartSec=30
TimeoutStartSec=300
NoNewPrivileges=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
ProtectSystem=strict
ProtectHome=read-only
SystemCallFilter=~@mount
ReadWritePaths=/var/lib/valheim/%i
[Install]
WantedBy=multi-user.target
примерно вот так
systemctl start valheim-server@XXX.service
вызовет запуск юнита в котором все %i
заменятся на XXX
, тоесть будет создана директория /var/lib/valheim/XXX
в неё будет установлен valheim dedicated server, в ней же он будет запущен, и только в неё же он сможет писать, а все необходимые переменные будут взяты из файла /etc/valheim-XXX.conf
.
писал на память, может чего-то и опечатался, или упустил, но думаю общий смысл понятен.
systemd решает ВСЕ ваши проблемы с запуском сервисов, совершенно незачем для этого использовать docker. локально docker в первую очередь это инструмент тестирования. он больше имеет смысл в составе кубового кластера где нужно быстренько скалировать, где нужно чтобы работали life и health метрики (кстати, аналог health есть и у systemd, гуглить sd_notify). в общем не в ту сторону вы копнули.
спасибо за пример, смысл понятен. А можете, пожалуйста, подсказать, чем подход с докером хуже, чем ваш ?
1) зачем тащить на сервер дополнительный софт?
2) зачем тащить на сервер дополнительный рантайм пусть и в образе контейнера?
3) зачем нужны дополнительные абстракции?
4) зачем переусложнять конфигурацию сервиса и добавлять дополнительные точки отказа?
по большому счёту разворачивание сервисов в докере это НЕ плохо, просто зачастую это оверинженеринг без которого можно было обойтись. вроде бы не страшно что вы заняли на сервере пару лишних мегобайт дискового пространства и пару мегобайт ОЗУ, но из таких вот "да пусть будет" складываются привычки, а плохие привычки имеют свойство в будущем стрелять в ногу. конечно же иногда есть весомые причины развернуть что либо именно в контейнере, но в вашем кейсе я таких не вижу.
а как в вашем случае быть с обновлениями нескольких серверов ? и отдельно интересует, как происходит автоматизация через крон - вы прописываете для каждой директории /var/lib/valheim/XXX
отдельное правило в crontab или это можно как-то обобщить (по типу перебора всех подпапок в bash-скрипте, вызова там обновлений и уже этот скрипт вызывать в кроне?)
с моим подходом я устанавливаю обновления всего раз в месяц (force wipe) в одну единственную папку и эти изменения автоматически затрагивают все имеющиеся инстансы серверов.
если присмотреться в содержимое сервисфайла то можно увидеть что один из ExecStartPre
существует как для начальной установки так и для последующего обновления при перезапуске. так что для обновления конкретного инстанса я просто перезапускаю его (к тому же у меня в cron есть скрипт для бекапа всех инстансов который первым делом останавливает службы а предпоследним запускает их, поэтому автообновление раз в сутки гарантировано.
не берусь утверждать что это лучшее и/или самое правильное решение, но лучше я ничего не придумал за те 5 минут что потратил на эту задачу (самое обидное что играть то я не играю, некогда, для друзей держу несколько серверов)
почему было сделано именно так: одна из задач которую я решал делая этот сервис было опакетить его покласть в репозитории дистрибутива сервер для игры, поскольку нет явного разрешения класть серверную часть игры в репозиторий (и уж тем более исходников для сборки) это был самый простой и ничего не нарушающий путь.
правда версия с несколькими инстансами в репозитории не попала, я всё ещё ленюсь допроверить все возможные подводные камни, но одноинстансовый вариант уже давно там и его можно установить как пакет родным пакетным менеджером opensuse - zypper, возможно в будущем я так же опакечу для красношляпых и для deb, но пока на это времени просто нет. зато этот service легко модифицировать под любой сервер ставящийся силами steamcmd.
спасибо за развернутый ответ. Именно это я имел ввиду когда писал что докер излишен в данном случае
и это работало исправно, пока сервер был всего один. Но серверов стало два. И выключение всех серверов каждый раз, когда я выключаю один из них - меня не устраивало. Вот тут-то и появился он.
То есть вместо того, чтобы заменить pkill на kill, и вырубать нужный сервер по его process ID, вы замутили целый докер, а не разобравшись как пробросить каталог внутрь, замутили синхронизацию с рамдиском.
Давайте я решу все ваши проблемы, поправив run-server.sh
#!/bin/bash
WORKDIR=$(dirname $0)
PIDFILE=${WORKDIR}/server.pid
if [ "$1" == "start" ]; then
[ -e ${PIDFILE} ] && echo "Server is already running" && exit 1
SEED=$(cat ${WORKDIR}/server/$IDENTITY/seed.txt)
cp -R ${WORKDIR}/server/$IDENTITY/oxide/* ${WORKDIR}/oxide
./set-permissions.sh &
./watch-oxide-dir.sh &
${WORKDIR}/RustDedicated -batchmode \
+server.hostname "$HOSTNAME" \
+server.identity "$IDENTITY" \
+server.maxplayers $MAXPLAYERS \
+server.worldsize $WORLDSIZE \
+server.seed "$SEED" \
+server.tags "$SERVER_TAGS" \
+server.url "$SERVER_URL" \
+server.port $SERVER_PORT \
+server.queryport $QUERY_PORT &
echo $! > ${PIDFILE}
elif [ "$1" == "stop" ]; then
[ ! -e "${PIDFILE}" ] && echo "Server is not running" && exit 0
read PID<${PIDFILE}
if ps $PID >/dev/null 2>&1; then
kill $PID
else
echo "Server is not running and previous shutdown was not graceful"
fi
else
echo "Usage: $0 start|stop"
fi
если честно, я с этого начинал - пытался запоминать pid, чтобы потом вырубать через kill, только потом у меня в чем-то случилась загвоздка и я не смог этот вариант довести до конца.
замутили целый докер
а можете подсказать, почему использование докера будет избыточно ? кроме того, что нужно устанавливать новый софт.
Ну тем что вам пришлось
1. устанавливать докер
2. докеризировать сервер, что включает в себя и сеть и проброс дисков
3. вместо проброса дисков, вы нашли возможность использовать рамдрайв, но его надо синхронизировать - сделали еще лишний скрипт
4. усложнили поддержку своего сервера.
И вместо всего этого - можно просто удалить процесс по PID.
но корневая папка oxide-то все еще общая в вашем случае. Т.е. если я запущу второй сервер - он перезапишет эту папку и будет конфликт. И в итоге придется вернуться к изначальному подходу - т.е. копировать папку для каждого нового сервера.
Пожалуйста, исправьте меня, если я ошибаюсь.
проброс дисков
можете уточнить, что вы называете "пробросом дисков" ? монтирование (volumes) ? Если да, то несовсем понятен ваш следующий пункт
вместо проброса дисков, вы нашли возможность использовать рамдрайв
я и пробрасываю диск (вся папка Rust_Server) и использую рамдрайв (исключительно для одной подпапки, которая должна быть локальной для каждого запущенного сервера).
Т.е. не "вместо", а "вместе с" в данном случае будет корретнее.
усложнили поддержку своего сервера
можете развить эту мысль ? в чем сложность поддержки ?
Простите, а как вы раньше запускали два сервера?
Если вы хотели сделать какие-то папки общими для всех серверов - сделайте линками. Просто я не знаком с архитектурой серверов, что там можно обобщать, что нельзя. Но я уверен что Докер - это явно не тот инструмент, если вы хотели сэкономить место на дисках, и ln тут будет и быстрее и проще.
Хотите больше игроков? Отключите EAC. Я знаю всего один сервер сейчас где можно играть из-под Линукса, остальные не пускают из-за того что EAC не пашет в wine.
люто
А зачем хранить все файлы RustDedicated и Oxide локально?
Может вынести их установку в Dockerfile, а отдельно хранить только конфиги и каталоги Oxide/plugins для каждого сервера (подключенные к разным веткам git) и подмонтировать их в контейнеры в соответствующие каталоги (через volumes)?
В таком случае при получении изменений с репозитория с плагинами они сразу будут видны в контейнере.
P.S.: с серверами раста сталкивался лет 5 назад, может какие-то моменты не учел.
Facepunch буквально вынудили меня использовать Docker