289 lines
12 KiB
Diff
289 lines
12 KiB
Diff
|
|
From 65c782bb9b0b159f5644395cb291b8741b4400f4 Mon Sep 17 00:00:00 2001
|
||
|
|
From: lujingxiao <lujingxiao@huawei.com>
|
||
|
|
Date: Sat, 19 Jan 2019 11:15:40 +0800
|
||
|
|
Subject: [PATCH 011/111] hookspec: Allow adding custom hooks
|
||
|
|
|
||
|
|
reason: Add new flag "--hook-spec" which accept a file containing custom hook
|
||
|
|
definitions, custom hooks will be appended to system hooks which means
|
||
|
|
docker will execute its own hook first(libnetwork prestart hook) to make
|
||
|
|
sure everything predefined is working normally, user custom programme
|
||
|
|
can be executed afterwards
|
||
|
|
|
||
|
|
One example hook spec file can be of format:
|
||
|
|
```
|
||
|
|
{
|
||
|
|
"prestart": [
|
||
|
|
{
|
||
|
|
"path": "/bin/ls",
|
||
|
|
"args": ["ls"],
|
||
|
|
"env": []
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"poststart":[],
|
||
|
|
"poststop":[]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
Change-Id: Iee6f4e5b56ebf0647304c08c2948d599356192e6
|
||
|
|
Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
|
||
|
|
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||
|
|
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||
|
|
---
|
||
|
|
components/cli/cli/command/container/opts.go | 3 ++
|
||
|
|
.../cli/docs/reference/commandline/create.md | 1 +
|
||
|
|
.../cli/docs/reference/commandline/run.md | 1 +
|
||
|
|
components/cli/man/docker-run.1.md | 28 +++++++++++++++++++
|
||
|
|
.../docker/api/types/container/host_config.go | 1 +
|
||
|
|
.../engine/api/types/container/host_config.go | 1 +
|
||
|
|
components/engine/container/container.go | 4 ++-
|
||
|
|
components/engine/daemon/container.go | 24 ++++++++++++++++
|
||
|
|
components/engine/daemon/daemon_unix.go | 16 +++++++++++
|
||
|
|
components/engine/daemon/oci_linux.go | 6 ++++
|
||
|
|
10 files changed, 84 insertions(+), 1 deletion(-)
|
||
|
|
|
||
|
|
diff --git a/components/cli/cli/command/container/opts.go b/components/cli/cli/command/container/opts.go
|
||
|
|
index af30dfcbf2..8e07aa77cb 100644
|
||
|
|
--- a/components/cli/cli/command/container/opts.go
|
||
|
|
+++ b/components/cli/cli/command/container/opts.go
|
||
|
|
@@ -111,6 +111,7 @@ type containerOptions struct {
|
||
|
|
stopTimeout int
|
||
|
|
isolation string
|
||
|
|
shmSize opts.MemBytes
|
||
|
|
+ hookSpec string
|
||
|
|
noHealthcheck bool
|
||
|
|
healthCmd string
|
||
|
|
healthInterval time.Duration
|
||
|
|
@@ -283,6 +284,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||
|
|
flags.StringVar(&copts.isolation, "isolation", "", "Container isolation technology")
|
||
|
|
flags.StringVar(&copts.pidMode, "pid", "", "PID namespace to use")
|
||
|
|
flags.Var(&copts.shmSize, "shm-size", "Size of /dev/shm")
|
||
|
|
+ flags.StringVar(&copts.hookSpec, "hook-spec", "", "file containing hook definition(prestart, poststart, poststop)")
|
||
|
|
flags.StringVar(&copts.utsMode, "uts", "", "UTS namespace to use")
|
||
|
|
flags.StringVar(&copts.runtime, "runtime", "", "Runtime to use for this container")
|
||
|
|
|
||
|
|
@@ -619,6 +621,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*containerConfig, err
|
||
|
|
VolumeDriver: copts.volumeDriver,
|
||
|
|
Isolation: container.Isolation(copts.isolation),
|
||
|
|
ShmSize: copts.shmSize.Value(),
|
||
|
|
+ HookSpec: copts.hookSpec,
|
||
|
|
Resources: resources,
|
||
|
|
Tmpfs: tmpfs,
|
||
|
|
Sysctls: copts.sysctls.GetAll(),
|
||
|
|
diff --git a/components/cli/docs/reference/commandline/create.md b/components/cli/docs/reference/commandline/create.md
|
||
|
|
index 5d888183b3..34cb79a679 100644
|
||
|
|
--- a/components/cli/docs/reference/commandline/create.md
|
||
|
|
+++ b/components/cli/docs/reference/commandline/create.md
|
||
|
|
@@ -66,6 +66,7 @@ Options:
|
||
|
|
--health-start-period duration Start period for the container to initialize before counting retries towards unstable (ns|us|ms|s|m|h) (default 0s)
|
||
|
|
--help Print usage
|
||
|
|
-h, --hostname string Container host name
|
||
|
|
+ --hook-spec File containing hook definition(prestart, poststart, poststop)
|
||
|
|
--init Run an init inside the container that forwards signals and reaps processes
|
||
|
|
-i, --interactive Keep STDIN open even if not attached
|
||
|
|
--io-maxbandwidth string Maximum IO bandwidth limit for the system drive (Windows only)
|
||
|
|
diff --git a/components/cli/docs/reference/commandline/run.md b/components/cli/docs/reference/commandline/run.md
|
||
|
|
index 21b4fdf261..1dc43ddcd9 100644
|
||
|
|
--- a/components/cli/docs/reference/commandline/run.md
|
||
|
|
+++ b/components/cli/docs/reference/commandline/run.md
|
||
|
|
@@ -70,6 +70,7 @@ Options:
|
||
|
|
--health-start-period duration Start period for the container to initialize before counting retries towards unstable (ns|us|ms|s|m|h) (default 0s)
|
||
|
|
--help Print usage
|
||
|
|
-h, --hostname string Container host name
|
||
|
|
+ --hook-spec File containing hook definition(prestart, poststart, poststop)
|
||
|
|
--init Run an init inside the container that forwards signals and reaps processes
|
||
|
|
-i, --interactive Keep STDIN open even if not attached
|
||
|
|
--io-maxbandwidth string Maximum IO bandwidth limit for the system drive (Windows only)
|
||
|
|
diff --git a/components/cli/man/docker-run.1.md b/components/cli/man/docker-run.1.md
|
||
|
|
index 41f501d5b9..b0cbcd2e87 100644
|
||
|
|
--- a/components/cli/man/docker-run.1.md
|
||
|
|
+++ b/components/cli/man/docker-run.1.md
|
||
|
|
@@ -43,6 +43,7 @@ docker-run - Run a command in a new container
|
||
|
|
[**--group-add**[=*[]*]]
|
||
|
|
[**-h**|**--hostname**[=*HOSTNAME*]]
|
||
|
|
[**--help**]
|
||
|
|
+[**--hook-spec**[=*HOOKFILE*]]
|
||
|
|
[**--init**]
|
||
|
|
[**-i**|**--interactive**]
|
||
|
|
[**--ip**[=*IPv4-ADDRESS*]]
|
||
|
|
@@ -330,6 +331,33 @@ redirection on the host system.
|
||
|
|
**--help**
|
||
|
|
Print usage statement
|
||
|
|
|
||
|
|
+**--hook-spec**=""
|
||
|
|
+ Add custom hooks for container
|
||
|
|
+
|
||
|
|
+ With this flag, user can specify a file containing custom hook, an example hook file can be like this:
|
||
|
|
+
|
||
|
|
+```
|
||
|
|
+{
|
||
|
|
+ "prestart": [
|
||
|
|
+ {
|
||
|
|
+ "path": "/usr/libexec/oci/hooks.d/oci-systemd-hook",
|
||
|
|
+ "args": ["oci-systemd-hook", "prestart"],
|
||
|
|
+ "env": ["container=runc"]
|
||
|
|
+ }
|
||
|
|
+ ],
|
||
|
|
+ "poststop":[
|
||
|
|
+ {
|
||
|
|
+ "path": "/usr/libexec/oci/hooks.d/oci-systemd-hook",
|
||
|
|
+ "args": ["oci-systemd-hook", "poststop"],
|
||
|
|
+ "env": ["container=runc"]
|
||
|
|
+ }
|
||
|
|
+ ]
|
||
|
|
+}
|
||
|
|
+```
|
||
|
|
+
|
||
|
|
+ currently it supports three hooks: "prestart", "poststart", "poststop".
|
||
|
|
+ See OCI spec definition for more information about "hooks".
|
||
|
|
+
|
||
|
|
**--init**
|
||
|
|
Run an init inside the container that forwards signals and reaps processes
|
||
|
|
|
||
|
|
diff --git a/components/cli/vendor/github.com/docker/docker/api/types/container/host_config.go b/components/cli/vendor/github.com/docker/docker/api/types/container/host_config.go
|
||
|
|
index 1565b5e091..701cae55f1 100644
|
||
|
|
--- a/components/cli/vendor/github.com/docker/docker/api/types/container/host_config.go
|
||
|
|
+++ b/components/cli/vendor/github.com/docker/docker/api/types/container/host_config.go
|
||
|
|
@@ -395,6 +395,7 @@ type HostConfig struct {
|
||
|
|
// Applicable to Windows
|
||
|
|
ConsoleSize [2]uint // Initial console size (height,width)
|
||
|
|
Isolation Isolation // Isolation technology of the container (e.g. default, hyperv)
|
||
|
|
+ HookSpec string // specification file containing custom hook definition
|
||
|
|
|
||
|
|
// Contains container's resources (cgroups, ulimits)
|
||
|
|
Resources
|
||
|
|
diff --git a/components/engine/api/types/container/host_config.go b/components/engine/api/types/container/host_config.go
|
||
|
|
index 1565b5e091..701cae55f1 100644
|
||
|
|
--- a/components/engine/api/types/container/host_config.go
|
||
|
|
+++ b/components/engine/api/types/container/host_config.go
|
||
|
|
@@ -395,6 +395,7 @@ type HostConfig struct {
|
||
|
|
// Applicable to Windows
|
||
|
|
ConsoleSize [2]uint // Initial console size (height,width)
|
||
|
|
Isolation Isolation // Isolation technology of the container (e.g. default, hyperv)
|
||
|
|
+ HookSpec string // specification file containing custom hook definition
|
||
|
|
|
||
|
|
// Contains container's resources (cgroups, ulimits)
|
||
|
|
Resources
|
||
|
|
diff --git a/components/engine/container/container.go b/components/engine/container/container.go
|
||
|
|
index f74676f7ee..02adc2019a 100644
|
||
|
|
--- a/components/engine/container/container.go
|
||
|
|
+++ b/components/engine/container/container.go
|
||
|
|
@@ -38,6 +38,7 @@ import (
|
||
|
|
volumemounts "github.com/docker/docker/volume/mounts"
|
||
|
|
"github.com/docker/go-units"
|
||
|
|
agentexec "github.com/docker/swarmkit/agent/exec"
|
||
|
|
+ "github.com/opencontainers/runtime-spec/specs-go"
|
||
|
|
"github.com/pkg/errors"
|
||
|
|
"github.com/sirupsen/logrus"
|
||
|
|
)
|
||
|
|
@@ -93,6 +94,8 @@ type Container struct {
|
||
|
|
LogCopier *logger.Copier `json:"-"`
|
||
|
|
restartManager restartmanager.RestartManager
|
||
|
|
attachContext *attachContext
|
||
|
|
+ Hooks specs.Hooks
|
||
|
|
+ CgroupParent string
|
||
|
|
|
||
|
|
// Fields here are specific to Unix platforms
|
||
|
|
AppArmorProfile string
|
||
|
|
@@ -106,7 +109,6 @@ type Container struct {
|
||
|
|
// Fields here are specific to Windows
|
||
|
|
NetworkSharedContainerID string `json:"-"`
|
||
|
|
SharedEndpointList []string `json:"-"`
|
||
|
|
- CgroupParent string
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewBaseContainer creates a new container with its
|
||
|
|
diff --git a/components/engine/daemon/container.go b/components/engine/daemon/container.go
|
||
|
|
index bd96de2571..8e68904b16 100644
|
||
|
|
--- a/components/engine/daemon/container.go
|
||
|
|
+++ b/components/engine/daemon/container.go
|
||
|
|
@@ -1,6 +1,7 @@
|
||
|
|
package daemon // import "github.com/docker/docker/daemon"
|
||
|
|
|
||
|
|
import (
|
||
|
|
+ "encoding/json"
|
||
|
|
"fmt"
|
||
|
|
"os"
|
||
|
|
"path"
|
||
|
|
@@ -224,11 +225,34 @@ func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
+ // register hooks to container
|
||
|
|
+ if err := daemon.registerHooks(container, hostConfig); err != nil {
|
||
|
|
+ return err
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
runconfig.SetDefaultNetModeIfBlank(hostConfig)
|
||
|
|
container.HostConfig = hostConfig
|
||
|
|
return container.CheckpointTo(daemon.containersReplica)
|
||
|
|
}
|
||
|
|
|
||
|
|
+
|
||
|
|
+func (daemon *Daemon) registerHooks(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
||
|
|
+ if hostConfig.HookSpec == "" {
|
||
|
|
+ return nil
|
||
|
|
+ }
|
||
|
|
+ // the hook spec has already been sanitized, so no need for validation again
|
||
|
|
+ f, err := os.Open(hostConfig.HookSpec)
|
||
|
|
+ if err != nil {
|
||
|
|
+ return fmt.Errorf("open hook spec file error: %v", err)
|
||
|
|
+ }
|
||
|
|
+ defer f.Close()
|
||
|
|
+
|
||
|
|
+ if err = json.NewDecoder(f).Decode(&container.Hooks); err != nil {
|
||
|
|
+ return fmt.Errorf("malformed hook spec, is your spec file in json format? error: %v", err)
|
||
|
|
+ }
|
||
|
|
+ return nil
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
// verifyContainerSettings performs validation of the hostconfig and config
|
||
|
|
// structures.
|
||
|
|
func (daemon *Daemon) verifyContainerSettings(platform string, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
||
|
|
diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go
|
||
|
|
index f4b75055f5..ebf4e067fb 100644
|
||
|
|
--- a/components/engine/daemon/daemon_unix.go
|
||
|
|
+++ b/components/engine/daemon/daemon_unix.go
|
||
|
|
@@ -627,6 +627,22 @@ func (daemon *Daemon) verifyPlatformContainerSettings(hostConfig *containertypes
|
||
|
|
return warnings, fmt.Errorf("cgroup-parent for systemd cgroup should be a valid slice named as \"xxx.slice\"")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+ if hostConfig.HookSpec != "" {
|
||
|
|
+ hostConfig.HookSpec = filepath.Clean(hostConfig.HookSpec)
|
||
|
|
+ if !filepath.IsAbs(hostConfig.HookSpec) {
|
||
|
|
+ return warnings, fmt.Errorf("Hook spec file must be an absolute path")
|
||
|
|
+ }
|
||
|
|
+ fi, err := os.Stat(hostConfig.HookSpec)
|
||
|
|
+ if err != nil {
|
||
|
|
+ return warnings, fmt.Errorf("stat hook spec file failed: %v", err)
|
||
|
|
+ }
|
||
|
|
+ if !fi.Mode().IsRegular() {
|
||
|
|
+ return warnings, fmt.Errorf("Hook spec file must be a regular text file")
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+
|
||
|
|
if hostConfig.Runtime == "" {
|
||
|
|
hostConfig.Runtime = daemon.configStore.GetDefaultRuntimeName()
|
||
|
|
}
|
||
|
|
diff --git a/components/engine/daemon/oci_linux.go b/components/engine/daemon/oci_linux.go
|
||
|
|
index 5018b21f0d..884739c07e 100644
|
||
|
|
--- a/components/engine/daemon/oci_linux.go
|
||
|
|
+++ b/components/engine/daemon/oci_linux.go
|
||
|
|
@@ -818,6 +818,12 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
+ // apppend user custom hooks after system hooks
|
||
|
|
+ // make sure docker's predefined hooks are executed before custom hooks
|
||
|
|
+ s.Hooks.Prestart = append(s.Hooks.Prestart, c.Hooks.Prestart...)
|
||
|
|
+ s.Hooks.Poststart = append(s.Hooks.Poststart, c.Hooks.Poststart...)
|
||
|
|
+ s.Hooks.Poststop = append(s.Hooks.Poststop, c.Hooks.Poststop...)
|
||
|
|
+
|
||
|
|
if apparmor.IsEnabled() {
|
||
|
|
var appArmorProfile string
|
||
|
|
if c.AppArmorProfile != "" {
|
||
|
|
--
|
||
|
|
2.17.1
|
||
|
|
|