Get more of the container creation fleshed out
This commit is contained in:
		
							parent
							
								
									3e4fcd527d
								
							
						
					
					
						commit
						c683809efc
					
				| 
						 | 
				
			
			@ -3,7 +3,9 @@ package server
 | 
			
		|||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/docker/docker/api/types/container"
 | 
			
		||||
	"github.com/docker/docker/api/types/mount"
 | 
			
		||||
	"github.com/docker/docker/client"
 | 
			
		||||
	"github.com/docker/docker/daemon/logger/jsonfilelog"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
| 
						 | 
				
			
			@ -79,6 +81,8 @@ func (d *DockerEnvironment) Create() error {
 | 
			
		|||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var oomDisabled = true
 | 
			
		||||
 | 
			
		||||
	// 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
 | 
			
		||||
	// container anyways.
 | 
			
		||||
| 
						 | 
				
			
			@ -87,16 +91,16 @@ func (d *DockerEnvironment) Create() error {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	conf := &container.Config{
 | 
			
		||||
		Hostname: "container",
 | 
			
		||||
		User: d.Configuration.Container.User,
 | 
			
		||||
		AttachStdin: true,
 | 
			
		||||
		Hostname:     "container",
 | 
			
		||||
		User:         d.Configuration.Container.User,
 | 
			
		||||
		AttachStdin:  true,
 | 
			
		||||
		AttachStdout: true,
 | 
			
		||||
		AttachStderr: true,
 | 
			
		||||
		OpenStdin: true,
 | 
			
		||||
		Tty: true,
 | 
			
		||||
		OpenStdin:    true,
 | 
			
		||||
		Tty:          true,
 | 
			
		||||
 | 
			
		||||
		Image: d.Server.Container.Image,
 | 
			
		||||
		Env: d.environmentVariables(),
 | 
			
		||||
		Env:   d.environmentVariables(),
 | 
			
		||||
 | 
			
		||||
		Labels: map[string]string{
 | 
			
		||||
			"Service": "Pterodactyl",
 | 
			
		||||
| 
						 | 
				
			
			@ -104,9 +108,69 @@ func (d *DockerEnvironment) Create() error {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	hostConf := &container.HostConfig{
 | 
			
		||||
		Resources: container.Resources{
 | 
			
		||||
			Memory: d.Server.Build.MemoryLimit * 1000000,
 | 
			
		||||
		// Configure the mounts for this container. First mount the server data directory
 | 
			
		||||
		// 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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -135,4 +199,4 @@ func (d *DockerEnvironment) environmentVariables() []string {
 | 
			
		|||
 | 
			
		||||
func (d *DockerEnvironment) volumes() map[string]struct{} {
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
	fs *Filesystem
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
	// 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 host. A value of 200% represents complete utilization of two cores. This
 | 
			
		||||
| 
						 | 
				
			
			@ -65,6 +67,28 @@ type BuildSettings struct {
 | 
			
		|||
	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
 | 
			
		||||
// driver these correspond to mappings for the container that allow external connections.
 | 
			
		||||
type Allocations struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -156,9 +180,19 @@ func FromConfiguration(data []byte, cfg DockerConfiguration) (*Server, error) {
 | 
			
		|||
 | 
			
		||||
	s.environment = env
 | 
			
		||||
 | 
			
		||||
	s.fs = &Filesystem{
 | 
			
		||||
		// @todo adjust this to be configuration provided!
 | 
			
		||||
		Root: "/srv/daemon-data",
 | 
			
		||||
		Server: s,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
// indicate why a server is not bootable, only if it is.
 | 
			
		||||
func (s *Server) IsBootable() bool {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user