diff --git a/README.md b/README.md index 851ddb4fce..c955a1dcf2 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ Running an interactive shell ```bash # Download a base image -docker import base +docker pull base # Run an interactive shell in the base image, # allocate a tty, attach stdin and stdout diff --git a/commands.go b/commands.go index 0de3c77c39..869581c2bb 100644 --- a/commands.go +++ b/commands.go @@ -30,14 +30,13 @@ func (srv *Server) Name() string { func (srv *Server) Help() string { help := "Usage: docker COMMAND [arg...]\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n" for _, cmd := range [][]interface{}{ - {"run", "Run a command in a container"}, - {"ps", "Display a list of containers"}, - {"import", "Create a new filesystem image from the contents of a tarball"}, {"attach", "Attach to a running container"}, {"commit", "Create a new image from a container's changes"}, - {"history", "Show the history of an image"}, {"diff", "Inspect changes on a container's filesystem"}, + {"export", "Stream the contents of a container as a tar archive"}, + {"history", "Show the history of an image"}, {"images", "List images"}, + {"import", "Create a new filesystem image from the contents of a tarball"}, {"info", "Display system-wide information"}, {"inspect", "Return low-level information on a container"}, {"kill", "Kill a running container"}, @@ -53,7 +52,7 @@ func (srv *Server) Help() string { {"run", "Run a command in a new container"}, {"start", "Start a stopped container"}, {"stop", "Stop a running container"}, - {"export", "Stream the contents of a container as a tar archive"}, + {"tag", "Tag an image into a repository"}, {"version", "Show the docker version information"}, {"wait", "Block until a container stops, then print its exit code"}, } { @@ -98,6 +97,8 @@ func (srv *Server) CmdLogin(stdin io.ReadCloser, stdout io.Writer, args ...strin status, err := auth.Login(newAuthConfig) if err != nil { fmt.Fprintf(stdout, "Error : %s\n", err) + } else { + srv.runtime.authConfig = newAuthConfig } if status != "" { fmt.Fprintf(stdout, status) @@ -400,7 +401,7 @@ func (srv *Server) CmdImport(stdin io.ReadCloser, stdout io.Writer, args ...stri } func (srv *Server) CmdPush(stdin io.ReadCloser, stdout io.Writer, args ...string) error { - cmd := rcli.Subcmd(stdout, "push", "LOCAL", "Push an image or a repository to the registry") + cmd := rcli.Subcmd(stdout, "push", "NAME", "Push an image or a repository to the registry") if err := cmd.Parse(args); err != nil { return nil } @@ -412,15 +413,22 @@ func (srv *Server) CmdPush(stdin io.ReadCloser, stdout io.Writer, args ...string } // If the login failed, abort - if srv.runtime.authConfig == nil { - return fmt.Errorf("Please login prior to push. ('docker login')") + if srv.runtime.authConfig == nil || srv.runtime.authConfig.Username == "" { + if err := srv.CmdLogin(stdin, stdout, args...); err != nil { + return err + } + if srv.runtime.authConfig == nil || srv.runtime.authConfig.Username == "" { + return fmt.Errorf("Please login prior to push. ('docker login')") + } } var remote string tmp := strings.SplitN(local, "/", 2) if len(tmp) == 1 { - remote = srv.runtime.authConfig.Username + "/" + local + return fmt.Errorf( + "Impossible to push a \"root\" repository. Please rename your repository in / (ex: %s/%s)", + srv.runtime.authConfig.Username, local) } else { remote = local } @@ -458,7 +466,7 @@ func (srv *Server) CmdPush(stdin io.ReadCloser, stdout io.Writer, args ...string } func (srv *Server) CmdPull(stdin io.ReadCloser, stdout io.Writer, args ...string) error { - cmd := rcli.Subcmd(stdout, "pull", "IMAGE", "Pull an image or a repository from the registry") + cmd := rcli.Subcmd(stdout, "pull", "NAME", "Pull an image or a repository from the registry") if err := cmd.Parse(args); err != nil { return nil } @@ -468,10 +476,6 @@ func (srv *Server) CmdPull(stdin io.ReadCloser, stdout io.Writer, args ...string return nil } - if srv.runtime.authConfig == nil { - return fmt.Errorf("Please login prior to push. ('docker login')") - } - if srv.runtime.graph.LookupRemoteImage(remote, srv.runtime.authConfig) { fmt.Fprintf(stdout, "Pulling %s...\n", remote) if err := srv.runtime.graph.PullImage(remote, srv.runtime.authConfig); err != nil { @@ -555,8 +559,8 @@ func (srv *Server) CmdImages(stdin io.ReadCloser, stdout io.Writer, args ...stri for id, image := range allImages { if !*quiet { for idx, field := range []string{ - /* REPOSITORY */ "", - /* TAG */ "", + /* REPOSITORY */ "", + /* TAG */ "", /* ID */ id, /* CREATED */ HumanDuration(time.Now().Sub(image.Created)) + " ago", /* PARENT */ srv.runtime.repositories.ImageName(image.Parent), diff --git a/container.go b/container.go index bd5e10ac5b..7e7077c123 100644 --- a/container.go +++ b/container.go @@ -76,6 +76,15 @@ func ParseRun(args []string) (*Config, error) { if err := cmd.Parse(args); err != nil { return nil, err } + parsedArgs := cmd.Args() + runCmd := []string{} + image := "" + if len(parsedArgs) >= 1 { + image = cmd.Arg(0) + } + if len(parsedArgs) > 1 { + runCmd = parsedArgs[1:] + } config := &Config{ Ports: fl_ports, User: *fl_user, @@ -84,8 +93,8 @@ func ParseRun(args []string) (*Config, error) { Memory: *fl_memory, Detach: *fl_detach, Env: fl_env, - Cmd: cmd.Args()[1:], - Image: cmd.Arg(0), + Cmd: runCmd, + Image: image, } return config, nil } diff --git a/deb/debian/control b/deb/debian/control index 35a842df1e..5fd3f36f2d 100644 --- a/deb/debian/control +++ b/deb/debian/control @@ -10,7 +10,7 @@ Standards-Version: 3.9.2 Package: dotcloud-docker Architecture: amd64 Provides: dotcloud-docker -Depends: lxc, wget, bsdtar, curl, sqlite3 +Depends: lxc, wget, bsdtar, curl, libsqlite3-0 Conflicts: docker Description: A process manager with superpowers It encapsulates heterogeneous payloads in Standard Containers, and runs diff --git a/network.go b/network.go index b2c6f638ce..95b5893122 100644 --- a/network.go +++ b/network.go @@ -349,6 +349,9 @@ func newNetworkManager(bridgeIface string) (*NetworkManager, error) { } portMapper, err := newPortMapper() + if err != nil { + return nil, err + } manager := &NetworkManager{ bridgeIface: bridgeIface, diff --git a/registry.go b/registry.go index 62394d63fc..8076e3184c 100644 --- a/registry.go +++ b/registry.go @@ -32,7 +32,7 @@ func NewImgJson(src []byte) (*Image, error) { func NewMultipleImgJson(src []byte) ([]*Image, error) { ret := []*Image{} - dec := json.NewDecoder(strings.NewReader(strings.Replace(string(src), "null", "\"\"", -1))) + dec := json.NewDecoder(strings.NewReader(string(src))) for { m := &Image{} if err := dec.Decode(m); err == io.EOF { @@ -164,7 +164,15 @@ func (graph *Graph) PullRepository(stdout io.Writer, remote, askedTag string, re fmt.Fprintf(stdout, "Pulling repo: %s\n", REGISTRY_ENDPOINT+"/users/"+remote) - req, err := http.NewRequest("GET", REGISTRY_ENDPOINT+"/users/"+remote, nil) + var repositoryTarget string + // If we are asking for 'root' repository, lookup on the Library's registry + if strings.Index(remote, "/") == -1 { + repositoryTarget = REGISTRY_ENDPOINT + "/library/" + remote + } else { + repositoryTarget = REGISTRY_ENDPOINT + "/users/" + remote + } + + req, err := http.NewRequest("GET", repositoryTarget, nil) if err != nil { return err } diff --git a/utils.go b/utils.go index ce722f264f..b9b230305f 100644 --- a/utils.go +++ b/utils.go @@ -7,11 +7,12 @@ import ( "fmt" "github.com/dotcloud/docker/rcli" "io" - "log" "net/http" "os" "os/exec" "path/filepath" + "runtime" + "strings" "sync" "time" ) @@ -43,9 +44,19 @@ func Download(url string, stderr io.Writer) (*http.Response, error) { // If Docker is in damon mode, also send the debug info on the socket func Debugf(format string, a ...interface{}) { if rcli.DEBUG_FLAG { - log.Printf(format, a...) + + // Retrieve the stack infos + _, file, line, ok := runtime.Caller(1) + if !ok { + file = "" + line = -1 + } else { + file = file[strings.LastIndex(file, "/")+1:] + } + + fmt.Fprintf(os.Stderr, fmt.Sprintf("[debug] %s:%d %s\n", file, line, format), a...) if rcli.CLIENT_SOCKET != nil { - fmt.Fprintf(rcli.CLIENT_SOCKET, log.Prefix()+format, a...) + fmt.Fprintf(rcli.CLIENT_SOCKET, fmt.Sprintf("[debug] %s:%d %s\n", file, line, format), a...) } } }