253 lines
7.4 KiB
C#
253 lines
7.4 KiB
C#
using Docker.DotNet.Models;
|
|
using MoonlightServers.Daemon.Models;
|
|
|
|
namespace MoonlightServers.Daemon.ServerSystem.Implementations.Docker;
|
|
|
|
public class ContainerConfigMapper
|
|
{
|
|
public CreateContainerParameters GetRuntimeConfig(
|
|
string uuid,
|
|
string name,
|
|
RuntimeConfiguration configuration,
|
|
string runtimeStoragePath
|
|
)
|
|
{
|
|
var parameters = new CreateContainerParameters()
|
|
{
|
|
HostConfig = new()
|
|
};
|
|
|
|
ApplySharedOptions(parameters, configuration);
|
|
|
|
// Limits
|
|
|
|
if (configuration.Limits.CpuPercent.HasValue)
|
|
{
|
|
parameters.HostConfig.CPUQuota = configuration.Limits.CpuPercent.Value * 1000;
|
|
parameters.HostConfig.CPUPeriod = 100000;
|
|
parameters.HostConfig.CPUShares = 1024;
|
|
}
|
|
|
|
if (configuration.Limits.MemoryMb.HasValue)
|
|
{
|
|
var memoryLimit = configuration.Limits.MemoryMb.Value;
|
|
|
|
// The overhead multiplier gives the container a little bit more memory to prevent crashes
|
|
var memoryOverhead = memoryLimit + memoryLimit * 0.05f;
|
|
|
|
parameters.HostConfig.Memory = (long)memoryOverhead * 1024L * 1024L;
|
|
parameters.HostConfig.MemoryReservation = (long)memoryLimit * 1024L * 1024L;
|
|
|
|
if (configuration.Limits.SwapMb.HasValue)
|
|
{
|
|
var rawSwap = configuration.Limits.SwapMb.Value * 1024L * 1024L;
|
|
parameters.HostConfig.MemorySwap = rawSwap + (long)memoryOverhead;
|
|
}
|
|
}
|
|
|
|
parameters.HostConfig.BlkioWeight = 100;
|
|
parameters.HostConfig.OomKillDisable = true;
|
|
|
|
// Storage
|
|
|
|
parameters.HostConfig.Tmpfs = new Dictionary<string, string>()
|
|
{
|
|
{ "/tmp", "rw,exec,nosuid,size=100M" } // TODO: Config
|
|
};
|
|
|
|
parameters.WorkingDir = "/home/container";
|
|
|
|
parameters.HostConfig.Mounts = new List<Mount>();
|
|
parameters.HostConfig.Mounts.Add(new Mount()
|
|
{
|
|
Source = runtimeStoragePath,
|
|
Target = "/home/container",
|
|
Type = "bind",
|
|
ReadOnly = false
|
|
});
|
|
|
|
// Labels
|
|
parameters.Labels = new Dictionary<string, string>()
|
|
{
|
|
{ "dev.moonlightpanel", "true" },
|
|
{ "dev.moonlightpanel.id", uuid }
|
|
};
|
|
|
|
foreach (var label in configuration.Environment.Labels)
|
|
parameters.Labels.Add(label.Key, label.Value);
|
|
|
|
// Security
|
|
|
|
parameters.HostConfig.CapDrop = new List<string>()
|
|
{
|
|
"setpcap", "mknod", "audit_write", "net_raw", "dac_override",
|
|
"fowner", "fsetid", "net_bind_service", "sys_chroot", "setfcap"
|
|
};
|
|
|
|
parameters.HostConfig.ReadonlyRootfs = true;
|
|
parameters.HostConfig.SecurityOpt = new List<string>()
|
|
{
|
|
"no-new-privileges"
|
|
};
|
|
|
|
// Name
|
|
|
|
parameters.Name = name;
|
|
|
|
// Docker Image
|
|
parameters.Image = configuration.Template.DockerImage;
|
|
|
|
// Networking
|
|
|
|
if (configuration.Network.Ports.Length > 0 && !string.IsNullOrWhiteSpace(configuration.Network.FriendlyName))
|
|
parameters.Hostname = configuration.Network.FriendlyName;
|
|
|
|
parameters.ExposedPorts = new Dictionary<string, EmptyStruct>();
|
|
parameters.HostConfig.PortBindings = new Dictionary<string, IList<PortBinding>>();
|
|
|
|
foreach (var port in configuration.Network.Ports)
|
|
{
|
|
parameters.ExposedPorts.Add($"{port.Port}/tcp", new());
|
|
parameters.ExposedPorts.Add($"{port.Port}/udp", new());
|
|
|
|
parameters.HostConfig.PortBindings.Add($"{port.Port}/tcp", new List<PortBinding>
|
|
{
|
|
new()
|
|
{
|
|
HostPort = port.Port.ToString(),
|
|
HostIP = port.IpAddress
|
|
}
|
|
});
|
|
|
|
parameters.HostConfig.PortBindings.Add($"{port.Port}/udp", new List<PortBinding>
|
|
{
|
|
new()
|
|
{
|
|
HostPort = port.Port.ToString(),
|
|
HostIP = port.IpAddress
|
|
}
|
|
});
|
|
}
|
|
|
|
// TODO: Force outgoing ip stuff
|
|
|
|
// User
|
|
parameters.User = "1000:1000";
|
|
|
|
return parameters;
|
|
}
|
|
|
|
public CreateContainerParameters GetInstallConfig(
|
|
string uuid,
|
|
string name,
|
|
RuntimeConfiguration runtimeConfiguration,
|
|
InstallConfiguration installConfiguration,
|
|
string runtimeStoragePath,
|
|
string installStoragePath
|
|
)
|
|
{
|
|
var parameters = new CreateContainerParameters()
|
|
{
|
|
HostConfig = new()
|
|
};
|
|
|
|
ApplySharedOptions(parameters, runtimeConfiguration);
|
|
|
|
// Labels
|
|
parameters.Labels = new Dictionary<string, string>()
|
|
{
|
|
{ "dev.moonlightpanel", "true" },
|
|
{ "dev.moonlightpanel.id", uuid }
|
|
};
|
|
|
|
foreach (var label in runtimeConfiguration.Environment.Labels)
|
|
parameters.Labels.Add(label.Key, label.Value);
|
|
|
|
// Name
|
|
|
|
parameters.Name = name;
|
|
|
|
// Docker Image
|
|
parameters.Image = installConfiguration.DockerImage;
|
|
|
|
// User
|
|
parameters.User = "1000:1000";
|
|
|
|
// Storage
|
|
parameters.WorkingDir = "/mnt/server";
|
|
|
|
parameters.HostConfig.Mounts = new List<Mount>();
|
|
|
|
parameters.HostConfig.Mounts.Add(new Mount()
|
|
{
|
|
Source = runtimeStoragePath,
|
|
Target = "/mnt/server",
|
|
ReadOnly = false,
|
|
Type = "bind"
|
|
});
|
|
|
|
parameters.HostConfig.Mounts.Add(new Mount()
|
|
{
|
|
Source = installStoragePath,
|
|
Target = "/mnt/install",
|
|
ReadOnly = false,
|
|
Type = "bind"
|
|
});
|
|
|
|
// Command
|
|
parameters.Cmd = [installConfiguration.Shell, "/mnt/install/install.sh"];
|
|
|
|
return parameters;
|
|
}
|
|
|
|
private void ApplySharedOptions(
|
|
CreateContainerParameters parameters,
|
|
RuntimeConfiguration configuration
|
|
)
|
|
{
|
|
// Input, output & error streams and TTY
|
|
|
|
parameters.Tty = true;
|
|
parameters.AttachStderr = true;
|
|
parameters.AttachStdin = true;
|
|
parameters.AttachStdout = true;
|
|
parameters.OpenStdin = true;
|
|
|
|
// Logging
|
|
|
|
parameters.HostConfig.LogConfig = new()
|
|
{
|
|
Type = "json-file", // We need to use this provider, as the GetLogs endpoint needs it
|
|
Config = new Dictionary<string, string>()
|
|
};
|
|
|
|
// Environment variables
|
|
|
|
parameters.Env = new List<string>()
|
|
{
|
|
$"STARTUP={configuration.Template.StartupCommand}",
|
|
//TODO: Add timezone, add server ip
|
|
};
|
|
|
|
if (configuration.Limits.MemoryMb.HasValue)
|
|
parameters.Env.Add($"SERVER_MEMORY={configuration.Limits.MemoryMb.Value}");
|
|
|
|
if (configuration.Network.MainPort != null)
|
|
{
|
|
parameters.Env.Add($"SERVER_IP={configuration.Network.MainPort.IpAddress}");
|
|
parameters.Env.Add($"SERVER_PORT={configuration.Network.MainPort.Port}");
|
|
}
|
|
|
|
// Handle port variables
|
|
var i = 1;
|
|
foreach (var port in configuration.Network.Ports)
|
|
{
|
|
parameters.Env.Add($"ML_PORT_{i}={port.Port}");
|
|
i++;
|
|
}
|
|
|
|
// Copy variables as env vars
|
|
foreach (var variable in configuration.Environment.Variables)
|
|
parameters.Env.Add($"{variable.Key}={variable.Value}");
|
|
}
|
|
} |