Merge pull request #37 from pterodactyl/server-environment-tweaks

Tweaks to Server Environment
This commit is contained in:
Dane Everitt 2020-07-05 10:40:32 -07:00 committed by GitHub
commit fe531e400d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 46 deletions

View File

@ -39,6 +39,9 @@ type DockerConfiguration struct {
// for containers run through the daemon. // for containers run through the daemon.
Network DockerNetworkConfiguration `json:"network" yaml:"network"` Network DockerNetworkConfiguration `json:"network" yaml:"network"`
// Domainname is the Docker domainname for all containers.
Domainname string `default:"" json:"domainname" yaml:"domainname"`
// If true, container images will be updated when a server starts if there // If true, container images will be updated when a server starts if there
// is an update available. If false the daemon will not attempt updates and will // is an update available. If false the daemon will not attempt updates and will
// defer to the host system to manage image updates. // defer to the host system to manage image updates.

View File

@ -94,9 +94,7 @@ func (d *DockerEnvironment) Exists() (bool, error) {
// //
// @see docker/client/errors.go // @see docker/client/errors.go
func (d *DockerEnvironment) IsRunning() (bool, error) { func (d *DockerEnvironment) IsRunning() (bool, error) {
ctx := context.Background() c, err := d.Client.ContainerInspect(context.Background(), d.Server.Uuid)
c, err := d.Client.ContainerInspect(ctx, d.Server.Uuid)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -122,12 +120,14 @@ func (d *DockerEnvironment) InSituUpdate() error {
return errors.WithStack(err) return errors.WithStack(err)
} }
ctx, _ := context.WithTimeout(context.Background(), time.Second * 10)
u := container.UpdateConfig{ u := container.UpdateConfig{
Resources: d.getResourcesForServer(), Resources: d.getResourcesForServer(),
} }
d.Server.Log().WithField("limits", fmt.Sprintf("%+v", u.Resources)).Debug("updating server container on-the-fly with passed limits") d.Server.Log().WithField("limits", fmt.Sprintf("%+v", u.Resources)).Debug("updating server container on-the-fly with passed limits")
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
if _, err := d.Client.ContainerUpdate(ctx, d.Server.Uuid, u); err != nil { if _, err := d.Client.ContainerUpdate(ctx, d.Server.Uuid, u); err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
@ -254,7 +254,8 @@ func (d *DockerEnvironment) Start() error {
return errors.WithStack(err) return errors.WithStack(err)
} }
ctx, _ := context.WithTimeout(context.Background(), time.Second * 10) ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
if err := d.Client.ContainerStart(ctx, d.Server.Uuid, types.ContainerStartOptions{}); err != nil { if err := d.Client.ContainerStart(ctx, d.Server.Uuid, types.ContainerStartOptions{}); err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
@ -323,9 +324,7 @@ func (d *DockerEnvironment) WaitForStop(seconds int, terminate bool) error {
// Forcefully terminates the container using the signal passed through. // Forcefully terminates the container using the signal passed through.
func (d *DockerEnvironment) Terminate(signal os.Signal) error { func (d *DockerEnvironment) Terminate(signal os.Signal) error {
ctx := context.Background() c, err := d.Client.ContainerInspect(context.Background(), d.Server.Uuid)
c, err := d.Client.ContainerInspect(ctx, d.Server.Uuid)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
@ -337,19 +336,17 @@ func (d *DockerEnvironment) Terminate(signal os.Signal) error {
d.Server.SetState(ProcessStoppingState) d.Server.SetState(ProcessStoppingState)
return d.Client.ContainerKill( return d.Client.ContainerKill(
ctx, d.Server.Uuid, strings.TrimSuffix(strings.TrimPrefix(signal.String(), "signal "), "ed"), context.Background(), d.Server.Uuid, strings.TrimSuffix(strings.TrimPrefix(signal.String(), "signal "), "ed"),
) )
} }
// Remove the Docker container from the machine. If the container is currently running // Remove the Docker container from the machine. If the container is currently running
// it will be forcibly stopped by Docker. // it will be forcibly stopped by Docker.
func (d *DockerEnvironment) Destroy() error { func (d *DockerEnvironment) Destroy() error {
ctx := context.Background()
// Avoid crash detection firing off. // Avoid crash detection firing off.
d.Server.SetState(ProcessStoppingState) d.Server.SetState(ProcessStoppingState)
err := d.Client.ContainerRemove(ctx, d.Server.Uuid, types.ContainerRemoveOptions{ err := d.Client.ContainerRemove(context.Background(), d.Server.Uuid, types.ContainerRemoveOptions{
RemoveVolumes: true, RemoveVolumes: true,
RemoveLinks: false, RemoveLinks: false,
Force: true, Force: true,
@ -403,10 +400,8 @@ func (d *DockerEnvironment) Attach() error {
return errors.WithStack(err) return errors.WithStack(err)
} }
ctx := context.Background()
var err error var err error
d.stream, err = d.Client.ContainerAttach(ctx, d.Server.Uuid, types.ContainerAttachOptions{ d.stream, err = d.Client.ContainerAttach(context.Background(), d.Server.Uuid, types.ContainerAttachOptions{
Stdin: true, Stdin: true,
Stdout: true, Stdout: true,
Stderr: true, Stderr: true,
@ -453,7 +448,6 @@ func (d *DockerEnvironment) FollowConsoleOutput() error {
return errors.New(fmt.Sprintf("no such container: %s", d.Server.Uuid)) return errors.New(fmt.Sprintf("no such container: %s", d.Server.Uuid))
} }
ctx := context.Background()
opts := types.ContainerLogsOptions{ opts := types.ContainerLogsOptions{
ShowStderr: true, ShowStderr: true,
ShowStdout: true, ShowStdout: true,
@ -461,7 +455,7 @@ func (d *DockerEnvironment) FollowConsoleOutput() error {
Since: time.Now().Format(time.RFC3339), Since: time.Now().Format(time.RFC3339),
} }
reader, err := d.Client.ContainerLogs(ctx, d.Server.Uuid, opts) reader, err := d.Client.ContainerLogs(context.Background(), d.Server.Uuid, opts)
go func(r io.ReadCloser) { go func(r io.ReadCloser) {
defer r.Close() defer r.Close()
@ -487,9 +481,7 @@ func (d *DockerEnvironment) EnableResourcePolling() error {
return errors.New("cannot enable resource polling on a server that is not running") return errors.New("cannot enable resource polling on a server that is not running")
} }
ctx := context.Background() stats, err := d.Client.ContainerStats(context.Background(), d.Server.Uuid, true)
stats, err := d.Client.ContainerStats(ctx, d.Server.Uuid, true)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
@ -563,15 +555,16 @@ func (d *DockerEnvironment) DisableResourcePolling() error {
// correctly if anything. // correctly if anything.
// //
// @todo handle authorization & local images // @todo handle authorization & local images
func (d *DockerEnvironment) ensureImageExists(c *client.Client) error { func (d *DockerEnvironment) ensureImageExists() error {
// Give it up to 15 minutes to pull the image. I think this should cover 99.8% of cases where an // Give it up to 15 minutes to pull the image. I think this should cover 99.8% of cases where an
// image pull might fail. I can't imagine it will ever take more than 15 minutes to fully pull // image pull might fail. I can't imagine it will ever take more than 15 minutes to fully pull
// an image. Let me know when I am inevitably wrong here... // an image. Let me know when I am inevitably wrong here...
ctx, _ := context.WithTimeout(context.Background(), time.Minute*15) ctx, cancel := context.WithTimeout(context.Background(), time.Minute*15)
defer cancel()
out, err := c.ImagePull(ctx, d.Server.Container.Image, types.ImagePullOptions{All: false}) out, err := d.Client.ImagePull(ctx, d.Server.Container.Image, types.ImagePullOptions{All: false})
if err != nil { if err != nil {
images, ierr := c.ImageList(ctx, types.ImageListOptions{}) images, ierr := d.Client.ImageList(ctx, types.ImageListOptions{})
if ierr != nil { if ierr != nil {
// Well damn, something has gone really wrong here, just go ahead and abort there // Well damn, something has gone really wrong here, just go ahead and abort there
// isn't much anything we can do to try and self-recover from this. // isn't much anything we can do to try and self-recover from this.
@ -580,7 +573,10 @@ func (d *DockerEnvironment) ensureImageExists(c *client.Client) error {
for _, img := range images { for _, img := range images {
for _, t := range img.RepoTags { for _, t := range img.RepoTags {
if t == d.Server.Container.Image { if t != d.Server.Container.Image {
continue
}
d.Server.Log().WithFields(log.Fields{ d.Server.Log().WithFields(log.Fields{
"image": d.Server.Container.Image, "image": d.Server.Container.Image,
"error": errors.New(err.Error()), "error": errors.New(err.Error()),
@ -591,7 +587,6 @@ func (d *DockerEnvironment) ensureImageExists(c *client.Client) error {
return nil return nil
} }
} }
}
return err return err
} }
@ -616,12 +611,6 @@ func (d *DockerEnvironment) ensureImageExists(c *client.Client) error {
// Creates a new container for the server using all of the data that is currently // Creates a new container for the server using all of the data that is currently
// available for it. If the container already exists it will be returned. // available for it. If the container already exists it will be returned.
func (d *DockerEnvironment) Create() error { func (d *DockerEnvironment) Create() error {
ctx := context.Background()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
return errors.WithStack(err)
}
// Ensure the data directory exists before getting too far through this process. // Ensure the data directory exists before getting too far through this process.
if err := d.Server.Filesystem.EnsureDataDirectory(); err != nil { if err := d.Server.Filesystem.EnsureDataDirectory(); err != nil {
return errors.WithStack(err) return errors.WithStack(err)
@ -630,19 +619,20 @@ func (d *DockerEnvironment) Create() error {
// 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.
if _, err := cli.ContainerInspect(ctx, d.Server.Uuid); err == nil { if _, err := d.Client.ContainerInspect(context.Background(), d.Server.Uuid); err == nil {
return nil return nil
} else if !client.IsErrNotFound(err) { } else if !client.IsErrNotFound(err) {
return errors.WithStack(err) return errors.WithStack(err)
} }
// Try to pull the requested image before creating the container. // Try to pull the requested image before creating the container.
if err := d.ensureImageExists(cli); err != nil { if err := d.ensureImageExists(); err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
conf := &container.Config{ conf := &container.Config{
Hostname: "container", Hostname: d.Server.Uuid,
Domainname: config.Get().Docker.Domainname,
User: strconv.Itoa(config.Get().System.User.Uid), User: strconv.Itoa(config.Get().System.User.Uid),
AttachStdin: true, AttachStdin: true,
AttachStdout: true, AttachStdout: true,
@ -708,7 +698,7 @@ func (d *DockerEnvironment) Create() error {
NetworkMode: container.NetworkMode(config.Get().Docker.Network.Mode), NetworkMode: container.NetworkMode(config.Get().Docker.Network.Mode),
} }
if _, err := cli.ContainerCreate(ctx, conf, hostConf, nil, d.Server.Uuid); err != nil { if _, err := d.Client.ContainerCreate(context.Background(), conf, hostConf, nil, d.Server.Uuid); err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
@ -730,9 +720,7 @@ func (d *DockerEnvironment) SendCommand(c string) error {
// Reads the log file for the server. This does not care if the server is running or not, it will // Reads the log file for the server. This does not care if the server is running or not, it will
// simply try to read the last X bytes of the file and return them. // simply try to read the last X bytes of the file and return them.
func (d *DockerEnvironment) Readlog(len int64) ([]string, error) { func (d *DockerEnvironment) Readlog(len int64) ([]string, error) {
ctx := context.Background() j, err := d.Client.ContainerInspect(context.Background(), d.Server.Uuid)
j, err := d.Client.ContainerInspect(ctx, d.Server.Uuid)
if err != nil { if err != nil {
return nil, err return nil, err
} }