Jak postawić serwer na Dockerze (na przykładzie gry Minecraft)?

W życiu każdego programisty ważne jest zachowanie odpowiedniego work-life balance. Co robią pracownicy Dogtronic, żeby nie zwariować od ciągłego klikania w komputer? Dalej klikają w komputer, ale dla zabawy…

Ostatnio z chłopakami z zespołu w trakcie rozmowy doszliśmy do wniosku, że fajnie będzie cofnąć się o kilkanaście lat i pograć w znaną wszystkim grę Minecraft. Nie będzie to jednak poradnik jak przetrwać swoją pierwszą noc, a poradnik jak uruchomić serwer Minecraft (Java Edition) korzystając z metod konteneryzacji.

Podczas stawiania pierwszych serwerów Minecraft Alpha (albo Beta, nie pamiętam) w okolicy roku 2010 korzystałem z takich narzędzi jak Hamachi

Było to, a nawet wciąż jest, narzędzie do tworzenia prywatnych sieci wirtualnych, które pozwalało imitować sieci przypominające LAN. Dzięki niemu mogliśmy stawiać lokalnie serwery Minecraft i udostępniać je kolegom, żeby sobie pograć po pszyrce.

Elementy z gry Minecraft.
Minecraft to survivalowa gra komputerowa z otwartym światem. Gra pozwala graczom na budowanie i niszczenie obiektów położonych w losowo generowanym świecie. Gracz może między innymi atakować napotkane istoty, zbierać surowce i wytwarzać przedmioty.

Na tamten moment nie miałem pojęcia jak to wszystko działa. Chciałem po prostu kopać bloki w popularniej gierce i jedyne co się dla mnie liczyło to, czy obok mojej sieci wirtualnej świeci się zielona kropka, która była indykatorem, że wszystko działa.

Obecnie jako osobie, która w zakresie klikania w komputer, potrafi dużo więcej niż 10-letnie dziecko, postawienie serwera nie stanowi dla mnie żadnego wyzwania.

Miałem jednak jeden duży problem. Nie chciałem „brudzić” naszego serwera deweloperskiego instalowaniem na nim Javy. Całe szczęście z pomocą przyszedł mój dobry przyjaciel

Docker.

Czym jest Docker?

Docker to platforma pozwalająca na budowanie, wdrażanie oraz zarządzanie skonteneryzowanych aplikacji, czyli komponentów łączących ze sobą kod źródłowy naszych aplikacji oraz systemów operacyjnych działających w odseparowanych środowiskach.

Dzięki Dockerowi nie potrzebujemy w żaden sposób przygotowywać środowisk lokalnych ani produkcyjnych pod uruchomienie naszych aplikacji, wystarczy go zainstalować.
Dzięki Dockerowi nie potrzebujemy w żaden sposób przygotowywać środowisk lokalnych ani produkcyjnych pod uruchomienie naszych aplikacji, wystarczy go zainstalować.

Wyjaśnijmy to teraz na przykładzie
Załóżmy, że napisałem API w NodeJS, które chce szybko udostępnić mojemu koledze z zespołu. Zakładając, że nie mamy możliwości szybkiego wdrożenia go na żaden serwer, to w „bezdockerowej sytuacji” muszę wysłać koledze repozytorium z kodem źródłowym, a on musi je pobrać, przygotować środowisko oraz uruchomić aplikację.

Teraz załóżmy, że nie zna on Node’a i nie ma go zainstalowanego. Pojawia się problem, coś mu nie działa, apka sypie błędami i tak dalej… 

W konsekwencji tracimy dużo czasu.

Co się stanie, kiedy skorzystamy z Dockera? 

Budujemy obraz z gotową aplikacją lokalnie, wypychamy go na wybrane przez nas repozytorium obrazów dockerowych (np. Docker Hub lub Github Registry).

Nasz kolega sobie taki obraz pobiera i uruchamia go jedną komendą.
Nasz kolega sobie taki obraz pobiera i uruchamia go jedną komendą.

Dzięki temu nie musi on znać Node’a ani mieć go zainstalowanego na swoim środowisku, wszystko dzieje się w Dockerze i zakładając, że dobrze zbudowaliśmy obraz, to otwiera on w kilka minut poprawnie działającą aplikację na swoim systemie.

Ale jak to się ma do obecnego problemu, który próbujemy rozwiązać? Dowiecie się tego w dalszej części artykułu. 

O ile można nazwać postawienie serwera Minecraft problemem…

Konteneryzacja serwera Minecraft

Tak więc chcemy pograć z kolegami z zespołu w Minecrafta. Nie chcemy Javy na serwerze deweloperskim. Mamy za to Dockera. Rozwiązanie nasuwa się samo. W celu maksymalnego uproszczenia i szybkiego uruchomienia serwera skorzystałem z docker-compose, czyli narzędzia, które ułatwia definiowanie serwisów kontenerowych, ale raczej powinno się go używać do pracy lokalnej niż wdrożeń produkcyjnych. 

Niemniej, na nasze potrzeby powinien w zupełności wystarczyć, chcemy po prostu pograć w gierkę, która pewnie nam się znudzi po kilku dniach, nie ma więc sensu tracić za dużo czasu na zabawę w Kubernetes czy inne czary mary.

Docker ma bardzo dużą społeczność.
Docker ma bardzo dużą społeczność.

