ソースを参照

Merge pull request #2467 from dotcloud/release_hotfix

0.6.5 hotfixes
Michael Crosby 11 年 前
コミット
23b3747945
7 ファイル変更102 行追加145 行削除
  1. 4 4
      buildfile.go
  2. 28 22
      docs/sources/examples/linking_into_redis.rst
  3. 28 94
      docs/sources/use/host_integration.rst
  4. 1 1
      links.go
  5. 12 11
      runtime.go
  6. 15 0
      runtime_test.go
  7. 14 13
      server.go

+ 4 - 4
buildfile.go

@@ -187,9 +187,6 @@ func (b *buildFile) CmdCmd(args string) error {
 }
 
 func (b *buildFile) CmdExpose(args string) error {
-	if strings.Contains(args, ":") {
-		return fmt.Errorf("EXPOSE cannot be used to bind to a host ip or port")
-	}
 	ports := strings.Split(args, " ")
 	b.config.PortSpecs = append(ports, b.config.PortSpecs...)
 	return b.commit("", b.config.Cmd, fmt.Sprintf("EXPOSE %v", ports))
@@ -433,10 +430,13 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error {
 			}
 		}
 
-		container, _, err := b.runtime.Create(b.config, "")
+		container, warnings, err := b.runtime.Create(b.config, "")
 		if err != nil {
 			return err
 		}
+		for _, warning := range warnings {
+			fmt.Fprintf(b.out, " ---> [Warning] %s\n", warning)
+		}
 		b.tmpContainers[container.ID] = struct{}{}
 		fmt.Fprintf(b.out, " ---> Running in %s\n", utils.TruncateID(container.ID))
 		id = container.ID

+ 28 - 22
docs/sources/examples/linking_into_redis.rst

@@ -14,12 +14,16 @@ Building a redis container to link as a child of our web application.
 Building the redis container
 ----------------------------
 
-We will use a pre-build version of redis from the index under 
-the name ``crosbymichael/redis``.  If you are interested in the 
-Dockerfile that was used to build this container here it is.
+Lets build a redis image with the following Dockerfile.
 
 .. code-block:: bash
-    
+
+    git clone https://github.com/antirez/redis.git
+    cd redis
+    git checkout 2.6
+
+    # Save this Dockerfile to the root of the redis repository.  
+
     # Build redis from source
     # Make sure you have the redis source code checked out in
     # the same directory as this Dockerfile
@@ -34,7 +38,6 @@ Dockerfile that was used to build this container here it is.
     ADD . /redis
 
     RUN (cd /redis && make)
-    RUN (cd /redis && make test)
 
     RUN mkdir -p /redis-data
     VOLUME ["/redis-data"]
@@ -43,6 +46,9 @@ Dockerfile that was used to build this container here it is.
     ENTRYPOINT ["/redis/src/redis-server"]
     CMD ["--dir", "/redis-data"]
 
+    # docker build our new redis image from source
+    docker build -t redis-2.6 .
+
 
 We need to ``EXPOSE`` the default port of 6379 so that our link knows what ports 
 to connect to our redis container on.  If you do not expose any ports for the
@@ -54,31 +60,28 @@ Run the redis container
 
 .. code-block:: bash
     
-    docker run -d -e PASSWORD=docker -name redis crosbymichael/redis --requirepass=docker
+    docker run -d -e PASSWORD=docker -name redis redis-2.6 --requirepass docker
  
-This will run our redis container using the default port of 6379 and using docker 
-as password to secure our service.  By specifying the ``-name`` flag on run 
-we will assign the name ``redis`` to this container. 
-We can issue all the commands that you would expect; start, stop, attach, using the name.
-The name also allows us to link other containers into this one.  If you do not specify a 
-name on docker run, docker will automatically generate a name for your container. 
+This will run our redis container wit the password docker 
+to secure our service.  By specifying the ``-name`` flag on run 
+we will assign the name ``redis`` to this container.  If we do not specify a name  for 
+our container via the ``-name`` flag docker will automatically generate a name for us.
+We can issue all the commands that you would expect; start, stop, attach, using the name for our container.
+The name also allows us to link other containers into this one.
 
 Linking redis as a child
 ------------------------
 
 Next we can start a new web application that has a dependency on redis and apply a link 
