Add detach to runc

By adding detach to runc the container process is the only thing running
on the system is the containers process.
This allows better usage of memeory and no runc process being long
lived.  With this addition you also need a delete command because the
detached container will not be able to remove state and the left over
cgroups directories.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2016-01-11 16:57:18 -08:00
parent 480e5f4416
commit bb6a747825
4 changed files with 91 additions and 15 deletions

15
delete.go Normal file
View File

@ -0,0 +1,15 @@
package main
import "github.com/codegangsta/cli"
var deleteCommand = cli.Command{
Name: "delete",
Usage: "delete any resources held by the container often used with detached containers",
Action: func(context *cli.Context) {
container, err := getContainer(context)
if err != nil {
fatal(err)
}
destroy(container)
},
}

View File

@ -219,5 +219,8 @@ func (n *createdState) transition(s containerState) error {
}
func (n *createdState) destroy() error {
return nil
if err := n.c.refreshState(); err != nil {
return err
}
return n.c.state.destroy()
}

14
main.go
View File

@ -70,16 +70,18 @@ func main() {
},
}
app.Commands = []cli.Command{
startCommand,
checkpointCommand,
deleteCommand,
eventsCommand,
restoreCommand,
killCommand,
specCommand,
pauseCommand,
resumeCommand,
execCommand,
execCommand,
killCommand,
listCommand,
pauseCommand,
restoreCommand,
resumeCommand,
specCommand,
startCommand,
}
app.Before = func(context *cli.Context) error {
if context.GlobalBool("debug") {

View File

@ -7,6 +7,7 @@ import (
"os"
"runtime"
"strconv"
"syscall"
"github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
@ -31,6 +32,15 @@ var startCommand = cli.Command{
Value: "",
Usage: "specify the pty slave path for use with the container",
},
cli.BoolFlag{
Name: "detach,d",
Usage: "detach from the container's process",
},
cli.StringFlag{
Name: "pid-file",
Value: "",
Usage: "specify the file to write the process id to",
},
},
Action: func(context *cli.Context) {
bundle := context.String("bundle")
@ -107,10 +117,11 @@ func startContainer(context *cli.Context, spec *specs.LinuxSpec, rspec *specs.Li
}
// ensure that the container is always removed if we were the process
// that created it.
defer destroy(container)
detach := context.Bool("detach")
if !detach {
defer destroy(container)
}
process := newProcess(spec.Process)
// Support on-demand socket activation by passing file descriptors into the container init process.
if os.Getenv("LISTEN_FDS") != "" {
listenFdsInt, err := strconv.Atoi(os.Getenv("LISTEN_FDS"))
@ -121,18 +132,63 @@ func startContainer(context *cli.Context, spec *specs.LinuxSpec, rspec *specs.Li
process.ExtraFiles = append(process.ExtraFiles, os.NewFile(uintptr(i), ""))
}
}
tty, err := newTty(spec.Process.Terminal, process, rootuid, context.String("console"))
if err != nil {
return -1, err
var tty *tty
if spec.Process.Terminal {
if tty, err = createTty(process, rootuid, context.String("console")); err != nil {
return -1, err
}
} else if detach {
if err := dupStdio(process, rootuid); err != nil {
return -1, err
}
} else {
if tty, err = createStdioPipes(process, rootuid); err != nil {
return -1, err
}
}
handler := newSignalHandler(tty)
defer handler.Close()
if err := container.Start(process); err != nil {
return -1, err
}
if pidFile := context.String("pid-file"); pidFile != "" {
pid, err := process.Pid()
if err != nil {
return -1, err
}
f, err := os.Create(pidFile)
if err != nil {
logrus.WithField("pid", pid).Error("create pid file")
} else {
_, err = fmt.Fprintf(f, "%d", pid)
f.Close()
if err != nil {
logrus.WithField("error", err).Error("write pid file")
}
}
}
if detach {
return 0, nil
}
handler := newSignalHandler(tty)
defer handler.Close()
return handler.forward(process)
}
func dupStdio(process *libcontainer.Process, rootuid int) error {
process.Stdin = os.Stdin
process.Stdout = os.Stdout
process.Stderr = os.Stderr
for _, fd := range []uintptr{
os.Stdin.Fd(),
os.Stdout.Fd(),
os.Stderr.Fd(),
} {
if err := syscall.Fchown(int(fd), rootuid, rootuid); err != nil {
return err
}
}
return nil
}
// If systemd is supporting sd_notify protocol, this function will add support
// for sd_notify protocol from within the container.
func setupSdNotify(spec *specs.LinuxSpec, rspec *specs.LinuxRuntimeSpec, notifySocket string) {