Update Dockerfile, settings.json, utils.py, nginx-example.conf, docker-compose.yml, and app.py

This commit is contained in:
Janis
2023-12-19 19:20:10 +01:00
parent 5775cb087a
commit 4844c26002
13 changed files with 376 additions and 227 deletions

View File

@@ -1,4 +1,7 @@
{ {
"python.analysis.typeCheckingMode": "off", "python.analysis.typeCheckingMode": "off",
"python.analysis.autoImportCompletions": true "python.analysis.autoImportCompletions": true,
"python.analysis.diagnosticSeverityOverrides": {
"reportMissingTypeStubs": "none"
}
} }

View File

@@ -13,8 +13,7 @@ RUN apt-get update && apt-get install -y python3 python3-pip python3-venv
RUN python3 -m venv /app/venv RUN python3 -m venv /app/venv
ENV PATH="/app/venv/bin:$PATH" ENV PATH="/app/venv/bin:$PATH"
# Copy the Python app files to the container ADD app/ /app/
COPY app/* /app/
# Set the working directory # Set the working directory
WORKDIR /app WORKDIR /app

0
app/__init__.py Normal file
View File

View File

@@ -1,50 +1,52 @@
import logging from math import log
import time
from requestHandler import RequestHandler
from utils import docker_container_mapping
from dockerHandler import DockerHandler from dockerHandler import DockerHandler
from nginxHandler import NginxHandler from nginxHandler import NginxHandler
from minecraftServerHandler import MinecraftServerHandler
from requestHandler import RequestHandler
import logging
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
def main(): def main() -> None:
try: try:
port_map = docker_container_mapping() logging.info('[INIT] initializing auto starter...')
logging.info('[INIT] initializing docker handler...')
docker_handler: DockerHandler = DockerHandler(
'unix://var/run/docker.sock')
logging.info('[INIT] docker handler initialized')
# Create a DockerHandler instance logging.info('[INIT] initializing nginx handler...')
docker_handler = DockerHandler( nginx_handler: NginxHandler = NginxHandler('/etc/nginx/nginx.conf')
'unix://var/run/docker.sock', port_map)
# Create an NginxHandler instance nginx_handler.update_config_file(
nginx_handler = NginxHandler('/etc/nginx/nginx.conf') docker_handler)
docker_handler.get_ip_by_dns_name(
docker_handler.get_current_container_name())
nginx_handler.setup_config_file( logging.info('[INIT] nginx handler initialized')
port_map, docker_handler.get_ip_by_dns_name(docker_handler.get_current_container_name()), docker_handler)
nginx_handler.print_config() logging.info('[INIT] initializing minecraft server handler...')
minecraft_server_handler: MinecraftServerHandler = MinecraftServerHandler(
docker_handler, nginx_handler)
# Find all Minecraft servers and add them to the MinecraftServerHandler instance
for service_name in docker_handler.get_port_map().values():
minecraft_server_handler.add_server(service_name)
logging.info('[INIT] wait 10 seconds before stopping all servers...')
time.sleep(10)
minecraft_server_handler.stop_all_servers()
logging.info('[INIT] minecraft server handler initialized')
logging.info('[INIT] initializing request handlers...')
# Create a RequestHandler instance for each port # Create a RequestHandler instance for each port
for port in port_map.keys(): for port in docker_handler.get_port_map().keys():
logging.info(f'Creating request handler for port {port}') logging.info(f'[INIT] creating request handler for port {port}')
request_handler = RequestHandler(int(port), docker_handler) request_handler: RequestHandler = RequestHandler(
int(port), docker_handler, minecraft_server_handler)
request_handler.start() request_handler.start()
logging.info('[INIT] request handlers initialized')
# DEBUG
logging.info(
'-----------------------------DEBUG--------------------------------')
logging.info(
f'Current container: {docker_handler.get_current_container_name()}')
logging.info(
f'Current container ip: {docker_handler.get_ip_by_dns_name(docker_handler.get_current_container_name())}')
logging.info(
f'Current network: {docker_handler.get_current_network()}')
docker_handler.print_all_container_names()
logging.info(
'-----------------------------DEBUG END--------------------------------')
except Exception as e: except Exception as e:
logging.error(f'An error occurred: {e}') logging.error(f'An error occurred: {e}')

View File

@@ -1,101 +1,98 @@
from typing import Dict
import docker import docker
from docker import DockerClient
from docker.models.networks import Network
import os import os
import logging import logging
from utils import docker_container_mapping
class DockerHandler: class DockerHandler:
def __init__(self, base_url, port_map): def __init__(self, base_url: str):
logging.info( logging.info(
f'Initializing docker handler with base url {base_url} and port ip map: {port_map}') f'[DockerHandler] initializing docker handler with base url {base_url} and port ip map: {self.get_port_map()}...')
self.base_url = base_url self.base_url: str = base_url
self.client = docker.DockerClient(base_url=base_url) self.client: DockerClient = DockerClient(base_url=base_url)
self.port_map = port_map self.current_network: Network = self.get_current_network()
self.current_network = self.get_current_network() logging.info('[DockerHandler] docker handler initialized')
logging.info('Docker handler initialized')
logging.info( logging.info(
f'Current container name: {self.get_current_container_name()}') f'[DockerHandler] current container name: {self.get_auto_starter_container_name()}')
logging.info(f'Current network: {self.current_network}') logging.info(
f'[DockerHandler] current network: {str(self.current_network)}')
def get_current_container(self): def get_port_map(self) -> Dict[str, str]:
hostname = self.get_current_container_name() return docker_container_mapping()
def stop_container(self, container) -> None:
if container:
logging.info(
f'[DockerHandler] stopping container {str(container.name)}')
container.stop()
logging.info(f'[DockerHandler] container {container.name} stopped')
else:
logging.info('[DockerHandler] no container to stop')
def start_container(self, container) -> None:
if container:
logging.info(
f'[DockerHandler] starting container {container.name}')
container.start()
logging.info(f'[DockerHandler] container {container.name} started')
else:
logging.info('[DockerHandler] no container to start')
def get_container_by_service_name(self, service_name):
logging.info(
f'[DockerHandler] getting container by service name {service_name}...')
try:
containers = self.client.containers.list(
all=True, filters={"network": self.current_network})
if containers is None:
logging.info('[DockerHandler] no containers found in network')
return None
for container in containers:
networks = container.attrs['NetworkSettings']['Networks']
if self.current_network in networks and service_name in networks[self.current_network]['Aliases']:
logging.info(
f'[DockerHandler] found container {container.name} with service name {service_name} in network {self.current_network}')
return container
logging.info(
f'[DockerHandler] no docker container found with service name {service_name} in network {self.current_network}')
return None
except docker.errors.APIError as e:
logging.error(f'Error getting container list: {e}')
return None
def get_auto_starter_container_name(self) -> str | None:
return os.environ.get('HOSTNAME')
def get_auto_starter_container(self):
hostname = os.environ.get('HOSTNAME')
if hostname: if hostname:
return self.client.containers.get(hostname) return self.client.containers.get(hostname)
return None return None
def get_current_container_name(self): def get_current_network(self) -> Network:
return os.environ.get('HOSTNAME') current_container = self.get_auto_starter_container()
def get_current_network(self):
current_container = self.get_current_container()
if current_container: if current_container:
networks = current_container.attrs['NetworkSettings']['Networks'] networks = current_container.attrs['NetworkSettings']['Networks']
return list(networks.keys())[0] return list(networks.keys())[0]
return None return None
def get_container_by_ip(self, ip): def get_ip_by_service_name(self, service_name: str) -> str:
try: container = self.get_container_by_service_name(service_name)
containers = self.client.containers.list(all=True)
except docker.errors.APIError as e:
logging.error(f'Error getting container list: {e}')
return None
for container in containers:
networks = container.attrs['NetworkSettings']['Networks']
if self.current_network in networks and networks[self.current_network]['IPAddress'] == ip:
logging.info(
f'Found container {container.name} with ip {ip} in network {self.current_network}')
return container
logging.info(
f'No docker container found with ip {ip} in network {self.current_network}')
return None
def is_container_starting(self, container):
if container: if container:
return container.attrs['State']['Health']['Status'] == 'starting'
return False
def print_all_container_names(self):
try:
containers = self.client.containers.list(
all=True, filters={"network": self.current_network})
if containers is None:
logging.info('No containers found')
return None
for container in containers:
logging.info(f'Container name: {container.name}')
# get docker compose dns name
networks = container.attrs['NetworkSettings']['Networks'] networks = container.attrs['NetworkSettings']['Networks']
if self.current_network in networks: return networks[self.current_network]['IPAddress']
logging.info( return ""
f'Container ip: {networks[self.current_network]["IPAddress"]}')
else:
logging.info(f'Container ip: None')
except docker.errors.APIError as e: def get_auto_starter_container_ip(self) -> str:
logging.error(f'Error getting container list: {e}') container = self.get_auto_starter_container()
return None if container:
def get_ip_by_dns_name(self, dns_name):
try:
containers = self.client.containers.list(
all=True, filters={"network": self.current_network})
if containers is None:
logging.info('No containers found')
return None
for container in containers:
networks = container.attrs['NetworkSettings']['Networks'] networks = container.attrs['NetworkSettings']['Networks']
if self.current_network in networks and dns_name in networks[self.current_network]['Aliases']: return networks[self.current_network]['IPAddress']
ip = networks[self.current_network]['IPAddress'] return ""
logging.info(
f'Found container {container.name} with dns name {dns_name} with ip {ip} in network {self.current_network}')
return ip
logging.info(
f'No docker container found with dns name {dns_name} in network {self.current_network}')
return None
except docker.errors.APIError as e:
logging.error(f'Error getting container list: {e}')
return None

View File

@@ -0,0 +1,53 @@
import logging
from typing import Dict, Optional
from nginxHandler import NginxHandler
from dockerHandler import DockerHandler
from objects.minecraftServer import MinecraftServer
class MinecraftServerHandler:
def __init__(self, docker_handler: DockerHandler, nginx_handler: NginxHandler):
logging.info(
'[MinecraftServerHandler] initializing minecraft server handler...')
self.minecraft_servers: Dict[str, MinecraftServer] = {}
self.docker_handler: DockerHandler = docker_handler
self.nginx_handler: NginxHandler = nginx_handler
self.active_service_name: str | None = None
logging.info(
'[MinecraftServerHandler] minecraft server handler initialized')
def add_server(self, service_name: str) -> None:
logging.info(
f'[MinecraftServerHandler] adding server {service_name}')
self.minecraft_servers[service_name] = MinecraftServer(
self.docker_handler, service_name)
logging.info(
f'[MinecraftServerHandler] added server {service_name}')
def get_server(self, service_name: str) -> MinecraftServer | None:
logging.info(f'[MinecraftServerHandler] getting server {service_name}')
return self.minecraft_servers.get(service_name)
def stop_all_servers(self, exclude_service_name: Optional[str] = None) -> None:
logging.info(f'[MinecraftServerHandler] stopping all servers')
for service_name, server in self.minecraft_servers.items():
logging.info(
f'[MinecraftServerHandler] stopping server {service_name}')
server.stop()
def start_server(self, service_name: str) -> None:
logging.info(
f'[MinecraftServerHandler] starting server {service_name}')
self.stop_all_servers()
server = self.get_server(service_name)
if server:
server.start()
logging.info(
f'[MinecraftServerHandler] started server {service_name}')
self.nginx_handler.update_config_file(
self.docker_handler)
self.nginx_handler.print_config()
else:
logging.info(
f'[MinecraftServerHandler] No server found with service name {service_name}')

View File

@@ -1,39 +1,49 @@
import os import os
import logging import logging
from typing import TextIO, Dict
from dockerHandler import DockerHandler
class NginxHandler: class NginxHandler:
def __init__(self, config_path): def __init__(self, config_path: str):
self.config_path = config_path logging.info('[NginxHandler] initializing nginx handler...')
self.config_path: str = config_path
def start(self): def start(self) -> None:
logging.info('Starting NGINX...') logging.info('[NginxHandler] starting nginx...')
os.system('nginx > /dev/null 2>&1 &') os.system('nginx > /dev/null 2>&1 &')
logging.info('NGINX started') logging.info('[NginxHandler] nginx started')
def stop(self): def stop(self) -> None:
logging.info('Stopping NGINX...') logging.info('[NginxHandler] stopping nginx...')
os.system('nginx -s stop') os.system('nginx -s stop')
logging.info('NGINX stopped') logging.info('[NginxHandler] nginx stopped')
def restart(self): def restart(self) -> None:
self.stop() self.stop()
self.start() self.start()
def print_config(self): def print_config(self) -> None:
logging.info('[NginxHandler] printing nginx config file...')
logging.info('========================================')
with open(self.config_path, 'r') as f: with open(self.config_path, 'r') as f:
logging.info(f.read()) logging.info(f.read())
logging.info('========================================')
logging.info('[NginxHandler] nginx config file printed')
def setup_config_file(self, port_map, current_container_ip, docker_handler): def update_config_file(self, docker_handler: DockerHandler) -> None:
logging.info('[NginxHandler] updating nginx config file...')
self.stop()
port_map: Dict[str, str] = docker_handler.get_port_map()
if port_map is None: if port_map is None:
logging.error('port_map is None') logging.error('[NginxHandler] port_map is None')
return return
proxy_timeout = "5s" proxy_timeout: str = "5s"
self.stop() logging.info('[NginxHandler] setting up NGINX config file...')
logging.info('Setting up NGINX config file...') logging.info('[NginxHandler] port_map: {}'.format(port_map))
logging.info('port_map: {}'.format(port_map)) nginx_conf: TextIO = open(self.config_path, 'w+')
nginx_conf = open(self.config_path, 'w+')
nginx_conf.truncate() nginx_conf.truncate()
nginx_conf.write('worker_processes 5;\n') nginx_conf.write('worker_processes 5;\n')
nginx_conf.write('events { \n') nginx_conf.write('events { \n')
@@ -46,16 +56,23 @@ class NginxHandler:
# Example for the nginx-example.conf file is in the repo root directory # Example for the nginx-example.conf file is in the repo root directory
if isinstance(port_map, dict): if isinstance(port_map, dict):
for port in port_map: for port in port_map:
ip = docker_handler.get_ip_by_dns_name(port_map[port]) ip = docker_handler.get_ip_by_service_name(port_map[port])
nginx_conf.write(
f' # docker service {port_map[port]} on port {port}\n')
nginx_conf.write(f' upstream upstream_{port} {{\n') nginx_conf.write(f' upstream upstream_{port} {{\n')
if ip == "":
nginx_conf.write(f' server 127.0.0.1:{port};\n')
else:
nginx_conf.write(f' server {ip}:25565;\n') nginx_conf.write(f' server {ip}:25565;\n')
nginx_conf.write(f' server 127.0.0.1:{port} backup;\n') nginx_conf.write(
f' server 127.0.0.1:{port} backup;\n')
nginx_conf.write(' }\n') nginx_conf.write(' }\n')
nginx_conf.write(' server {\n') nginx_conf.write(' server {\n')
nginx_conf.write( nginx_conf.write(
f' listen {current_container_ip}:{port};\n') f' listen {docker_handler.get_auto_starter_container_ip()}:{port};\n')
nginx_conf.write( nginx_conf.write(
f' proxy_connect_timeout {proxy_timeout};\n') f' proxy_connect_timeout {proxy_timeout};\n')
@@ -68,5 +85,8 @@ class NginxHandler:
nginx_conf.write('}\n') nginx_conf.write('}\n')
nginx_conf.close() nginx_conf.close()
logging.info('NGINX config file setup complete') logging.info('[NginxHandler] nginx config file setup complete')
self.start() self.start()
# Restart for good measure. Add inconsistency issues with nginx
self.restart()

0
app/objects/__init__.py Normal file
View File

View File

@@ -0,0 +1,57 @@
import docker
import logging
from dockerHandler import DockerHandler
class MinecraftServer:
def __init__(self, docker_handler: DockerHandler, service_name: str):
self.docker_handler: DockerHandler = docker_handler
self.service_name: str = service_name
def get_container(self):
return self.docker_handler.get_container_by_service_name(
self.service_name)
def start(self) -> None:
self.docker_handler.start_container(
self.get_container())
def stop(self) -> None:
self.docker_handler.stop_container(
self.get_container())
def is_starting(self) -> bool:
if self.get_container():
return self.get_container().attrs['State']['Health']['Status'] == 'starting'
return False
def is_running(self) -> bool:
if self.get_container():
return self.get_container().attrs['State']['Health']['Status'] == 'healthy'
return False
def get_ip(self) -> str | None:
try:
containers = self.docker_handler.client.containers.list(
all=True, filters={"network": self.docker_handler.current_network})
if containers is None:
logging.info('[MinecraftServer] no containers found')
return None
for container in containers:
networks = container.attrs['NetworkSettings']['Networks']
if self.docker_handler.current_network in networks and self.service_name in networks[self.docker_handler.current_network]['Aliases']:
ip = networks[self.docker_handler.current_network]['IPAddress']
logging.info(
f'[MinecraftServer] found container {container.name} with service name {self.service_name} with ip {ip} in network {self.docker_handler.current_network}')
return ip
logging.info(
f'[MinecraftServer] no docker container found with service name {self.service_name} in network {self.docker_handler.current_network}')
return None
except docker.errors.APIError as e:
logging.error(
f'[MinecraftServer] error getting container list: {e}')
return None

View File

@@ -2,104 +2,143 @@ import os
import socket import socket
import logging import logging
import threading import threading
from utils import docker_container_mapping from typing import Literal
from dockerHandler import DockerHandler
from minecraftServerHandler import MinecraftServerHandler
from objects.minecraftServer import MinecraftServer
class RequestHandler(threading.Thread): class RequestHandler(threading.Thread):
def __init__(self, port, docker_handler): def __init__(self, port: str, docker_handler: DockerHandler, minecraft_server_handler: MinecraftServerHandler):
super().__init__()
self.port = port
self.docker_handler = docker_handler
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_address = ('localhost', self.port)
logging.info( logging.info(
f'Starting up on {server_address[0]} port {server_address[1]}') f'[RequestHandler:{port}] initializing request handler...')
super().__init__()
self.port: str = port
if not self.port:
logging.info(
f'[RequestHandler:{self.port}] no port specified')
return
self.docker_handler: DockerHandler = docker_handler
self.minecraft_server_handler: MinecraftServerHandler = minecraft_server_handler
self.sock: socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_address: tuple[Literal['localhost'], str] = (
'localhost', self.port)
logging.info(
f'[RequestHandler:{self.port}] starting up on {server_address[0]} port {server_address[1]}')
self.sock.bind(server_address) self.sock.bind(server_address)
self.sock.listen(1) self.sock.listen(1)
logging.info(
f'[RequestHandler:{self.port}] request handler initialized')
def restart(self): def restart(self):
logging.info(f'Restarting request handler for port {self.port}') logging.info(
f'[RequestHandler:{self.port}] restarting request handler for port {self.port}')
self.sock.close() self.sock.close()
self.__init__(self.port, self.docker_handler) self.__init__(self.port, self.docker_handler,
self.minecraft_server_handler)
def run(self): def run(self) -> None:
while True: while True:
try: try:
logging.info(f'Waiting for a connection on port {self.port}') logging.info(
f'[RequestHandler:{self.port}] waiting for a connection on port {self.port}')
self.connection, self.client_address = self.sock.accept() self.connection, self.client_address = self.sock.accept()
try: try:
logging.info(f'Connection from {self.client_address}') logging.info(
f'[RequestHandler:{self.port}] connection from {self.client_address}')
self.handle_request() self.handle_request()
except Exception as e: except Exception as e:
logging.info( logging.info(
f'Error in request handler for port {self.port}: {e}') f'[RequestHandler:{self.port}] error in request handler for port {self.port}: {e}')
logging.info('Restarting request handler...') logging.info(
'[RequestHandler:{self.port}] restarting request handler...')
self.restart() self.restart()
finally: finally:
self.connection.close() self.connection.close()
self.restart() self.restart()
except Exception as e: except Exception as e:
logging.info( logging.info(
f'Error in request handler for port {self.port}: {e}') f'[RequestHandler:{self.port}] error in request handler for port {self.port}: {e}')
logging.info('Restarting request handler...') logging.info(
'[RequestHandler:{self.port}] restarting request handler...')
self.restart() self.restart()
def handle_request(self): def handle_request(self) -> None:
logging.info(f'Handling request on port {self.port}') logging.info(
print(docker_container_mapping().get(str(self.port))) f'[RequestHandler:{self.port}] handling request on port {self.port}')
container_ip = self.docker_handler.get_ip_by_dns_name(
docker_container_mapping().get(str(self.port)))
print(f"----Container IP: {container_ip}")
if container_ip: service_name = self.docker_handler.get_port_map().get(str(self.port))
container = self.docker_handler.get_container_by_ip( logging.info(
container_ip) f'[RequestHandler:{self.port}] service name: {service_name}')
isStarting = self.docker_handler.is_container_starting(container)
if service_name:
minecraft_server: MinecraftServer = self.minecraft_server_handler.get_server(
service_name)
if not minecraft_server:
logging.info(
f'[RequestHandler:{self.port}] no minecraft server found for service name {service_name}')
return
request = self.connection.recv(1024) request = self.connection.recv(1024)
logging.info(f'Received request: {request}') logging.info(
f'[RequestHandler:{self.port}] received request: {request}')
# b'\x1b\x00\xfb\x05\x14mc.tealfire.de\x00FML3\x00c\xa0\x02\x1a\x00\x07DerTyp7\x01\xf2]\x9a\x18*\xeaJ\xed\xbe0g\x9c\x8aT\xa9t' # b'\x1b\x00\xfb\x05\x14mc.tealfire.de\x00FML3\x00c\xa0\x02\x1a\x00\x07DerTyp7\x01\xf2]\x9a\x18*\xeaJ\xed\xbe0g\x9c\x8aT\xa9t'
if request[0] == 0x10 or request[0] == 0x15 or request[0] == 0x1b: if request[0] == 0x10 or request[0] == 0x15 or request[0] == 0x1b:
if b'\x02' in request: if b'\x02' in request:
logging.info( logging.info(
f'Detected join/login request for {container_ip}') f'[RequestHandler:{self.port}] detected join/login request for {service_name}')
if isStarting: if minecraft_server.is_starting() == True:
logging.info( logging.info(
f'Container {container_ip} is already starting...') f'[RequestHandler:{self.port}] container {service_name} is already starting...')
self.forward_request_to_placeholder( self.forward_request_to_placeholder(
request, isStarting) request, minecraft_server)
else: else:
logging.info(f'Starting container {container_ip}') logging.info(
container.start() f'[RequestHandler:{self.port}] starting container {service_name}')
self.minecraft_server_handler.start_server(
service_name)
elif b'\x01' in request: elif b'\x01' in request:
logging.info(f'Detected ping request for {container_ip}') logging.info(
self.forward_request_to_placeholder(request, isStarting) f'[RequestHandler:{self.port}] detected ping request for {service_name}')
self.forward_request_to_placeholder(
request, minecraft_server)
elif request[0] == 0xFE: elif request[0] == 0xFE:
logging.info( logging.info(
f'Detected legacy ping request for {container_ip}') f'[RequestHandler:{self.port}] detected legacy ping request for {service_name}')
self.forward_request_to_placeholder(request, isStarting) self.forward_request_to_placeholder(request, minecraft_server)
else: else:
logging.info(f'Detected unknown request for {container_ip}')
self.forward_request_to_placeholder(request, isStarting)
else:
logging.info(f'No container mapped to port {self.port}')
def forward_request_to_placeholder(self, request, isStarting=False):
logging.info('Forwarding request to placeholder server')
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
ip = self.docker_handler.get_ip_by_dns_name(
os.environ.get('PLACEHOLDER_SERVER_SLEEPING_SERVICE'))
if isStarting:
logging.info( logging.info(
'Container is starting. Using starting placeholder IP') f'[RequestHandler:{self.port}] detected unknown request for {service_name}')
ip = self.docker_handler.get_ip_by_dns_name( self.forward_request_to_placeholder(request, minecraft_server)
else:
logging.info(
f'[RequestHandler:{self.port}] no container mapped to port {self.port}')
def forward_request_to_placeholder(self, request, minecraft_server: MinecraftServer) -> None:
logging.info(
'[RequestHandler:{self.port}] forwarding request to placeholder server')
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
ip = self.docker_handler.get_ip_by_service_name(
os.environ.get('PLACEHOLDER_SERVER_SLEEPING_SERVICE'))
if minecraft_server.is_starting() == True:
logging.info(
'[RequestHandler:{self.port}] container is starting. Using starting placeholder ip')
ip = self.docker_handler.get_ip_by_service_name(
os.environ.get('PLACEHOLDER_SERVER_STARTING_SERVICE')) os.environ.get('PLACEHOLDER_SERVER_STARTING_SERVICE'))
if not ip: if not ip:
logging.info('No placeholder server IP found') logging.info(
'[RequestHandler:{self.port}] no placeholder server ip found')
return return
logging.info(
f'[RequestHandler:{self.port}] placeholder server ip: {ip}')
try: try:
server_socket.connect((ip, 25565)) server_socket.connect((ip, 25565))
server_socket.sendall(request) server_socket.sendall(request)
@@ -107,5 +146,5 @@ class RequestHandler(threading.Thread):
self.connection.sendall(response) self.connection.sendall(response)
except Exception as e: except Exception as e:
logging.info( logging.info(
f'Error while handling request on port {self.port}: {e}') f'[RequestHandler:{self.port}] error while handling request on port {self.port}: {e}')
self.restart() self.restart()

View File

@@ -18,11 +18,3 @@ def docker_container_mapping():
for port in port_map: for port in port_map:
logging.info(f'{port} -> {port_map[port]}') logging.info(f'{port} -> {port_map[port]}')
return port_map return port_map
def get_ip_by_dns_name(dns_name):
try:
return socket.gethostbyname(dns_name, resolver='127.0.0.1')
except socket.gaierror:
logging.error(f'Could not resolve dns name {dns_name}')
return None

View File

@@ -3,7 +3,7 @@ version: "3.9"
services: services:
auto_starter: auto_starter:
container_name: mc_auto_starter container_name: mc_auto_starter
restart: always restart: no
image: dertyp7/minecraft_server_auto_starter:latest image: dertyp7/minecraft_server_auto_starter:latest
ports: ports:
- 25565:25565 - 25565:25565
@@ -77,40 +77,23 @@ services:
mc: mc:
container_name: example_mc_server_1 container_name: example_mc_server_1
image: itzg/minecraft-server image: itzg/minecraft-server
restart: no #! This is important. If you restart the server automatically, the auto_starter will not work restart: unless-stopped #! This is important. If you restart the server automatically, the auto_starter will not work
environment: environment:
type: "PAPER" type: "PAPER"
VERSION: "1.12.2"
EULA: "TRUE" EULA: "TRUE"
MOTD: "Starting, please wait..." MOTD: "Example Server 1"
MAX_PLAYERS: "1"
# The placeholder servers should be as lightweight as possible #! Dont change SERVER_PORT. Use PORT_IP_MAP in auto_starter instead.
MAX_PLAYERS: "0" # SERVER_PORT default is "25565"
MAX_MEMORY: "512M"
INIT_MEMORY: "512M"
LEVEL_TYPE: "FLAT"
JVM_XX_OPTS: "-XX:+UseConcMarkSweepGC -XX:+DisableExplicitGC -XX:+UseCompressedOops"
VIEW_DISTANCE: "1"
SPAWN_ANIMALS: "false"
SPAWN_MONSTERS: "false"
SNOOPER_ENABLED: "false"
GENERATE_STRUCTURES: "false"
ALLOW_NETHER: "false"
ALLOW_END: "false"
mc2: mc2:
container_name: example_mc_server_2 container_name: example_mc_server_2
image: itzg/minecraft-server image: itzg/minecraft-server
restart: no #! This is important. If you restart the server automatically, the auto_starter will not work restart: unless-stopped #! This is important. If you restart the server automatically, the auto_starter will not work
environment: environment:
type: "PAPER" type: "PAPER"
EULA: "TRUE" EULA: "TRUE"
MOTD: "Example Server 2" MOTD: "Example Server 2"
MAX_PLAYERS: "1" MAX_PLAYERS: "1"
# Enable autostop, so the auto_starter makes sense
ENABLE_AUTOSTOP: "FALSE"
AUTOSTOP_TIMEOUT_EST: "10"
AUTOSTOP_TIMEOUT_INIT: "10"
#! Dont change SERVER_PORT. Use PORT_IP_MAP in auto_starter instead. #! Dont change SERVER_PORT. Use PORT_IP_MAP in auto_starter instead.
# SERVER_PORT default is "25565" # SERVER_PORT default is "25565"

View File

@@ -1,21 +1,25 @@
events { } worker_processes 5;
events {
worker_connections 1024;
multi_accept on;
}
stream { stream {
upstream upstream_25565 { upstream upstream_25565 {
server 172.20.0.5:25565; server 192.168.144.5:25565;
server 127.0.0.1:25565 backup; server 127.0.0.1:25565 backup;
} }
server { server {
listen 172.20.0.2:25565; listen 192.168.144.6:25565;
proxy_connect_timeout 5s; proxy_connect_timeout 5s;
proxy_timeout 5s; proxy_timeout 5s;
proxy_pass upstream_25565; proxy_pass upstream_25565;
} }
upstream upstream_25566 { upstream upstream_25566 {
server 172.20.0.6:25565; server 192.168.144.3:25565;
server 127.0.0.1:25566 backup; server 127.0.0.1:25566 backup;
} }
server { server {
listen 172.20.0.2:25566; listen 192.168.144.6:25566;
proxy_connect_timeout 5s; proxy_connect_timeout 5s;
proxy_timeout 5s; proxy_timeout 5s;
proxy_pass upstream_25566; proxy_pass upstream_25566;