Bazowy obraz, na którym wszystko jest gotowe możecie znaleźć go na Docker HubMa on ponad 100 milionów pobrań więc zakładam, że musi działać całkiem dobrze… 

W celu skorzystania z niego w prosty sposób użyjemy docker-compose. Zacznijmy jednak od początku i przygotujmy katalog na serwerze, w którym umieścimy nasze pliki. W naszym przypadku utworzymy katalog:

/home/minecraft

Po wejściu na serwer (w naszym przypadku Debian 10) przez ssh i wejściu na roota uruchamiamy komendę:

cd /home && mkdir minecraft && cd minecraft && nano docker-compose.yml

A w pliku docker-compose.yml umieszczamy następującą zawartość:

version: "3"

services:
  mc:
    image: itzg/minecraft-server
    ports:
      - 25565:25565
    environment:
      EULA: "TRUE"
      OPS: "Karek,Majk"
      MOTD: "Welcome to Dogtronic Craft"
      SPAWN_PROTECTION: 0
    restart: unless-stopped
    volumes:
      - ./data:/data

Załączony kod możecie również znaleźć w repozytorium na Githubie. Jak możecie zauważyć po rozszerzeniu piszemy w YAMLu, dzięki czemu definicja naszego kontenera jest bardzo czytelna.

Niżej wyjaśniam działanie powyższego pliku (zaczynając od góry):

version
Definiujemy wersje docker-compose, w tym przypadku nie ma różnicy czy użyjemy 2 czy 3.

services
Nagłówek ten oznacza rozpoczęcie sekcji, w której definiować będziemy kontenery (serwisy), na jakie będzie składać się nasze środowisko. Tutaj mamy tylko jeden, ale gdybyśmy z jakiegoś powodu zapragnęli postawić coś obok to wystarczy dopisać kolejny serwis.

mc
Nazwa serwisu z serwerem Minecraft.

image
Nazwa obrazu, z jakiego ma korzystać nasz serwis, w tym przypadku będzie to obraz znaleziony przez nas na Docker Hub.

ports
Mapowanie portów z wewnątrz kontenera na porty hosta. Serwer Minecraft działa na porcie 25565 i mapujemy go na ten sam port hosta, ale może to być dowolny, nie zajęty port.

environment
Zmienne środowiskowe, tutaj użyłem kilka przykładowych:

  • EULA – ta zmienna musi być zawsze ustawiona na TRUE, ponieważ Mojang/Microsoft zawsze wymaga zaakceptowania tzw. end-user licence agreement.
  • OPS – tutaj wymieniamy po przecinku nazwy graczy, który mają mieć uprawnienia administratora.
  • MOTD – tutaj ustawiamy tzw. Message of the Day, czyli tekst wyświetlany pod naszym serwerem Minecraft.
  • SPAWN_PROTECTION – liczba kratek od globalnego spawna, które mają być niezniszczalne.

restart
Definiujemy tutaj kiedy kontener ma się restartować, w naszym przypadku zrestartuje się on zawsze poza sytuacją, gdy sami go zastopujemy.

volumes
Tutaj mapujemy pliki z wewnątrz kontenera na zewnątrz. W naszym przypadku mapujemy katalog /data z kontenera na relatywny katalog /data (czyli /home/minecraft/data), żeby mieć dostęp do plików serwerowych z poziomu hosta. Dzięki temu możemy w prosty sposób zmienić świat gry czy edytować właściwości serwera.

Dokładną instrukcję oraz rozpiskę wszystkich zmiennych środowiskowych znajdziecie na githubie Goeff’a Bourne’a.

Jeśli chodzi o zmienne środowiskowe to musicie wiedzieć, że będą one zaciągnięte tylko za pierwszym uruchomieniem kontenera. Potem będziecie musieli edytować odpowiednie wartości w plikach serwera, najczęściej w server.properties.

Ostatnie co nam zostało do zrobienia to otworzenie portu, na którym działa nasz serwer. Jeżeli podobnie jak ja korzystacie z ufw to zrobicie to komendą:

ufw allow 25565

Teraz wszystko powinno już działać i powinniście móc klikać w Minecrafta z kolegami z zespołu (po godzinach oczywiście, żeby nie było, że namawiam kogoś do grania w pracy…).

Bonus: Jak przetrwać pierwszą noc w Minecraft?

Wiele początkujących graczy boryka się z problemem przetrwania pierwszej nocy, bo nie są świadomi, że gdy zachodzi słońce, to wychodzą potwory…
Wiele początkujących graczy boryka się z problemem przetrwania pierwszej nocy, bo nie są świadomi, że gdy zachodzi słońce, to wychodzą potwory…

Nie no żartuję… Wracam do pracy, trzymajcie się cieplutko.


Szukasz nie tylko kolegów do wspólnego grania w Minecrafta, ale również pierwszej pracy?
Pobierz e-book z praktycznymi poradami dla programistów poszukujących pierwszej pracy i sprawdź, czy znajdzie się dla Ciebie miejsce w naszym zespole?

Karol Ścibior

Specjalista TypeScript | Node | React. Full-Stack Developer, dla którego nie ma projektów niewykonalnych.

Przekształć
swoje pomysły w rzeczywistość

Skontaktuj się z nami i pozwól nam sprawdzić jak możemy Ci pomóc.

Najciekawsze treści na Blogu