Get more of the container creation fleshed out
This commit is contained in:
parent
3e4fcd527d
commit
c683809efc
|
@ -3,7 +3,9 @@ package server
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
|
"github.com/docker/docker/api/types/mount"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
"github.com/docker/docker/daemon/logger/jsonfilelog"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -79,6 +81,8 @@ func (d *DockerEnvironment) Create() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var oomDisabled = true
|
||||||
|
|
||||||
// If the container already exists don't hit the user with an error, just return
|
// If the container already exists don't hit the user with an error, just return
|
||||||
// the current information about it which is what we would do when creating the
|
// the current information about it which is what we would do when creating the
|
||||||
// container anyways.
|
// container anyways.
|
||||||
|
@ -87,16 +91,16 @@ func (d *DockerEnvironment) Create() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
conf := &container.Config{
|
conf := &container.Config{
|
||||||
Hostname: "container",
|
Hostname: "container",
|
||||||
User: d.Configuration.Container.User,
|
User: d.Configuration.Container.User,
|
||||||
AttachStdin: true,
|
AttachStdin: true,
|
||||||
AttachStdout: true,
|
AttachStdout: true,
|
||||||
AttachStderr: true,
|
AttachStderr: true,
|
||||||
OpenStdin: true,
|
OpenStdin: true,
|
||||||
Tty: true,
|
Tty: true,
|
||||||
|
|
||||||
Image: d.Server.Container.Image,
|
Image: d.Server.Container.Image,
|
||||||
Env: d.environmentVariables(),
|
Env: d.environmentVariables(),
|
||||||
|
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"Service": "Pterodactyl",
|
"Service": "Pterodactyl",
|
||||||
|
@ -104,9 +108,69 @@ func (d *DockerEnvironment) Create() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
hostConf := &container.HostConfig{
|
hostConf := &container.HostConfig{
|
||||||
Resources: container.Resources{
|
// Configure the mounts for this container. First mount the server data directory
|
||||||
Memory: d.Server.Build.MemoryLimit * 1000000,
|
// into the container as a r/w bind. Additionally mount the host timezone data into
|
||||||
|
// the container as a readonly bind so that software running in the container uses
|
||||||
|
// the same time as the host system.
|
||||||
|
Mounts: []mount.Mount{
|
||||||
|
{
|
||||||
|
Target: "/home/container",
|
||||||
|
Source: d.Server.Filesystem().Path(),
|
||||||
|
Type: mount.TypeBind,
|
||||||
|
ReadOnly: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Target: d.Configuration.TimezonePath,
|
||||||
|
Source: d.Configuration.TimezonePath,
|
||||||
|
Type: mount.TypeBind,
|
||||||
|
ReadOnly: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Configure the /tmp folder mapping in containers. This is necessary for some
|
||||||
|
// games that need to make use of it for downloads and other installation processes.
|
||||||
|
Tmpfs: map[string]string{
|
||||||
|
"/tmp": "rw,exec,nosuid,size=50M",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Define resource limits for the container based on the data passed through
|
||||||
|
// from the Panel.
|
||||||
|
Resources: container.Resources{
|
||||||
|
// @todo memory limit should be slightly higher than the reservation
|
||||||
|
Memory: d.Server.Build.MemoryLimit * 1000000,
|
||||||
|
MemoryReservation: d.Server.Build.MemoryLimit * 1000000,
|
||||||
|
MemorySwap: d.Server.Build.ConvertedSwap(),
|
||||||
|
|
||||||
|
CPUQuota: d.Server.Build.ConvertedCpuLimit(),
|
||||||
|
CPUPeriod: 100000,
|
||||||
|
CPUShares: 1024,
|
||||||
|
|
||||||
|
BlkioWeight: d.Server.Build.IoWeight,
|
||||||
|
OomKillDisable: &oomDisabled,
|
||||||
|
},
|
||||||
|
|
||||||
|
// @todo make this configurable again
|
||||||
|
DNS: []string{"1.1.1.1", "8.8.8.8"},
|
||||||
|
|
||||||
|
// Configure logging for the container to make it easier on the Daemon to grab
|
||||||
|
// the server output. Ensure that we don't use too much space on the host machine
|
||||||
|
// since we only need it for the last few hundred lines of output and don't care
|
||||||
|
// about anything else in it.
|
||||||
|
LogConfig: container.LogConfig{
|
||||||
|
Type: jsonfilelog.Name,
|
||||||
|
Config: map[string]string{
|
||||||
|
"max-size": "5m",
|
||||||
|
"max-file": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
SecurityOpt: []string{"no-new-privileges"},
|
||||||
|
ReadonlyRootfs: true,
|
||||||
|
CapDrop: []string{
|
||||||
|
"setpcap", "mknod", "audit_write", "net_raw", "dac_override",
|
||||||
|
"fowner", "fsetid", "net_bind_service", "sys_chroot", "setfcap",
|
||||||
|
},
|
||||||
|
NetworkMode: "pterodactyl_nw",
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := cli.ContainerCreate(ctx, conf, hostConf, nil, d.Server.Uuid); err != nil {
|
if _, err := cli.ContainerCreate(ctx, conf, hostConf, nil, d.Server.Uuid); err != nil {
|
||||||
|
@ -135,4 +199,4 @@ func (d *DockerEnvironment) environmentVariables() []string {
|
||||||
|
|
||||||
func (d *DockerEnvironment) volumes() map[string]struct{} {
|
func (d *DockerEnvironment) volumes() map[string]struct{} {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
22
server/filesystem.go
Normal file
22
server/filesystem.go
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import "path"
|
||||||
|
|
||||||
|
type Filesystem struct {
|
||||||
|
// The root directory where all of the server data is contained. By default
|
||||||
|
// this is going to be /srv/daemon-data but can vary depending on the system.
|
||||||
|
Root string
|
||||||
|
|
||||||
|
// The server object associated with this Filesystem.
|
||||||
|
Server *Server
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the root path that contains all of a server's data.
|
||||||
|
func (fs *Filesystem) Path() string {
|
||||||
|
return path.Join(fs.Root, fs.Server.Uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a safe path for a server object.
|
||||||
|
func (fs *Filesystem) SafePath(p string) string {
|
||||||
|
return fs.Path()
|
||||||
|
}
|
|
@ -40,6 +40,8 @@ type Server struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
environment Environment
|
environment Environment
|
||||||
|
|
||||||
|
fs *Filesystem
|
||||||
}
|
}
|
||||||
|
|
||||||
// The build settings for a given server that impact docker container creation and
|
// The build settings for a given server that impact docker container creation and
|
||||||
|
@ -54,7 +56,7 @@ type BuildSettings struct {
|
||||||
|
|
||||||
// The relative weight for IO operations in a container. This is relative to other
|
// The relative weight for IO operations in a container. This is relative to other
|
||||||
// containers on the system and should be a value between 10 and 1000.
|
// containers on the system and should be a value between 10 and 1000.
|
||||||
IoWeight int64 `yaml:"io"`
|
IoWeight uint16 `yaml:"io"`
|
||||||
|
|
||||||
// The percentage of CPU that this instance is allowed to consume relative to
|
// The percentage of CPU that this instance is allowed to consume relative to
|
||||||
// the host. A value of 200% represents complete utilization of two cores. This
|
// the host. A value of 200% represents complete utilization of two cores. This
|
||||||
|
@ -65,6 +67,28 @@ type BuildSettings struct {
|
||||||
DiskSpace int64 `yaml:"disk"`
|
DiskSpace int64 `yaml:"disk"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Converts the CPU limit for a server build into a number that can be better understood
|
||||||
|
// by the Docker environment. If there is no limit set, return -1 which will indicate to
|
||||||
|
// Docker that it has unlimited CPU quota.
|
||||||
|
func (b *BuildSettings) ConvertedCpuLimit() int64 {
|
||||||
|
if b.CpuLimit == 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.CpuLimit * 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the amount of swap available as a total in bytes. This is returned as the amount
|
||||||
|
// of memory available to the server initially, PLUS the amount of additional swap to include
|
||||||
|
// which is the format used by Docker.
|
||||||
|
func (b *BuildSettings) ConvertedSwap() int64 {
|
||||||
|
if b.Swap < 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return (b.Swap * 1000000) + (b.MemoryLimit * 1000000)
|
||||||
|
}
|
||||||
|
|
||||||
// Defines the allocations available for a given server. When using the Docker environment
|
// Defines the allocations available for a given server. When using the Docker environment
|
||||||
// driver these correspond to mappings for the container that allow external connections.
|
// driver these correspond to mappings for the container that allow external connections.
|
||||||
type Allocations struct {
|
type Allocations struct {
|
||||||
|
@ -156,9 +180,19 @@ func FromConfiguration(data []byte, cfg DockerConfiguration) (*Server, error) {
|
||||||
|
|
||||||
s.environment = env
|
s.environment = env
|
||||||
|
|
||||||
|
s.fs = &Filesystem{
|
||||||
|
// @todo adjust this to be configuration provided!
|
||||||
|
Root: "/srv/daemon-data",
|
||||||
|
Server: s,
|
||||||
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) Filesystem() *Filesystem {
|
||||||
|
return s.fs
|
||||||
|
}
|
||||||
|
|
||||||
// Determine if the server is bootable in it's current state or not. This will not
|
// Determine if the server is bootable in it's current state or not. This will not
|
||||||
// indicate why a server is not bootable, only if it is.
|
// indicate why a server is not bootable, only if it is.
|
||||||
func (s *Server) IsBootable() bool {
|
func (s *Server) IsBootable() bool {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user