-to connect both containers.  If you noticed when running our redis service we did not use
-the ``-p`` option to publish the redis port to the host system.  Redis exposed port 6379
-but we did not publish the port.  This allows docker to prevent all network traffic to
-the redis container except when explicitly specified within a link.  This is a big win
-for security.  
-
+to connect both containers.  If you noticed when running our redis server we did not use
+the ``-p`` flag to publish the redis port to the host system.  Redis exposed port 6379 via the Dockerfile 
+and this is all we need to establish a link.
 
 Now lets start our web application with a link into redis.
 
 .. code-block:: bash
    
-    docker run -t -i -link /redis:db -name webapp ubuntu bash
+    docker run -t -i -link redis:db -name webapp ubuntu bash
 
     root@4c01db0b339c:/# env
 
@@ -101,22 +104,25 @@ Now lets start our web application with a link into redis.
 
 
 When we inspect the environment of the linked container we can see a few extra environment 
-variables have been added.  When you specified ``-link /redis:db`` you are telling docker
-to link the container named ``/redis`` into this new container with the alias ``db``.  
+variables have been added.  When you specified ``-link redis:db`` you are telling docker
+to link the container named ``redis`` into this new container with the alias ``db``.  
 Environment variables are prefixed with the alias so that the parent container can access
-network and environment information from the child.
+network and environment information from the containers that are linked into it.
 
 .. code-block:: bash
 
     # The name of the child container
     DB_NAME=/webapp/db
+
     # The default protocol, ip, and port of the service running in the container
     DB_PORT=tcp://172.17.0.8:6379
+
     # A specific protocol, ip, and port of various services
     DB_PORT_6379_TCP=tcp://172.17.0.8:6379
     DB_PORT_6379_TCP_PROTO=tcp
     DB_PORT_6379_TCP_ADDR=172.17.0.8
     DB_PORT_6379_TCP_PORT=6379
+
     # Get environment variables of the container 
     DB_ENV_PASSWORD=dockerpass
 

+ 28 - 94
docs/sources/use/host_integration.rst

@@ -13,113 +13,47 @@ You can use your Docker containers with process managers like ``upstart``,
 Introduction
 ------------
 
+If you want a process manager to manage your containers you will need to run
+the docker daemon with the ``-r=false`` so that docker will not automatically 
+restart your containers when the host is restarted.  
+
 When you have finished setting up your image and are happy with your
 running container, you may want to use a process manager to manage
-it. To help with this, we provide a simple image: ``creack/manager:min``
-
-This image takes the container ID as parameter. We also can specify
-the kind of process manager and metadata like *Author* and
-*Description*. The output will will be text suitable for a
-configuration file, echoed to stdout. It is up to you to create the
-.conf file (for `upstart
-<http://upstart.ubuntu.com/cookbook/#job-configuration-file>`_) or
-.service file (for `systemd
-<http://0pointer.de/public/systemd-man/systemd.service.html>`_) and
-put it in the right place for your system.
-
-Usage
------
-
-.. code-block:: bash
-
-   docker run creack/manager:min [OPTIONS] <container id>
-
-.. program:: docker run creack/manager:min
+it.  When your run ``docker start -a`` docker will automatically attach 
+to the process and forward all signals so that the process manager can 
+detect when a container stops and correctly restart it.  
 
-.. cmdoption:: -a="<none>" 
+Here are a few sample scripts for systemd and upstart to integrate with docker.
 
-   Author of the image
 
-.. cmdoption:: -d="<none>"
-
-   Description of the image
-
-.. cmdoption:: -t="upstart" 
-
-   Type of manager requested: ``upstart`` or ``systemd``
-
-Example Output
-..............
+Sample Upstart Script
+---------------------
 
 .. code-block:: bash
 
