// NewClient returns a new docker test client. func NewClient() ( cli *client.DockerCli, stdout *io.PipeReader, stdoutPipe *io.PipeWriter) { proto, addr, _ := DockerHost() stdout, stdoutPipe = io.Pipe() dockerCertPath := os.Getenv("DOCKER_CERT_PATH") // Boot2docker use TLS per default, Jenkins not if dockerCertPath != "" { var ( tlsConfig tls.Config ) tlsConfig.InsecureSkipVerify = true flCert := filepath.Join(dockerCertPath, defaultCertFile) flKey := filepath.Join(dockerCertPath, defaultKeyFile) _, errCert := os.Stat(flCert) _, errKey := os.Stat(flKey) if errCert == nil && errKey == nil { cert, err := tls.LoadX509KeyPair(flCert, flKey) if err != nil { log.Fatalf("Couldn't load X509 key pair: %s. Key encrypted?", err) } tlsConfig.Certificates = []tls.Certificate{cert} } // Avoid fallback to SSL protocols < TLS1.0 tlsConfig.MinVersion = tls.VersionTLS10 cli = client.NewDockerCli(nil, stdoutPipe, nil, nil, proto, addr, &tlsConfig) } else { cli = client.NewDockerCli(nil, stdoutPipe, nil, nil, proto, addr, nil) } return }
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(os.Stdout, "Usage: docker [OPTIONS] COMMAND [arg...]\n"+daemonUsage+" docker [ -h | --help | -v | --version ]\n\n") fmt.Fprint(os.Stdout, "A self-sufficient runtime for containers.\n\nOptions:\n") flag.CommandLine.SetOutput(os.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(os.Stdout, "%s\n", help) } flag.Parse() if *flVersion { showVersion() return } clientCli := client.NewDockerCli(stdin, stdout, stderr, clientFlags) // TODO: remove once `-d` is retired handleGlobalDaemonFlag() if *flHelp { // if global flag --help is present, regardless of what other options and commands there are, // just print the usage. flag.Usage() return } 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(os.Stderr, sterr.Status) os.Exit(1) } os.Exit(sterr.StatusCode) } fmt.Fprintln(os.Stderr, err) os.Exit(1) } }
// Ensure that CIDFile gets deleted if it's empty // Perform this test by making `docker run` fail func TestRunCidFileCleanupIfEmpty(t *testing.T) { tmpDir, err := ioutil.TempDir("", "TestRunCidFile") if err != nil { t.Fatal(err) } tmpCidFile := path.Join(tmpDir, "cid") cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) defer cleanup(globalEngine, t) c := make(chan struct{}) go func() { defer close(c) if err := cli.CmdRun("--cidfile", tmpCidFile, unitTestImageID); err == nil { t.Fatal("running without a command should haveve failed") } if _, err := os.Stat(tmpCidFile); err == nil { t.Fatalf("empty CIDFile '%s' should've been deleted", tmpCidFile) } }() defer os.RemoveAll(tmpDir) setTimeout(t, "CmdRun timed out", 5*time.Second, func() { <-c }) }
func BuildImage(dockerfile string, name string) (string, error) { cli := dockerCli.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, nil, "unix", "/var/run/docker.sock", nil) err := cli.CmdBuild("-t", name, strings.TrimSuffix(dockerfile, "Dockerfile")) if err != nil { return "", err } return GetImageId(name, "") }
// TestHttpsInfo connects via two-way authenticated HTTPS to the info endpoint func TestHttpsInfo(t *testing.T) { cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonHttpsAddr, getTlsConfig("client-cert.pem", "client-key.pem", t)) setTimeout(t, "Reading command output time out", 10*time.Second, func() { if err := cli.CmdInfo(); err != nil { t.Fatal(err) } }) }
// NewCobraAdaptor returns a new handler func NewCobraAdaptor(clientFlags *cliflags.ClientFlags) CobraAdaptor { stdin, stdout, stderr := term.StdStreams() dockerCli := client.NewDockerCli(stdin, stdout, stderr, clientFlags) var rootCmd = &cobra.Command{ Use: "docker", SilenceUsage: true, SilenceErrors: true, } rootCmd.SetUsageTemplate(usageTemplate) rootCmd.SetHelpTemplate(helpTemplate) rootCmd.SetFlagErrorFunc(cli.FlagErrorFunc) rootCmd.SetOutput(stdout) rootCmd.AddCommand( container.NewAttachCommand(dockerCli), container.NewCreateCommand(dockerCli), container.NewDiffCommand(dockerCli), container.NewExportCommand(dockerCli), container.NewKillCommand(dockerCli), container.NewLogsCommand(dockerCli), container.NewPauseCommand(dockerCli), container.NewPortCommand(dockerCli), container.NewRenameCommand(dockerCli), container.NewRestartCommand(dockerCli), container.NewRmCommand(dockerCli), container.NewRunCommand(dockerCli), container.NewStartCommand(dockerCli), container.NewStatsCommand(dockerCli), container.NewStopCommand(dockerCli), container.NewTopCommand(dockerCli), container.NewUnpauseCommand(dockerCli), container.NewWaitCommand(dockerCli), image.NewBuildCommand(dockerCli), image.NewHistoryCommand(dockerCli), image.NewImagesCommand(dockerCli), image.NewLoadCommand(dockerCli), image.NewRemoveCommand(dockerCli), image.NewSaveCommand(dockerCli), image.NewSearchCommand(dockerCli), image.NewImportCommand(dockerCli), image.NewTagCommand(dockerCli), network.NewNetworkCommand(dockerCli), system.NewEventsCommand(dockerCli), system.NewVersionCommand(dockerCli), volume.NewVolumeCommand(dockerCli), ) rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage") rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help") return CobraAdaptor{ rootCmd: rootCmd, dockerCli: dockerCli, } }
func newDockerClient() *client.DockerCli { // Set terminal emulation based on platform as required. stdin, stdout, stderr := term.StdStreams() setDefaultConfFlag(flTrustKey, defaultTrustKeyFile) if len(flHosts) > 1 { log.Fatal("Please specify only one -H") } protoAddrParts := strings.SplitN(flHosts[0], "://", 2) var ( cli *client.DockerCli tlsConfig tls.Config ) tlsConfig.InsecureSkipVerify = true // 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 flag.IsSet("-tlsverify") { *flTls = true } // If we should verify the server, we need to load a trusted ca if *flTlsVerify { certPool := x509.NewCertPool() file, err := ioutil.ReadFile(*flCa) if err != nil { log.Fatalf("Couldn't read ca cert %s: %s", *flCa, err) } certPool.AppendCertsFromPEM(file) tlsConfig.RootCAs = certPool tlsConfig.InsecureSkipVerify = false } // If tls is enabled, try to load and send client certificates if *flTls || *flTlsVerify { _, errCert := os.Stat(*flCert) _, errKey := os.Stat(*flKey) if errCert == nil && errKey == nil { *flTls = true cert, err := tls.LoadX509KeyPair(*flCert, *flKey) if err != nil { log.Fatalf("Couldn't load X509 key pair: %q. Make sure the key is encrypted", err) } tlsConfig.Certificates = []tls.Certificate{cert} } // Avoid fallback to SSL protocols < TLS1.0 tlsConfig.MinVersion = tls.VersionTLS10 } cli = client.NewDockerCli(stdin, stdout, stderr, *flTrustKey, protoAddrParts[0], protoAddrParts[1], &tlsConfig) return cli }
// TestRunDetach checks attaching and detaching with the escape sequence. func TestRunDetach(t *testing.T) { stdout, stdoutPipe := io.Pipe() cpty, tty, err := pty.Open() if err != nil { t.Fatal(err) } key, err := libtrust.GenerateECP256PrivateKey() if err != nil { t.Fatal(err) } cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil) defer cleanup(globalEngine, t) ch := make(chan struct{}) go func() { defer close(ch) cli.CmdRun("-i", "-t", unitTestImageID, "cat") }() container := waitContainerStart(t, 10*time.Second) state := setRaw(t, container) defer unsetRaw(t, container, state) setTimeout(t, "First read/write assertion timed out", 2*time.Second, func() { if err := assertPipe("hello\n", "hello", stdout, cpty, 150); err != nil { t.Fatal(err) } }) setTimeout(t, "Escape sequence timeout", 5*time.Second, func() { cpty.Write([]byte{16}) time.Sleep(100 * time.Millisecond) cpty.Write([]byte{17}) }) // wait for CmdRun to return setTimeout(t, "Waiting for CmdRun timed out", 15*time.Second, func() { <-ch }) closeWrap(cpty, stdout, stdoutPipe) time.Sleep(500 * time.Millisecond) if !container.IsRunning() { t.Fatal("The detached container should be still running") } setTimeout(t, "Waiting for container to die timed out", 20*time.Second, func() { container.Kill() }) }
// Expected behaviour: the process stay alive when the client disconnects // but the client detaches. func TestRunDisconnectTty(t *testing.T) { stdin, stdinPipe := io.Pipe() stdout, stdoutPipe := io.Pipe() key, err := libtrust.GenerateECP256PrivateKey() if err != nil { t.Fatal(err) } cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil) defer cleanup(globalEngine, t) c1 := make(chan struct{}) go func() { defer close(c1) // We're simulating a disconnect so the return value doesn't matter. What matters is the // fact that CmdRun returns. if err := cli.CmdRun("-i", "-t", unitTestImageID, "/bin/cat"); err != nil { log.Debugf("Error CmdRun: %s", err) } }() container := waitContainerStart(t, 10*time.Second) state := setRaw(t, container) defer unsetRaw(t, container, state) // Client disconnect after run -i should keep stdin out in TTY mode setTimeout(t, "Read/Write assertion timed out", 2*time.Second, func() { if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 150); err != nil { t.Fatal(err) } }) // Close pipes (simulate disconnect) if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil { t.Fatal(err) } // wait for CmdRun to return setTimeout(t, "Waiting for CmdRun timed out", 5*time.Second, func() { <-c1 }) // In tty mode, we expect the process to stay alive even after client's stdin closes. // Give some time to monitor to do his thing container.WaitStop(500 * time.Millisecond) if !container.IsRunning() { t.Fatalf("/bin/cat should still be running after closing stdin (tty mode)") } }
func TestRunExit(t *testing.T) { stdin, stdinPipe := io.Pipe() stdout, stdoutPipe := io.Pipe() cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) defer cleanup(globalEngine, t) c1 := make(chan struct{}) go func() { cli.CmdRun("-i", unitTestImageID, "/bin/cat") close(c1) }() setTimeout(t, "Read/Write assertion timed out", 2*time.Second, func() { if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 150); err != nil { t.Fatal(err) } }) container := globalDaemon.List()[0] // Closing /bin/cat stdin, expect it to exit if err := stdin.Close(); err != nil { t.Fatal(err) } // as the process exited, CmdRun must finish and unblock. Wait for it setTimeout(t, "Waiting for CmdRun timed out", 10*time.Second, func() { <-c1 go func() { cli.CmdWait(container.ID) }() if _, err := bufio.NewReader(stdout).ReadString('\n'); err != nil { t.Fatal(err) } }) // Make sure that the client has been disconnected setTimeout(t, "The client should have been disconnected once the remote process exited.", 2*time.Second, func() { // Expecting pipe i/o error, just check that read does not block stdin.Read([]byte{}) }) // Cleanup pipes if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil { t.Fatal(err) } }
// TestHttpsInfoRogueCert connects via two-way authenticated HTTPS to the info endpoint // by using a rogue client certificate and checks that it fails with the expected error. func TestHttpsInfoRogueCert(t *testing.T) { cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonHttpsAddr, getTlsConfig("client-rogue-cert.pem", "client-rogue-key.pem", t)) setTimeout(t, "Reading command output time out", 10*time.Second, func() { err := cli.CmdInfo() if err == nil { t.Fatal("Expected error but got nil") } if !strings.Contains(err.Error(), errBadCertificate) { t.Fatalf("Expected error: %s, got instead: %s", errBadCertificate, err) } }) }
// #2098 - Docker cidFiles only contain short version of the containerId //sudo docker run --cidfile /tmp/docker_test.cid ubuntu echo "test" // TestRunCidFile tests that run --cidfile returns the longid func TestRunCidFileCheckIDLength(t *testing.T) { stdout, stdoutPipe := io.Pipe() tmpDir, err := ioutil.TempDir("", "TestRunCidFile") if err != nil { t.Fatal(err) } tmpCidFile := path.Join(tmpDir, "cid") cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) defer cleanup(globalEngine, t) c := make(chan struct{}) go func() { defer close(c) if err := cli.CmdRun("--cidfile", tmpCidFile, unitTestImageID, "ls"); err != nil { t.Fatal(err) } }() defer os.RemoveAll(tmpDir) setTimeout(t, "Reading command output time out", 2*time.Second, func() { cmdOutput, err := bufio.NewReader(stdout).ReadString('\n') if err != nil { t.Fatal(err) } if len(cmdOutput) < 1 { t.Fatalf("'ls' should return something , not '%s'", cmdOutput) } //read the tmpCidFile buffer, err := ioutil.ReadFile(tmpCidFile) if err != nil { t.Fatal(err) } id := string(buffer) if len(id) != len("2bf44ea18873287bd9ace8a4cb536a7cbe134bed67e805fdf2f58a57f69b320c") { t.Fatalf("--cidfile should be a long id, not '%s'", id) } //test that its a valid cid? (though the container is gone..) //remove the file and dir. }) setTimeout(t, "CmdRun timed out", 5*time.Second, func() { <-c }) }
// Expected behaviour: the process dies when the client disconnects func TestRunDisconnect(t *testing.T) { stdin, stdinPipe := io.Pipe() stdout, stdoutPipe := io.Pipe() key, err := libtrust.GenerateECP256PrivateKey() if err != nil { t.Fatal(err) } cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil) defer cleanup(globalEngine, t) c1 := make(chan struct{}) go func() { // We're simulating a disconnect so the return value doesn't matter. What matters is the // fact that CmdRun returns. cli.CmdRun("-i", unitTestImageID, "/bin/cat") close(c1) }() setTimeout(t, "Read/Write assertion timed out", 2*time.Second, func() { if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 150); err != nil { t.Fatal(err) } }) // Close pipes (simulate disconnect) if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil { t.Fatal(err) } // as the pipes are close, we expect the process to die, // therefore CmdRun to unblock. Wait for CmdRun setTimeout(t, "Waiting for CmdRun timed out", 2*time.Second, func() { <-c1 }) // Client disconnect after run -i should cause stdin to be closed, which should // cause /bin/cat to exit. setTimeout(t, "Waiting for /bin/cat to exit timed out", 2*time.Second, func() { container := globalDaemon.List()[0] container.WaitStop(-1 * time.Second) if container.IsRunning() { t.Fatalf("/bin/cat is still running after closing stdin") } }) }
// TestRunWorkdirExistsAndIsFile checks that if 'docker run -w' with existing file can be detected func TestRunWorkdirExistsAndIsFile(t *testing.T) { cli := client.NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) defer cleanup(globalEngine, t) c := make(chan struct{}) go func() { defer close(c) if err := cli.CmdRun("-w", "/bin/cat", unitTestImageID, "pwd"); err == nil { t.Fatal("should have failed to run when using /bin/cat as working dir.") } }() setTimeout(t, "CmdRun timed out", 5*time.Second, func() { <-c }) }
func (s *BPacker) Build(endpoint string, certpath string, imagename string) { cert := fmt.Sprintf(certFileFormat, certpath) key := fmt.Sprintf(keyFileFormat, certpath) ca := fmt.Sprintf(caFileFormat, certpath) client, err := docker.NewTLSClient(endpoint, cert, key, ca) outputbuf, errbuf := bytes.NewBuffer(nil), bytes.NewBuffer(nil) dockerfileString := s.CreateDockerFile() fmt.Println(dockerfileString) ioutil.WriteFile("./Dockerfile", []byte(dockerfileString), os.ModePerm) defer os.Remove("Dockerfile") reader := strings.NewReader("") inputbuf := ioutil.NopCloser(reader) endpoint = strings.TrimPrefix(endpoint, fmt.Sprintf("%s://", DefaultProto)) dcli := dkr.NewDockerCli(inputbuf, outputbuf, errbuf, key, DefaultProto, endpoint, client.TLSConfig) err = dcli.CmdBuild("--force-rm=true", "--rm=true", fmt.Sprintf("--tag=\"%s\"", imagename), "./") fmt.Println(err) fmt.Println(outputbuf) }
// Expected behaviour: error out when attempting to bind mount non-existing source paths func TestRunErrorBindNonExistingSource(t *testing.T) { cli := client.NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) defer cleanup(globalEngine, t) c := make(chan struct{}) go func() { defer close(c) // This check is made at runtime, can't be "unit tested" if err := cli.CmdRun("-v", "/i/dont/exist:/tmp", unitTestImageID, "echo 'should fail'"); err == nil { t.Fatal("should have failed to run when using /i/dont/exist as a source for the bind mount") } }() setTimeout(t, "CmdRun timed out", 5*time.Second, func() { <-c }) }
func generateManPages(path string) error { header := &doc.GenManHeader{ Title: "DOCKER", Section: "1", Source: "Docker Community", } stdin, stdout, stderr := term.StdStreams() dockerCli := client.NewDockerCli(stdin, stdout, stderr) cmd := &cobra.Command{Use: "docker"} command.AddCommands(cmd, dockerCli) cmd.DisableAutoGenTag = true return doc.GenManTreeFromOpts(cmd, doc.GenManTreeOptions{ Header: header, Path: path, CommandSeparator: "-", }) }
// TestHttpsInfoRogueServerCert connects via two-way authenticated HTTPS to the info endpoint // which provides a rogue server certificate and checks that it fails with the expected error func TestHttpsInfoRogueServerCert(t *testing.T) { key, err := libtrust.GenerateECP256PrivateKey() if err != nil { t.Fatal(err) } cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, key, testDaemonProto, testDaemonRogueHttpsAddr, getTlsConfig("client-cert.pem", "client-key.pem", t)) setTimeout(t, "Reading command output time out", 10*time.Second, func() { err := cli.CmdInfo() if err == nil { t.Fatal("Expected error but got nil") } if !strings.Contains(err.Error(), errCaUnknown) { t.Fatalf("Expected error: %s, got instead: %s", errBadCertificate, err) } }) }
// Expected behaviour: container gets deleted automatically after exit func TestRunAutoRemove(t *testing.T) { t.Skip("Fixme. Skipping test for now, race condition") stdout, stdoutPipe := io.Pipe() key, err := libtrust.GenerateECP256PrivateKey() if err != nil { t.Fatal(err) } cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil) defer cleanup(globalEngine, t) c := make(chan struct{}) go func() { defer close(c) if err := cli.CmdRun("--rm", unitTestImageID, "hostname"); err != nil { t.Fatal(err) } }() var temporaryContainerID string setTimeout(t, "Reading command output time out", 2*time.Second, func() { cmdOutput, err := bufio.NewReader(stdout).ReadString('\n') if err != nil { t.Fatal(err) } temporaryContainerID = cmdOutput if err := closeWrap(stdout, stdoutPipe); err != nil { t.Fatal(err) } }) setTimeout(t, "CmdRun timed out", 10*time.Second, func() { <-c }) time.Sleep(500 * time.Millisecond) if len(globalDaemon.List()) > 0 { t.Fatalf("failed to remove container automatically: container %s still exists", temporaryContainerID) } }
func main() { // Set terminal emulation based on platform as required. stdin, stdout, stderr := term.StdStreams() logrus.SetOutput(stderr) dockerCli := client.NewDockerCli(stdin, stdout, stderr) cmd := newDockerCommand(dockerCli) if err := cmd.Execute(); err != nil { if sterr, ok := err.(cli.StatusError); ok { if sterr.Status != "" { fmt.Fprintln(stderr, sterr.Status) } // StatusError should only be used for errors, and all errors should // have a non-zero exit status, so never exit with 0 if sterr.StatusCode == 0 { os.Exit(1) } os.Exit(sterr.StatusCode) } fmt.Fprintln(stderr, err) os.Exit(1) } }
// TestAttachDetach checks that attach in tty mode can be detached using the long container ID func TestAttachDetach(t *testing.T) { stdout, stdoutPipe := io.Pipe() cpty, tty, err := pty.Open() if err != nil { t.Fatal(err) } cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil) defer cleanup(globalEngine, t) ch := make(chan struct{}) go func() { defer close(ch) if err := cli.CmdRun("-i", "-t", "-d", unitTestImageID, "cat"); err != nil { t.Fatal(err) } }() container := waitContainerStart(t, 10*time.Second) setTimeout(t, "Reading container's id timed out", 10*time.Second, func() { buf := make([]byte, 1024) n, err := stdout.Read(buf) if err != nil { t.Fatal(err) } if strings.Trim(string(buf[:n]), " \r\n") != container.ID { t.Fatalf("Wrong ID received. Expect %s, received %s", container.ID, buf[:n]) } }) setTimeout(t, "Starting container timed out", 10*time.Second, func() { <-ch }) state := setRaw(t, container) defer unsetRaw(t, container, state) stdout, stdoutPipe = io.Pipe() cpty, tty, err = pty.Open() if err != nil { t.Fatal(err) } cli = client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil) ch = make(chan struct{}) go func() { defer close(ch) if err := cli.CmdAttach(container.ID); err != nil { if err != io.ErrClosedPipe { t.Fatal(err) } } }() setTimeout(t, "First read/write assertion timed out", 2*time.Second, func() { if err := assertPipe("hello\n", "hello", stdout, cpty, 150); err != nil { if err != io.ErrClosedPipe { t.Fatal(err) } } }) setTimeout(t, "Escape sequence timeout", 5*time.Second, func() { cpty.Write([]byte{16}) time.Sleep(100 * time.Millisecond) cpty.Write([]byte{17}) }) // wait for CmdRun to return setTimeout(t, "Waiting for CmdAttach timed out", 15*time.Second, func() { <-ch }) closeWrap(cpty, stdout, stdoutPipe) time.Sleep(500 * time.Millisecond) if !container.IsRunning() { t.Fatal("The detached container should be still running") } setTimeout(t, "Waiting for container to die timedout", 5*time.Second, func() { container.Kill() }) }
func main() { if len(dockerConfDir) == 0 { dockerConfDir = filepath.Join(os.Getenv("HOME"), ".docker") } if selfPath := utils.SelfPath(); strings.Contains(selfPath, ".dockerinit") { // Running in init mode sysinit.SysInit() return } var ( flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit") flDaemon = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode") flGraphOpts opts.ListOpts flDebug = flag.Bool([]string{"D", "-debug"}, false, "Enable debug mode") flAutoRestart = flag.Bool([]string{"r", "-restart"}, true, "Restart previously running containers") bridgeName = flag.String([]string{"b", "-bridge"}, "", "Attach containers to a pre-existing network bridge\nuse 'none' to disable container networking") bridgeIp = flag.String([]string{"#bip", "-bip"}, "", "Use this CIDR notation address for the network bridge's IP, not compatible with -b") pidfile = flag.String([]string{"p", "-pidfile"}, "/var/run/docker.pid", "Path to use for daemon PID file") flRoot = flag.String([]string{"g", "-graph"}, "/var/lib/docker", "Path to use as the root of the Docker runtime") flSocketGroup = flag.String([]string{"G", "-group"}, "docker", "Group to assign the unix socket specified by -H when running in daemon mode\nuse '' (the empty string) to disable setting of a group") flEnableCors = flag.Bool([]string{"#api-enable-cors", "-api-enable-cors"}, false, "Enable CORS headers in the remote API") flDns = opts.NewListOpts(opts.ValidateIPAddress) flDnsSearch = opts.NewListOpts(opts.ValidateDnsSearch) flEnableIptables = flag.Bool([]string{"#iptables", "-iptables"}, true, "Enable Docker's addition of iptables rules") flEnableIpForward = flag.Bool([]string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward") flDefaultIp = flag.String([]string{"#ip", "-ip"}, "0.0.0.0", "Default IP address to use when binding container ports") flInterContainerComm = flag.Bool([]string{"#icc", "-icc"}, true, "Enable inter-container communication") flGraphDriver = flag.String([]string{"s", "-storage-driver"}, "", "Force the Docker runtime to use a specific storage driver") flExecDriver = flag.String([]string{"e", "-exec-driver"}, "native", "Force the Docker runtime to use a specific exec driver") flHosts = opts.NewListOpts(api.ValidateHost) flMtu = flag.Int([]string{"#mtu", "-mtu"}, 0, "Set the containers network MTU\nif no value is provided: default to the default route MTU or 1500 if no default route is available") flTls = flag.Bool([]string{"-tls"}, false, "Use TLS; implied by tls-verify flags") flTlsVerify = flag.Bool([]string{"-tlsverify"}, false, "Use TLS and verify the remote (daemon: verify client, client: verify daemon)") flCa = flag.String([]string{"-tlscacert"}, filepath.Join(dockerConfDir, defaultCaFile), "Trust only remotes providing a certificate signed by the CA given here") flCert = flag.String([]string{"-tlscert"}, filepath.Join(dockerConfDir, defaultCertFile), "Path to TLS certificate file") flKey = flag.String([]string{"-tlskey"}, filepath.Join(dockerConfDir, defaultKeyFile), "Path to TLS key file") flSelinuxEnabled = flag.Bool([]string{"-selinux-enabled"}, false, "Enable selinux support. SELinux does not presently support the BTRFS storage driver") ) flag.Var(&flDns, []string{"#dns", "-dns"}, "Force Docker to use specific DNS servers") flag.Var(&flDnsSearch, []string{"-dns-search"}, "Force Docker to use specific DNS search domains") flag.Var(&flHosts, []string{"H", "-host"}, "The socket(s) to bind to in daemon mode\nspecified using one or more tcp://host:port, unix:///path/to/socket, fd://* or fd://socketfd.") flag.Var(&flGraphOpts, []string{"-storage-opt"}, "Set storage driver options") flag.Parse() if *flVersion { showVersion() return } if flHosts.Len() == 0 { defaultHost := os.Getenv("DOCKER_HOST") if defaultHost == "" || *flDaemon { // If we do not have a host, default to unix socket defaultHost = fmt.Sprintf("unix://%s", api.DEFAULTUNIXSOCKET) } if _, err := api.ValidateHost(defaultHost); err != nil { log.Fatal(err) } flHosts.Set(defaultHost) } if *bridgeName != "" && *bridgeIp != "" { log.Fatal("You specified -b & --bip, mutually exclusive options. Please specify only one.") } if !*flEnableIptables && !*flInterContainerComm { log.Fatal("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.") } if net.ParseIP(*flDefaultIp) == nil { log.Fatalf("Specified --ip=%s is not in correct format \"0.0.0.0\".", *flDefaultIp) } if *flDebug { os.Setenv("DEBUG", "1") } if *flDaemon { if runtime.GOOS != "linux" { log.Fatalf("The Docker daemon is only supported on linux") } if os.Geteuid() != 0 { log.Fatalf("The Docker daemon needs to be run as root") } if flag.NArg() != 0 { flag.Usage() return } // set up the TempDir to use a canonical path tmp := os.TempDir() realTmp, err := utils.ReadSymlinkedDirectory(tmp) if err != nil { log.Fatalf("Unable to get the full path to the TempDir (%s): %s", tmp, err) } os.Setenv("TMPDIR", realTmp) // get the canonical path to the Docker root directory root := *flRoot var realRoot string if _, err := os.Stat(root); err != nil && os.IsNotExist(err) { realRoot = root } else { realRoot, err = utils.ReadSymlinkedDirectory(root) if err != nil { log.Fatalf("Unable to get the full path to root (%s): %s", root, err) } } if err := checkKernelAndArch(); err != nil { log.Fatal(err) } eng := engine.New() // Load builtins if err := builtins.Register(eng); err != nil { log.Fatal(err) } // handle the pidfile early. https://github.com/docker/docker/issues/6973 if len(*pidfile) > 0 { job := eng.Job("initserverpidfile", *pidfile) if err := job.Run(); err != nil { log.Fatal(err) } } // load the daemon in the background so we can immediately start // the http api so that connections don't fail while the daemon // is booting go func() { // Load plugin: httpapi job := eng.Job("initserver") // include the variable here too, for the server config job.Setenv("Pidfile", *pidfile) job.Setenv("Root", realRoot) job.SetenvBool("AutoRestart", *flAutoRestart) job.SetenvList("Dns", flDns.GetAll()) job.SetenvList("DnsSearch", flDnsSearch.GetAll()) job.SetenvBool("EnableIptables", *flEnableIptables) job.SetenvBool("EnableIpForward", *flEnableIpForward) job.Setenv("BridgeIface", *bridgeName) job.Setenv("BridgeIP", *bridgeIp) job.Setenv("DefaultIp", *flDefaultIp) job.SetenvBool("InterContainerCommunication", *flInterContainerComm) job.Setenv("GraphDriver", *flGraphDriver) job.SetenvList("GraphOptions", flGraphOpts.GetAll()) job.Setenv("ExecDriver", *flExecDriver) job.SetenvInt("Mtu", *flMtu) job.SetenvBool("EnableSelinuxSupport", *flSelinuxEnabled) job.SetenvList("Sockets", flHosts.GetAll()) if err := job.Run(); err != nil { log.Fatal(err) } // after the daemon is done setting up we can tell the api to start // accepting connections if err := eng.Job("acceptconnections").Run(); err != nil { log.Fatal(err) } }() // TODO actually have a resolved graphdriver to show? log.Printf("docker daemon: %s %s; execdriver: %s; graphdriver: %s", dockerversion.VERSION, dockerversion.GITCOMMIT, *flExecDriver, *flGraphDriver) // Serve api job := eng.Job("serveapi", flHosts.GetAll()...) job.SetenvBool("Logging", true) job.SetenvBool("EnableCors", *flEnableCors) job.Setenv("Version", dockerversion.VERSION) job.Setenv("SocketGroup", *flSocketGroup) job.SetenvBool("Tls", *flTls) job.SetenvBool("TlsVerify", *flTlsVerify) job.Setenv("TlsCa", *flCa) job.Setenv("TlsCert", *flCert) job.Setenv("TlsKey", *flKey) job.SetenvBool("BufferRequests", true) if err := job.Run(); err != nil { log.Fatal(err) } } else { if flHosts.Len() > 1 { log.Fatal("Please specify only one -H") } protoAddrParts := strings.SplitN(flHosts.GetAll()[0], "://", 2) var ( cli *client.DockerCli tlsConfig tls.Config ) tlsConfig.InsecureSkipVerify = true // If we should verify the server, we need to load a trusted ca if *flTlsVerify { *flTls = true certPool := x509.NewCertPool() file, err := ioutil.ReadFile(*flCa) if err != nil { log.Fatalf("Couldn't read ca cert %s: %s", *flCa, err) } certPool.AppendCertsFromPEM(file) tlsConfig.RootCAs = certPool tlsConfig.InsecureSkipVerify = false } // If tls is enabled, try to load and send client certificates if *flTls || *flTlsVerify { _, errCert := os.Stat(*flCert) _, errKey := os.Stat(*flKey) if errCert == nil && errKey == nil { *flTls = true cert, err := tls.LoadX509KeyPair(*flCert, *flKey) if err != nil { log.Fatalf("Couldn't load X509 key pair: %s. Key encrypted?", err) } tlsConfig.Certificates = []tls.Certificate{cert} } } if *flTls || *flTlsVerify { cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, protoAddrParts[0], protoAddrParts[1], &tlsConfig) } else { cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, protoAddrParts[0], protoAddrParts[1], nil) } if err := cli.ParseCommands(flag.Args()...); err != nil { if sterr, ok := err.(*utils.StatusError); ok { if sterr.Status != "" { log.Println(sterr.Status) } os.Exit(sterr.StatusCode) } log.Fatal(err) } } }
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) cobraAdaptor := cobraadaptor.NewCobraAdaptor(clientFlags) 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" dockerCommands := append(cli.DockerCommandUsage, cobraAdaptor.Usage()...) for _, cmd := range sortCommands(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(), cobraAdaptor) if err := c.Run(flag.Args()...); err != nil { if sterr, ok := err.(cli.StatusError); ok { if sterr.Status != "" { fmt.Fprintln(stderr, sterr.Status) } // StatusError should only be used for errors, and all errors should // have a non-zero exit status, so never exit with 0 if sterr.StatusCode == 0 { os.Exit(1) } os.Exit(sterr.StatusCode) } fmt.Fprintln(stderr, err) os.Exit(1) } }
func main() { if reexec.Init() { return } // Set terminal emulation based on platform as required. stdin, stdout, stderr := term.StdStreams() initLogging(stderr) flag.Parse() // FIXME: validate daemon flags here if *flVersion { showVersion() return } if *flLogLevel != "" { lvl, err := logrus.ParseLevel(*flLogLevel) if err != nil { fmt.Fprintf(os.Stderr, "Unable to parse logging level: %s\n", *flLogLevel) os.Exit(1) } setLogLevel(lvl) } else { setLogLevel(logrus.InfoLevel) } if *flDebug { os.Setenv("DEBUG", "1") setLogLevel(logrus.DebugLevel) } if len(flHosts) == 0 { defaultHost := os.Getenv("DOCKER_HOST") if defaultHost == "" || *flDaemon { if runtime.GOOS != "windows" { // If we do not have a host, default to unix socket defaultHost = fmt.Sprintf("unix://%s", opts.DefaultUnixSocket) } else { // If we do not have a host, default to TCP socket on Windows defaultHost = fmt.Sprintf("tcp://%s:%d", opts.DefaultHTTPHost, opts.DefaultHTTPPort) } } defaultHost, err := opts.ValidateHost(defaultHost) if err != nil { if *flDaemon { logrus.Fatal(err) } else { fmt.Fprint(os.Stderr, err) } os.Exit(1) } flHosts = append(flHosts, defaultHost) } setDefaultConfFlag(flTrustKey, defaultTrustKeyFile) if *flDaemon { if *flHelp { flag.Usage() return } mainDaemon() return } if len(flHosts) > 1 { fmt.Fprintf(os.Stderr, "Please specify only one -H") os.Exit(0) } protoAddrParts := strings.SplitN(flHosts[0], "://", 2) var ( cli *client.DockerCli tlsConfig tls.Config ) tlsConfig.InsecureSkipVerify = true // 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 flag.IsSet("-tlsverify") { *flTls = true } // If we should verify the server, we need to load a trusted ca if *flTlsVerify { certPool := x509.NewCertPool() file, err := ioutil.ReadFile(*flCa) if err != nil { fmt.Fprintf(os.Stderr, "Couldn't read ca cert %s: %s\n", *flCa, err) os.Exit(1) } certPool.AppendCertsFromPEM(file) tlsConfig.RootCAs = certPool tlsConfig.InsecureSkipVerify = false } // If tls is enabled, try to load and send client certificates if *flTls || *flTlsVerify { _, errCert := os.Stat(*flCert) _, errKey := os.Stat(*flKey) if errCert == nil && errKey == nil { *flTls = true cert, err := tls.LoadX509KeyPair(*flCert, *flKey) if err != nil { fmt.Fprintf(os.Stderr, "Couldn't load X509 key pair: %q. Make sure the key is encrypted\n", err) os.Exit(1) } tlsConfig.Certificates = []tls.Certificate{cert} } // Avoid fallback to SSL protocols < TLS1.0 tlsConfig.MinVersion = tls.VersionTLS10 } if *flTls || *flTlsVerify { cli = client.NewDockerCli(stdin, stdout, stderr, *flTrustKey, protoAddrParts[0], protoAddrParts[1], &tlsConfig) } else { cli = client.NewDockerCli(stdin, stdout, stderr, *flTrustKey, protoAddrParts[0], protoAddrParts[1], nil) } if err := cli.Cmd(flag.Args()...); err != nil { if sterr, ok := err.(client.StatusError); ok { if sterr.Status != "" { fmt.Fprintln(cli.Err(), sterr.Status) os.Exit(1) } os.Exit(sterr.StatusCode) } fmt.Fprintln(cli.Err(), err) os.Exit(1) } }
func main() { if reexec.Init() { return } flag.Parse() // FIXME: validate daemon flags here if *flVersion { showVersion() return } if *flLogLevel != "" { lvl, err := log.ParseLevel(*flLogLevel) if err != nil { log.Fatalf("Unable to parse logging level: %s", *flLogLevel) } initLogging(lvl) } else { initLogging(log.InfoLevel) } // -D, --debug, -l/--log-level=debug processing // When/if -D is removed this block can be deleted if *flDebug { os.Setenv("DEBUG", "1") initLogging(log.DebugLevel) } if len(flHosts) == 0 { defaultHost := os.Getenv("DOCKER_HOST") if defaultHost == "" || *flDaemon { // If we do not have a host, default to unix socket defaultHost = fmt.Sprintf("unix://%s", api.DEFAULTUNIXSOCKET) } defaultHost, err := api.ValidateHost(defaultHost) if err != nil { log.Fatal(err) } flHosts = append(flHosts, defaultHost) } setDefaultConfFlag(flTrustKey, defaultTrustKeyFile) if *flDaemon { mainDaemon() return } if len(flHosts) > 1 { log.Fatal("Please specify only one -H") } protoAddrParts := strings.SplitN(flHosts[0], "://", 2) var ( cli *client.DockerCli tlsConfig tls.Config ) tlsConfig.InsecureSkipVerify = true // 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 flag.IsSet("-tlsverify") { *flTls = true } // If we should verify the server, we need to load a trusted ca if *flTlsVerify { certPool := x509.NewCertPool() file, err := ioutil.ReadFile(*flCa) if err != nil { log.Fatalf("Couldn't read ca cert %s: %s", *flCa, err) } certPool.AppendCertsFromPEM(file) tlsConfig.RootCAs = certPool tlsConfig.InsecureSkipVerify = false } // If tls is enabled, try to load and send client certificates if *flTls || *flTlsVerify { _, errCert := os.Stat(*flCert) _, errKey := os.Stat(*flKey) if errCert == nil && errKey == nil { *flTls = true cert, err := tls.LoadX509KeyPair(*flCert, *flKey) if err != nil { log.Fatalf("Couldn't load X509 key pair: %s. Key encrypted?", err) } tlsConfig.Certificates = []tls.Certificate{cert} } // Avoid fallback to SSL protocols < TLS1.0 tlsConfig.MinVersion = tls.VersionTLS10 } if *flTls || *flTlsVerify { cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, *flTrustKey, protoAddrParts[0], protoAddrParts[1], &tlsConfig) } else { cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, *flTrustKey, protoAddrParts[0], protoAddrParts[1], nil) } if err := cli.Cmd(flag.Args()...); err != nil { if sterr, ok := err.(*utils.StatusError); ok { if sterr.Status != "" { log.Println(sterr.Status) } os.Exit(sterr.StatusCode) } log.Fatal(err) } }
func main() { if reexec.Init() { return } // Set terminal emulation based on platform as required. stdin, stdout, stderr := term.StdStreams() initLogging(stderr) flag.Parse() // FIXME: validate daemon flags here if *flVersion { showVersion() return } if *flConfigDir != "" { cliconfig.SetConfigDir(*flConfigDir) } if *flLogLevel != "" { lvl, err := logrus.ParseLevel(*flLogLevel) if err != nil { fmt.Fprintf(os.Stderr, "Unable to parse logging level: %s\n", *flLogLevel) os.Exit(1) } setLogLevel(lvl) } else { setLogLevel(logrus.InfoLevel) } if *flDebug { os.Setenv("DEBUG", "1") setLogLevel(logrus.DebugLevel) } if len(flHosts) == 0 { defaultHost := os.Getenv("DOCKER_HOST") if defaultHost == "" || *flDaemon { if runtime.GOOS != "windows" { // If we do not have a host, default to unix socket defaultHost = fmt.Sprintf("unix://%s", opts.DefaultUnixSocket) } else { // If we do not have a host, default to TCP socket on Windows defaultHost = fmt.Sprintf("tcp://%s:%d", opts.DefaultHTTPHost, opts.DefaultHTTPPort) } } defaultHost, err := opts.ValidateHost(defaultHost) if err != nil { if *flDaemon { logrus.Fatal(err) } else { fmt.Fprint(os.Stderr, err) } os.Exit(1) } flHosts = append(flHosts, defaultHost) } setDefaultConfFlag(flTrustKey, defaultTrustKeyFile) // Regardless of whether the user sets it to true or false, if they // specify --tlsverify at all then we need to turn on tls // *flTlsVerify can be true even if not set due to DOCKER_TLS_VERIFY env var, so we need to check that here as well if flag.IsSet("-tlsverify") || *flTlsVerify { *flTls = true } if *flDaemon { if *flHelp { flag.Usage() return } mainDaemon() return } // From here on, we assume we're a client, not a server. if len(flHosts) > 1 { fmt.Fprintf(os.Stderr, "Please specify only one -H") os.Exit(0) } protoAddrParts := strings.SplitN(flHosts[0], "://", 2) var tlsConfig *tls.Config if *flTls { tlsOptions.InsecureSkipVerify = !*flTlsVerify if !flag.IsSet("-tlscert") { if _, err := os.Stat(tlsOptions.CertFile); os.IsNotExist(err) { tlsOptions.CertFile = "" } } if !flag.IsSet("-tlskey") { if _, err := os.Stat(tlsOptions.KeyFile); os.IsNotExist(err) { tlsOptions.KeyFile = "" } } var err error tlsConfig, err = tlsconfig.Client(tlsOptions) if err != nil { fmt.Fprintln(stderr, err) os.Exit(1) } } cli := client.NewDockerCli(stdin, stdout, stderr, *flTrustKey, protoAddrParts[0], protoAddrParts[1], tlsConfig) if err := cli.Cmd(flag.Args()...); err != nil { if sterr, ok := err.(client.StatusError); ok { if sterr.Status != "" { fmt.Fprintln(cli.Err(), sterr.Status) os.Exit(1) } os.Exit(sterr.StatusCode) } fmt.Fprintln(cli.Err(), err) os.Exit(1) } }
// Expected behaviour, the process stays alive when the client disconnects func TestAttachDisconnect(t *testing.T) { stdin, stdinPipe := io.Pipe() stdout, stdoutPipe := io.Pipe() cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) defer cleanup(globalEngine, t) go func() { // Start a process in daemon mode if err := cli.CmdRun("-d", "-i", unitTestImageID, "/bin/cat"); err != nil { utils.Debugf("Error CmdRun: %s", err) } }() setTimeout(t, "Waiting for CmdRun timed out", 10*time.Second, func() { if _, err := bufio.NewReader(stdout).ReadString('\n'); err != nil { t.Fatal(err) } }) setTimeout(t, "Waiting for the container to be started timed out", 10*time.Second, func() { for { l := globalDaemon.List() if len(l) == 1 && l[0].State.IsRunning() { break } time.Sleep(10 * time.Millisecond) } }) container := globalDaemon.List()[0] // Attach to it c1 := make(chan struct{}) go func() { // We're simulating a disconnect so the return value doesn't matter. What matters is the // fact that CmdAttach returns. cli.CmdAttach(container.ID) close(c1) }() setTimeout(t, "First read/write assertion timed out", 2*time.Second, func() { if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 150); err != nil { t.Fatal(err) } }) // Close pipes (client disconnects) if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil { t.Fatal(err) } // Wait for attach to finish, the client disconnected, therefore, Attach finished his job setTimeout(t, "Waiting for CmdAttach timed out", 2*time.Second, func() { <-c1 }) // We closed stdin, expect /bin/cat to still be running // Wait a little bit to make sure container.monitor() did his thing _, err := container.State.WaitStop(500 * time.Millisecond) if err == nil || !container.State.IsRunning() { t.Fatalf("/bin/cat is not running after closing stdin") } // Try to avoid the timeout in destroy. Best effort, don't check error cStdin, _ := container.StdinPipe() cStdin.Close() container.State.WaitStop(-1 * time.Second) }
// TestAttachDetachTruncatedID checks that attach in tty mode can be detached func TestAttachDetachTruncatedID(t *testing.T) { stdin, stdinPipe := io.Pipe() stdout, stdoutPipe := io.Pipe() cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) defer cleanup(globalEngine, t) // Discard the CmdRun output go stdout.Read(make([]byte, 1024)) setTimeout(t, "Starting container timed out", 2*time.Second, func() { if err := cli.CmdRun("-i", "-t", "-d", unitTestImageID, "cat"); err != nil { t.Fatal(err) } }) container := waitContainerStart(t, 10*time.Second) state := setRaw(t, container) defer unsetRaw(t, container, state) stdin, stdinPipe = io.Pipe() stdout, stdoutPipe = io.Pipe() cli = client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) ch := make(chan struct{}) go func() { defer close(ch) if err := cli.CmdAttach(utils.TruncateID(container.ID)); err != nil { if err != io.ErrClosedPipe { t.Fatal(err) } } }() setTimeout(t, "First read/write assertion timed out", 2*time.Second, func() { if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 150); err != nil { if err != io.ErrClosedPipe { t.Fatal(err) } } }) setTimeout(t, "Escape sequence timeout", 5*time.Second, func() { stdinPipe.Write([]byte{16}) time.Sleep(100 * time.Millisecond) stdinPipe.Write([]byte{17}) }) // wait for CmdRun to return setTimeout(t, "Waiting for CmdAttach timed out", 15*time.Second, func() { <-ch }) closeWrap(stdin, stdinPipe, stdout, stdoutPipe) time.Sleep(500 * time.Millisecond) if !container.State.IsRunning() { t.Fatal("The detached container should be still running") } setTimeout(t, "Waiting for container to die timedout", 5*time.Second, func() { container.Kill() }) }
func main() { if reexec.Init() { return } flag.Parse() // FIXME: validate daemon flags here if *flVersion { showVersion() return } if *flDebug { os.Setenv("DEBUG", "1") } if len(flHosts) == 0 { defaultHost := os.Getenv("DOCKER_HOST") if defaultHost == "" || *flDaemon { // If we do not have a host, default to unix socket defaultHost = fmt.Sprintf("unix://%s", api.DEFAULTUNIXSOCKET) } defaultHost, err := api.ValidateHost(defaultHost) if err != nil { log.Fatal(err) } flHosts = append(flHosts, defaultHost) } if *flDaemon { mainDaemon() return } if len(flHosts) > 1 { log.Fatal("Please specify only one -H") } protoAddrParts := strings.SplitN(flHosts[0], "://", 2) var ( cli *client.DockerCli tlsConfig tls.Config ) tlsConfig.InsecureSkipVerify = true // If we should verify the server, we need to load a trusted ca if *flTlsVerify { *flTls = true certPool := x509.NewCertPool() file, err := ioutil.ReadFile(*flCa) if err != nil { log.Fatalf("Couldn't read ca cert %s: %s", *flCa, err) } certPool.AppendCertsFromPEM(file) tlsConfig.RootCAs = certPool tlsConfig.InsecureSkipVerify = false } // If tls is enabled, try to load and send client certificates if *flTls || *flTlsVerify { _, errCert := os.Stat(*flCert) _, errKey := os.Stat(*flKey) if errCert == nil && errKey == nil { *flTls = true cert, err := tls.LoadX509KeyPair(*flCert, *flKey) if err != nil { log.Fatalf("Couldn't load X509 key pair: %s. Key encrypted?", err) } tlsConfig.Certificates = []tls.Certificate{cert} } } if *flTls || *flTlsVerify { cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, nil, protoAddrParts[0], protoAddrParts[1], &tlsConfig) } else { cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, nil, protoAddrParts[0], protoAddrParts[1], nil) } if err := cli.Cmd(flag.Args()...); err != nil { if sterr, ok := err.(*utils.StatusError); ok { if sterr.Status != "" { log.Infof("%s", sterr.Status) } os.Exit(sterr.StatusCode) } log.Fatal(err) } }
// NewCobraAdaptor returns a new handler func NewCobraAdaptor(clientFlags *cliflags.ClientFlags) CobraAdaptor { stdin, stdout, stderr := term.StdStreams() dockerCli := client.NewDockerCli(stdin, stdout, stderr, clientFlags) var rootCmd = &cobra.Command{ Use: "docker [OPTIONS]", Short: "A self-sufficient runtime for containers", SilenceUsage: true, SilenceErrors: true, } rootCmd.SetUsageTemplate(usageTemplate) rootCmd.SetHelpTemplate(helpTemplate) rootCmd.SetFlagErrorFunc(cli.FlagErrorFunc) rootCmd.SetOutput(stdout) rootCmd.AddCommand( node.NewNodeCommand(dockerCli), service.NewServiceCommand(dockerCli), stack.NewStackCommand(dockerCli), stack.NewTopLevelDeployCommand(dockerCli), swarm.NewSwarmCommand(dockerCli), container.NewAttachCommand(dockerCli), container.NewCommitCommand(dockerCli), container.NewCopyCommand(dockerCli), container.NewCreateCommand(dockerCli), container.NewDiffCommand(dockerCli), container.NewExecCommand(dockerCli), container.NewExportCommand(dockerCli), container.NewKillCommand(dockerCli), container.NewLogsCommand(dockerCli), container.NewPauseCommand(dockerCli), container.NewPortCommand(dockerCli), container.NewPsCommand(dockerCli), container.NewRenameCommand(dockerCli), container.NewRestartCommand(dockerCli), container.NewRmCommand(dockerCli), container.NewRunCommand(dockerCli), container.NewStartCommand(dockerCli), container.NewStatsCommand(dockerCli), container.NewStopCommand(dockerCli), container.NewTopCommand(dockerCli), container.NewUnpauseCommand(dockerCli), container.NewUpdateCommand(dockerCli), container.NewWaitCommand(dockerCli), image.NewBuildCommand(dockerCli), image.NewHistoryCommand(dockerCli), image.NewImagesCommand(dockerCli), image.NewLoadCommand(dockerCli), image.NewRemoveCommand(dockerCli), image.NewSaveCommand(dockerCli), image.NewPullCommand(dockerCli), image.NewPushCommand(dockerCli), image.NewSearchCommand(dockerCli), image.NewImportCommand(dockerCli), image.NewTagCommand(dockerCli), network.NewNetworkCommand(dockerCli), system.NewEventsCommand(dockerCli), registry.NewLoginCommand(dockerCli), registry.NewLogoutCommand(dockerCli), system.NewVersionCommand(dockerCli), volume.NewVolumeCommand(dockerCli), system.NewInfoCommand(dockerCli), ) plugin.NewPluginCommand(rootCmd, dockerCli) rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage") rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help") return CobraAdaptor{ rootCmd: rootCmd, dockerCli: dockerCli, } }