У меня есть собственные Rust сервера на арендованной удаленной машине. Онлайн пока что крайне мал (в основном - никого, хотя бывает и 1-3 игроков), но мне нравится настройка и администрирование, поэтому в первую очередь мой сервер мне служит в образовательных целях. Начинал я с малого: пытался писать небольшие плагины для OxideMod с помощью ChatGPT и, организовав git репозиторий прямо в папке oxide/plugins, сделал процесс обновления плагинов максимально удобным. А недавно мне досталась задача посложнее: в свете недавнего обновления RustDedicated Server (которое стало отправной точкой) я решил наконец по максимуму автоматизировать имеющиеся задачи - об этом далее в статье. Все началось с того, что разработчики Rust Dedicated Server починили сломали функцию restart. Она и ранее не работала, поскольку выключала сервер вместо того, чтобы перезагружать его. А теперь она стала работать согласно названию, но параллельно с ней перезагружать почему-то начала и функция quit. Очевидно, что это два названия одного и того же, но разработчики не определились, чего же именно. Как бы то ни было - данный фикс создал мне проблему: теперь я мог выключить запущенный сервер только нативными средствами Linux: и это работало исправно, пока сервер был всего один. Но серверов стало два. И выключение всех серверов каждый раз, когда я выключаю один из них - меня не устраивало. Вот тут-то и появился он. Давно уже посматривал на эту технологию, но как-то не было повода ее применить. А теперь, когда мне потребовалось запускать каждый сервер в изолированной среде - docker оказался вполне подходящим инструментом (плюс появился хороший повод наконец изучить его на практике). Сама по себе папка с сервером представляет собой развернутое с помощью steamcmd приложение, куда дополнительно устанавливается oxidemod. Когда я начинал использовать docker, я так же добавил в эту папку Dockerfile с настройками.  Типичная структура сервера примерно такая: Когда мне понадобилось больше серверов, я просто копировал всю папку Rust_Server каждый раз, когда хотел добавить еще один. Очевидно, что подход избыточный, особенно в условиях ограниченного места на диске, ведь папка сама по себе весит более 7 ГБ, а вдобавок еще и каждый docker-образ занимает столько же. Поэтому в конце-концов структура эволюционировала в единственную папку, в которой для каждого нового сервера (./server/$IDENTITY) я просто добавлял локальную подпапку oxide с отдельным набором плагинов и конфиг-файлами, что значительно экономило место на диске. Для запуска/сборки всех серверов было решено использовать docker-compose.  В итоге, преобразования произошли только в подпапке server, остальная структура осталась без изменений: На этом этапе возникла проблема - корневая папка oxide (строка 11 выше) оказалась общей для всех контейнеров (поскольку она, как и остальные папки, примонтирована в volumes), тогда как мне было нужно, чтобы в каждом контейнере такая папка была изолированной (поскольку наборы плагинов разные). И хотя в wiki Facepunch я не нашел, как я могу указать кастомный путь к папке oxide, решение, к счастью, было найдено. В процессе изучения документации докера я наткнулся на этот тип монтирования, при котором создается временная папка, доступная только в рамках текущего контейнера и удаляемая при его остановке. Итоговый конфиг docker-compose.yml при этом стал таким: В конфиге выше меня смущает только необходимость дублировать SERVER_ROOT (см args, container_name, volumes, tmpfs), поэтому если не найду другого решения - просто создам bash-script для генерации docker-compose.yml, а дублирующееся значение перенесу в переменную. А в файле для запуске сервера run-server.sh я просто выполняю копирование из текущей подпапки oxide в изолированную корневую tmpfs папку oxide: Однако, данный подход забрал у меня одну важную фичу - live reload папки oxide. Папка копируется всего один раз на старте и больше не обновляется. Т.е. если я залью новый плагин в эту папку (./server/$IDENTITY/oxide), мне придется подключаться к контейнеру: и выполнять вот это действие вручную: Поэтому было решено использовать watch на каждой папке ./server/$IDENTITY/oxide и выполнять обновление tmpfs oxide при изменениях. В самом docker уже имеется такая фича, но она помечена как experimental, что лично меня отпугивает, поэтому решил пока воспользоваться проверенными средствами линукс - inotify-tools. Я сделал bash-скрипт watch-oxide-dir.sh, который будет отслеживать изменения в папках oxide каждого сервера и при необходимости обновлять содержимое tmpfs oxide: Итоговый run-server.sh стал таким: Здесь добавление амперсанда (&) на строке 7 и 8 делает скрипт выполняемым в фоне. Итоговый Dockerfile с необходимыми зависимостями, устанавливаемыми при сборке образа: Далее все отлично запускается командой docker-compose up -d В качестве бонуса буду рад поделиться ссылкой на свой консольный rcon-client для Rust серверов, который написан на языке Rust. Предельно прост в использовании. А вы администрировали подобные сервера ? React/Rust Developer