-   docker run creack/manager:min -t="systemd" b28605f2f9a4
-   [Unit]
-   	Description=<none>
-   	Author=<none>
-   	After=docker.service
-
-   [Service]
-   	Restart=always
-   	ExecStart=/usr/bin/docker start -a b28605f2f9a4
-   	ExecStop=/usr/bin/docker stop -t 2 b28605f2f9a4
-
-   [Install]
-   	WantedBy=local.target
+   description "Redis container"
+   author "Me"
+   start on filesystem and started lxc-net and started docker
+   stop on runlevel [!2345]
+   respawn
+   exec docker start -a 0a7e070b698b
 
 
-
-Development
------------
-
-The image ``creack/manager:min`` is a ``busybox`` base with the
-compiled binary of ``manager.go`` as the :ref:`Entrypoint
-<entrypoint_def>`.  It is meant to be light and fast to download.
-
-If you would like to change or add things, you can download the full
-``creack/manager`` repository that contains ``creack/manager:min`` and
-``creack/manager:dev``.
-
-The Dockerfiles and the sources are available in
-`/contrib/host_integration
-<https://github.com/dotcloud/docker/tree/master/contrib/host_integration>`_.
-
-
-Upstart
--------
-
-Upstart is the default process manager. The generated script will
-start the container after the ``docker`` daemon. If the container
-dies, it will respawn.  Start/Restart/Stop/Reload are
-supported. Reload will send a SIGHUP to the container.
-
-Example (``upstart`` on Debian)
-...............................
+Sample systemd Script
+---------------------
 
 .. code-block:: bash
 
-   CID=$(docker run -d creack/firefo-vnc)
-   docker run creack/manager:min -a 'Guillaume J. Charmes <guillaume@dotcloud.com>' -d 'Awesome Firefox in VLC' $CID > /etc/init/firefoxvnc.conf
-
-You can now ``start firefoxvnc`` or ``stop firefoxvnc`` and if the container
-dies for some reason, upstart will restart it.
-
-Systemd
--------
+    [Unit]
+    Description=Redis container
+    Author=Me
+    After=docker.service
 
-In order to generate a systemd script, we need to use the ``-t``
-option. The generated script will start the container after docker
-daemon. If the container dies, it will respawn.
-``Start/Restart/Reload/Stop`` are supported.
-
-Example (``systemd`` on Fedora)
-...............................
-
-.. code-block:: bash
+    [Service]
+    Restart=always
+    ExecStart=/usr/bin/docker start -a 0a7e070b698b
+    ExecStop=/usr/bin/docker stop -t 2 0a7e070b698b
 
-   CID=$(docker run -d creack/firefo-vnc)
-   docker run creack/manager:min -t systemd -a 'Guillaume J. Charmes <guillaume@dotcloud.com>' -d 'Awesome Firefox in VLC' $CID > /usr/lib/systemd/system/firefoxvnc.service
+    [Install]
+    WantedBy=local.target
 
-You can now run ``systemctl start firefoxvnc`` or ``systemctl stop
-firefoxvnc`` and if the container dies for some reason, ``systemd``
-will restart it.

+ 1 - 1
links.go

@@ -22,7 +22,7 @@ func NewLink(parent, child *Container, name, bridgeInterface string) (*Link, err
 		return nil, fmt.Errorf("Cannot link to self: %s == %s", parent.ID, child.ID)
 	}
 	if !child.State.Running {
-		return nil, fmt.Errorf("Cannot link to a non running container: %s AS %s", child.ID, name)
+		return nil, fmt.Errorf("Cannot link to a non running container: %s AS %s", child.Name, name)
 	}
 
 	ports := make([]Port, len(child.Config.ExposedPorts))

+ 12 - 11
runtime.go

@@ -317,22 +317,20 @@ func (runtime *Runtime) Create(config *Config, name string) (*Container, []strin
 		return nil, nil, err
 	}
 
