mirror of
https://github.com/DerTyp7/docker_minecraft_server_auto_starter.git
synced 2025-10-28 12:22:12 +01:00
Update Dockerfile and utils.py
This commit is contained in:
@@ -3,11 +3,9 @@ FROM nginx:1.25.3
|
||||
|
||||
ENV PORT_MAP ""
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
ENV PLACEHOLDER_SERVER_SLEEPING_IP ""
|
||||
ENV PLACEHOLDER_SERVER_STARTING_IP ""
|
||||
|
||||
# Install Python and pip
|
||||
RUN apt-get update && apt-get install -y python3 python3-pip python3-venv
|
||||
# Install Python, pip and git
|
||||
RUN apt-get update && apt-get install -y python3 python3-pip python3-venv
|
||||
|
||||
# Create a virtual environment and activate it
|
||||
RUN python3 -m venv /app/venv
|
||||
|
||||
1
app/FakeMCServer
Submodule
1
app/FakeMCServer
Submodule
Submodule app/FakeMCServer added at d7d7bedb2b
132
app/app.py
132
app/app.py
@@ -1,56 +1,76 @@
|
||||
from math import log
|
||||
import time
|
||||
from dockerHandler import DockerHandler
|
||||
from nginxHandler import NginxHandler
|
||||
from minecraftServerHandler import MinecraftServerHandler
|
||||
from requestHandler import RequestHandler
|
||||
import logging
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
try:
|
||||
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')
|
||||
|
||||
logging.info('[INIT] initializing nginx handler...')
|
||||
nginx_handler: NginxHandler = NginxHandler('/etc/nginx/nginx.conf')
|
||||
|
||||
nginx_handler.update_config_file(
|
||||
docker_handler)
|
||||
|
||||
logging.info('[INIT] nginx handler initialized')
|
||||
|
||||
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 20 seconds before stopping all servers...')
|
||||
time.sleep(20)
|
||||
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
|
||||
for port in docker_handler.get_port_map().keys():
|
||||
logging.info(f'[INIT] creating request handler for port {port}')
|
||||
request_handler: RequestHandler = RequestHandler(
|
||||
int(port), docker_handler, minecraft_server_handler)
|
||||
request_handler.start()
|
||||
logging.info('[INIT] request handlers initialized')
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f'An error occurred: {e}')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
import os
|
||||
import time
|
||||
from dockerHandler import DockerHandler
|
||||
from nginxHandler import NginxHandler
|
||||
from minecraftServerHandler import MinecraftServerHandler
|
||||
from requestHandler import RequestHandler
|
||||
import logging
|
||||
from FakeMCServer.fake_mc_server import FakeMCServer
|
||||
import threading
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
def init_placeholder_servers():
|
||||
sleeping = FakeMCServer(port=20000, motd={
|
||||
"1": "sleeping!", "2": "§aCheck example.com for more information!"})
|
||||
starting = FakeMCServer(port=20001, motd={
|
||||
"1": "starting!", "2": "§aCheck example.com for more information!"})
|
||||
|
||||
# Create threads for each server initialization
|
||||
sleeping_thread = threading.Thread(target=sleeping.start_server)
|
||||
starting_thread = threading.Thread(target=starting.start_server)
|
||||
|
||||
# Start the threads
|
||||
sleeping_thread.start()
|
||||
starting_thread.start()
|
||||
|
||||
|
||||
def main() -> None:
|
||||
try:
|
||||
logging.info('[INIT] initializing placeholder servers...')
|
||||
init_placeholder_servers()
|
||||
logging.info('[INIT] placeholder servers initialized')
|
||||
|
||||
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')
|
||||
|
||||
logging.info('[INIT] initializing nginx handler...')
|
||||
nginx_handler: NginxHandler = NginxHandler('/etc/nginx/nginx.conf')
|
||||
|
||||
nginx_handler.update_config_file(
|
||||
docker_handler)
|
||||
|
||||
logging.info('[INIT] nginx handler initialized')
|
||||
|
||||
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 20 seconds before stopping all servers...')
|
||||
time.sleep(20)
|
||||
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
|
||||
for port in docker_handler.get_port_map().keys():
|
||||
logging.info(f'[INIT] creating request handler for port {port}')
|
||||
request_handler: RequestHandler = RequestHandler(
|
||||
int(port), docker_handler, minecraft_server_handler)
|
||||
request_handler.start()
|
||||
logging.info('[INIT] request handlers initialized')
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f'An error occurred: {e}')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -1,98 +1,98 @@
|
||||
from typing import Dict
|
||||
import docker
|
||||
from docker import DockerClient
|
||||
from docker.models.networks import Network
|
||||
import os
|
||||
import logging
|
||||
|
||||
from utils import docker_container_mapping
|
||||
|
||||
|
||||
class DockerHandler:
|
||||
def __init__(self, base_url: str):
|
||||
logging.info(
|
||||
f'[DockerHandler] initializing docker handler with base url {base_url} and port ip map: {self.get_port_map()}...')
|
||||
self.base_url: str = base_url
|
||||
self.client: DockerClient = DockerClient(base_url=base_url)
|
||||
self.current_network: Network = self.get_current_network()
|
||||
logging.info('[DockerHandler] docker handler initialized')
|
||||
logging.info(
|
||||
f'[DockerHandler] current container name: {self.get_auto_starter_container_name()}')
|
||||
logging.info(
|
||||
f'[DockerHandler] current network: {str(self.current_network)}')
|
||||
|
||||
def get_port_map(self) -> Dict[str, str]:
|
||||
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:
|
||||
return self.client.containers.get(hostname)
|
||||
return None
|
||||
|
||||
def get_current_network(self) -> Network:
|
||||
current_container = self.get_auto_starter_container()
|
||||
if current_container:
|
||||
networks = current_container.attrs['NetworkSettings']['Networks']
|
||||
return list(networks.keys())[0]
|
||||
return None
|
||||
|
||||
def get_ip_by_service_name(self, service_name: str) -> str:
|
||||
container = self.get_container_by_service_name(service_name)
|
||||
if container:
|
||||
networks = container.attrs['NetworkSettings']['Networks']
|
||||
return networks[self.current_network]['IPAddress']
|
||||
return ""
|
||||
|
||||
def get_auto_starter_container_ip(self) -> str:
|
||||
container = self.get_auto_starter_container()
|
||||
if container:
|
||||
networks = container.attrs['NetworkSettings']['Networks']
|
||||
return networks[self.current_network]['IPAddress']
|
||||
return ""
|
||||
from typing import Dict
|
||||
import docker
|
||||
from docker import DockerClient
|
||||
from docker.models.networks import Network
|
||||
import os
|
||||
import logging
|
||||
|
||||
from utils import docker_container_mapping
|
||||
|
||||
|
||||
class DockerHandler:
|
||||
def __init__(self, base_url: str):
|
||||
logging.info(
|
||||
f'[DockerHandler] initializing docker handler with base url {base_url} and port ip map: {self.get_port_map()}...')
|
||||
self.base_url: str = base_url
|
||||
self.client: DockerClient = DockerClient(base_url=base_url)
|
||||
self.current_network: Network = self.get_current_network()
|
||||
logging.info('[DockerHandler] docker handler initialized')
|
||||
logging.info(
|
||||
f'[DockerHandler] current container name: {self.get_auto_starter_container_name()}')
|
||||
logging.info(
|
||||
f'[DockerHandler] current network: {str(self.current_network)}')
|
||||
|
||||
def get_port_map(self) -> Dict[str, str]:
|
||||
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:
|
||||
return self.client.containers.get(hostname)
|
||||
return None
|
||||
|
||||
def get_current_network(self) -> Network:
|
||||
current_container = self.get_auto_starter_container()
|
||||
if current_container:
|
||||
networks = current_container.attrs['NetworkSettings']['Networks']
|
||||
return list(networks.keys())[0]
|
||||
return None
|
||||
|
||||
def get_ip_by_service_name(self, service_name: str) -> str:
|
||||
container = self.get_container_by_service_name(service_name)
|
||||
if container:
|
||||
networks = container.attrs['NetworkSettings']['Networks']
|
||||
return networks[self.current_network]['IPAddress']
|
||||
return ""
|
||||
|
||||
def get_auto_starter_container_ip(self) -> str:
|
||||
container = self.get_auto_starter_container()
|
||||
if container:
|
||||
networks = container.attrs['NetworkSettings']['Networks']
|
||||
return networks[self.current_network]['IPAddress']
|
||||
return ""
|
||||
|
||||
@@ -1,92 +1,92 @@
|
||||
import os
|
||||
import logging
|
||||
from typing import TextIO, Dict
|
||||
|
||||
from dockerHandler import DockerHandler
|
||||
|
||||
|
||||
class NginxHandler:
|
||||
def __init__(self, config_path: str):
|
||||
logging.info('[NginxHandler] initializing nginx handler...')
|
||||
self.config_path: str = config_path
|
||||
|
||||
def start(self) -> None:
|
||||
logging.info('[NginxHandler] starting nginx...')
|
||||
os.system('nginx > /dev/null 2>&1 &')
|
||||
logging.info('[NginxHandler] nginx started')
|
||||
|
||||
def stop(self) -> None:
|
||||
logging.info('[NginxHandler] stopping nginx...')
|
||||
os.system('nginx -s stop')
|
||||
logging.info('[NginxHandler] nginx stopped')
|
||||
|
||||
def restart(self) -> None:
|
||||
self.stop()
|
||||
self.start()
|
||||
|
||||
def print_config(self) -> None:
|
||||
logging.info('[NginxHandler] printing nginx config file...')
|
||||
logging.info('========================================')
|
||||
with open(self.config_path, 'r') as f:
|
||||
logging.info(f.read())
|
||||
logging.info('========================================')
|
||||
logging.info('[NginxHandler] nginx config file printed')
|
||||
|
||||
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:
|
||||
logging.error('[NginxHandler] port_map is None')
|
||||
return
|
||||
|
||||
proxy_timeout: str = "5s"
|
||||
logging.info('[NginxHandler] setting up NGINX config file...')
|
||||
logging.info('[NginxHandler] port_map: {}'.format(port_map))
|
||||
nginx_conf: TextIO = open(self.config_path, 'w+')
|
||||
nginx_conf.truncate()
|
||||
nginx_conf.write('worker_processes 5;\n')
|
||||
nginx_conf.write('events { \n')
|
||||
nginx_conf.write(' worker_connections 1024;\n')
|
||||
nginx_conf.write(' multi_accept on;\n')
|
||||
nginx_conf.write('}\n')
|
||||
nginx_conf.write('stream {\n')
|
||||
|
||||
# This looks confusing, but the nginx.conf looks good when it's done
|
||||
# Example for the nginx-example.conf file is in the repo root directory
|
||||
if isinstance(port_map, dict):
|
||||
for port in port_map:
|
||||
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')
|
||||
|
||||
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 127.0.0.1:{port} backup;\n')
|
||||
nginx_conf.write(' }\n')
|
||||
|
||||
nginx_conf.write(' server {\n')
|
||||
nginx_conf.write(
|
||||
f' listen {docker_handler.get_auto_starter_container_ip()}:{port};\n')
|
||||
|
||||
nginx_conf.write(
|
||||
f' proxy_connect_timeout {proxy_timeout};\n')
|
||||
nginx_conf.write(f' proxy_timeout {proxy_timeout};\n')
|
||||
|
||||
nginx_conf.write(f' proxy_pass upstream_{port};\n')
|
||||
nginx_conf.write(' }\n')
|
||||
else:
|
||||
logging.error('port_map is not a dictionary')
|
||||
|
||||
nginx_conf.write('}\n')
|
||||
nginx_conf.close()
|
||||
logging.info('[NginxHandler] nginx config file setup complete')
|
||||
self.start()
|
||||
|
||||
# Restart for good measure. Add inconsistency issues with nginx
|
||||
self.restart()
|
||||
import os
|
||||
import logging
|
||||
from typing import TextIO, Dict
|
||||
|
||||
from dockerHandler import DockerHandler
|
||||
|
||||
|
||||
class NginxHandler:
|
||||
def __init__(self, config_path: str):
|
||||
logging.info('[NginxHandler] initializing nginx handler...')
|
||||
self.config_path: str = config_path
|
||||
|
||||
def start(self) -> None:
|
||||
logging.info('[NginxHandler] starting nginx...')
|
||||
os.system('nginx > /dev/null 2>&1 &')
|
||||
logging.info('[NginxHandler] nginx started')
|
||||
|
||||
def stop(self) -> None:
|
||||
logging.info('[NginxHandler] stopping nginx...')
|
||||
os.system('nginx -s stop')
|
||||
logging.info('[NginxHandler] nginx stopped')
|
||||
|
||||
def restart(self) -> None:
|
||||
self.stop()
|
||||
self.start()
|
||||
|
||||
def print_config(self) -> None:
|
||||
logging.info('[NginxHandler] printing nginx config file...')
|
||||
logging.info('========================================')
|
||||
with open(self.config_path, 'r') as f:
|
||||
logging.info(f.read())
|
||||
logging.info('========================================')
|
||||
logging.info('[NginxHandler] nginx config file printed')
|
||||
|
||||
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:
|
||||
logging.error('[NginxHandler] port_map is None')
|
||||
return
|
||||
|
||||
proxy_timeout: str = "5s"
|
||||
logging.info('[NginxHandler] setting up NGINX config file...')
|
||||
logging.info('[NginxHandler] port_map: {}'.format(port_map))
|
||||
nginx_conf: TextIO = open(self.config_path, 'w+')
|
||||
nginx_conf.truncate()
|
||||
nginx_conf.write('worker_processes 5;\n')
|
||||
nginx_conf.write('events { \n')
|
||||
nginx_conf.write(' worker_connections 1024;\n')
|
||||
nginx_conf.write(' multi_accept on;\n')
|
||||
nginx_conf.write('}\n')
|
||||
nginx_conf.write('stream {\n')
|
||||
|
||||
# This looks confusing, but the nginx.conf looks good when it's done
|
||||
# Example for the nginx-example.conf file is in the repo root directory
|
||||
if isinstance(port_map, dict):
|
||||
for port in port_map:
|
||||
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')
|
||||
|
||||
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 127.0.0.1:{port} backup;\n')
|
||||
nginx_conf.write(' }\n')
|
||||
|
||||
nginx_conf.write(' server {\n')
|
||||
nginx_conf.write(
|
||||
f' listen {docker_handler.get_auto_starter_container_ip()}:{port};\n')
|
||||
|
||||
nginx_conf.write(
|
||||
f' proxy_connect_timeout {proxy_timeout};\n')
|
||||
nginx_conf.write(f' proxy_timeout {proxy_timeout};\n')
|
||||
|
||||
nginx_conf.write(f' proxy_pass upstream_{port};\n')
|
||||
nginx_conf.write(' }\n')
|
||||
else:
|
||||
logging.error('port_map is not a dictionary')
|
||||
|
||||
nginx_conf.write('}\n')
|
||||
nginx_conf.close()
|
||||
logging.info('[NginxHandler] nginx config file setup complete')
|
||||
self.start()
|
||||
|
||||
# Restart for good measure. Add inconsistency issues with nginx
|
||||
self.restart()
|
||||
|
||||
@@ -1,150 +1,147 @@
|
||||
import os
|
||||
import socket
|
||||
import logging
|
||||
import threading
|
||||
from typing import Literal
|
||||
from dockerHandler import DockerHandler
|
||||
from minecraftServerHandler import MinecraftServerHandler
|
||||
from objects.minecraftServer import MinecraftServer
|
||||
|
||||
|
||||
class RequestHandler(threading.Thread):
|
||||
def __init__(self, port: str, docker_handler: DockerHandler, minecraft_server_handler: MinecraftServerHandler):
|
||||
logging.info(
|
||||
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.listen(1)
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] request handler initialized')
|
||||
|
||||
def restart(self):
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] restarting request handler for port {self.port}')
|
||||
self.sock.close()
|
||||
self.__init__(self.port, self.docker_handler,
|
||||
self.minecraft_server_handler)
|
||||
|
||||
def run(self) -> None:
|
||||
while True:
|
||||
try:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] waiting for a connection on port {self.port}')
|
||||
self.connection, self.client_address = self.sock.accept()
|
||||
try:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] connection from {self.client_address}')
|
||||
self.handle_request()
|
||||
except Exception as e:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] error in request handler for port {self.port}: {e}')
|
||||
logging.info(
|
||||
'[RequestHandler:{self.port}] restarting request handler...')
|
||||
self.restart()
|
||||
finally:
|
||||
self.connection.close()
|
||||
self.restart()
|
||||
except Exception as e:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] error in request handler for port {self.port}: {e}')
|
||||
logging.info(
|
||||
'[RequestHandler:{self.port}] restarting request handler...')
|
||||
self.restart()
|
||||
|
||||
def handle_request(self) -> None:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] handling request on port {self.port}')
|
||||
|
||||
service_name = self.docker_handler.get_port_map().get(str(self.port))
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] service name: {service_name}')
|
||||
|
||||
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)
|
||||
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'
|
||||
if request[0] == 0x10 or request[0] == 0x15 or request[0] == 0x1b:
|
||||
if b'\x02' in request:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] detected join/login request for {service_name}')
|
||||
if minecraft_server.is_starting() == True:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] container {service_name} is already starting...')
|
||||
self.forward_request_to_placeholder(
|
||||
request, minecraft_server)
|
||||
else:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] starting container {service_name}')
|
||||
self.minecraft_server_handler.start_server(
|
||||
service_name)
|
||||
elif b'\x01' in request:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] detected ping request for {service_name}')
|
||||
self.forward_request_to_placeholder(
|
||||
request, minecraft_server)
|
||||
|
||||
elif request[0] == 0xFE:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] detected legacy ping request for {service_name}')
|
||||
self.forward_request_to_placeholder(request, minecraft_server)
|
||||
else:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] detected unknown request for {service_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'))
|
||||
|
||||
if not ip:
|
||||
logging.info(
|
||||
'[RequestHandler:{self.port}] no placeholder server ip found')
|
||||
return
|
||||
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] placeholder server ip: {ip}')
|
||||
try:
|
||||
server_socket.connect((ip, 25565))
|
||||
server_socket.sendall(request)
|
||||
response = server_socket.recv(1024)
|
||||
self.connection.sendall(response)
|
||||
except Exception as e:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] error while handling request on port {self.port}: {e}')
|
||||
self.restart()
|
||||
import os
|
||||
import socket
|
||||
import logging
|
||||
import threading
|
||||
from typing import Literal
|
||||
from dockerHandler import DockerHandler
|
||||
from minecraftServerHandler import MinecraftServerHandler
|
||||
from objects.minecraftServer import MinecraftServer
|
||||
|
||||
|
||||
class RequestHandler(threading.Thread):
|
||||
def __init__(self, port: str, docker_handler: DockerHandler, minecraft_server_handler: MinecraftServerHandler):
|
||||
logging.info(
|
||||
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.settimeout(5)
|
||||
self.sock.listen(30)
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] request handler initialized')
|
||||
|
||||
def restart(self):
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] restarting request handler for port {self.port}')
|
||||
self.sock.close()
|
||||
self.__init__(self.port, self.docker_handler,
|
||||
self.minecraft_server_handler)
|
||||
|
||||
def run(self) -> None:
|
||||
while True:
|
||||
try:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] waiting for a connection on port {self.port}')
|
||||
self.connection, self.client_address = self.sock.accept()
|
||||
try:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] connection from {self.client_address}')
|
||||
self.handle_request()
|
||||
except Exception as e:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] error in request handler for port {self.port}: {e}')
|
||||
logging.info(
|
||||
'[RequestHandler:{self.port}] restarting request handler...')
|
||||
self.restart()
|
||||
finally:
|
||||
self.connection.close()
|
||||
self.restart()
|
||||
except Exception as e:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] error in request handler for port {self.port}: {e}')
|
||||
logging.info(
|
||||
'[RequestHandler:{self.port}] restarting request handler...')
|
||||
self.restart()
|
||||
|
||||
def handle_request(self) -> None:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] handling request on port {self.port}')
|
||||
|
||||
service_name = self.docker_handler.get_port_map().get(str(self.port))
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] service name: {service_name}')
|
||||
|
||||
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)
|
||||
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'
|
||||
if request[0] == 0x10 or request[0] == 0x15 or request[0] == 0x1b:
|
||||
if b'\x02' in request:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] detected join/login request for {service_name}')
|
||||
if minecraft_server.is_starting() == True:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] container {service_name} is already starting...')
|
||||
self.forward_request_to_placeholder(
|
||||
request, minecraft_server)
|
||||
else:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] starting container {service_name}')
|
||||
self.minecraft_server_handler.start_server(
|
||||
service_name)
|
||||
elif b'\x01' in request:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] detected ping request for {service_name}')
|
||||
self.forward_request_to_placeholder(
|
||||
request, minecraft_server)
|
||||
|
||||
elif request[0] == 0xFE:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] detected legacy ping request for {service_name}')
|
||||
self.forward_request_to_placeholder(request, minecraft_server)
|
||||
else:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] detected unknown request for {service_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 = "127.0.0.1"
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] placeholder server ip: {ip}')
|
||||
try:
|
||||
if minecraft_server.is_starting() == True:
|
||||
logging.info(
|
||||
'[RequestHandler:{self.port}] container is starting. Using placeholder port 20001')
|
||||
server_socket.connect((ip, 20001))
|
||||
else:
|
||||
logging.info(
|
||||
'[RequestHandler:{self.port}] container is not starting. Using placeholder port 20000')
|
||||
server_socket.connect((ip, 20000))
|
||||
|
||||
server_socket.sendall(request)
|
||||
response = server_socket.recv(1024)
|
||||
self.connection.sendall(response)
|
||||
except Exception as e:
|
||||
logging.info(
|
||||
f'[RequestHandler:{self.port}] error while handling request on port {self.port}: {e}')
|
||||
self.restart()
|
||||
|
||||
70
app/utils.py
70
app/utils.py
@@ -1,20 +1,50 @@
|
||||
import logging
|
||||
import os
|
||||
import socket
|
||||
|
||||
|
||||
def docker_container_mapping():
|
||||
port_map_str = os.environ.get('PORT_MAP')
|
||||
|
||||
port_map = {}
|
||||
for line in port_map_str.split('\n'):
|
||||
if line:
|
||||
port, name = line.split(':')
|
||||
port_map[port.strip()] = name.strip().replace(
|
||||
"'", "").replace('"', "").strip()
|
||||
|
||||
# print port map for debugging
|
||||
logging.info('PORT_MAP:')
|
||||
for port in port_map:
|
||||
logging.info(f'{port} -> {port_map[port]}')
|
||||
return port_map
|
||||
import logging
|
||||
import os
|
||||
import json
|
||||
import json
|
||||
from typing import List, Dict
|
||||
|
||||
|
||||
def docker_container_mapping() -> Dict[str, str]:
|
||||
port_map_str = os.environ.get('PORT_MAP')
|
||||
|
||||
port_map = {}
|
||||
for line in port_map_str.split('\n'):
|
||||
if line:
|
||||
port, name = line.split(':')
|
||||
port_map[port.strip()] = name.strip().replace(
|
||||
"'", "").replace('"', "").strip()
|
||||
|
||||
# print port map for debugging
|
||||
logging.info('PORT_MAP:')
|
||||
for port in port_map:
|
||||
logging.info(f'{port} -> {port_map[port]}')
|
||||
return port_map
|
||||
|
||||
|
||||
# motd = {
|
||||
# "1": "§4Maintenance!",
|
||||
# "2": "§aCheck example.com for more information!"
|
||||
# }
|
||||
# version_text = "§4Maintenance"
|
||||
# samples = ["§bexample.com", "", "§4Maintenance"]
|
||||
# kick_message = ["§bSorry", "", "§aThis server is offline!"]
|
||||
|
||||
def generate_placeholder_server_config_file(path: str, ip: str, port: int, motd: Dict[str, str], version_text: str, samples: List[str], kick_message: List[str]) -> None:
|
||||
config = {
|
||||
"ip": ip,
|
||||
"kick_message": kick_message,
|
||||
"motd": motd,
|
||||
"player_max": 0,
|
||||
"player_online": 0,
|
||||
"port": port,
|
||||
"protocol": 2,
|
||||
"samples": samples,
|
||||
"server_icon": "server_icon.png",
|
||||
"show_hostname_if_available": True,
|
||||
"show_ip_if_hostname_available": True,
|
||||
"version_text": version_text
|
||||
}
|
||||
|
||||
with open(path, 'w') as f:
|
||||
json.dump(config, f, indent=4)
|
||||
|
||||
@@ -1,99 +1,46 @@
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
auto_starter:
|
||||
container_name: mc_auto_starter
|
||||
restart: no
|
||||
image: dertyp7/minecraft_server_auto_starter:latest
|
||||
ports:
|
||||
- 25565:25565
|
||||
- 25566:25566
|
||||
environment:
|
||||
# The ip of the placeholder servers below
|
||||
PLACEHOLDER_SERVER_SLEEPING_SERVICE: "mc_placeholder_server_sleeping"
|
||||
PLACEHOLDER_SERVER_STARTING_SERVICE: "mc_placeholder_server_starting"
|
||||
|
||||
# Port mapping for the servers
|
||||
# The key is the external port of the placeholder server
|
||||
# The value is the internal ip of the actual server
|
||||
# Don't change the server port in the actual server. Use this instead
|
||||
PORT_MAP: |
|
||||
25565: "mc"
|
||||
25566: "mc2"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
# These are the placeholder servers. They are used to show the player a message
|
||||
# They are not needed, but they are nice to have
|
||||
# Keep in mind these servers are consuming some resources
|
||||
mc_placeholder_server_sleeping:
|
||||
container_name: mc_placeholder_server_sleeping
|
||||
restart: always
|
||||
image: itzg/minecraft-server:java8
|
||||
environment:
|
||||
VERSION: "1.12.2"
|
||||
EULA: "TRUE"
|
||||
MOTD: "Sleeping | Join to wake up"
|
||||
|
||||
# The placeholder servers should be as lightweight as possible
|
||||
MAX_PLAYERS: "0"
|
||||
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"
|
||||
|
||||
mc_placeholder_server_starting:
|
||||
container_name: mc_placeholder_server_starting
|
||||
restart: always
|
||||
image: itzg/minecraft-server:java8
|
||||
environment:
|
||||
VERSION: "1.12.2"
|
||||
EULA: "TRUE"
|
||||
MOTD: "Starting, please wait..."
|
||||
|
||||
# The placeholder servers should be as lightweight as possible
|
||||
MAX_PLAYERS: "0"
|
||||
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"
|
||||
|
||||
# These are the actual servers
|
||||
# For itzg/minecraft-server you can find the documentation here: https://docker-minecraft-server.readthedocs.io/en/latest/variables/
|
||||
mc:
|
||||
container_name: example_mc_server_1
|
||||
image: itzg/minecraft-server
|
||||
restart: unless-stopped #! This is important. If you restart the server always automatically, the auto_starter will not work
|
||||
environment:
|
||||
type: "PAPER"
|
||||
EULA: "TRUE"
|
||||
MOTD: "Example Server 1"
|
||||
MAX_PLAYERS: "1"
|
||||
#! Dont change SERVER_PORT. Use PORT_IP_MAP in auto_starter instead.
|
||||
# SERVER_PORT default is "25565"
|
||||
|
||||
mc2:
|
||||
container_name: example_mc_server_2
|
||||
image: itzg/minecraft-server
|
||||
restart: unless-stopped #! This is important. If you restart the server always automatically, the auto_starter will not work
|
||||
environment:
|
||||
type: "PAPER"
|
||||
EULA: "TRUE"
|
||||
MOTD: "Example Server 2"
|
||||
MAX_PLAYERS: "1"
|
||||
#! Dont change SERVER_PORT. Use PORT_IP_MAP in auto_starter instead.
|
||||
# SERVER_PORT default is "25565"
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
auto_starter:
|
||||
container_name: mc_auto_starter
|
||||
restart: no
|
||||
image: dertyp7/minecraft_server_auto_starter:latest
|
||||
ports:
|
||||
- 25565:25565
|
||||
- 25566:25566
|
||||
environment:
|
||||
# Port mapping for the servers
|
||||
# The key is the external port of the placeholder server
|
||||
# The value is the internal ip of the actual server
|
||||
# Don't change the server port in the actual server. Use this instead
|
||||
PORT_MAP: |
|
||||
25565: "mc"
|
||||
25566: "mc2"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
# These are the actual servers
|
||||
# For itzg/minecraft-server you can find the documentation here: https://docker-minecraft-server.readthedocs.io/en/latest/variables/
|
||||
mc:
|
||||
container_name: example_mc_server_1
|
||||
image: itzg/minecraft-server
|
||||
restart: unless-stopped #! This is important. If you restart the server always automatically, the auto_starter will not work
|
||||
environment:
|
||||
type: "PAPER"
|
||||
EULA: "TRUE"
|
||||
MOTD: "Example Server 1"
|
||||
MAX_PLAYERS: "1"
|
||||
#! Dont change SERVER_PORT. Use PORT_IP_MAP in auto_starter instead.
|
||||
# SERVER_PORT default is "25565"
|
||||
|
||||
mc2:
|
||||
container_name: example_mc_server_2
|
||||
image: itzg/minecraft-server
|
||||
restart: unless-stopped #! This is important. If you restart the server always automatically, the auto_starter will not work
|
||||
environment:
|
||||
type: "PAPER"
|
||||
EULA: "TRUE"
|
||||
MOTD: "Example Server 2"
|
||||
MAX_PLAYERS: "1"
|
||||
#! Dont change SERVER_PORT. Use PORT_IP_MAP in auto_starter instead.
|
||||
# SERVER_PORT default is "25565"
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
worker_processes 5;
|
||||
events {
|
||||
worker_connections 1024;
|
||||
multi_accept on;
|
||||
}
|
||||
stream {
|
||||
upstream upstream_25565 {
|
||||
server 192.168.144.5:25565;
|
||||
server 127.0.0.1:25565 backup;
|
||||
}
|
||||
server {
|
||||
listen 192.168.144.6:25565;
|
||||
proxy_connect_timeout 5s;
|
||||
proxy_timeout 5s;
|
||||
proxy_pass upstream_25565;
|
||||
}
|
||||
upstream upstream_25566 {
|
||||
server 192.168.144.3:25565;
|
||||
server 127.0.0.1:25566 backup;
|
||||
}
|
||||
server {
|
||||
listen 192.168.144.6:25566;
|
||||
proxy_connect_timeout 5s;
|
||||
proxy_timeout 5s;
|
||||
proxy_pass upstream_25566;
|
||||
}
|
||||
}
|
||||
worker_processes 5;
|
||||
events {
|
||||
worker_connections 1024;
|
||||
multi_accept on;
|
||||
}
|
||||
stream {
|
||||
upstream upstream_25565 {
|
||||
server 192.168.144.5:25565;
|
||||
server 127.0.0.1:25565 backup;
|
||||
}
|
||||
server {
|
||||
listen 192.168.144.6:25565;
|
||||
proxy_connect_timeout 5s;
|
||||
proxy_timeout 5s;
|
||||
proxy_pass upstream_25565;
|
||||
}
|
||||
upstream upstream_25566 {
|
||||
server 192.168.144.3:25565;
|
||||
server 127.0.0.1:25566 backup;
|
||||
}
|
||||
server {
|
||||
listen 192.168.144.6:25566;
|
||||
proxy_connect_timeout 5s;
|
||||
proxy_timeout 5s;
|
||||
proxy_pass upstream_25566;
|
||||
}
|
||||
}
|
||||
|
||||
34
readme.md
34
readme.md
@@ -1,17 +1,17 @@
|
||||
# Minecraft Server Auto Starter for Docker Compose
|
||||
|
||||
This container will manage the access to your Minecraft server. It will start the Minecraft server when a player tries to connect.
|
||||
This container is designed to work with the [itzg/minecraft-server](https://hub.docker.com/r/itzg/minecraft-server) container.
|
||||
It uses the AutoStop feature of the [itzg/minecraft-server](https://hub.docker.com/r/itzg/minecraft-server) container to stop the Minecraft server when no player is connected.
|
||||
|
||||
## Usage
|
||||
|
||||
See the [docker-compose.yml](https://github.com/DerTyp7/docker_minecraft_server_auto_starter/blob/main/docker-compose.yml) file for an example.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description | Default | Example |
|
||||
| -------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------- | -------------- |
|
||||
| `PLACEHOLDER_SERVER_SLEEPING_IP` | (optional) The internal docker-compose IP for the placeholder server when a server is sleeping | `""` | `"172.20.0.3"` |
|
||||
| `PLACEHOLDER_SERVER_STARTING_IP` | (optional) The internal docker-compose IP for the placeholder server when a server is starting | `""` | `"172.20.0.4"` |
|
||||
| `PORT_IP_MAP` | Map which matches the external Minecraft ports to the internal docker-compose IPs for the Minecraft-Servers | | |
|
||||
# Minecraft Server Auto Starter for Docker Compose
|
||||
|
||||
This container will manage the access to your Minecraft server. It will start the Minecraft server when a player tries to connect.
|
||||
This container is designed to work with the [itzg/minecraft-server](https://hub.docker.com/r/itzg/minecraft-server) container.
|
||||
It uses the AutoStop feature of the [itzg/minecraft-server](https://hub.docker.com/r/itzg/minecraft-server) container to stop the Minecraft server when no player is connected.
|
||||
|
||||
## Usage
|
||||
|
||||
See the [docker-compose.yml](https://github.com/DerTyp7/docker_minecraft_server_auto_starter/blob/main/docker-compose.yml) file for an example.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description | Default | Example |
|
||||
| -------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------- | -------------- |
|
||||
| `PLACEHOLDER_SERVER_SLEEPING_IP` | (optional) The internal docker-compose IP for the placeholder server when a server is sleeping | `""` | `"172.20.0.3"` |
|
||||
| `PLACEHOLDER_SERVER_STARTING_IP` | (optional) The internal docker-compose IP for the placeholder server when a server is starting | `""` | `"172.20.0.4"` |
|
||||
| `PORT_IP_MAP` | Map which matches the external Minecraft ports to the internal docker-compose IPs for the Minecraft-Servers | | |
|
||||
|
||||
Reference in New Issue
Block a user