diff --git a/components/engine/container.go b/components/engine/container.go index dc26b017b0..c1c98c5a07 100644 --- a/components/engine/container.go +++ b/components/engine/container.go @@ -16,6 +16,12 @@ import ( "time" ) +var sysInitPath string + +func init() { + sysInitPath = SelfPath() +} + type Container struct { Id string Root string @@ -29,6 +35,7 @@ type Container struct { Filesystem *Filesystem State *State + SysInitPath string lxcConfigPath string cmd *exec.Cmd stdout *writeBroadcaster @@ -58,6 +65,7 @@ func createContainer(id string, root string, command string, args []string, laye Filesystem: newFilesystem(path.Join(root, "rootfs"), path.Join(root, "rw"), layers), State: newState(), + SysInitPath: sysInitPath, lxcConfigPath: path.Join(root, "config.lxc"), stdout: newWriteBroadcaster(), stderr: newWriteBroadcaster(), @@ -261,6 +269,7 @@ func (container *Container) Start() error { "-n", container.Id, "-f", container.lxcConfigPath, "--", + "/sbin/init", container.Path, } params = append(params, container.Args...) diff --git a/components/engine/docker_test.go b/components/engine/docker_test.go index 8dc4f60807..21bdae4753 100644 --- a/components/engine/docker_test.go +++ b/components/engine/docker_test.go @@ -6,6 +6,13 @@ import ( "testing" ) +// Hack to run sys init during unit testing +func init() { + if SelfPath() == "/sbin/init" { + SysInit() + } +} + func newTestDocker() (*Docker, error) { root, err := ioutil.TempDir("", "docker-test") if err != nil { diff --git a/components/engine/dockerd/dockerd.go b/components/engine/dockerd/dockerd.go index 3f0fe003aa..2ee5bd4b18 100644 --- a/components/engine/dockerd/dockerd.go +++ b/components/engine/dockerd/dockerd.go @@ -705,6 +705,11 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string) } func main() { + if docker.SelfPath() == "/sbin/init" { + // Running in init mode + docker.SysInit() + return + } future.Seed() flag.Parse() d, err := New() diff --git a/components/engine/lxc_template.go b/components/engine/lxc_template.go index 27d0f12a44..4ac72da273 100755 --- a/components/engine/lxc_template.go +++ b/components/engine/lxc_template.go @@ -74,6 +74,9 @@ lxc.mount.entry = devpts {{$ROOTFS}}/dev/pts devpts newinstance,ptmxmode=0666,no #lxc.mount.entry = varlock {{$ROOTFS}}/var/lock tmpfs size=1024k,nosuid,nodev,noexec 0 0 #lxc.mount.entry = shm {{$ROOTFS}}/dev/shm tmpfs size=65536k,nosuid,nodev,noexec 0 0 +# Inject docker-init +lxc.mount.entry = {{.SysInitPath}} {{$ROOTFS}}/sbin/init none bind,ro 0 0 + # In order to get a working DNS environment, mount bind (ro) the host's /etc/resolv.conf into the container lxc.mount.entry = /etc/resolv.conf {{$ROOTFS}}/etc/resolv.conf none bind,ro 0 0 diff --git a/components/engine/sysinit.go b/components/engine/sysinit.go new file mode 100644 index 0000000000..4feef57639 --- /dev/null +++ b/components/engine/sysinit.go @@ -0,0 +1,29 @@ +package docker + +import ( + "fmt" + "log" + "os" + "os/exec" + "syscall" +) + +// Sys Init code +// This code is run INSIDE the container and is responsible for setting +// up the environment before running the actual process +func SysInit() { + if len(os.Args) <= 1 { + fmt.Println("You should not invoke docker-init manually") + os.Exit(1) + } + + path, err := exec.LookPath(os.Args[1]) + if err != nil { + log.Printf("Unable to locate %v", os.Args[1]) + os.Exit(127) + } + + if err := syscall.Exec(path, os.Args[1:], os.Environ()); err != nil { + panic(err) + } +}