Merge pull request #20639 from dnephin/split_client

Split the binary into two: client and daemon
This commit is contained in:
John Howard 2016-04-23 14:14:20 -07:00
commit 27f44b8af6
40 changed files with 442 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}')
# 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
DOCKER_ENVS := \
-e BUILDFLAGS \
-e KEEPBUNDLE \
-e DOCKER_BUILD_GOGC \
-e DOCKER_BUILD_PKGS \
-e DOCKER_CLIENTONLY \
-e DOCKER_DEBUG \
-e DOCKER_EXPERIMENTAL \
-e DOCKER_GITCOMMIT \

View file

@ -1,4 +1,4 @@
package main
package flags
import (
"fmt"
@ -14,26 +14,32 @@ import (
)
const (
defaultTrustKeyFile = "key.json"
defaultCaFile = "ca.pem"
defaultKeyFile = "key.pem"
defaultCertFile = "cert.pem"
tlsVerifyKey = "tlsverify"
// DefaultTrustKeyFile is the default filename for the trust key
DefaultTrustKeyFile = "key.json"
// DefaultCaFile is the default filename for the CA pem file
DefaultCaFile = "ca.pem"
// 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 (
commonFlags = &cli.CommonFlags{FlagSet: new(flag.FlagSet)}
dockerCertPath = os.Getenv("DOCKER_CERT_PATH")
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 == "" {
dockerCertPath = cliconfig.ConfigDir()
}
commonFlags.PostParse = postParseCommon
commonFlags.PostParse = func() { postParseCommon(commonFlags) }
cmd := commonFlags.FlagSet
@ -46,22 +52,24 @@ func init() {
var tlsOptions tlsconfig.Options
commonFlags.TLSOptions = &tlsOptions
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.KeyFile, []string{"-tlskey"}, filepath.Join(dockerCertPath, defaultKeyFile), "Path to TLS key file")
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.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")
return commonFlags
}
func postParseCommon() {
func postParseCommon(commonFlags *cli.CommonFlags) {
cmd := commonFlags.FlagSet
setDaemonLogLevel(commonFlags.LogLevel)
SetDaemonLogLevel(commonFlags.LogLevel)
// Regardless of whether the user sets it to true or false, if they
// 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
if cmd.IsSet("-"+tlsVerifyKey) || commonFlags.TLSVerify {
// TLSVerify can be true even if not set due to DOCKER_TLS_VERIFY env var, so we need
// to check that here as well
if cmd.IsSet("-"+TLSVerifyKey) || commonFlags.TLSVerify {
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 != "" {
lvl, err := logrus.ParseLevel(logLevel)
if err != nil {

View file

@ -4,14 +4,19 @@ import (
"path/filepath"
"github.com/docker/docker/cli"
cliflags "github.com/docker/docker/cli/flags"
"github.com/docker/docker/cliconfig"
flag "github.com/docker/docker/pkg/mflag"
"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() {
client := clientFlags.FlagSet
client.StringVar(&clientFlags.ConfigDir, []string{"-config"}, cliconfig.ConfigDir(), "Location of client config files")
@ -23,7 +28,7 @@ func init() {
}
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 {

11
client/daemon.go Normal file
View file

@ -0,0 +1,11 @@
package main
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{}
}

37
client/daemon_unix.go Normal file
View file

@ -0,0 +1,37 @@
// +build !windows
package main
import (
"os"
"os/exec"
"syscall"
)
// CmdDaemon execs dockerd with the same flags
// TODO: add a deprecation warning?
func (p DaemonProxy) CmdDaemon(args ...string) error {
// Use os.Args[1:] so that "global" args are passed to dockerd
args = stripDaemonArg(os.Args[1:])
// TODO: check dirname args[0] first
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
}

11
client/daemon_windows.go Normal file
View file

@ -0,0 +1,11 @@
package main
import (
"fmt"
)
// CmdDaemon reports on an error on windows, because there is no exec
func (p DaemonProxy) CmdDaemon(args ...string) error {
return fmt.Errorf(
"`docker daemon` does not exist on windows. Please run `dockerd` directly")
}

View file

@ -0,0 +1,18 @@
package main
import (
"strings"
"testing"
)
func TestCmdDaemon(t *testing.T) {
proxy := NewDaemonProxy()
err := proxy.CmdDaemon("--help")
if err == nil {
t.Fatal("Expected CmdDaemon to fail in Windows.")
}
if !strings.Contains(err.Error(), "Please run `dockerd`") {
t.Fatalf("Expected an error about running dockerd, got %s", err)
}
}

77
client/docker.go Normal file
View file

@ -0,0 +1,77 @@
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/term"
"github.com/docker/docker/utils"
)
func main() {
// 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
import (
@ -26,6 +24,7 @@ import (
"github.com/docker/docker/api/server/router/volume"
"github.com/docker/docker/builder/dockerfile"
"github.com/docker/docker/cli"
cliflags "github.com/docker/docker/cli/flags"
"github.com/docker/docker/cliconfig"
"github.com/docker/docker/daemon"
"github.com/docker/docker/daemon/logger"
@ -46,18 +45,14 @@ import (
)
const (
daemonUsage = " docker daemon [ --help | ... ]\n"
daemonConfigFileFlag = "-config-file"
)
var (
daemonCli cli.Handler = NewDaemonCli()
)
// DaemonCli represents the daemon CLI.
type DaemonCli struct {
*daemon.Config
flags *flag.FlagSet
commonFlags *cli.CommonFlags
configFile *string
}
func presentInHelp(usage string) string { return usage }
@ -65,8 +60,6 @@ func absentFromHelp(string) string { return "" }
// NewDaemonCli returns a pre-configured daemon CLI
func NewDaemonCli() *DaemonCli {
daemonFlags := cli.Subcmd("daemon", nil, "Enable daemon mode", true)
// TODO(tiborvass): remove InstallFlags?
daemonConfig := new(daemon.Config)
daemonConfig.LogConfig.Config = make(map[string]string)
@ -76,20 +69,21 @@ func NewDaemonCli() *DaemonCli {
daemonConfig.V2Only = true
}
daemonConfig.InstallFlags(daemonFlags, presentInHelp)
daemonConfig.InstallFlags(flag.CommandLine, absentFromHelp)
daemonFlags.Require(flag.Exact, 0)
daemonConfig.InstallFlags(flag.CommandLine, presentInHelp)
configFile := flag.CommandLine.String([]string{daemonConfigFileFlag}, defaultDaemonConfigFile, "Daemon configuration file")
flag.CommandLine.Require(flag.Exact, 0)
return &DaemonCli{
Config: daemonConfig,
flags: daemonFlags,
Config: daemonConfig,
commonFlags: cliflags.InitCommonFlags(),
configFile: configFile,
}
}
func migrateKey() (err error) {
// Migrate trust key if exists at ~/.docker/key.json and owned by current user
oldPath := filepath.Join(cliconfig.ConfigDir(), defaultTrustKeyFile)
newPath := filepath.Join(getDaemonConfDir(), defaultTrustKeyFile)
oldPath := filepath.Join(cliconfig.ConfigDir(), cliflags.DefaultTrustKeyFile)
newPath := filepath.Join(getDaemonConfDir(), cliflags.DefaultTrustKeyFile)
if _, statErr := os.Stat(newPath); os.IsNotExist(statErr) && currentUserIsOwner(oldPath) {
defer func() {
// Ensure old path is removed if no error occurred
@ -127,47 +121,17 @@ func migrateKey() (err error) {
return nil
}
func getGlobalFlag() (globalFlag *flag.Flag) {
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 {
func (cli *DaemonCli) start() {
// warn from uuid package when running the daemon
uuid.Loggerf = logrus.Warnf
if !commonFlags.FlagSet.IsEmpty() || !clientFlags.FlagSet.IsEmpty() {
// deny `docker -D daemon`
illegalFlag := getGlobalFlag()
fmt.Fprintf(os.Stderr, "invalid flag '-%s'.\nSee 'docker daemon --help'.\n", illegalFlag.Names[0])
os.Exit(1)
} else {
// allow new form `docker daemon -D`
flag.Merge(cli.flags, commonFlags.FlagSet)
flags := flag.CommandLine
cli.commonFlags.PostParse()
if cli.commonFlags.TrustKey == "" {
cli.commonFlags.TrustKey = filepath.Join(getDaemonConfDir(), cliflags.DefaultTrustKeyFile)
}
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)
cliConfig, err := loadDaemonCliConfig(cli.Config, flags, cli.commonFlags, *cli.configFile)
if err != nil {
fmt.Fprint(os.Stderr, err)
os.Exit(1)
@ -278,7 +242,7 @@ func (cli *DaemonCli) CmdDaemon(args ...string) error {
if err := migrateKey(); err != nil {
logrus.Fatal(err)
}
cli.TrustKeyPath = commonFlags.TrustKey
cli.TrustKeyPath = cli.commonFlags.TrustKey
registryService := registry.NewService(cli.Config.ServiceOptions)
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
// 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)
}
return nil
}
// 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.Hosts = commonConfig.Hosts
config.LogLevel = commonConfig.LogLevel
@ -396,9 +359,9 @@ func loadDaemonCliConfig(config *daemon.Config, daemonFlags *flag.FlagSet, commo
}
if configFile != "" {
c, err := daemon.MergeDaemonConfigurations(config, daemonFlags, configFile)
c, err := daemon.MergeDaemonConfigurations(config, flags, configFile)
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)
}
}
@ -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
// specify TLSVerify at all then we need to turn on TLS
if config.IsValueSet(tlsVerifyKey) {
if config.IsValueSet(cliflags.TLSVerifyKey) {
config.TLS = true
}
// ensure that the log level is the one set after merging configurations
setDaemonLogLevel(config.LogLevel)
cliflags.SetDaemonLogLevel(config.LogLevel)
return config, nil
}

View file

@ -1,5 +1,3 @@
// +build daemon
package main
// 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
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
import (

View file

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

View file

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

View file

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

View file

@ -5,8 +5,6 @@ import (
"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"
@ -14,36 +12,38 @@ import (
"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() {
if reexec.Init() {
return
}
// Set terminal emulation based on platform as required.
stdin, stdout, stderr := term.StdStreams()
_, stdout, stderr := term.StdStreams()
logrus.SetOutput(stderr)
flag.Merge(flag.CommandLine, clientFlags.FlagSet, commonFlags.FlagSet)
flag.Merge(flag.CommandLine, daemonCli.commonFlags.FlagSet)
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")
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.CommandLine.ShortUsage = func() {
fmt.Fprint(stderr, "\nUsage:\tdockerd [OPTIONS]\n")
}
flag.Parse()
if err := flag.CommandLine.ParseFlags(os.Args[1:], false); err != nil {
os.Exit(1)
}
if *flVersion {
showVersion()
@ -56,21 +56,7 @@ func main() {
flag.Usage()
return
}
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)
}
daemonCli.start()
}
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
# 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
DOCKER_ENVS := \
-e BUILDFLAGS \
-e DOCKER_CLIENTONLY \
-e DOCKER_GRAPHDRIVER \
-e TESTDIRS \
-e TESTFLAGS \

View file

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

View file

@ -3,7 +3,7 @@
set +xe
SCRIPT_VER="Thu Feb 25 18:54:57 UTC 2016"
# TODO to make (even) more resilient:
# TODO to make (even) more resilient:
# - Wait for daemon to be running before executing docker commands
# - Check if jq is installed
# - Make sure bash is v4.3 or later. Can't do until all Azure nodes on the latest version
@ -78,7 +78,7 @@ if [ $ec -eq 0 ]; then
ping $ip
else
echo "INFO: The Linux nodes outer daemon replied to a ping. Good!"
fi
fi
fi
# Get the version from the remote node. Note this may fail if jq is not installed.
@ -134,16 +134,16 @@ if [ $ec -eq 0 ]; then
# Force remove the image if it exists
! docker rmi -f "docker-$COMMITHASH" &>/dev/null
# This SHOULD never happen, but just in case, also blow away any containers
# that might be around.
# that might be around.
! if [ ! `docker ps -aq | wc -l` -eq 0 ]; then
echo WARN: There were some leftover containers. Cleaning them up.
! docker rm -f $(docker ps -aq)
fi
fi
# Provide the docker version for debugging purposes. If these fail, game over.
# Provide the docker version for debugging purposes. If these fail, game over.
# as the Linux box isn't responding for some reason.
if [ $ec -eq 0 ]; then
echo INFO: Docker version and info of the outer daemon on the Linux node
@ -188,7 +188,7 @@ if [ $ec -eq 0 ]; then
ec=$?
set +x
if [ 0 -ne $ec ]; then
echo "ERROR: Failed to compile and start the linux daemon"
echo "ERROR: Failed to compile and start the linux daemon"
fi
fi
@ -201,7 +201,7 @@ if [ $ec -eq 0 ]; then
export DOCKER_TEST_HOST="tcp://$ip:$port_inner"
unset DOCKER_CLIENTONLY
export DOCKER_REMOTE_DAEMON=1
hack/make.sh binary
hack/make.sh binary
ec=$?
set +x
if [ 0 -ne $ec ]; then
@ -267,7 +267,7 @@ fi
# Tell the user how we did.
if [ $ec -eq 0 ]; then
echo INFO: Completed successfully at `date`.
echo INFO: Completed successfully at `date`.
else
echo ERROR: Failed with exitcode $ec at `date`.
fi

View file

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

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
override_dh_auto_test:
./bundles/$(VERSION)/dynbinary/docker -v
./bundles/$(VERSION)/dynbinary-daemon/dockerd -v
./bundles/$(VERSION)/dynbinary-client/docker -v
override_dh_strip:
# Go has lots of problems with stripping, so just don't
override_dh_auto_install:
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-shim debian/docker-engine/usr/bin/docker-containerd-shim
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
%check
./bundles/%{_origversion}/dynbinary/docker -v
./bundles/%{_origversion}/dynbinary-client/docker -v
./bundles/%{_origversion}/dynbinary-daemon/dockerd -v
%install
# install binary
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 -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
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
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
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 docker version &> /dev/null; then
echo >&2 'skipping daemon start, since daemon appears to be already started'
@ -16,6 +23,11 @@ if [ -z "$DOCKER_TEST_HOST" ]; then
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
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
( set -x; exec \
docker daemon --debug \
dockerd --debug \
--host "$DOCKER_HOST" \
--storage-driver "$DOCKER_GRAPHDRIVER" \
--pidfile "$DEST/docker.pid" \

View file

@ -1,65 +1,14 @@
#!/bin/bash
set -e
BINARY_NAME="docker-$VERSION"
BINARY_EXTENSION="$(binary_extension)"
BINARY_FULLNAME="$BINARY_NAME$BINARY_EXTENSION"
source "${MAKEDIR}/.go-autogen"
# This script exists as backwards compatibility for CI
(
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
" \
./docker
DEST="${DEST}-client"
ABS_DEST="${ABS_DEST}-client"
. hack/make/binary-client
)
(
DEST="${DEST}-daemon"
ABS_DEST="${ABS_DEST}-daemon"
. hack/make/binary-daemon
)
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 [ -x "$DEST/../binary/docker-$VERSION" ]; then
if [ -x "$DEST/../binary-daemon/dockerd-$VERSION" ]; then
mkdir -p "$DEST/linux/amd64"
(
cd "$DEST/linux/amd64"
ln -s ../../../binary/* ./
ln -s ../../../binary-daemon/* ./
ln -s ../../../binary-client/* ./
)
echo "Created symlinks:" "$DEST/linux/amd64/"*
fi
@ -25,16 +26,20 @@ for platform in $DOCKER_CROSSPLATFORMS; do
ABS_DEST="$(cd "$DEST" && pwd -P)"
export GOOS=${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 !!!
# See Dockerfile
if [ "$platform" == "windows/amd64" ]; then
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:,")
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

View file

@ -1,10 +1,15 @@
#!/bin/bash
set -e
# This script exists as backwards compatiblity for CI
(
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"
DEST="${DEST}-client"
ABS_DEST="${ABS_DEST}-client"
. hack/make/dynbinary-client
)
(
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
set -e
BINARY_NAME="docker-$VERSION"
BINARY_NAME="dockerd-$VERSION"
BINARY_EXTENSION="$(binary_extension)"
BINARY_FULLNAME="$BINARY_NAME$BINARY_EXTENSION"
CLIENTBIN_NAME="docker-$VERSION"
CLIENTBIN_FULLNAME="$CLIENTBIN_NAME$BINARY_EXTENSION"
source "${MAKEDIR}/.go-autogen"
if [[ "${BUILDFLAGS[@]}" =~ 'netgo ' ]]; then
@ -24,7 +27,24 @@ go build -compiler=gccgo \
./docker
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"
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

View file

@ -1290,6 +1290,9 @@ func appendBaseEnv(isTLS bool, env ...string) []string {
// windows: requires preserving SystemRoot, otherwise dial tcp fails
// with "GetAddrInfoW: A non-recoverable error occurred during a database lookup."
"SystemRoot",
// testing help text requires the $PATH to dockerd is set
"PATH",
}
if isTLS {
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
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
export DOCKER_CLIENTONLY=1
./hack/make.sh binary-client
```
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:
```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.
## System Dependencies