|
@@ -14,7 +14,6 @@ import (
|
|
|
"os"
|
|
|
"path"
|
|
|
"path/filepath"
|
|
|
- "regexp"
|
|
|
"runtime"
|
|
|
"strings"
|
|
|
"sync"
|
|
@@ -27,16 +26,12 @@ import (
|
|
|
"github.com/docker/docker/container"
|
|
|
"github.com/docker/docker/daemon/events"
|
|
|
"github.com/docker/docker/daemon/exec"
|
|
|
- "github.com/docker/docker/errors"
|
|
|
"github.com/docker/engine-api/types"
|
|
|
containertypes "github.com/docker/engine-api/types/container"
|
|
|
- networktypes "github.com/docker/engine-api/types/network"
|
|
|
- "github.com/docker/engine-api/types/strslice"
|
|
|
// register graph drivers
|
|
|
_ "github.com/docker/docker/daemon/graphdriver/register"
|
|
|
dmetadata "github.com/docker/docker/distribution/metadata"
|
|
|
"github.com/docker/docker/distribution/xfer"
|
|
|
- "github.com/docker/docker/dockerversion"
|
|
|
"github.com/docker/docker/image"
|
|
|
"github.com/docker/docker/layer"
|
|
|
"github.com/docker/docker/libcontainerd"
|
|
@@ -58,11 +53,9 @@ import (
|
|
|
volumedrivers "github.com/docker/docker/volume/drivers"
|
|
|
"github.com/docker/docker/volume/local"
|
|
|
"github.com/docker/docker/volume/store"
|
|
|
- "github.com/docker/go-connections/nat"
|
|
|
"github.com/docker/libnetwork"
|
|
|
nwconfig "github.com/docker/libnetwork/config"
|
|
|
"github.com/docker/libtrust"
|
|
|
- "golang.org/x/net/context"
|
|
|
)
|
|
|
|
|
|
var (
|
|
@@ -317,35 +310,6 @@ func (daemon *Daemon) waitForNetworks(c *container.Container) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func (daemon *Daemon) generateHostname(id string, config *containertypes.Config) {
|
|
|
- // Generate default hostname
|
|
|
- if config.Hostname == "" {
|
|
|
- config.Hostname = id[:12]
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint strslice.StrSlice, configCmd strslice.StrSlice) (string, []string) {
|
|
|
- if len(configEntrypoint) != 0 {
|
|
|
- return configEntrypoint[0], append(configEntrypoint[1:], configCmd...)
|
|
|
- }
|
|
|
- return configCmd[0], configCmd[1:]
|
|
|
-}
|
|
|
-
|
|
|
-// GetLabels for a container or image id
|
|
|
-func (daemon *Daemon) GetLabels(id string) map[string]string {
|
|
|
- // TODO: TestCase
|
|
|
- container := daemon.containers.Get(id)
|
|
|
- if container != nil {
|
|
|
- return container.Config.Labels
|
|
|
- }
|
|
|
-
|
|
|
- img, err := daemon.GetImage(id)
|
|
|
- if err == nil {
|
|
|
- return img.ContainerConfig.Labels
|
|
|
- }
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
func (daemon *Daemon) children(c *container.Container) map[string]*container.Container {
|
|
|
return daemon.linkIndex.children(c)
|
|
|
}
|
|
@@ -762,37 +726,6 @@ func tempDir(rootDir string, rootUID, rootGID int) (string, error) {
|
|
|
return tmpDir, idtools.MkdirAllAs(tmpDir, 0700, rootUID, rootGID)
|
|
|
}
|
|
|
|
|
|
-func (daemon *Daemon) setSecurityOptions(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
|
|
- container.Lock()
|
|
|
- defer container.Unlock()
|
|
|
- return parseSecurityOpt(container, hostConfig)
|
|
|
-}
|
|
|
-
|
|
|
-func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
|
|
- // Do not lock while creating volumes since this could be calling out to external plugins
|
|
|
- // Don't want to block other actions, like `docker ps` because we're waiting on an external plugin
|
|
|
- if err := daemon.registerMountPoints(container, hostConfig); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- container.Lock()
|
|
|
- defer container.Unlock()
|
|
|
-
|
|
|
- // Register any links from the host config before starting the container
|
|
|
- if err := daemon.registerLinks(container, hostConfig); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- // make sure links is not nil
|
|
|
- // this ensures that on the next daemon restart we don't try to migrate from legacy sqlite links
|
|
|
- if hostConfig.Links == nil {
|
|
|
- hostConfig.Links = []string{}
|
|
|
- }
|
|
|
-
|
|
|
- container.HostConfig = hostConfig
|
|
|
- return container.ToDisk()
|
|
|
-}
|
|
|
-
|
|
|
func (daemon *Daemon) setupInitLayer(initPath string) error {
|
|
|
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
|
|
return setupInitLayer(initPath, rootUID, rootGID)
|
|
@@ -806,73 +739,6 @@ func setDefaultMtu(config *Config) {
|
|
|
config.Mtu = defaultNetworkMtu
|
|
|
}
|
|
|
|
|
|
-// verifyContainerSettings performs validation of the hostconfig and config
|
|
|
-// structures.
|
|
|
-func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
|
|
-
|
|
|
- // First perform verification of settings common across all platforms.
|
|
|
- if config != nil {
|
|
|
- if config.WorkingDir != "" {
|
|
|
- config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics
|
|
|
- if !system.IsAbs(config.WorkingDir) {
|
|
|
- return nil, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path", config.WorkingDir)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if len(config.StopSignal) > 0 {
|
|
|
- _, err := signal.ParseSignal(config.StopSignal)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Validate if the given hostname is RFC 1123 (https://tools.ietf.org/html/rfc1123) compliant.
|
|
|
- if len(config.Hostname) > 0 {
|
|
|
- // RFC1123 specifies that 63 bytes is the maximium length
|
|
|
- // Windows has the limitation of 63 bytes in length
|
|
|
- // Linux hostname is limited to HOST_NAME_MAX=64, not not including the terminating null byte.
|
|
|
- // We limit the length to 63 bytes here to match RFC1035 and RFC1123.
|
|
|
- matched, _ := regexp.MatchString("^(([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])\\.)*([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])$", config.Hostname)
|
|
|
- if len(config.Hostname) > 63 || !matched {
|
|
|
- return nil, fmt.Errorf("invalid hostname format: %s", config.Hostname)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if hostConfig == nil {
|
|
|
- return nil, nil
|
|
|
- }
|
|
|
-
|
|
|
- for port := range hostConfig.PortBindings {
|
|
|
- _, portStr := nat.SplitProtoPort(string(port))
|
|
|
- if _, err := nat.ParsePort(portStr); err != nil {
|
|
|
- return nil, fmt.Errorf("Invalid port specification: %q", portStr)
|
|
|
- }
|
|
|
- for _, pb := range hostConfig.PortBindings[port] {
|
|
|
- _, err := nat.NewPort(nat.SplitProtoPort(pb.HostPort))
|
|
|
- if err != nil {
|
|
|
- return nil, fmt.Errorf("Invalid port specification: %q", pb.HostPort)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Now do platform-specific verification
|
|
|
- return verifyPlatformContainerSettings(daemon, hostConfig, config, update)
|
|
|
-}
|
|
|
-
|
|
|
-// Checks if the client set configurations for more than one network while creating a container
|
|
|
-func (daemon *Daemon) verifyNetworkingConfig(nwConfig *networktypes.NetworkingConfig) error {
|
|
|
- if nwConfig == nil || len(nwConfig.EndpointsConfig) <= 1 {
|
|
|
- return nil
|
|
|
- }
|
|
|
- l := make([]string, 0, len(nwConfig.EndpointsConfig))
|
|
|
- for k := range nwConfig.EndpointsConfig {
|
|
|
- l = append(l, k)
|
|
|
- }
|
|
|
- err := fmt.Errorf("Container cannot be connected to network endpoints: %s", strings.Join(l, ", "))
|
|
|
- return errors.NewBadRequestError(err)
|
|
|
-}
|
|
|
-
|
|
|
func configureVolumes(config *Config, rootUID, rootGID int) (*store.VolumeStore, error) {
|
|
|
volumesDriver, err := local.New(config.Root, rootUID, rootGID)
|
|
|
if err != nil {
|
|
@@ -883,84 +749,11 @@ func configureVolumes(config *Config, rootUID, rootGID int) (*store.VolumeStore,
|
|
|
return store.New(config.Root)
|
|
|
}
|
|
|
|
|
|
-// AuthenticateToRegistry checks the validity of credentials in authConfig
|
|
|
-func (daemon *Daemon) AuthenticateToRegistry(ctx context.Context, authConfig *types.AuthConfig) (string, string, error) {
|
|
|
- return daemon.RegistryService.Auth(ctx, authConfig, dockerversion.DockerUserAgent(ctx))
|
|
|
-}
|
|
|
-
|
|
|
// IsShuttingDown tells whether the daemon is shutting down or not
|
|
|
func (daemon *Daemon) IsShuttingDown() bool {
|
|
|
return daemon.shutdown
|
|
|
}
|
|
|
|
|
|
-// GetContainerStats collects all the stats published by a container
|
|
|
-func (daemon *Daemon) GetContainerStats(container *container.Container) (*types.StatsJSON, error) {
|
|
|
- stats, err := daemon.stats(container)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- if stats.Networks, err = daemon.getNetworkStats(container); err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- return stats, nil
|
|
|
-}
|
|
|
-
|
|
|
-// Resolve Network SandboxID in case the container reuse another container's network stack
|
|
|
-func (daemon *Daemon) getNetworkSandboxID(c *container.Container) (string, error) {
|
|
|
- curr := c
|
|
|
- for curr.HostConfig.NetworkMode.IsContainer() {
|
|
|
- containerID := curr.HostConfig.NetworkMode.ConnectedContainer()
|
|
|
- connected, err := daemon.GetContainer(containerID)
|
|
|
- if err != nil {
|
|
|
- return "", fmt.Errorf("Could not get container for %s", containerID)
|
|
|
- }
|
|
|
- curr = connected
|
|
|
- }
|
|
|
- return curr.NetworkSettings.SandboxID, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (daemon *Daemon) getNetworkStats(c *container.Container) (map[string]types.NetworkStats, error) {
|
|
|
- sandboxID, err := daemon.getNetworkSandboxID(c)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- sb, err := daemon.netController.SandboxByID(sandboxID)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- lnstats, err := sb.Statistics()
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- stats := make(map[string]types.NetworkStats)
|
|
|
- // Convert libnetwork nw stats into engine-api stats
|
|
|
- for ifName, ifStats := range lnstats {
|
|
|
- stats[ifName] = types.NetworkStats{
|
|
|
- RxBytes: ifStats.RxBytes,
|
|
|
- RxPackets: ifStats.RxPackets,
|
|
|
- RxErrors: ifStats.RxErrors,
|
|
|
- RxDropped: ifStats.RxDropped,
|
|
|
- TxBytes: ifStats.TxBytes,
|
|
|
- TxPackets: ifStats.TxPackets,
|
|
|
- TxErrors: ifStats.TxErrors,
|
|
|
- TxDropped: ifStats.TxDropped,
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return stats, nil
|
|
|
-}
|
|
|
-
|
|
|
-// newBaseContainer creates a new container with its initial
|
|
|
-// configuration based on the root storage from the daemon.
|
|
|
-func (daemon *Daemon) newBaseContainer(id string) *container.Container {
|
|
|
- return container.NewBaseContainer(id, daemon.containerRoot(id))
|
|
|
-}
|
|
|
-
|
|
|
// initDiscovery initializes the discovery watcher for this daemon.
|
|
|
func (daemon *Daemon) initDiscovery(config *Config) error {
|
|
|
advertise, err := parseClusterAdvertiseSettings(config.ClusterStore, config.ClusterAdvertise)
|
|
@@ -1112,13 +905,6 @@ func (daemon *Daemon) reloadClusterDiscovery(config *Config) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-func validateID(id string) error {
|
|
|
- if id == "" {
|
|
|
- return fmt.Errorf("Invalid empty id")
|
|
|
- }
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
func isBridgeNetworkDisabled(config *Config) bool {
|
|
|
return config.bridgeConfig.Iface == disableNetworkBridge
|
|
|
}
|