- Баллы
- 66
- Имя в Minecraft
- MassonNn
Введение
Итак, написать данную статью мне пришла идея после того, как я узнал что многие сервера до сих пор запускают с помощью screen. Если вы читаете данный текст, то знайте, что вы можете забыть об этой утилите как абсолютно бесполезной и вредной для любых (а не только майнкрафт) серверов. Почитав пару гайдов на данном и соседних форумах я заметил что все без исключения форумчане пытаются вручную самостоятельно настраивать сервера, скачивать и настраивать все необходимые утилиты, а ради чего? Чтобы сделать по сути всё тоже самое, что Docker делает за 5 минут.
Что такое Docker?
Docker - в переводе с англ. "грузчик" - это утилита контейнеризации, которая позволяет развёртывать приложения в изолированных окружениях - контейнерах. Краткая справка откуда вообще это взялось. В международной логистике уже давно принято за стандарт перевозить что бы то ни было в специальных контейнерах. Независимо от содержимого, контейнеры с легкостью загружаются на поезда, с поездов на корабли-контейнеровозы, с кораблей в грузовые самолёты и т.д. Такая мера стандартизации позволила значительно ускорить логистику, поскольку рабочим не требуется постоянно "играть в тетрис" на каждом логистическом узле.
Итак, Docker позволяет нам переносить наше приложение (будь то Minecraft сервер или что либо другое) в виде Docker-образа (Docker Image). Затем этот образ развёртывается на сервере в виде контейнера (Docker Container), который в свою очередь является некоторым окружением для нашего приложения. Что такое окружение? Это всё, что требуется для работы нашего приложения: файлы (Docker Volumes), настройки (конфигурации), секреты (Docker Secrets) и многое другое. Если бы мы рассматривали это на примере классического майнкрафт сервера, то образом нашего приложения мы бы назвали Spigot.jar, а окружением всё остальное: server.properties, plugins, world и т.д. Основная идея в том, что мы можем с лёгкостью скачать на наш сервер тот или иной образ с помощью одной простой команды, а затем без всякого труда создать контейнер и сразу же его запустить.
Как устроен Docker Image?
Это очень важная часть нашего туториала, поскольку понимание как устроен образ, даст вам понять почему Docker - это невероятно крутой инструмент. Итак, почти все образы основываются на других образах. Это первое, что нам нужно понять. Если мы посмотрим на один из самых популярных докер-образов для майнкрафт сервера itzg/minecraft-server, то увидим, что по большому счёту данный образ создаётся на основе образа Java, та в свою очередь основывается на образе той или иной ОС (linux/oracle/alpine, windows, или др.). Таким образом, устанавливая образ майнкрафт-сервера, докер сразу же подтащит для него подходящую версию Java и все необходимые библиотеки\инструменты для корректной её работы.
Одна из основных идей устройства образа состоит в том, что все они состоят из слоёв. Слой представляет собой определённый этап сборки образа. Например, мы с вами формируем образ нашего майнкрафт сервера, делается это с помощью Dockerfile:
Здесь мы определили, что наш образ основывается на образе Java (это первый слой).
Устанавливаем переменные окружения, а именно указываем что тип сервера будет ванильный, версия - последний релиз, eula = True. Это второй слой.
Копируем папку с плагинами в наш образ
Определяем что точкой входа нашего сервера будет файл start.sh, то есть этот файл должен быть запущен при запуске контейнера.
Инструкции FROM, COPY, ENTRYPOINT и мн. др. - это начало каждого нового слоя. Изюминка в том, что Docker кеширует каждый слой на вашем устройстве и при повторной сборке образа, если тот или иной слой не изменился, то он будет подтянут из кеша. Это делает образ более гибким и менее ресурсоёмким для развёртывания, поскольку если на вашем сервере уже есть образ Java, то при деплое вашего сервера, он не будет скачивать его с hub.docker.com, а возьмёт уже имеющийся.
Таким образом, несмотря на кажущуюся сложность, вся установка нашего с вами сервера займёт всего лишь одну строчку:
Пока не разбираю её, оставим это на десерт.
Я не буду залезать в дебри того как устроен докер, но вы можете довериться профессионалам в вопросе насколько он эффективен так как метод контейнеризации (не только с помощью Docker) уже давно используется всеми крупными компаниями, в том числе такими именитыми как Microsoft, Google и Amazon.
Как устроен Docker Container?
Мы уже успели обсудить что такое контейнер, а также я уже сказал, что контейнер - это окружение для нашего образа. В действительности это не совсем так. Под капотом Docker устроен куда сложнее, но нам с вами понимать это не совсем обязательно. Устройство Docker Container напоминает в каком-то смысле отдельную ОС. Одна из фишек докера как раз в том, что вы можете без особого труда запускать на вашем сервере сразу несколько контейнеров одного и того же образа, например, 2, 3 или 10 контейнеров MySQL или Redis или чего только пожелаете - и всё это будет работать слаженно, без всяких проблем с доступом к ресурсам серверной машины и т.д. При этом, наличие изолированных контейнеров, как раз из-за особенностей устройства докера, не нагружает вашу систему так, как нагружали бы две или три полноценные операционные системы на том же самом сервере.
Контейнер состоит из монтированных папок (Docker Volumes), переменных окружения, секретов (Docker Secrets) и т.д. и т.п. Вся эта "котовасия" нужна нам для корректной работы нашего основного приложения. Однако, стоит отметить, что в большинстве ситуаций Docker Container - это Stateless приложение, то есть зависимое от перезапуска. Это означало бы, что в случае остановки\перезапуска вашего сервера, вся информация о нём (в том числе игровая карта, данные игроков и т.д.) полностью терялись и начиналось бы всё с чистого листа, но нам на помощь приходят Docker Volumes.
Docker Volumes - или в простонародии монтированные папки - это буквально папки (или более корректнее - директории), которые при запуске вашего контейнера докер присоединяет к окружению образа. Таким образом, если вы создадите volume для вашей игровой карты и укажете докеру монтировать его для конкретного контейнера, то Docker предоставит контейнеру доступ к этой папке, а папке - доступ к контейнеру. После остановки вашего контейнера, volume не будет утерян, а вы, например, сможете спокойно скачать эту директорию или каким-либо иным образом взаимодействовать с ней. Проще говоря, все те файлы, которые вы хотите сохранять при перезапуске, следует хранить в volume, а всё то, что вам потребуется только при работе сервера, собирать в образе.
Деплой вашего сервера и его настройка
Итак, после того как мы разобрались с тем как работает докер, можем приступать к практической части. Давайте вернёмся к той самой команде, которую я нагло вывалил на вас без всякого объяснения:
В данной команде мы сообщаем докеру о желании запустить контейнер в detached (-d) режиме на основе образа itzg/minecraft-server, который ему следует скачать с hub.docker.com, затем мы сообщаем ему о желании установить для нашего контейнера переменную окружения EULA=TRUE. В данном образе эта переменная отвечает за автоматическое подтверждение eula. После чего мы определяем что мы должны слушать порт 25565 извне и направлять всю поступающую по нему информацию в контейнер по порту 25565. То есть, Docker не будет слушать никакие другие порты, кроме тех, что вы сами указали ему слушать (где-то слышится радостный крик желающих выкинуть UFW, поскольку Docker гораздо надёжнее в вопросе защиты сервера, более того Docker настолько "гигачад", что настройки UFW им впринципе игнорируются). Тут важный момент, что если бы вы запустили ваш сервер на другом, отличном от 25565, порту, то вам бы следовало перенаправлять соединения на другой внутренний в контейнере порт, то есть данный аргумент выглядел бы так:
Где 1000 - это как раз какой-то другой порт на котором у вас запущен сервер. То же самое верно и для обратного: если бы вы хотели открыть ваш сервер для внешних подключений на каком-то другом порту, то настройки сервера можно и не трогать, а просто указать следующую настройку портов:
Теперь ваш сервер доступен по порту 1000, но внутри контейнера соединения проходят по порту 25565.
Итого, мы имеем запущенный сервер, однако в данном случае по умолчанию будет запущен сервер Spigot. Если мы хотим выбрать другое ядро, то достаточно указать переменную окружения TYPE:
Теперь наш сервер будет скачивать последний релиз PaperMC, мы также можем сразу указать ему версию:
В данном образе для монтирования существует mountpoint "data/". Это означает, что наш с вами контейнер внутри для себя так или иначе создаст директорию data/ со всеми важными данными, другой вопрос будет она удалена при остановке сервера или будет подгружена извне с помощью механизма Volume. Для того, чтобы замонтировать папку к нашему контейнеру, её для начала нужно создать:
Естественно, где именно у вас будет располагаться эта папка - только ваш выбор, но предположим я в home создал директорию для своего сервера minecraft_server и в нём уже создал директорию data/, которую планирую монтировать. Кстати, абсолютно не важно как именно вы её назовёте. После чего, всё что мне нужно сделать для сохранения важных для меня данных, это указать ещё один аргумент при запуске контейнера:
В данной команде мы видим аргумент -v, а также два разных пути: один до двоеточия, другой после. Тот, что "до" - это расположение вашей директории на вашем сервере. Тот, что "после" - это куда именно докер должен замонтировать вашу папку в контейнере. Как я уже сказал, данный образ имеет mountpoint /data/, и мы просто монтируем именно туда. Если вы найдёте другой образ майнкрафт сервера, например, только для Spigot, то читайте к нему документацию куда у него идёт монтирование.
Теперь, при запуске нашего контейнера, папка /home/minecraft_server/data/ заполнится важными для нас данными,
Напоминаю, докер не копирует папку к себе, а именно даёт доступ к ней из контейнера, поэтому меняя что либо в ней, эти изменения сразу же коснутся вашего сервера.
Итак, написать данную статью мне пришла идея после того, как я узнал что многие сервера до сих пор запускают с помощью screen. Если вы читаете данный текст, то знайте, что вы можете забыть об этой утилите как абсолютно бесполезной и вредной для любых (а не только майнкрафт) серверов. Почитав пару гайдов на данном и соседних форумах я заметил что все без исключения форумчане пытаются вручную самостоятельно настраивать сервера, скачивать и настраивать все необходимые утилиты, а ради чего? Чтобы сделать по сути всё тоже самое, что Docker делает за 5 минут.
Что такое Docker?
Docker - в переводе с англ. "грузчик" - это утилита контейнеризации, которая позволяет развёртывать приложения в изолированных окружениях - контейнерах. Краткая справка откуда вообще это взялось. В международной логистике уже давно принято за стандарт перевозить что бы то ни было в специальных контейнерах. Независимо от содержимого, контейнеры с легкостью загружаются на поезда, с поездов на корабли-контейнеровозы, с кораблей в грузовые самолёты и т.д. Такая мера стандартизации позволила значительно ускорить логистику, поскольку рабочим не требуется постоянно "играть в тетрис" на каждом логистическом узле.
Итак, Docker позволяет нам переносить наше приложение (будь то Minecraft сервер или что либо другое) в виде Docker-образа (Docker Image). Затем этот образ развёртывается на сервере в виде контейнера (Docker Container), который в свою очередь является некоторым окружением для нашего приложения. Что такое окружение? Это всё, что требуется для работы нашего приложения: файлы (Docker Volumes), настройки (конфигурации), секреты (Docker Secrets) и многое другое. Если бы мы рассматривали это на примере классического майнкрафт сервера, то образом нашего приложения мы бы назвали Spigot.jar, а окружением всё остальное: server.properties, plugins, world и т.д. Основная идея в том, что мы можем с лёгкостью скачать на наш сервер тот или иной образ с помощью одной простой команды, а затем без всякого труда создать контейнер и сразу же его запустить.
Как устроен Docker Image?
Это очень важная часть нашего туториала, поскольку понимание как устроен образ, даст вам понять почему Docker - это невероятно крутой инструмент. Итак, почти все образы основываются на других образах. Это первое, что нам нужно понять. Если мы посмотрим на один из самых популярных докер-образов для майнкрафт сервера itzg/minecraft-server, то увидим, что по большому счёту данный образ создаётся на основе образа Java, та в свою очередь основывается на образе той или иной ОС (linux/oracle/alpine, windows, или др.). Таким образом, устанавливая образ майнкрафт-сервера, докер сразу же подтащит для него подходящую версию Java и все необходимые библиотеки\инструменты для корректной её работы.
Одна из основных идей устройства образа состоит в том, что все они состоят из слоёв. Слой представляет собой определённый этап сборки образа. Например, мы с вами формируем образ нашего майнкрафт сервера, делается это с помощью Dockerfile:
Код:
FROM ghcr.io/graalvm/graalvm-ce:ol8-java11 AS Java
Код:
ENV TYPE=VANILLA VERSION=LATEST EULA="True"
Код:
COPY --chmod=644 plugins/ /app/plugins/
Код:
ENTRYPOINT [ "/start.sh" ]
Инструкции FROM, COPY, ENTRYPOINT и мн. др. - это начало каждого нового слоя. Изюминка в том, что Docker кеширует каждый слой на вашем устройстве и при повторной сборке образа, если тот или иной слой не изменился, то он будет подтянут из кеша. Это делает образ более гибким и менее ресурсоёмким для развёртывания, поскольку если на вашем сервере уже есть образ Java, то при деплое вашего сервера, он не будет скачивать его с hub.docker.com, а возьмёт уже имеющийся.
Таким образом, несмотря на кажущуюся сложность, вся установка нашего с вами сервера займёт всего лишь одну строчку:
Код:
docker run -d -it -p 25565:25565 -e EULA=TRUE itzg/minecraft-server
Я не буду залезать в дебри того как устроен докер, но вы можете довериться профессионалам в вопросе насколько он эффективен так как метод контейнеризации (не только с помощью Docker) уже давно используется всеми крупными компаниями, в том числе такими именитыми как Microsoft, Google и Amazon.
Как устроен Docker Container?
Мы уже успели обсудить что такое контейнер, а также я уже сказал, что контейнер - это окружение для нашего образа. В действительности это не совсем так. Под капотом Docker устроен куда сложнее, но нам с вами понимать это не совсем обязательно. Устройство Docker Container напоминает в каком-то смысле отдельную ОС. Одна из фишек докера как раз в том, что вы можете без особого труда запускать на вашем сервере сразу несколько контейнеров одного и того же образа, например, 2, 3 или 10 контейнеров MySQL или Redis или чего только пожелаете - и всё это будет работать слаженно, без всяких проблем с доступом к ресурсам серверной машины и т.д. При этом, наличие изолированных контейнеров, как раз из-за особенностей устройства докера, не нагружает вашу систему так, как нагружали бы две или три полноценные операционные системы на том же самом сервере.
Контейнер состоит из монтированных папок (Docker Volumes), переменных окружения, секретов (Docker Secrets) и т.д. и т.п. Вся эта "котовасия" нужна нам для корректной работы нашего основного приложения. Однако, стоит отметить, что в большинстве ситуаций Docker Container - это Stateless приложение, то есть зависимое от перезапуска. Это означало бы, что в случае остановки\перезапуска вашего сервера, вся информация о нём (в том числе игровая карта, данные игроков и т.д.) полностью терялись и начиналось бы всё с чистого листа, но нам на помощь приходят Docker Volumes.
Docker Volumes - или в простонародии монтированные папки - это буквально папки (или более корректнее - директории), которые при запуске вашего контейнера докер присоединяет к окружению образа. Таким образом, если вы создадите volume для вашей игровой карты и укажете докеру монтировать его для конкретного контейнера, то Docker предоставит контейнеру доступ к этой папке, а папке - доступ к контейнеру. После остановки вашего контейнера, volume не будет утерян, а вы, например, сможете спокойно скачать эту директорию или каким-либо иным образом взаимодействовать с ней. Проще говоря, все те файлы, которые вы хотите сохранять при перезапуске, следует хранить в volume, а всё то, что вам потребуется только при работе сервера, собирать в образе.
Деплой вашего сервера и его настройка
Итак, после того как мы разобрались с тем как работает докер, можем приступать к практической части. Давайте вернёмся к той самой команде, которую я нагло вывалил на вас без всякого объяснения:
Код:
docker run -d -it -p 25565:25565 -e EULA=TRUE itzg/minecraft-server
В данной команде мы сообщаем докеру о желании запустить контейнер в detached (-d) режиме на основе образа itzg/minecraft-server, который ему следует скачать с hub.docker.com, затем мы сообщаем ему о желании установить для нашего контейнера переменную окружения EULA=TRUE. В данном образе эта переменная отвечает за автоматическое подтверждение eula. После чего мы определяем что мы должны слушать порт 25565 извне и направлять всю поступающую по нему информацию в контейнер по порту 25565. То есть, Docker не будет слушать никакие другие порты, кроме тех, что вы сами указали ему слушать (где-то слышится радостный крик желающих выкинуть UFW, поскольку Docker гораздо надёжнее в вопросе защиты сервера, более того Docker настолько "гигачад", что настройки UFW им впринципе игнорируются). Тут важный момент, что если бы вы запустили ваш сервер на другом, отличном от 25565, порту, то вам бы следовало перенаправлять соединения на другой внутренний в контейнере порт, то есть данный аргумент выглядел бы так:
Код:
-p 25565:1000
Код:
-p 1000:25565
Итого, мы имеем запущенный сервер, однако в данном случае по умолчанию будет запущен сервер Spigot. Если мы хотим выбрать другое ядро, то достаточно указать переменную окружения TYPE:
Код:
docker run -d -it -p 25565:25565 -e EULA=TRUE TYPE=PAPER itzg/minecraft-server
Код:
docker run -d -it -p 25565:25565 -e EULA=TRUE TYPE=PAPER VERSION=1.20.6 itzg/minecraft-server
В данном образе для монтирования существует mountpoint "data/". Это означает, что наш с вами контейнер внутри для себя так или иначе создаст директорию data/ со всеми важными данными, другой вопрос будет она удалена при остановке сервера или будет подгружена извне с помощью механизма Volume. Для того, чтобы замонтировать папку к нашему контейнеру, её для начала нужно создать:
Код:
mkdir /home/minecraft_server/data/
Код:
docker run -d -it -p 25565:25565 -v /home/minecraft_server/data/:/data/ -e EULA=TRUE TYPE=PAPER VERSION=1.20.4 itzg/minecraft-server
Теперь, при запуске нашего контейнера, папка /home/minecraft_server/data/ заполнится важными для нас данными,
Напоминаю, докер не копирует папку к себе, а именно даёт доступ к ней из контейнера, поэтому меняя что либо в ней, эти изменения сразу же коснутся вашего сервера.