Build two binaries client and daemon.

Add a proxy to support 'docker daemon'
Fix configFile option, and remove a test that is no longer relevant.
Remove daemon build tag.
Remove DOCKER_CLIENTONLY from build scripts.

Signed-off-by: Daniel Nephin <dnephin@docker.com>

Change docker-daemon to dockerd.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
Daniel Nephin 2016-02-19 17:42:51 -05:00
parent 9b00817dc6
commit 9e7651db4d
37 changed files with 413 additions and 238 deletions

View file

@ -8,14 +8,13 @@ DOCKER_OSARCH := $(shell bash -c 'source hack/make/.detect-daemon-osarch && echo
DOCKERFILE := $(shell bash -c 'source hack/make/.detect-daemon-osarch && echo $${DOCKERFILE}') DOCKERFILE := $(shell bash -c 'source hack/make/.detect-daemon-osarch && echo $${DOCKERFILE}')
# env vars passed through directly to Docker's build scripts # env vars passed through directly to Docker's build scripts
# to allow things like `make DOCKER_CLIENTONLY=1 binary` easily # to allow things like `make KEEPBUNDLE=1 binary` easily
# `docs/sources/contributing/devenvironment.md ` and `project/PACKAGERS.md` have some limited documentation of some of these # `docs/sources/contributing/devenvironment.md ` and `project/PACKAGERS.md` have some limited documentation of some of these
DOCKER_ENVS := \ DOCKER_ENVS := \
-e BUILDFLAGS \ -e BUILDFLAGS \
-e KEEPBUNDLE \ -e KEEPBUNDLE \
-e DOCKER_BUILD_GOGC \ -e DOCKER_BUILD_GOGC \
-e DOCKER_BUILD_PKGS \ -e DOCKER_BUILD_PKGS \
-e DOCKER_CLIENTONLY \
-e DOCKER_DEBUG \ -e DOCKER_DEBUG \
-e DOCKER_EXPERIMENTAL \ -e DOCKER_EXPERIMENTAL \
-e DOCKER_GITCOMMIT \ -e DOCKER_GITCOMMIT \

View file

@ -1,4 +1,4 @@
package main package flags
import ( import (
"fmt" "fmt"
@ -14,26 +14,32 @@ import (
) )
const ( const (
defaultTrustKeyFile = "key.json" // DefaultTrustKeyFile is the default filename for the trust key
defaultCaFile = "ca.pem" DefaultTrustKeyFile = "key.json"
defaultKeyFile = "key.pem" // DefaultCaFile is the default filename for the CA pem file
defaultCertFile = "cert.pem" DefaultCaFile = "ca.pem"
tlsVerifyKey = "tlsverify" // DefaultKeyFile is the default filename for the key pem file
DefaultKeyFile = "key.pem"
// DefaultCertFile is the default filename for the cert pem file
DefaultCertFile = "cert.pem"
// TLSVerifyKey is the default flag name for the tls verification option
TLSVerifyKey = "tlsverify"
) )
var ( var (
commonFlags = &cli.CommonFlags{FlagSet: new(flag.FlagSet)}
dockerCertPath = os.Getenv("DOCKER_CERT_PATH") dockerCertPath = os.Getenv("DOCKER_CERT_PATH")
dockerTLSVerify = os.Getenv("DOCKER_TLS_VERIFY") != "" dockerTLSVerify = os.Getenv("DOCKER_TLS_VERIFY") != ""
) )
func init() { // InitCommonFlags initializes flags common to both client and daemon
func InitCommonFlags() *cli.CommonFlags {
var commonFlags = &cli.CommonFlags{FlagSet: new(flag.FlagSet)}
if dockerCertPath == "" { if dockerCertPath == "" {
dockerCertPath = cliconfig.ConfigDir() dockerCertPath = cliconfig.ConfigDir()
} }
commonFlags.PostParse = postParseCommon commonFlags.PostParse = func() { postParseCommon(commonFlags) }
cmd := commonFlags.FlagSet cmd := commonFlags.FlagSet
@ -46,22 +52,24 @@ func init() {
var tlsOptions tlsconfig.Options var tlsOptions tlsconfig.Options
commonFlags.TLSOptions = &tlsOptions commonFlags.TLSOptions = &tlsOptions
cmd.StringVar(&tlsOptions.CAFile, []string{"-tlscacert"}, filepath.Join(dockerCertPath, defaultCaFile), "Trust certs signed only by this CA") cmd.StringVar(&tlsOptions.CAFile, []string{"-tlscacert"}, filepath.Join(dockerCertPath, DefaultCaFile), "Trust certs signed only by this CA")
cmd.StringVar(&tlsOptions.CertFile, []string{"-tlscert"}, filepath.Join(dockerCertPath, defaultCertFile), "Path to TLS certificate file") cmd.StringVar(&tlsOptions.CertFile, []string{"-tlscert"}, filepath.Join(dockerCertPath, DefaultCertFile), "Path to TLS certificate file")
cmd.StringVar(&tlsOptions.KeyFile, []string{"-tlskey"}, filepath.Join(dockerCertPath, defaultKeyFile), "Path to TLS key file") cmd.StringVar(&tlsOptions.KeyFile, []string{"-tlskey"}, filepath.Join(dockerCertPath, DefaultKeyFile), "Path to TLS key file")
cmd.Var(opts.NewNamedListOptsRef("hosts", &commonFlags.Hosts, opts.ValidateHost), []string{"H", "-host"}, "Daemon socket(s) to connect to") cmd.Var(opts.NewNamedListOptsRef("hosts", &commonFlags.Hosts, opts.ValidateHost), []string{"H", "-host"}, "Daemon socket(s) to connect to")
return commonFlags
} }
func postParseCommon() { func postParseCommon(commonFlags *cli.CommonFlags) {
cmd := commonFlags.FlagSet cmd := commonFlags.FlagSet
setDaemonLogLevel(commonFlags.LogLevel) SetDaemonLogLevel(commonFlags.LogLevel)
// Regardless of whether the user sets it to true or false, if they // Regardless of whether the user sets it to true or false, if they
// specify --tlsverify at all then we need to turn on tls // specify --tlsverify at all then we need to turn on tls
// TLSVerify can be true even if not set due to DOCKER_TLS_VERIFY env var, so we need to check that here as well // TLSVerify can be true even if not set due to DOCKER_TLS_VERIFY env var, so we need
if cmd.IsSet("-"+tlsVerifyKey) || commonFlags.TLSVerify { // to check that here as well
if cmd.IsSet("-"+TLSVerifyKey) || commonFlags.TLSVerify {
commonFlags.TLS = true commonFlags.TLS = true
} }
@ -86,7 +94,9 @@ func postParseCommon() {
} }
} }
func setDaemonLogLevel(logLevel string) { // SetDaemonLogLevel sets the logrus logging level
// TODO: this is a bad name, it applies to the client as well.
func SetDaemonLogLevel(logLevel string) {
if logLevel != "" { if logLevel != "" {
lvl, err := logrus.ParseLevel(logLevel) lvl, err := logrus.ParseLevel(logLevel)
if err != nil { if err != nil {

View file

@ -4,14 +4,19 @@ import (
"path/filepath" "path/filepath"
"github.com/docker/docker/cli" "github.com/docker/docker/cli"
cliflags "github.com/docker/docker/cli/flags"
"github.com/docker/docker/cliconfig" "github.com/docker/docker/cliconfig"
flag "github.com/docker/docker/pkg/mflag" flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/utils" "github.com/docker/docker/utils"
) )
var clientFlags = &cli.ClientFlags{FlagSet: new(flag.FlagSet), Common: commonFlags} var (
commonFlags = cliflags.InitCommonFlags()
clientFlags = &cli.ClientFlags{FlagSet: new(flag.FlagSet), Common: commonFlags}
)
func init() { func init() {
client := clientFlags.FlagSet client := clientFlags.FlagSet
client.StringVar(&clientFlags.ConfigDir, []string{"-config"}, cliconfig.ConfigDir(), "Location of client config files") client.StringVar(&clientFlags.ConfigDir, []string{"-config"}, cliconfig.ConfigDir(), "Location of client config files")
@ -23,7 +28,7 @@ func init() {
} }
if clientFlags.Common.TrustKey == "" { if clientFlags.Common.TrustKey == "" {
clientFlags.Common.TrustKey = filepath.Join(cliconfig.ConfigDir(), defaultTrustKeyFile) clientFlags.Common.TrustKey = filepath.Join(cliconfig.ConfigDir(), cliflags.DefaultTrustKeyFile)
} }
if clientFlags.Common.Debug { if clientFlags.Common.Debug {

43
client/daemon.go Normal file
View file

@ -0,0 +1,43 @@
package main
import (
"os"
"os/exec"
"syscall"
)
const daemonBinary = "dockerd"
// DaemonProxy acts as a cli.Handler to proxy calls to the daemon binary
type DaemonProxy struct{}
// NewDaemonProxy returns a new handler
func NewDaemonProxy() DaemonProxy {
return DaemonProxy{}
}
// CmdDaemon execs dockerd with the same flags
// TODO: add a deprecation warning?
func (p DaemonProxy) CmdDaemon(args ...string) error {
args = stripDaemonArg(os.Args[1:])
binaryAbsPath, err := exec.LookPath(daemonBinary)
if err != nil {
return err
}
return syscall.Exec(
binaryAbsPath,
append([]string{daemonBinary}, args...),
os.Environ())
}
// stripDaemonArg removes the `daemon` argument from the list
func stripDaemonArg(args []string) []string {
for i, arg := range args {
if arg == "daemon" {
return append(args[:i], args[i+1:]...)
}
}
return args
}

82
client/docker.go Normal file
View file

@ -0,0 +1,82 @@
package main
import (
"fmt"
"os"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/client"
"github.com/docker/docker/cli"
"github.com/docker/docker/dockerversion"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/reexec"
"github.com/docker/docker/pkg/term"
"github.com/docker/docker/utils"
)
func main() {
if reexec.Init() {
return
}
// Set terminal emulation based on platform as required.
stdin, stdout, stderr := term.StdStreams()
logrus.SetOutput(stderr)
flag.Merge(flag.CommandLine, clientFlags.FlagSet, commonFlags.FlagSet)
flag.Usage = func() {
fmt.Fprint(stdout, "Usage: docker [OPTIONS] COMMAND [arg...]\n docker [ --help | -v | --version ]\n\n")
fmt.Fprint(stdout, "A self-sufficient runtime for containers.\n\nOptions:\n")
flag.CommandLine.SetOutput(stdout)
flag.PrintDefaults()
help := "\nCommands:\n"
for _, cmd := range dockerCommands {
help += fmt.Sprintf(" %-10.10s%s\n", cmd.Name, cmd.Description)
}
help += "\nRun 'docker COMMAND --help' for more information on a command."
fmt.Fprintf(stdout, "%s\n", help)
}
flag.Parse()
if *flVersion {
showVersion()
return
}
if *flHelp {
// if global flag --help is present, regardless of what other options and commands there are,
// just print the usage.
flag.Usage()
return
}
clientCli := client.NewDockerCli(stdin, stdout, stderr, clientFlags)
c := cli.New(clientCli, NewDaemonProxy())
if err := c.Run(flag.Args()...); err != nil {
if sterr, ok := err.(cli.StatusError); ok {
if sterr.Status != "" {
fmt.Fprintln(stderr, sterr.Status)
os.Exit(1)
}
os.Exit(sterr.StatusCode)
}
fmt.Fprintln(stderr, err)
os.Exit(1)
}
}
func showVersion() {
if utils.ExperimentalBuild() {
fmt.Printf("Docker version %s, build %s, experimental\n", dockerversion.Version, dockerversion.GitCommit)
} else {
fmt.Printf("Docker version %s, build %s\n", dockerversion.Version, dockerversion.GitCommit)
}
}

5
client/docker_windows.go Normal file
View file

@ -0,0 +1,5 @@
package main
import (
_ "github.com/docker/docker/autogen/winresources"
)

View file

@ -1,5 +1,3 @@
// +build daemon
package main package main
import ( import (
@ -26,6 +24,7 @@ import (
"github.com/docker/docker/api/server/router/volume" "github.com/docker/docker/api/server/router/volume"
"github.com/docker/docker/builder/dockerfile" "github.com/docker/docker/builder/dockerfile"
"github.com/docker/docker/cli" "github.com/docker/docker/cli"
cliflags "github.com/docker/docker/cli/flags"
"github.com/docker/docker/cliconfig" "github.com/docker/docker/cliconfig"
"github.com/docker/docker/daemon" "github.com/docker/docker/daemon"
"github.com/docker/docker/daemon/logger" "github.com/docker/docker/daemon/logger"
@ -46,18 +45,14 @@ import (
) )
const ( const (
daemonUsage = " docker daemon [ --help | ... ]\n"
daemonConfigFileFlag = "-config-file" daemonConfigFileFlag = "-config-file"
) )
var (
daemonCli cli.Handler = NewDaemonCli()
)
// DaemonCli represents the daemon CLI. // DaemonCli represents the daemon CLI.
type DaemonCli struct { type DaemonCli struct {
*daemon.Config *daemon.Config
flags *flag.FlagSet commonFlags *cli.CommonFlags
configFile *string
} }
func presentInHelp(usage string) string { return usage } func presentInHelp(usage string) string { return usage }
@ -65,8 +60,6 @@ func absentFromHelp(string) string { return "" }
// NewDaemonCli returns a pre-configured daemon CLI // NewDaemonCli returns a pre-configured daemon CLI
func NewDaemonCli() *DaemonCli { func NewDaemonCli() *DaemonCli {
daemonFlags := cli.Subcmd("daemon", nil, "Enable daemon mode", true)
// TODO(tiborvass): remove InstallFlags? // TODO(tiborvass): remove InstallFlags?
daemonConfig := new(daemon.Config) daemonConfig := new(daemon.Config)
daemonConfig.LogConfig.Config = make(map[string]string) daemonConfig.LogConfig.Config = make(map[string]string)
@ -76,20 +69,21 @@ func NewDaemonCli() *DaemonCli {
daemonConfig.V2Only = true daemonConfig.V2Only = true
} }
daemonConfig.InstallFlags(daemonFlags, presentInHelp) daemonConfig.InstallFlags(flag.CommandLine, presentInHelp)
daemonConfig.InstallFlags(flag.CommandLine, absentFromHelp) configFile := flag.CommandLine.String([]string{daemonConfigFileFlag}, defaultDaemonConfigFile, "Daemon configuration file")
daemonFlags.Require(flag.Exact, 0) flag.CommandLine.Require(flag.Exact, 0)
return &DaemonCli{ return &DaemonCli{
Config: daemonConfig, Config: daemonConfig,
flags: daemonFlags, commonFlags: cliflags.InitCommonFlags(),
configFile: configFile,
} }
} }
func migrateKey() (err error) { func migrateKey() (err error) {
// Migrate trust key if exists at ~/.docker/key.json and owned by current user // Migrate trust key if exists at ~/.docker/key.json and owned by current user
oldPath := filepath.Join(cliconfig.ConfigDir(), defaultTrustKeyFile) oldPath := filepath.Join(cliconfig.ConfigDir(), cliflags.DefaultTrustKeyFile)
newPath := filepath.Join(getDaemonConfDir(), defaultTrustKeyFile) newPath := filepath.Join(getDaemonConfDir(), cliflags.DefaultTrustKeyFile)
if _, statErr := os.Stat(newPath); os.IsNotExist(statErr) && currentUserIsOwner(oldPath) { if _, statErr := os.Stat(newPath); os.IsNotExist(statErr) && currentUserIsOwner(oldPath) {
defer func() { defer func() {
// Ensure old path is removed if no error occurred // Ensure old path is removed if no error occurred
@ -127,47 +121,17 @@ func migrateKey() (err error) {
return nil return nil
} }
func getGlobalFlag() (globalFlag *flag.Flag) { func (cli *DaemonCli) start() {
defer func() {
if x := recover(); x != nil {
switch f := x.(type) {
case *flag.Flag:
globalFlag = f
default:
panic(x)
}
}
}()
visitor := func(f *flag.Flag) { panic(f) }
commonFlags.FlagSet.Visit(visitor)
clientFlags.FlagSet.Visit(visitor)
return
}
// CmdDaemon is the daemon command, called the raw arguments after `docker daemon`.
func (cli *DaemonCli) CmdDaemon(args ...string) error {
// warn from uuid package when running the daemon // warn from uuid package when running the daemon
uuid.Loggerf = logrus.Warnf uuid.Loggerf = logrus.Warnf
if !commonFlags.FlagSet.IsEmpty() || !clientFlags.FlagSet.IsEmpty() { flags := flag.CommandLine
// deny `docker -D daemon` cli.commonFlags.PostParse()
illegalFlag := getGlobalFlag()
fmt.Fprintf(os.Stderr, "invalid flag '-%s'.\nSee 'docker daemon --help'.\n", illegalFlag.Names[0]) if cli.commonFlags.TrustKey == "" {
os.Exit(1) cli.commonFlags.TrustKey = filepath.Join(getDaemonConfDir(), cliflags.DefaultTrustKeyFile)
} else {
// allow new form `docker daemon -D`
flag.Merge(cli.flags, commonFlags.FlagSet)
} }
cliConfig, err := loadDaemonCliConfig(cli.Config, flags, cli.commonFlags, *cli.configFile)
configFile := cli.flags.String([]string{daemonConfigFileFlag}, defaultDaemonConfigFile, "Daemon configuration file")
cli.flags.ParseFlags(args, true)
commonFlags.PostParse()
if commonFlags.TrustKey == "" {
commonFlags.TrustKey = filepath.Join(getDaemonConfDir(), defaultTrustKeyFile)
}
cliConfig, err := loadDaemonCliConfig(cli.Config, cli.flags, commonFlags, *configFile)
if err != nil { if err != nil {
fmt.Fprint(os.Stderr, err) fmt.Fprint(os.Stderr, err)
os.Exit(1) os.Exit(1)
@ -278,7 +242,7 @@ func (cli *DaemonCli) CmdDaemon(args ...string) error {
if err := migrateKey(); err != nil { if err := migrateKey(); err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }
cli.TrustKeyPath = commonFlags.TrustKey cli.TrustKeyPath = cli.commonFlags.TrustKey
registryService := registry.NewService(cli.Config.ServiceOptions) registryService := registry.NewService(cli.Config.ServiceOptions)
containerdRemote, err := libcontainerd.New(cli.getLibcontainerdRoot(), cli.getPlatformRemoteOptions()...) containerdRemote, err := libcontainerd.New(cli.getLibcontainerdRoot(), cli.getPlatformRemoteOptions()...)
@ -326,7 +290,7 @@ func (cli *DaemonCli) CmdDaemon(args ...string) error {
} }
} }
setupConfigReloadTrap(*configFile, cli.flags, reload) setupConfigReloadTrap(*cli.configFile, flags, reload)
// The serve API routine never exits unless an error occurs // The serve API routine never exits unless an error occurs
// We need to start it as a goroutine and wait on it so // We need to start it as a goroutine and wait on it so
@ -361,7 +325,6 @@ func (cli *DaemonCli) CmdDaemon(args ...string) error {
} }
logrus.Fatalf("Shutting down due to ServeAPI error: %v", errAPI) logrus.Fatalf("Shutting down due to ServeAPI error: %v", errAPI)
} }
return nil
} }
// shutdownDaemon just wraps daemon.Shutdown() to handle a timeout in case // shutdownDaemon just wraps daemon.Shutdown() to handle a timeout in case
@ -381,7 +344,7 @@ func shutdownDaemon(d *daemon.Daemon, timeout time.Duration) {
} }
} }
func loadDaemonCliConfig(config *daemon.Config, daemonFlags *flag.FlagSet, commonConfig *cli.CommonFlags, configFile string) (*daemon.Config, error) { func loadDaemonCliConfig(config *daemon.Config, flags *flag.FlagSet, commonConfig *cli.CommonFlags, configFile string) (*daemon.Config, error) {
config.Debug = commonConfig.Debug config.Debug = commonConfig.Debug
config.Hosts = commonConfig.Hosts config.Hosts = commonConfig.Hosts
config.LogLevel = commonConfig.LogLevel config.LogLevel = commonConfig.LogLevel
@ -396,9 +359,9 @@ func loadDaemonCliConfig(config *daemon.Config, daemonFlags *flag.FlagSet, commo
} }
if configFile != "" { if configFile != "" {
c, err := daemon.MergeDaemonConfigurations(config, daemonFlags, configFile) c, err := daemon.MergeDaemonConfigurations(config, flags, configFile)
if err != nil { if err != nil {
if daemonFlags.IsSet(daemonConfigFileFlag) || !os.IsNotExist(err) { if flags.IsSet(daemonConfigFileFlag) || !os.IsNotExist(err) {
return nil, fmt.Errorf("unable to configure the Docker daemon with file %s: %v\n", configFile, err) return nil, fmt.Errorf("unable to configure the Docker daemon with file %s: %v\n", configFile, err)
} }
} }
@ -411,12 +374,12 @@ func loadDaemonCliConfig(config *daemon.Config, daemonFlags *flag.FlagSet, commo
// Regardless of whether the user sets it to true or false, if they // Regardless of whether the user sets it to true or false, if they
// specify TLSVerify at all then we need to turn on TLS // specify TLSVerify at all then we need to turn on TLS
if config.IsValueSet(tlsVerifyKey) { if config.IsValueSet(cliflags.TLSVerifyKey) {
config.TLS = true config.TLS = true
} }
// ensure that the log level is the one set after merging configurations // ensure that the log level is the one set after merging configurations
setDaemonLogLevel(config.LogLevel) cliflags.SetDaemonLogLevel(config.LogLevel)
return config, nil return config, nil
} }

View file

@ -1,5 +1,3 @@
// +build daemon
package main package main
// notifySystem sends a message to the host when the server is ready to be used // notifySystem sends a message to the host when the server is ready to be used

View file

@ -1,5 +1,3 @@
// +build daemon
package main package main
import ( import (

View file

@ -1,9 +0,0 @@
// +build !daemon
package main
import "github.com/docker/docker/cli"
const daemonUsage = ""
var daemonCli cli.Handler

View file

@ -1,5 +1,3 @@
// +build daemon
package main package main
import ( import (

View file

@ -1,4 +1,4 @@
// +build daemon,!windows // +build !windows
package main package main

View file

@ -1,4 +1,4 @@
// +build daemon,!windows // +build !windows
package main package main

View file

@ -1,5 +1,3 @@
// +build daemon
package main package main
import ( import (

View file

@ -5,8 +5,6 @@ import (
"os" "os"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/docker/docker/api/client"
"github.com/docker/docker/cli"
"github.com/docker/docker/dockerversion" "github.com/docker/docker/dockerversion"
flag "github.com/docker/docker/pkg/mflag" flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/reexec" "github.com/docker/docker/pkg/reexec"
@ -14,37 +12,39 @@ import (
"github.com/docker/docker/utils" "github.com/docker/docker/utils"
) )
var (
daemonCli = NewDaemonCli()
flHelp = flag.Bool([]string{"h", "-help"}, false, "Print usage")
flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
)
func main() { func main() {
if reexec.Init() { if reexec.Init() {
return return
} }
// Set terminal emulation based on platform as required. // Set terminal emulation based on platform as required.
stdin, stdout, stderr := term.StdStreams() _, stdout, stderr := term.StdStreams()
logrus.SetOutput(stderr) logrus.SetOutput(stderr)
flag.Merge(flag.CommandLine, clientFlags.FlagSet, commonFlags.FlagSet) flag.Merge(flag.CommandLine, daemonCli.commonFlags.FlagSet)
flag.Usage = func() { flag.Usage = func() {
fmt.Fprint(stdout, "Usage: docker [OPTIONS] COMMAND [arg...]\n"+daemonUsage+" docker [ --help | -v | --version ]\n\n") fmt.Fprint(stdout, "Usage: dockerd [ --help | -v | --version ]\n\n")
fmt.Fprint(stdout, "A self-sufficient runtime for containers.\n\nOptions:\n") fmt.Fprint(stdout, "A self-sufficient runtime for containers.\n\nOptions:\n")
flag.CommandLine.SetOutput(stdout) flag.CommandLine.SetOutput(stdout)
flag.PrintDefaults() flag.PrintDefaults()
}
help := "\nCommands:\n" flag.CommandLine.ShortUsage = func() {
fmt.Fprint(stderr, "\nUsage:\tdockerd [OPTIONS]\n")
for _, cmd := range dockerCommands {
help += fmt.Sprintf(" %-10.10s%s\n", cmd.Name, cmd.Description)
} }
help += "\nRun 'docker COMMAND --help' for more information on a command." if err := flag.CommandLine.ParseFlags(os.Args[1:], false); err != nil {
fmt.Fprintf(stdout, "%s\n", help) os.Exit(1)
} }
flag.Parse()
if *flVersion { if *flVersion {
showVersion() showVersion()
return return
@ -56,21 +56,7 @@ func main() {
flag.Usage() flag.Usage()
return return
} }
daemonCli.start()
clientCli := client.NewDockerCli(stdin, stdout, stderr, clientFlags)
c := cli.New(clientCli, daemonCli)
if err := c.Run(flag.Args()...); err != nil {
if sterr, ok := err.(cli.StatusError); ok {
if sterr.Status != "" {
fmt.Fprintln(stderr, sterr.Status)
os.Exit(1)
}
os.Exit(sterr.StatusCode)
}
fmt.Fprintln(stderr, err)
os.Exit(1)
}
} }
func showVersion() { func showVersion() {

View file

@ -1,11 +1,10 @@
.PHONY: all binary build cross default docs docs-build docs-shell shell test test-unit test-integration test-integration-cli test-docker-py validate .PHONY: all binary build cross default docs docs-build docs-shell shell test test-unit test-integration test-integration-cli test-docker-py validate
# env vars passed through directly to Docker's build scripts # env vars passed through directly to Docker's build scripts
# to allow things like `make DOCKER_CLIENTONLY=1 binary` easily # to allow things like `make BUILDFLAGS=... binary` easily
# `docs/sources/contributing/devenvironment.md ` and `project/PACKAGERS.md` have some limited documentation of some of these # `docs/sources/contributing/devenvironment.md ` and `project/PACKAGERS.md` have some limited documentation of some of these
DOCKER_ENVS := \ DOCKER_ENVS := \
-e BUILDFLAGS \ -e BUILDFLAGS \
-e DOCKER_CLIENTONLY \
-e DOCKER_GRAPHDRIVER \ -e DOCKER_GRAPHDRIVER \
-e TESTDIRS \ -e TESTDIRS \
-e TESTFLAGS \ -e TESTFLAGS \

View file

@ -75,7 +75,8 @@ _dockerfile_env() {
clean() { clean() {
local packages=( local packages=(
"${PROJECT}/docker" # package main "${PROJECT}/docker" # daemon package main
"${PROJECT}/client" # client package main
"${PROJECT}/integration-cli" # external tests "${PROJECT}/integration-cli" # external tests
) )
local dockerPlatforms=( ${DOCKER_ENGINE_OSARCH:="linux/amd64"} $(_dockerfile_env DOCKER_CROSSPLATFORMS) ) local dockerPlatforms=( ${DOCKER_ENGINE_OSARCH:="linux/amd64"} $(_dockerfile_env DOCKER_CROSSPLATFORMS) )

View file

@ -66,7 +66,8 @@ DEFAULT_BUNDLES=(
validate-toml validate-toml
validate-vet validate-vet
binary binary-client
binary-daemon
dynbinary dynbinary
test-unit test-unit
@ -126,14 +127,11 @@ if [ "$DOCKER_EXPERIMENTAL" ]; then
DOCKER_BUILDTAGS+=" experimental" DOCKER_BUILDTAGS+=" experimental"
fi fi
if [ -z "$DOCKER_CLIENTONLY" ]; then
DOCKER_BUILDTAGS+=" daemon"
if pkg-config 'libsystemd >= 209' 2> /dev/null ; then if pkg-config 'libsystemd >= 209' 2> /dev/null ; then
DOCKER_BUILDTAGS+=" journald" DOCKER_BUILDTAGS+=" journald"
elif pkg-config 'libsystemd-journal' 2> /dev/null ; then elif pkg-config 'libsystemd-journal' 2> /dev/null ; then
DOCKER_BUILDTAGS+=" journald journald_compat" DOCKER_BUILDTAGS+=" journald journald_compat"
fi fi
fi
# test whether "btrfs/version.h" exists and apply btrfs_noversion appropriately # test whether "btrfs/version.h" exists and apply btrfs_noversion appropriately
if \ if \

64
hack/make/.binary Normal file
View file

@ -0,0 +1,64 @@
#!/bin/bash
set -e
BINARY_NAME="$BINARY_SHORT_NAME-$VERSION"
BINARY_EXTENSION="$(binary_extension)"
BINARY_FULLNAME="$BINARY_NAME$BINARY_EXTENSION"
source "${MAKEDIR}/.go-autogen"
(
export GOGC=${DOCKER_BUILD_GOGC:-1000}
if [ "$(go env GOOS)/$(go env GOARCH)" != "$(go env GOHOSTOS)/$(go env GOHOSTARCH)" ]; then
# must be cross-compiling!
case "$(go env GOOS)/$(go env GOARCH)" in
windows/amd64)
export CC=x86_64-w64-mingw32-gcc
export CGO_ENABLED=1
;;
esac
fi
if [ "$(go env GOOS)" == "linux" ] ; then
case "$(go env GOARCH)" in
arm*|386)
# linking for Linux on arm or x86 needs external linking to avoid
# https://github.com/golang/go/issues/9510 until we move to Go 1.6
if [ "$IAMSTATIC" == "true" ] ; then
export EXTLDFLAGS_STATIC="$EXTLDFLAGS_STATIC -zmuldefs"
export LDFLAGS_STATIC_DOCKER="$LDFLAGS_STATIC -extldflags \"$EXTLDFLAGS_STATIC\""
else
export LDFLAGS="$LDFLAGS -extldflags -zmuldefs"
fi
;;
esac
fi
if [ "$IAMSTATIC" == "true" ] && [ "$(go env GOHOSTOS)" == "linux" ]; then
if [ "${GOOS}/${GOARCH}" == "darwin/amd64" ]; then
export CGO_ENABLED=1
export CC=o64-clang
export LDFLAGS='-linkmode external -s'
export LDFLAGS_STATIC_DOCKER='-extld='${CC}
else
export BUILDFLAGS=( "${BUILDFLAGS[@]/pkcs11 /}" ) # we cannot dlopen in pkcs11 in a static binary
fi
fi
echo "Building: $DEST/$BINARY_FULLNAME"
go build \
-o "$DEST/$BINARY_FULLNAME" \
"${BUILDFLAGS[@]}" \
-ldflags "
$LDFLAGS
$LDFLAGS_STATIC_DOCKER
" \
$SOURCE_PATH
)
echo "Created binary: $DEST/$BINARY_FULLNAME"
ln -sf "$BINARY_FULLNAME" "$DEST/$BINARY_SHORT_NAME$BINARY_EXTENSION"
hash_files "$DEST/$BINARY_FULLNAME"

View file

@ -12,14 +12,16 @@ override_dh_auto_build:
# ./man/md2man-all.sh runs outside the build container (if at all), since we don't have go-md2man here # ./man/md2man-all.sh runs outside the build container (if at all), since we don't have go-md2man here
override_dh_auto_test: override_dh_auto_test:
./bundles/$(VERSION)/dynbinary/docker -v ./bundles/$(VERSION)/dynbinary-daemon/dockerd -v
./bundles/$(VERSION)/dynbinary-client/docker -v
override_dh_strip: override_dh_strip:
# Go has lots of problems with stripping, so just don't # Go has lots of problems with stripping, so just don't
override_dh_auto_install: override_dh_auto_install:
mkdir -p debian/docker-engine/usr/bin mkdir -p debian/docker-engine/usr/bin
cp -aT "$$(readlink -f bundles/$(VERSION)/dynbinary/docker)" debian/docker-engine/usr/bin/docker cp -aT "$$(readlink -f bundles/$(VERSION)/dynbinary-client/docker)" debian/docker-engine/usr/bin/docker
cp -aT "$$(readlink -f bundles/$(VERSION)/dynbinary-daemon/dockerd)" debian/docker-engine/usr/bin/dockerd
cp -aT /usr/local/bin/containerd debian/docker-engine/usr/bin/docker-containerd cp -aT /usr/local/bin/containerd debian/docker-engine/usr/bin/docker-containerd
cp -aT /usr/local/bin/containerd-shim debian/docker-engine/usr/bin/docker-containerd-shim cp -aT /usr/local/bin/containerd-shim debian/docker-engine/usr/bin/docker-containerd-shim
cp -aT /usr/local/bin/ctr debian/docker-engine/usr/bin/docker-containerd-ctr cp -aT /usr/local/bin/ctr debian/docker-engine/usr/bin/docker-containerd-ctr

View file

@ -112,12 +112,14 @@ export DOCKER_GITCOMMIT=%{_gitcommit}
# ./man/md2man-all.sh runs outside the build container (if at all), since we don't have go-md2man here # ./man/md2man-all.sh runs outside the build container (if at all), since we don't have go-md2man here
%check %check
./bundles/%{_origversion}/dynbinary/docker -v ./bundles/%{_origversion}/dynbinary-client/docker -v
./bundles/%{_origversion}/dynbinary-daemon/dockerd -v
%install %install
# install binary # install binary
install -d $RPM_BUILD_ROOT/%{_bindir} install -d $RPM_BUILD_ROOT/%{_bindir}
install -p -m 755 bundles/%{_origversion}/dynbinary/docker-%{_origversion} $RPM_BUILD_ROOT/%{_bindir}/docker install -p -m 755 bundles/%{_origversion}/dynbinary-client/docker-%{_origversion} $RPM_BUILD_ROOT/%{_bindir}/docker
install -p -m 755 bundles/%{_origversion}/dynbinary-daemon/dockerd-%{_origversion} $RPM_BUILD_ROOT/%{_bindir}/dockerd
# install containerd # install containerd
install -p -m 755 /usr/local/bin/containerd $RPM_BUILD_ROOT/%{_bindir}/docker-containerd install -p -m 755 /usr/local/bin/containerd $RPM_BUILD_ROOT/%{_bindir}/docker-containerd

View file

@ -2,13 +2,20 @@
# see test-integration-cli for example usage of this script # see test-integration-cli for example usage of this script
export PATH="$ABS_DEST/../binary:$ABS_DEST/../dynbinary:$ABS_DEST/../gccgo:$ABS_DEST/../dyngccgo:$PATH" base="$ABS_DEST/.."
export PATH="$base/binary-client:$base/binary-daemon:$base/dynbinary:$base/gccgo:$base/dyngccgo:$PATH"
if ! command -v docker &> /dev/null; then if ! command -v docker &> /dev/null; then
echo >&2 'error: binary or dynbinary must be run before .integration-daemon-start' echo >&2 'error: binary-client or dynbinary-client must be run before .integration-daemon-start'
false false
fi fi
# This is a temporary hack for split-binary mode. It can be removed once
# https://github.com/docker/docker/pull/22134 is merged into docker master
if [ "$(go env GOOS)" = 'windows' ]; then
return
fi
if [ -z "$DOCKER_TEST_HOST" ]; then if [ -z "$DOCKER_TEST_HOST" ]; then
if docker version &> /dev/null; then if docker version &> /dev/null; then
echo >&2 'skipping daemon start, since daemon appears to be already started' echo >&2 'skipping daemon start, since daemon appears to be already started'
@ -16,6 +23,11 @@ if [ -z "$DOCKER_TEST_HOST" ]; then
fi fi
fi fi
if ! command -v dockerd &> /dev/null; then
echo >&2 'error: binary-daemon or dynbinary-daemon must be run before .integration-daemon-start'
false
fi
# intentionally open a couple bogus file descriptors to help test that they get scrubbed in containers # intentionally open a couple bogus file descriptors to help test that they get scrubbed in containers
exec 41>&1 42>&2 exec 41>&1 42>&2
@ -52,7 +64,7 @@ if [ -z "$DOCKER_TEST_HOST" ]; then
export DOCKER_HOST="unix://$(cd "$DEST" && pwd)/docker.sock" # "pwd" tricks to make sure $DEST is an absolute path, not a relative one export DOCKER_HOST="unix://$(cd "$DEST" && pwd)/docker.sock" # "pwd" tricks to make sure $DEST is an absolute path, not a relative one
( set -x; exec \ ( set -x; exec \
docker daemon --debug \ dockerd --debug \
--host "$DOCKER_HOST" \ --host "$DOCKER_HOST" \
--storage-driver "$DOCKER_GRAPHDRIVER" \ --storage-driver "$DOCKER_GRAPHDRIVER" \
--pidfile "$DEST/docker.pid" \ --pidfile "$DEST/docker.pid" \

View file

@ -1,65 +1,14 @@
#!/bin/bash #!/bin/bash
set -e set -e
BINARY_NAME="docker-$VERSION" # This script exists as backwards compatiblity for CI
BINARY_EXTENSION="$(binary_extension)"
BINARY_FULLNAME="$BINARY_NAME$BINARY_EXTENSION"
source "${MAKEDIR}/.go-autogen"
( (
export GOGC=${DOCKER_BUILD_GOGC:-1000} DEST="${DEST}-client"
ABS_DEST="${ABS_DEST}-client"
if [ "$(go env GOOS)/$(go env GOARCH)" != "$(go env GOHOSTOS)/$(go env GOHOSTARCH)" ]; then . hack/make/binary-client
# must be cross-compiling! )
case "$(go env GOOS)/$(go env GOARCH)" in (
windows/amd64) DEST="${DEST}-daemon"
export CC=x86_64-w64-mingw32-gcc ABS_DEST="${ABS_DEST}-daemon"
export CGO_ENABLED=1 . hack/make/binary-daemon
;;
esac
fi
if [ "$(go env GOOS)" == "linux" ] ; then
case "$(go env GOARCH)" in
arm*|386)
# linking for Linux on arm or x86 needs external linking to avoid
# https://github.com/golang/go/issues/9510 until we move to Go 1.6
if [ "$IAMSTATIC" == "true" ] ; then
export EXTLDFLAGS_STATIC="$EXTLDFLAGS_STATIC -zmuldefs"
export LDFLAGS_STATIC_DOCKER="$LDFLAGS_STATIC -extldflags \"$EXTLDFLAGS_STATIC\""
else
export LDFLAGS="$LDFLAGS -extldflags -zmuldefs"
fi
;;
esac
fi
if [ "$IAMSTATIC" == "true" ] && [ "$(go env GOHOSTOS)" == "linux" ]; then
if [ "${GOOS}/${GOARCH}" == "darwin/amd64" ]; then
export CGO_ENABLED=1
export CC=o64-clang
export LDFLAGS='-linkmode external -s'
export LDFLAGS_STATIC_DOCKER='-extld='${CC}
else
export BUILDFLAGS=( "${BUILDFLAGS[@]/pkcs11 /}" ) # we cannot dlopen in pkcs11 in a static binary
fi
fi
echo "Building: $DEST/$BINARY_FULLNAME"
go build \
-o "$DEST/$BINARY_FULLNAME" \
"${BUILDFLAGS[@]}" \
-ldflags "
$LDFLAGS
$LDFLAGS_STATIC_DOCKER
" \
./docker
) )
echo "Created binary: $DEST/$BINARY_FULLNAME"
ln -sf "$BINARY_FULLNAME" "$DEST/docker$BINARY_EXTENSION"
copy_containerd "$DEST" "hash"
hash_files "$DEST/$BINARY_FULLNAME"

7
hack/make/binary-client Normal file
View file

@ -0,0 +1,7 @@
#!/bin/bash
set -e
BINARY_SHORT_NAME="docker"
SOURCE_PATH="./client"
source "${MAKEDIR}/.binary"

8
hack/make/binary-daemon Normal file
View file

@ -0,0 +1,8 @@
#!/bin/bash
set -e
BINARY_SHORT_NAME="dockerd"
SOURCE_PATH="./docker"
source "${MAKEDIR}/.binary"
copy_containerd "$DEST" "hash"

View file

@ -9,11 +9,12 @@ daemonSupporting=(
) )
# if we have our linux/amd64 version compiled, let's symlink it in # if we have our linux/amd64 version compiled, let's symlink it in
if [ -x "$DEST/../binary/docker-$VERSION" ]; then if [ -x "$DEST/../binary-daemon/dockerd-$VERSION" ]; then
mkdir -p "$DEST/linux/amd64" mkdir -p "$DEST/linux/amd64"
( (
cd "$DEST/linux/amd64" cd "$DEST/linux/amd64"
ln -s ../../../binary/* ./ ln -s ../../../binary-daemon/* ./
ln -s ../../../binary-client/* ./
) )
echo "Created symlinks:" "$DEST/linux/amd64/"* echo "Created symlinks:" "$DEST/linux/amd64/"*
fi fi
@ -25,16 +26,20 @@ for platform in $DOCKER_CROSSPLATFORMS; do
ABS_DEST="$(cd "$DEST" && pwd -P)" ABS_DEST="$(cd "$DEST" && pwd -P)"
export GOOS=${platform%/*} export GOOS=${platform%/*}
export GOARCH=${platform##*/} export GOARCH=${platform##*/}
if [ -z "${daemonSupporting[$platform]}" ]; then
export LDFLAGS_STATIC_DOCKER="" # we just need a simple client for these platforms
export BUILDFLAGS=( "${ORIG_BUILDFLAGS[@]/ daemon/}" ) # remove the "daemon" build tag from platforms that aren't supported
fi
# !!! TEMPORARY HACK !!! # !!! TEMPORARY HACK !!!
# See Dockerfile # See Dockerfile
if [ "$platform" == "windows/amd64" ]; then if [ "$platform" == "windows/amd64" ]; then
export GOROOT="/usr/local/go${HACK_GO_VERSION}" export GOROOT="/usr/local/go${HACK_GO_VERSION}"
export PATH=$(echo "$PATH" | sed "s,:/usr/local/go/bin:,:/usr/local/go${HACK_GO_VERSION}/bin:,") export PATH=$(echo "$PATH" | sed "s,:/usr/local/go/bin:,:/usr/local/go${HACK_GO_VERSION}/bin:,")
fi fi
source "${MAKEDIR}/binary"
if [ -z "${daemonSupporting[$platform]}" ]; then
export LDFLAGS_STATIC_DOCKER="" # we just need a simple client for these platforms
source "${MAKEDIR}/binary-client"
else
source "${MAKEDIR}/binary-client"
source "${MAKEDIR}/binary-daemon"
fi
) )
done done

View file

@ -1,10 +1,15 @@
#!/bin/bash #!/bin/bash
set -e set -e
# This script exists as backwards compatiblity for CI
( (
export IAMSTATIC="false" DEST="${DEST}-client"
export LDFLAGS_STATIC_DOCKER='' ABS_DEST="${ABS_DEST}-client"
export BUILDFLAGS=( "${BUILDFLAGS[@]/netgo /}" ) # disable netgo, since we don't need it for a dynamic binary . hack/make/dynbinary-client
export BUILDFLAGS=( "${BUILDFLAGS[@]/static_build /}" ) # we're not building a "static" binary here )
source "${MAKEDIR}/binary" (
DEST="${DEST}-daemon"
ABS_DEST="${ABS_DEST}-daemon"
. hack/make/dynbinary-daemon
) )

View file

@ -0,0 +1,12 @@
#!/bin/bash
set -e
(
export BINARY_SHORT_NAME="docker-client"
export SOURCE_PATH="./client"
export IAMSTATIC="false"
export LDFLAGS_STATIC_DOCKER=''
export BUILDFLAGS=( "${BUILDFLAGS[@]/netgo /}" ) # disable netgo, since we don't need it for a dynamic binary
export BUILDFLAGS=( "${BUILDFLAGS[@]/static_build /}" ) # we're not building a "static" binary here
source "${MAKEDIR}/.binary"
)

View file

@ -0,0 +1,12 @@
#!/bin/bash
set -e
(
export BINARY_SHORT_NAME="dockerd"
export SOURCE_PATH="./docker"
export IAMSTATIC="false"
export LDFLAGS_STATIC_DOCKER=''
export BUILDFLAGS=( "${BUILDFLAGS[@]/netgo /}" ) # disable netgo, since we don't need it for a dynamic binary
export BUILDFLAGS=( "${BUILDFLAGS[@]/static_build /}" ) # we're not building a "static" binary here
source "${MAKEDIR}/.binary"
)

View file

@ -1,10 +1,13 @@
#!/bin/bash #!/bin/bash
set -e set -e
BINARY_NAME="docker-$VERSION" BINARY_NAME="dockerd-$VERSION"
BINARY_EXTENSION="$(binary_extension)" BINARY_EXTENSION="$(binary_extension)"
BINARY_FULLNAME="$BINARY_NAME$BINARY_EXTENSION" BINARY_FULLNAME="$BINARY_NAME$BINARY_EXTENSION"
CLIENTBIN_NAME="docker-$VERSION"
CLIENTBIN_FULLNAME="$CLIENTBIN_NAME$BINARY_EXTENSION"
source "${MAKEDIR}/.go-autogen" source "${MAKEDIR}/.go-autogen"
if [[ "${BUILDFLAGS[@]}" =~ 'netgo ' ]]; then if [[ "${BUILDFLAGS[@]}" =~ 'netgo ' ]]; then
@ -24,7 +27,24 @@ go build -compiler=gccgo \
./docker ./docker
echo "Created binary: $DEST/$BINARY_FULLNAME" echo "Created binary: $DEST/$BINARY_FULLNAME"
ln -sf "$BINARY_FULLNAME" "$DEST/docker$BINARY_EXTENSION" ln -sf "$BINARY_FULLNAME" "$DEST/dockerd$BINARY_EXTENSION"
copy_containerd "$DEST" "hash" copy_containerd "$DEST" "hash"
hash_files "$DEST/$BINARY_FULLNAME" hash_files "$DEST/$BINARY_FULLNAME"
go build -compiler=gccgo \
-o "$DEST/$CLIENTBIN_FULLNAME" \
"${BUILDFLAGS[@]}" \
-gccgoflags "
-g
$EXTLDFLAGS_STATIC
-Wl,--no-export-dynamic
-ldl
-pthread
" \
./client
echo "Created binary: $DEST/$CLIENTBIN_FULLNAME"
ln -sf "$CLIENTBIN_FULLNAME" "$DEST/docker$BINARY_EXTENSION"
hash_files "$DEST/$CLIENTBIN_FULLNAME"

View file

@ -1,4 +1,4 @@
// +build daemon,!windows // +build !windows
package main package main

View file

@ -1290,6 +1290,9 @@ func appendBaseEnv(isTLS bool, env ...string) []string {
// windows: requires preserving SystemRoot, otherwise dial tcp fails // windows: requires preserving SystemRoot, otherwise dial tcp fails
// with "GetAddrInfoW: A non-recoverable error occurred during a database lookup." // with "GetAddrInfoW: A non-recoverable error occurred during a database lookup."
"SystemRoot", "SystemRoot",
// testing help text requires the $PATH to dockerd is set
"PATH",
} }
if isTLS { if isTLS {
preserveList = append(preserveList, "DOCKER_TLS_VERIFY", "DOCKER_CERT_PATH") preserveList = append(preserveList, "DOCKER_TLS_VERIFY", "DOCKER_CERT_PATH")

View file

@ -216,10 +216,10 @@ the file "./VERSION". This binary is usually installed somewhere like
### Dynamic Daemon / Client-only Binary ### Dynamic Daemon / Client-only Binary
If you are only interested in a Docker client binary, set `DOCKER_CLIENTONLY` to a non-empty value using something similar to the following: If you are only interested in a Docker client binary, you can build using:
```bash ```bash
export DOCKER_CLIENTONLY=1 ./hack/make.sh binary-client
``` ```
If you need to (due to distro policy, distro library availability, or for other If you need to (due to distro policy, distro library availability, or for other
@ -228,10 +228,10 @@ interested in creating a client binary for Docker, use something similar to the
following: following:
```bash ```bash
./hack/make.sh dynbinary ./hack/make.sh dynbinary-client
``` ```
This will create "./bundles/$VERSION/dynbinary/docker-$VERSION", which for This will create "./bundles/$VERSION/dynbinary-client/docker-$VERSION", which for
client-only builds is the important file to grab and install as appropriate. client-only builds is the important file to grab and install as appropriate.
## System Dependencies ## System Dependencies