-	warnings := []string{}
 	if img.Config != nil {
-		if img.Config.PortSpecs != nil && warnings != nil {
-			for _, p := range img.Config.PortSpecs {
-				if strings.Contains(p, ":") {
-					warnings = append(warnings, "This image expects private ports to be mapped to public ports on your host. "+
-						"This has been deprecated and the public mappings will not be honored."+
-						"Use -p to publish the ports.")
-					break
-				}
-			}
-		}
 		if err := MergeConfig(config, img.Config); err != nil {
 			return nil, nil, err
 		}
 	}
+	warnings := []string{}
+	if config.PortSpecs != nil {
+		for _, p := range config.PortSpecs {
+			if strings.Contains(p, ":") {
+				warnings = append(warnings, "The mapping to public ports on your host has been deprecated. Use -p to publish the ports.")
+				break
+			}
+		}
+	}
 
 	if len(config.Entrypoint) != 0 && config.Cmd == nil {
 		config.Cmd = []string{}
@@ -357,6 +355,9 @@ func (runtime *Runtime) Create(config *Config, name string) (*Container, []strin
 
 	// Set the enitity in the graph using the default name specified
 	if _, err := runtime.containerGraph.Set(name, id); err != nil {
+		if strings.HasSuffix(err.Error(), "name are not unique") {
+			return nil, nil, fmt.Errorf("Conflict, %s already exists.", name)
+		}
 		return nil, nil, err
 	}
 

+ 15 - 0
runtime_test.go

@@ -260,6 +260,21 @@ func TestRuntimeCreate(t *testing.T) {
 	if err != nil {
 		t.Error(err)
 	}
+
+	// test expose 80:8000
+	container, warnings, err := runtime.Create(&Config{
+		Image:     GetTestImage(runtime).ID,
+		Cmd:       []string{"ls", "-al"},
+		PortSpecs: []string{"80:8000"},
+	},
+		"",
+	)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if warnings == nil || len(warnings) != 1 {
+		t.Error("Expected a warning, got none")
+	}
 }
 
 func TestDestroy(t *testing.T) {

+ 14 - 13
server.go

@@ -84,13 +84,13 @@ func (srv *Server) ContainerKill(name string, sig int) error {
 		// If no signal is passed, perform regular Kill (SIGKILL + wait())
 		if sig == 0 {
 			if err := container.Kill(); err != nil {
-				return fmt.Errorf("Error killing container %s: %s", name, err)
+				return fmt.Errorf("Cannot kill container %s: %s", name, err)
 			}
 			srv.LogEvent("kill", container.ShortID(), srv.runtime.repositories.ImageName(container.Image))
 		} else {
 			// Otherwise, just send the requested signal
 			if err := container.kill(sig); err != nil {
-				return fmt.Errorf("Error killing container %s: %s", name, err)
+				return fmt.Errorf("Cannot kill container %s: %s", name, err)
 			}
 			// FIXME: Add event for signals
 		}
@@ -187,7 +187,7 @@ func (srv *Server) ImagesViz(out io.Writer) error {
 	for _, image := range images {
 		parentImage, err = image.GetParent()
 		if err != nil {
-			return fmt.Errorf("Error while getting parent image: %v", err)
+			return err
 		}
 		if parentImage != nil {
 			out.Write([]byte(" \"" + parentImage.ShortID() + "\" -> \"" + image.ShortID() + "\"\n"))
@@ -335,7 +335,7 @@ func (srv *Server) ContainerTop(name, ps_args string) (*APITop, error) {
 	if container := srv.runtime.Get(name); container != nil {
 		output, err := exec.Command("lxc-ps", "--name", container.ID, "--", ps_args).CombinedOutput()
 		if err != nil {
-			return nil, fmt.Errorf("Error trying to use lxc-ps: %s (%s)", err, output)
+			return nil, fmt.Errorf("lxc-ps: %s (%s)", err, output)
 		}
 		procs := APITop{}
 		for i, line := range strings.Split(string(output), "\n") {
@@ -346,7 +346,7 @@ func (srv *Server) ContainerTop(name, ps_args string) (*APITop, error) {
 			scanner := bufio.NewScanner(strings.NewReader(line))
 			scanner.Split(bufio.ScanWords)
 			if !scanner.Scan() {
-				return nil, fmt.Errorf("Error trying to use lxc-ps")
+				return nil, fmt.Errorf("Wrong output using lxc-ps")
 			}
 			// no scanner.Text because we skip container id
 			for scanner.Scan() {
@@ -819,7 +819,7 @@ func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgID,
 	out = utils.NewWriteFlusher(out)
 	jsonRaw, err := ioutil.ReadFile(path.Join(srv.runtime.graph.Root, imgID, "json"))
 	if err != nil {
-		return "", fmt.Errorf("Error while retrieving the path for {%s}: %s", imgID, err)
+		return "", fmt.Errorf("Cannot retrieve the path for {%s}: %s", imgID, err)
 	}
 	out.Write(sf.FormatStatus("", "Pushing %s", imgID))
 
@@ -969,7 +969,7 @@ func (srv *Server) ContainerCreate(config *Config, name string) (string, []strin
 func (srv *Server) ContainerRestart(name string, t int) error {
 	if container := srv.runtime.Get(name); container != nil {
 		if err := container.Restart(t); err != nil {
-			return fmt.Errorf("Error restarting container %s: %s", name, err)
+			return fmt.Errorf("Cannot restart container %s: %s", name, err)
 		}
 		srv.LogEvent("restart", container.ShortID(), srv.runtime.repositories.ImageName(container.Image))
 	} else {
@@ -986,9 +986,10 @@ func (srv *Server) ContainerDestroy(name string, removeVolume, removeLink bool)
 			return fmt.Errorf("No such link: %s", name)
 		}
 		name = srv.runtime.getFullName(name)
-
 		parent, n := path.Split(name)
-
+		if parent == "/" {
+			return fmt.Errorf("Conflict, cannot remove the default name of the container")
+		}
 		pe := srv.runtime.containerGraph.Get(parent)
 		if pe == nil {
 			return fmt.Errorf("Cannot get parent %s for name %s", parent, name)
@@ -1021,7 +1022,7 @@ func (srv *Server) ContainerDestroy(name string, removeVolume, removeLink bool)
 			volumes[volumeId] = struct{}{}
 		}
 		if err := srv.runtime.Destroy(container); err != nil {
-			return fmt.Errorf("Error destroying container %s: %s", name, err)
+			return fmt.Errorf("Cannot destroy container %s: %s", name, err)
 		}
 		srv.LogEvent("destroy", container.ShortID(), srv.runtime.repositories.ImageName(container.Image))
 
@@ -1165,7 +1166,7 @@ func (srv *Server) ImageDelete(name string, autoPrune bool) ([]APIRmi, error) {
 	}
 	if !autoPrune {
 		if err := srv.runtime.graph.Delete(img.ID); err != nil {
-			return nil, fmt.Errorf("Error deleting image %s: %s", name, err)
+			return nil, fmt.Errorf("Cannot delete image %s: %s", name, err)
 		}
 		return nil, nil
 	}
@@ -1252,7 +1253,7 @@ func (srv *Server) ContainerStart(name string, hostConfig *HostConfig) error {
 	}
 
 	if err := container.Start(hostConfig); err != nil {
-		return fmt.Errorf("Error starting container %s: %s", name, err)
+		return fmt.Errorf("Cannot start container %s: %s", name, err)
 	}
 	srv.LogEvent("start", container.ShortID(), runtime.repositories.ImageName(container.Image))
 
@@ -1262,7 +1263,7 @@ func (srv *Server) ContainerStart(name string, hostConfig *HostConfig) error {
 func (srv *Server) ContainerStop(name string, t int) error {
 	if container := srv.runtime.Get(name); container != nil {
 		if err := container.Stop(t); err != nil {
-			return fmt.Errorf("Error stopping container %s: %s", name, err)
+			return fmt.Errorf("Cannot stop container %s: %s", name, err)
 		}
 		srv.LogEvent("stop", container.ShortID(), srv.runtime.repositories.ImageName(container.Image))
 	} else {