Browse Source

Merge pull request #8870 from tiborvass/merge_release_v1.3.1

Merge release v1.3.1
Tibor Vass 10 years ago
parent
commit
6d6dc2c1a1

+ 18 - 0
CHANGELOG.md

@@ -1,5 +1,23 @@
 # Changelog
 # Changelog
 
 
+## 1.3.1 (2014-10-28)
+
+#### Security
+* Prevent fallback to SSL protocols < TLS 1.0 for client, daemon and registry
++ Secure HTTPS connection to registries with certificate verification and without HTTP fallback unless `--insecure-registry` is specified
+
+#### Runtime
+- Fix issue where volumes would not be shared
+
+#### Client
+- Fix issue with `--iptables=false` not automatically setting `--ip-masq=false`
+- Fix docker run output to non-TTY stdout
+
+#### Builder
+- Fix escaping `$` for environment variables
+- Fix issue with lowercase `onbuild` Dockerfile instruction
+- Restrict envrionment variable expansion to `ENV`, `ADD`, `COPY`, `WORKDIR`, `EXPOSE`, `VOLUME` and `USER`
+
 ## 1.3.0 (2014-10-14)
 ## 1.3.0 (2014-10-14)
 
 
 #### Notable features since 1.2.0
 #### Notable features since 1.2.0

+ 1 - 1
VERSION

@@ -1 +1 @@
-1.3.0-dev
+1.3.1-dev

+ 2 - 2
builtins/builtins.go

@@ -10,7 +10,6 @@ import (
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/events"
 	"github.com/docker/docker/events"
 	"github.com/docker/docker/pkg/parsers/kernel"
 	"github.com/docker/docker/pkg/parsers/kernel"
-	"github.com/docker/docker/registry"
 )
 )
 
 
 func Register(eng *engine.Engine) error {
 func Register(eng *engine.Engine) error {
@@ -26,7 +25,8 @@ func Register(eng *engine.Engine) error {
 	if err := eng.Register("version", dockerVersion); err != nil {
 	if err := eng.Register("version", dockerVersion); err != nil {
 		return err
 		return err
 	}
 	}
-	return registry.NewService().Install(eng)
+
+	return nil
 }
 }
 
 
 // remote: a RESTful api for cross-docker communication
 // remote: a RESTful api for cross-docker communication

+ 2 - 0
daemon/config.go

@@ -31,6 +31,7 @@ type Config struct {
 	BridgeIface                 string
 	BridgeIface                 string
 	BridgeIP                    string
 	BridgeIP                    string
 	FixedCIDR                   string
 	FixedCIDR                   string
+	InsecureRegistries          []string
 	InterContainerCommunication bool
 	InterContainerCommunication bool
 	GraphDriver                 string
 	GraphDriver                 string
 	GraphOptions                []string
 	GraphOptions                []string
@@ -55,6 +56,7 @@ func (config *Config) InstallFlags() {
 	flag.StringVar(&config.BridgeIP, []string{"#bip", "-bip"}, "", "Use this CIDR notation address for the network bridge's IP, not compatible with -b")
 	flag.StringVar(&config.BridgeIP, []string{"#bip", "-bip"}, "", "Use this CIDR notation address for the network bridge's IP, not compatible with -b")
 	flag.StringVar(&config.BridgeIface, []string{"b", "-bridge"}, "", "Attach containers to a pre-existing network bridge\nuse 'none' to disable container networking")
 	flag.StringVar(&config.BridgeIface, []string{"b", "-bridge"}, "", "Attach containers to a pre-existing network bridge\nuse 'none' to disable container networking")
 	flag.StringVar(&config.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs (ex: 10.20.0.0/16)\nthis subnet must be nested in the bridge subnet (which is defined by -b or --bip)")
 	flag.StringVar(&config.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs (ex: 10.20.0.0/16)\nthis subnet must be nested in the bridge subnet (which is defined by -b or --bip)")
+	opts.ListVar(&config.InsecureRegistries, []string{"-insecure-registry"}, "Enable insecure communication with specified registries (no certificate verification for HTTPS and enable HTTP fallback)")
 	flag.BoolVar(&config.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
 	flag.BoolVar(&config.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
 	flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Force the Docker runtime to use a specific storage driver")
 	flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Force the Docker runtime to use a specific storage driver")
 	flag.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, "native", "Force the Docker runtime to use a specific exec driver")
 	flag.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, "native", "Force the Docker runtime to use a specific exec driver")

+ 1 - 1
daemon/daemon.go

@@ -832,7 +832,7 @@ func NewDaemonFromDirectory(config *Config, eng *engine.Engine) (*Daemon, error)
 	}
 	}
 
 
 	log.Debugf("Creating repository list")
 	log.Debugf("Creating repository list")
-	repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+driver.String()), g, config.Mirrors)
+	repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+driver.String()), g, config.Mirrors, config.InsecureRegistries)
 	if err != nil {
 	if err != nil {
 		return nil, fmt.Errorf("Couldn't create Tag store: %s", err)
 		return nil, fmt.Errorf("Couldn't create Tag store: %s", err)
 	}
 	}

+ 7 - 0
docker/daemon.go

@@ -13,6 +13,7 @@ import (
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/engine"
 	flag "github.com/docker/docker/pkg/mflag"
 	flag "github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/pkg/signal"
 	"github.com/docker/docker/pkg/signal"
+	"github.com/docker/docker/registry"
 )
 )
 
 
 const CanDaemon = true
 const CanDaemon = true
@@ -32,11 +33,17 @@ func mainDaemon() {
 	}
 	}
 	eng := engine.New()
 	eng := engine.New()
 	signal.Trap(eng.Shutdown)
 	signal.Trap(eng.Shutdown)
+
 	// Load builtins
 	// Load builtins
 	if err := builtins.Register(eng); err != nil {
 	if err := builtins.Register(eng); err != nil {
 		log.Fatal(err)
 		log.Fatal(err)
 	}
 	}
 
 
+	// load registry service
+	if err := registry.NewService(daemonCfg.InsecureRegistries).Install(eng); err != nil {
+		log.Fatal(err)
+	}
+
 	// load the daemon in the background so we can immediately start
 	// load the daemon in the background so we can immediately start
 	// the http api so that connections don't fail while the daemon
 	// the http api so that connections don't fail while the daemon
 	// is booting
 	// is booting

+ 1 - 0
docs/mkdocs.yml

@@ -26,6 +26,7 @@ pages:
 
 
 # Introduction:
 # Introduction:
 - ['index.md', 'About', 'Docker']
 - ['index.md', 'About', 'Docker']
+- ['release-notes.md', 'About', 'Release Notes']
 - ['introduction/index.md', '**HIDDEN**']
 - ['introduction/index.md', '**HIDDEN**']
 - ['introduction/understanding-docker.md', 'About', 'Understanding Docker']
 - ['introduction/understanding-docker.md', 'About', 'Understanding Docker']
 
 

+ 1 - 60
docs/sources/index.md

@@ -88,63 +88,4 @@ implementation, check out the [Docker User Guide](/userguide/).
 
 
 ## Release Notes
 ## Release Notes
 
 
-**Version 1.3.0**
-
-This version fixes a number of bugs and issues and adds new functions and other
-improvements. The [GitHub 1.3 milestone](https://github.com/docker/docker/issues?q=milestone%3A1.3.0+) has
-more detailed information. Major additions and changes include:
-
-*New command: `docker exec`*
-
-The new `docker exec` command lets you run a process in an existing, active
-container. The command has APIs for both the daemon and the client. With
-`docker exec`, you'll be able to do things like add or remove devices from
-running containers, debug running containers, and run commands that are not
-part of the container's static specification. Details in the [command line
-reference](/reference/commandline/cli/#exec).
-
-*New command: `docker create`*
-
-Traditionally, the `docker run` command has been used to both create a
-container and spawn a process to run it. The new `docker create` command breaks
-this apart, letting you set up a container without actually starting it. This
-provides more control over management of the container lifecycle, giving you the
-ability to configure things like volumes or port mappings before the container
-is started. For example, in a rapid-response scaling situation, you could use
-`create` to prepare and stage ten containers in anticipation of heavy loads.
-Details in the [command line reference](/reference/commandline/cli/#create).
-
-*Tech preview of new provenance features*
-
-This release offers a sneak peek at new image signing capabilities that are
-currently under development. Soon, these capabilities will allow any image
-author to sign their images to certify they have not been tampered with. For
-this release, Official images are now signed by Docker, Inc. Not only does this
-demonstrate the new functionality, we hope it will improve your confidence in
-the security of Official images. Look for the blue ribbons denoting signed
-images on the [Docker Hub](https://hub.docker.com/).
-The Docker Engine has been updated to automatically verify that a given
-Official Repo has a current, valid signature. When pulling a signed image,
-you'll see a message stating `the image you are pulling has been verified`. If
-no valid signature is detected, Docker Engine will fall back to pulling a
-regular, unsigned image.
-
-*Other improvements & changes*
-
-* We've added a new security options flag to the `docker run` command,
-`--security-opt`, that lets you set SELinux and AppArmor labels and profiles.
-This means you'll  no longer have to use `docker run --privileged` on kernels
-that support SE Linux or AppArmor. For more information, see the
-[command line reference](/reference/commandline/cli/#run).
-
-* A new flag, `--add-host`, has been added to `docker run` that lets you add
-lines to `/etc/hosts`. This allows you to specify different name
-resolution for the container than it would get via DNS. For more information,
-see the [command line reference](/reference/commandline/cli/#run).
-
-* You can now set a `DOCKER_TLS_VERIFY` environment variable to secure
-connections by default (rather than having to pass the `--tlsverify` flag on
-every call). For more information, see the [https guide](/articles/https).
-
-* Three security issues have been addressed in this release: [CVE-2014-5280,
-CVE-2014-5270, and CVE-2014-5282](https://groups.google.com/forum/#!msg/docker-announce/aQoVmQlcE0A/smPuBNYf8VwJ).
+A summary of the changes in each release in the current series can now be found on the separate [Release Notes page](/release-notes/)

+ 17 - 13
docs/sources/reference/api/hub_registry_spec.md

@@ -4,7 +4,9 @@ page_keywords: docker, registry, api, hub
 
 
 # The Docker Hub and the Registry spec
 # The Docker Hub and the Registry spec
 
 
-## The 3 roles
+## The three roles
+
+There are three major components playing a role in the Docker ecosystem.
 
 
 ### Docker Hub
 ### Docker Hub
 
 
@@ -21,13 +23,15 @@ The Docker Hub has different components:
  - Authentication service
  - Authentication service
  - Tokenization
  - Tokenization
 
 
-The Docker Hub is authoritative for those information.
+The Docker Hub is authoritative for that information.
 
 
-We expect that there will be only one instance of the Docker Hub, run and
+There is only one instance of the Docker Hub, run and
 managed by Docker Inc.
 managed by Docker Inc.
 
 
 ### Registry
 ### Registry
 
 
+The registry has the following characteristics:
+
  - It stores the images and the graph for a set of repositories
  - It stores the images and the graph for a set of repositories
  - It does not have user accounts data
  - It does not have user accounts data
  - It has no notion of user accounts or authorization
  - It has no notion of user accounts or authorization
@@ -37,35 +41,35 @@ managed by Docker Inc.
  - It doesn't have a local database
  - It doesn't have a local database
  - [Source Code](https://github.com/docker/docker-registry)
  - [Source Code](https://github.com/docker/docker-registry)
 
 
-We expect that there will be multiple registries out there. To help to
+We expect that there will be multiple registries out there. To help you
 grasp the context, here are some examples of registries:
 grasp the context, here are some examples of registries:
 
 
  - **sponsor registry**: such a registry is provided by a third-party
  - **sponsor registry**: such a registry is provided by a third-party
    hosting infrastructure as a convenience for their customers and the
    hosting infrastructure as a convenience for their customers and the
-   docker community as a whole. Its costs are supported by the third
+   Docker community as a whole. Its costs are supported by the third
    party, but the management and operation of the registry are
    party, but the management and operation of the registry are
-   supported by dotCloud. It features read/write access, and delegates
+   supported by Docker, Inc. It features read/write access, and delegates
    authentication and authorization to the Docker Hub.
    authentication and authorization to the Docker Hub.
  - **mirror registry**: such a registry is provided by a third-party
  - **mirror registry**: such a registry is provided by a third-party
    hosting infrastructure but is targeted at their customers only. Some
    hosting infrastructure but is targeted at their customers only. Some
    mechanism (unspecified to date) ensures that public images are
    mechanism (unspecified to date) ensures that public images are
    pulled from a sponsor registry to the mirror registry, to make sure
    pulled from a sponsor registry to the mirror registry, to make sure
-   that the customers of the third-party provider can “docker pull”
+   that the customers of the third-party provider can `docker pull`
    those images locally.
    those images locally.
  - **vendor registry**: such a registry is provided by a software
  - **vendor registry**: such a registry is provided by a software
-   vendor, who wants to distribute docker images. It would be operated
+   vendor who wants to distribute docker images. It would be operated
    and managed by the vendor. Only users authorized by the vendor would
    and managed by the vendor. Only users authorized by the vendor would
    be able to get write access. Some images would be public (accessible
    be able to get write access. Some images would be public (accessible
    for anyone), others private (accessible only for authorized users).
    for anyone), others private (accessible only for authorized users).
    Authentication and authorization would be delegated to the Docker Hub.
    Authentication and authorization would be delegated to the Docker Hub.
-   The goal of vendor registries is to let someone do docker pull
-   basho/riak1.3 and automatically push from the vendor registry
-   (instead of a sponsor registry); i.e. get all the convenience of a
+   The goal of vendor registries is to let someone do `docker pull
+   basho/riak1.3` and automatically push from the vendor registry
+   (instead of a sponsor registry); i.e., vendors get all the convenience of a
    sponsor registry, while retaining control on the asset distribution.
    sponsor registry, while retaining control on the asset distribution.
  - **private registry**: such a registry is located behind a firewall,
  - **private registry**: such a registry is located behind a firewall,
    or protected by an additional security layer (HTTP authorization,
    or protected by an additional security layer (HTTP authorization,
    SSL client-side certificates, IP address authorization...). The
    SSL client-side certificates, IP address authorization...). The
-   registry is operated by a private entity, outside of dotCloud's
+   registry is operated by a private entity, outside of Docker's
    control. It can optionally delegate additional authorization to the
    control. It can optionally delegate additional authorization to the
    Docker Hub, but it is not mandatory.
    Docker Hub, but it is not mandatory.
 
 
@@ -77,7 +81,7 @@ grasp the context, here are some examples of registries:
 > - local mount point;
 > - local mount point;
 > - remote docker addressed through SSH.
 > - remote docker addressed through SSH.
 
 
-The latter would only require two new commands in docker, e.g.,
+The latter would only require two new commands in Docker, e.g.,
 `registryget` and `registryput`,
 `registryget` and `registryput`,
 wrapping access to the local filesystem (and optionally doing
 wrapping access to the local filesystem (and optionally doing
 consistency checks). Authentication and authorization are then delegated
 consistency checks). Authentication and authorization are then delegated

+ 18 - 11
docs/sources/reference/api/registry_api.md

@@ -21,30 +21,30 @@ grasp the context, here are some examples of registries:
 
 
  - **sponsor registry**: such a registry is provided by a third-party
  - **sponsor registry**: such a registry is provided by a third-party
    hosting infrastructure as a convenience for their customers and the
    hosting infrastructure as a convenience for their customers and the
-   docker community as a whole. Its costs are supported by the third
+   Docker community as a whole. Its costs are supported by the third
    party, but the management and operation of the registry are
    party, but the management and operation of the registry are
-   supported by dotCloud. It features read/write access, and delegates
+   supported by Docker. It features read/write access, and delegates
    authentication and authorization to the Index.
    authentication and authorization to the Index.
  - **mirror registry**: such a registry is provided by a third-party
  - **mirror registry**: such a registry is provided by a third-party
    hosting infrastructure but is targeted at their customers only. Some
    hosting infrastructure but is targeted at their customers only. Some
    mechanism (unspecified to date) ensures that public images are
    mechanism (unspecified to date) ensures that public images are
    pulled from a sponsor registry to the mirror registry, to make sure
    pulled from a sponsor registry to the mirror registry, to make sure
-   that the customers of the third-party provider can “docker pull”
+   that the customers of the third-party provider can `docker pull`
    those images locally.
    those images locally.
  - **vendor registry**: such a registry is provided by a software
  - **vendor registry**: such a registry is provided by a software
-   vendor, who wants to distribute docker images. It would be operated
+   vendor, who wants to distribute Docker images. It would be operated
    and managed by the vendor. Only users authorized by the vendor would
    and managed by the vendor. Only users authorized by the vendor would
    be able to get write access. Some images would be public (accessible
    be able to get write access. Some images would be public (accessible
    for anyone), others private (accessible only for authorized users).
    for anyone), others private (accessible only for authorized users).
    Authentication and authorization would be delegated to the Index.
    Authentication and authorization would be delegated to the Index.
-   The goal of vendor registries is to let someone do docker pull
-   basho/riak1.3 and automatically push from the vendor registry
-   (instead of a sponsor registry); i.e. get all the convenience of a
+   The goal of vendor registries is to let someone do `docker pull
+   basho/riak1.3` and automatically push from the vendor registry
+   (instead of a sponsor registry); i.e., get all the convenience of a
    sponsor registry, while retaining control on the asset distribution.
    sponsor registry, while retaining control on the asset distribution.
  - **private registry**: such a registry is located behind a firewall,
  - **private registry**: such a registry is located behind a firewall,
    or protected by an additional security layer (HTTP authorization,
    or protected by an additional security layer (HTTP authorization,
    SSL client-side certificates, IP address authorization...). The
    SSL client-side certificates, IP address authorization...). The
-   registry is operated by a private entity, outside of dotCloud's
+   registry is operated by a private entity, outside of Docker's
    control. It can optionally delegate additional authorization to the
    control. It can optionally delegate additional authorization to the
    Index, but it is not mandatory.
    Index, but it is not mandatory.
 
 
@@ -52,7 +52,7 @@ grasp the context, here are some examples of registries:
 > Mirror registries and private registries which do not use the Index
 > Mirror registries and private registries which do not use the Index
 > don't even need to run the registry code. They can be implemented by any
 > don't even need to run the registry code. They can be implemented by any
 > kind of transport implementing HTTP GET and PUT. Read-only registries
 > kind of transport implementing HTTP GET and PUT. Read-only registries
-> can be powered by a simple static HTTP server.
+> can be powered by a simple static HTTPS server.
 
 
 > **Note**:
 > **Note**:
 > The latter implies that while HTTP is the protocol of choice for a registry,
 > The latter implies that while HTTP is the protocol of choice for a registry,
@@ -60,13 +60,20 @@ grasp the context, here are some examples of registries:
 >
 >
 >  - HTTP with GET (and PUT for read-write registries);
 >  - HTTP with GET (and PUT for read-write registries);
 >  - local mount point;
 >  - local mount point;
->  - remote docker addressed through SSH.
+>  - remote Docker addressed through SSH.
 
 
-The latter would only require two new commands in docker, e.g.,
+The latter would only require two new commands in Docker, e.g.,
 `registryget` and `registryput`, wrapping access to the local filesystem
 `registryget` and `registryput`, wrapping access to the local filesystem
 (and optionally doing consistency checks). Authentication and authorization
 (and optionally doing consistency checks). Authentication and authorization
 are then delegated to SSH (e.g., with public keys).
 are then delegated to SSH (e.g., with public keys).
 
 
+> **Note**:
+> Private registry servers that expose an HTTP endpoint need to be secured with
+> TLS (preferably TLSv1.2, but at least TLSv1.0). Make sure to put the CA
+> certificate at /etc/docker/certs.d/my.registry.com:5000/ca.crt on the Docker
+> host, so that the daemon can securely access the private registry.
+> Support for SSLv3 and lower is not available due to security issues.
+
 The default namespace for a private repository is `library`.
 The default namespace for a private repository is `library`.
 
 
 # Endpoints
 # Endpoints

+ 17 - 1
docs/sources/reference/commandline/cli.md

@@ -70,6 +70,7 @@ expect an integer, and they can only be specified once.
       -g, --graph="/var/lib/docker"              Path to use as the root of the Docker runtime
       -g, --graph="/var/lib/docker"              Path to use as the root of the Docker runtime
       -H, --host=[]                              The socket(s) to bind to in daemon mode or connect to in client mode, specified using one or more tcp://host:port, unix:///path/to/socket, fd://* or fd://socketfd.
       -H, --host=[]                              The socket(s) to bind to in daemon mode or connect to in client mode, specified using one or more tcp://host:port, unix:///path/to/socket, fd://* or fd://socketfd.
       --icc=true                                 Enable inter-container communication
       --icc=true                                 Enable inter-container communication
+      --insecure-registry=[]                     Enable insecure communication with specified registries (no certificate verification for HTTPS and enable HTTP fallback)
       --ip=0.0.0.0                               Default IP address to use when binding container ports
       --ip=0.0.0.0                               Default IP address to use when binding container ports
       --ip-forward=true                          Enable net.ipv4.ip_forward
       --ip-forward=true                          Enable net.ipv4.ip_forward
       --ip-masq=true                             Enable IP masquerading for bridge's IP range
       --ip-masq=true                             Enable IP masquerading for bridge's IP range
@@ -111,7 +112,12 @@ direct access to the Docker daemon - and should be secured either using the
 [built in https encrypted socket](/articles/https/), or by putting a secure web
 [built in https encrypted socket](/articles/https/), or by putting a secure web
 proxy in front of it. You can listen on port `2375` on all network interfaces
 proxy in front of it. You can listen on port `2375` on all network interfaces
 with `-H tcp://0.0.0.0:2375`, or on a particular network interface using its IP
 with `-H tcp://0.0.0.0:2375`, or on a particular network interface using its IP
-address: `-H tcp://192.168.59.103:2375`.
+address: `-H tcp://192.168.59.103:2375`. It is conventional to use port `2375`
+for un-encrypted, and port `2376` for encrypted communication with the daemon.
+
+> **Note** If you're using an HTTPS encrypted socket, keep in mind that only TLS1.0
+> and greater are supported. Protocols SSLv3 and under are not supported anymore
+> for security reasons.
 
 
 On Systemd based systems, you can communicate with the daemon via 
 On Systemd based systems, you can communicate with the daemon via 
 [systemd socket activation](http://0pointer.de/blog/projects/socket-activation.html), use
 [systemd socket activation](http://0pointer.de/blog/projects/socket-activation.html), use
@@ -194,6 +200,16 @@ to other machines on the Internet. This may interfere with some network topologi
 can be disabled with --ip-masq=false.
 can be disabled with --ip-masq=false.
 
 
 
 
+By default, Docker will assume all registries are secured via TLS with certificate verification
+enabled. Prior versions of Docker used an auto fallback if a registry did not support TLS
+(or if the TLS connection failed). This introduced the opportunity for Man In The Middle (MITM)
+attacks, so as of Docker 1.3.1, the user must now specify the `--insecure-registry` daemon flag
+for each insecure registry. An insecure registry is either not using TLS (i.e. plain text HTTP),
+or is using TLS with a CA certificate not known by the Docker daemon (i.e. certification
+verification disabled). For example, if there is a registry listening for HTTP at 127.0.0.1:5000,
+as of Docker 1.3.1 you are required to specify `--insecure-registry 127.0.0.1:5000` when starting
+the Docker daemon.
+
 
 
 Docker supports softlinks for the Docker data directory
 Docker supports softlinks for the Docker data directory
 (`/var/lib/docker`) and for `/var/lib/docker/tmp`. The `DOCKER_TMPDIR` and the data directory can be set like this:
 (`/var/lib/docker`) and for `/var/lib/docker/tmp`. The `DOCKER_TMPDIR` and the data directory can be set like this:

+ 291 - 0
docs/sources/release-notes.md

@@ -0,0 +1,291 @@
+page_title: Docker 1.x Series Release Notes page_description: Release Notes for
+Docker 1.x. page_keywords: docker, documentation, about, technology,
+understanding, release
+
+#Release Notes
+
+##Version 1.3.1
+(2014-10-28)
+
+This release fixes some bugs and addresses some security issues.
+
+*Security fixes*
+
+Patches and changes were made to address CVE-2014-5277 and CVE-2014-3566. Specifically, changes were made to:
+* Prevent fallback to SSL protocols < TLS 1.0 for client, daemon and registry
+* Secure HTTPS connection to registries with certificate verification and without HTTP fallback unless `--insecure-registry` is specified.
+
+*Runtime fixes*
+
+* Fixed issue where volumes would not be shared
+
+*Client fixes*
+
+* Fixed issue with `--iptables=false` not automatically setting
+`--ip-masq=false`
+* Fixed docker run output to non-TTY stdout
+
+*Builder fixes*
+
+* Fixed escaping `$` for environment variables
+* Fixed issue with lowercase `onbuild` Dockerfile instruction
+
+
+##Version 1.3.0
+
+This version fixes a number of bugs and issues and adds new functions and other
+improvements. The [GitHub 1.3milestone](https://github.com/docker/docker/issues?q=milestone%3A1.3.0+) has
+more detailed information. Major additions and changes include:
+
+###New Features
+
+*New command: `docker exec`*
+
+The new `docker exec` command lets you run a process in an existing, active
+container. The command has APIs for both the daemon and the client. With `docker
+exec`, you'll be able to do things like add or remove devices from running
+containers, debug running containers, and run commands that are not part of the
+container's static specification. Details in the [command line reference](/reference/commandline/cli/#exec).
+
+*New command: `docker create`*
+
+Traditionally, the `docker run` command has been used to both create a container
+and spawn a process to run it. The new `docker create` command breaks this
+apart, letting you set up a container without actually starting it. This
+provides more control over management of the container lifecycle, giving you the
+ability to configure things like volumes or port mappings before the container
+is started. For example, in a rapid-response scaling situation, you could use
+`create` to prepare and stage ten containers in anticipation of heavy loads.
+Details in the [command line reference](/reference/commandline/cli/#create).
+
+*Tech preview of new provenance features*
+
+This release offers a sneak peek at new image signing capabilities that are
+currently under development. Soon, these capabilities will allow any image
+author to sign their images to certify they have not been tampered with. For
+this release, Official images are now signed by Docker, Inc. Not only does this
+demonstrate the new functionality, we hope it will improve your confidence in
+the security of Official images. Look for the blue ribbons denoting signed
+images on the [Docker Hub](https://hub.docker.com/). The Docker Engine has been
+updated to automatically verify that a given Official Repo has a current, valid
+signature. When pulling a signed image, you'll see a message stating `the image
+you are pulling has been verified`. If no valid signature is detected, Docker
+Engine will fall back to pulling a regular, unsigned image.
+
+###Other improvements & changes*
+
+* We've added a new security options flag to the `docker run` command,
+`--security-opt`, that lets you set SELinux and AppArmor labels and profiles.
+This means you'll  no longer have to use `docker run --privileged` on kernels
+that support SE Linux or AppArmor. For more information, see the [command line
+reference](/reference/commandline/cli/#run).
+
+* A new flag, `--add-host`, has been added to `docker run` that lets you add
+lines to `/etc/hosts`. This allows you to specify different name resolution for
+the container than it would get via DNS. For more information, see the [command
+line reference](/reference/commandline/cli/#run).
+
+* You can now set a `DOCKER_TLS_VERIFY` environment variable to secure
+connections by default (rather than having to pass the `--tlsverify` flag on
+every call). For more information, see the [https guide](/articles/https).
+
+* Three security issues have been addressed in this release: [CVE-2014-5280,
+CVE-2014-5270, and
+CVE-2014-5282](https://groups.google.com/forum/#!msg/docker-announce/aQoVmQlcE0A/smPuBNYf8VwJ).
+
+##Version 1.2.0
+
+This version fixes a number of bugs and issues and adds new functions and other
+improvements. These include:
+
+###New Features
+
+*New restart policies*
+
+We added a `--restart flag` to `docker run` to specify a restart policy for your
+container. Currently, there are three policies available:
+
+* `no` – Do not restart the container if it dies. (default) * `on-failure` –
+Restart the container if it exits with a non-zero exit code. This can also
+accept an optional maximum restart count (e.g. `on-failure:5`). * `always` –
+Always restart the container no matter what exit code is returned. This
+deprecates the `--restart` flag on the Docker daemon.
+
+*New flags for `docker run`: `--cap-add` and `–-cap-drop`*
+
+In previous releases, Docker containers could either be given complete
+capabilities or they could all follow a whitelist of allowed capabilities while
+dropping all others. Further, using `--privileged` would grant all capabilities
+inside a container, rather than applying a whitelist. This was not recommended
+for production use because it’s really unsafe; it’s as if you were directly in
+the host.
+
+This release introduces two new flags for `docker run`, `--cap-add` and
+`--cap-drop`, that give you fine-grain control over the specific capabilities
+you want grant to a particular container.
+
+*New `-–device` flag for `docker run`*
+
+Previously, you could only use devices inside your containers by bind mounting
+them (with `-v`) in a `--privileged` container. With this release, we introduce
+the `--device flag` to `docker run` which lets you use a device without
+requiring a privileged container.
+
+*Writable `/etc/hosts`, `/etc/hostname` and `/etc/resolv.conf`*
+
+You can now edit `/etc/hosts`, `/etc/hostname` and `/etc/resolve.conf` in a
+running container. This is useful if you need to install BIND or other services
+that might override one of those files.
+
+Note, however, that changes to these files are not saved when running `docker
+build` and so will not be preserved in the resulting image. The changes will
+only “stick” in a running container.
+
+*Docker proxy in a separate process*
+
+The Docker userland proxy that routes outbound traffic to your containers now
+has its own separate process (one process per connection). This greatly reduces
+the load on the daemon, which increases stability and efficiency.
+
+###Other improvements & changes
+
+* When using `docker rm -f`, Docker now kills the container (instead of stopping
+it) before removing it . If you intend to stop the container cleanly, you can
+use `docker stop`.
+
+* Added support for IPv6 addresses in `--dns`
+
+* Added search capability in private registries
+
+##Version 1.1.0
+
+###New Features
+
+*`.dockerignore` support*
+
+You can now add a `.dockerignore` file next to your `Dockerfile` and Docker will
+ignore files and directories specified in that file when sending the build
+context to the daemon. Example:
+https://github.com/docker/docker/blob/master/.dockerignore
+
+*Pause containers during commit*
+
+Doing a commit on a running container was not recommended because you could end
+up with files in an inconsistent state (for example, if they were being written
+during the commit). Containers are now paused when a commit is made to them. You
+can disable this feature by doing a `docker commit --pause=false <container_id>`
+
+*Tailing logs*
+
+You can now tail the logs of a container. For example, you can get the last ten
+lines of a log by using `docker logs --tail 10 <container_id>`. You can also
+follow the logs of a container without having to read the whole log file with
+`docker logs --tail 0 -f <container_id>`.
+
+*Allow a tar file as context for docker build*
+
+You can now pass a tar archive to `docker build` as context. This can be used to
+automate docker builds, for example: `cat context.tar | docker build -` or
+`docker run builder_image | docker build -`
+
+*Bind mounting your whole filesystem in a container*
+
+`/` is now allowed as source of `--volumes`. This means you can bind-mount your
+whole system in a container if you need to. For example: `docker run -v
+/:/my_host ubuntu:ro ls /my_host`. However, it is now forbidden to mount to /.
+
+
+###Other Improvements & Changes
+
+* Port allocation has been improved. In the previous release, Docker could
+prevent you from starting a container with previously allocated ports which
+seemed to be in use when in fact they were not. This has been fixed.
+
+* A bug in `docker save` was introduced in the last release. The `docker save`
+command could produce images with invalid metadata. The command now produces
+images with correct metadata.
+
+* Running `docker inspect` in a container now returns which containers it is
+linked to.
+
+* Parsing of the `docker commit` flag has improved validation, to better prevent
+you from committing an image with a name such as  `-m`. Image names with dashes
+in them potentially conflict with command line flags.
+
+* The API now has Improved status codes for  `start` and `stop`. Trying to start
+a running container will now return a 304 error.
+
+* Performance has been improved overall. Starting the daemon is faster than in
+previous releases. The daemon’s performance has also been improved when it is
+working with large numbers of images and containers.
+
+* Fixed an issue with white-spaces and multi-lines in Dockerfiles.
+
+##Version 1.1.0
+
+###New Features
+
+*`.dockerignore` support*
+
+You can now add a `.dockerignore` file next to your `Dockerfile` and Docker will
+ignore files and directories specified in that file when sending the build
+context to the daemon. Example:
+https://github.com/dotcloud/docker/blob/master/.dockerignore
+
+*Pause containers during commit*
+
+Doing a commit on a running container was not recommended because you could end
+up with files in an inconsistent state (for example, if they were being written
+during the commit). Containers are now paused when a commit is made to them. You
+can disable this feature by doing a `docker commit --pause=false <container_id>`
+
+*Tailing logs*
+
+You can now tail the logs of a container. For example, you can get the last ten
+lines of a log by using `docker logs --tail 10 <container_id>`. You can also
+follow the logs of a container without having to read the whole log file with
+`docker logs --tail 0 -f <container_id>`.
+
+*Allow a tar file as context for docker build*
+
+You can now pass a tar archive to `docker build` as context. This can be used to
+automate docker builds, for example: `cat context.tar | docker build -` or
+`docker run builder_image | docker build -`
+
+*Bind mounting your whole filesystem in a container*
+
+`/` is now allowed as source of `--volumes`. This means you can bind-mount your
+whole system in a container if you need to. For example: `docker run -v
+/:/my_host ubuntu:ro ls /my_host`. However, it is now forbidden to mount to /.
+
+
+###Other Improvements & Changes
+
+* Port allocation has been improved. In the previous release, Docker could
+prevent you from starting a container with previously allocated ports which
+seemed to be in use when in fact they were not. This has been fixed.
+
+* A bug in `docker save` was introduced in the last release. The `docker save`
+command could produce images with invalid metadata. The command now produces
+images with correct metadata.
+
+* Running `docker inspect` in a container now returns which containers it is
+linked to.
+
+* Parsing of the `docker commit` flag has improved validation, to better prevent
+you from committing an image with a name such as  `-m`. Image names with dashes
+in them potentially conflict with command line flags.
+
+* The API now has Improved status codes for  `start` and `stop`. Trying to start
+a running container will now return a 304 error.
+
+* Performance has been improved overall. Starting the daemon is faster than in
+previous releases. The daemon’s performance has also been improved when it is
+working with large numbers of images and containers.
+
+* Fixed an issue with white-spaces and multi-lines in Dockerfiles.
+
+##Version 1.0.0
+
+First production-ready release. Prior development history can be found by
+searching in [GitHub](https://github.com/docker/docker).

+ 3 - 1
graph/pull.go

@@ -113,7 +113,9 @@ func (s *TagStore) CmdPull(job *engine.Job) engine.Status {
 		return job.Error(err)
 		return job.Error(err)
 	}
 	}
 
 
-	endpoint, err := registry.NewEndpoint(hostname)
+	secure := registry.IsSecure(hostname, s.insecureRegistries)
+
+	endpoint, err := registry.NewEndpoint(hostname, secure)
 	if err != nil {
 	if err != nil {
 		return job.Error(err)
 		return job.Error(err)
 	}
 	}

+ 3 - 1
graph/push.go

@@ -214,7 +214,9 @@ func (s *TagStore) CmdPush(job *engine.Job) engine.Status {
 		return job.Error(err)
 		return job.Error(err)
 	}
 	}
 
 
-	endpoint, err := registry.NewEndpoint(hostname)
+	secure := registry.IsSecure(hostname, s.insecureRegistries)
+
+	endpoint, err := registry.NewEndpoint(hostname, secure)
 	if err != nil {
 	if err != nil {
 		return job.Error(err)
 		return job.Error(err)
 	}
 	}

+ 14 - 11
graph/tags.go

@@ -23,10 +23,11 @@ var (
 )
 )
 
 
 type TagStore struct {
 type TagStore struct {
-	path         string
-	graph        *Graph
-	mirrors      []string
-	Repositories map[string]Repository
+	path               string
+	graph              *Graph
+	mirrors            []string
+	insecureRegistries []string
+	Repositories       map[string]Repository
 	sync.Mutex
 	sync.Mutex
 	// FIXME: move push/pull-related fields
 	// FIXME: move push/pull-related fields
 	// to a helper type
 	// to a helper type
@@ -54,18 +55,20 @@ func (r Repository) Contains(u Repository) bool {
 	return true
 	return true
 }
 }
 
 
-func NewTagStore(path string, graph *Graph, mirrors []string) (*TagStore, error) {
+func NewTagStore(path string, graph *Graph, mirrors []string, insecureRegistries []string) (*TagStore, error) {
 	abspath, err := filepath.Abs(path)
 	abspath, err := filepath.Abs(path)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
+
 	store := &TagStore{
 	store := &TagStore{
-		path:         abspath,
-		graph:        graph,
-		mirrors:      mirrors,
-		Repositories: make(map[string]Repository),
-		pullingPool:  make(map[string]chan struct{}),
-		pushingPool:  make(map[string]chan struct{}),
+		path:               abspath,
+		graph:              graph,
+		mirrors:            mirrors,
+		insecureRegistries: insecureRegistries,
+		Repositories:       make(map[string]Repository),
+		pullingPool:        make(map[string]chan struct{}),
+		pushingPool:        make(map[string]chan struct{}),
 	}
 	}
 	// Load the json file if it exists, otherwise create it.
 	// Load the json file if it exists, otherwise create it.
 	if err := store.reload(); os.IsNotExist(err) {
 	if err := store.reload(); os.IsNotExist(err) {

+ 1 - 1
graph/tags_unit_test.go

@@ -53,7 +53,7 @@ func mkTestTagStore(root string, t *testing.T) *TagStore {
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	store, err := NewTagStore(path.Join(root, "tags"), graph, nil)
+	store, err := NewTagStore(path.Join(root, "tags"), graph, nil, nil)
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}

+ 39 - 10
registry/endpoint.go

@@ -2,7 +2,6 @@ package registry
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"
-	"errors"
 	"fmt"
 	"fmt"
 	"io/ioutil"
 	"io/ioutil"
 	"net/http"
 	"net/http"
@@ -34,27 +33,40 @@ func scanForAPIVersion(hostname string) (string, APIVersion) {
 	return hostname, DefaultAPIVersion
 	return hostname, DefaultAPIVersion
 }
 }
 
 
-func NewEndpoint(hostname string) (*Endpoint, error) {
-	endpoint, err := newEndpoint(hostname)
+func NewEndpoint(hostname string, secure bool) (*Endpoint, error) {
+	endpoint, err := newEndpoint(hostname, secure)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
+	// Try HTTPS ping to registry
 	endpoint.URL.Scheme = "https"
 	endpoint.URL.Scheme = "https"
 	if _, err := endpoint.Ping(); err != nil {
 	if _, err := endpoint.Ping(); err != nil {
-		log.Debugf("Registry %s does not work (%s), falling back to http", endpoint, err)
-		// TODO: Check if http fallback is enabled
+
+		//TODO: triggering highland build can be done there without "failing"
+
+		if secure {
+			// If registry is secure and HTTPS failed, show user the error and tell them about `--insecure-registry`
+			// in case that's what they need. DO NOT accept unknown CA certificates, and DO NOT fallback to HTTP.
+			return nil, fmt.Errorf("Invalid registry endpoint %s: %v. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry %s` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/%s/ca.crt", endpoint, err, endpoint.URL.Host, endpoint.URL.Host)
+		}
+
+		// If registry is insecure and HTTPS failed, fallback to HTTP.
+		log.Debugf("Error from registry %q marked as insecure: %v. Insecurely falling back to HTTP", endpoint, err)
 		endpoint.URL.Scheme = "http"
 		endpoint.URL.Scheme = "http"
-		if _, err = endpoint.Ping(); err != nil {
-			return nil, errors.New("Invalid Registry endpoint: " + err.Error())
+		_, err2 := endpoint.Ping()
+		if err2 == nil {
+			return endpoint, nil
 		}
 		}
+
+		return nil, fmt.Errorf("Invalid registry endpoint %q. HTTPS attempt: %v. HTTP attempt: %v", endpoint, err, err2)
 	}
 	}
 
 
 	return endpoint, nil
 	return endpoint, nil
 }
 }
-func newEndpoint(hostname string) (*Endpoint, error) {
+func newEndpoint(hostname string, secure bool) (*Endpoint, error) {
 	var (
 	var (
-		endpoint        Endpoint
+		endpoint        = Endpoint{secure: secure}
 		trimmedHostname string
 		trimmedHostname string
 		err             error
 		err             error
 	)
 	)
@@ -72,6 +84,7 @@ func newEndpoint(hostname string) (*Endpoint, error) {
 type Endpoint struct {
 type Endpoint struct {
 	URL     *url.URL
 	URL     *url.URL
 	Version APIVersion
 	Version APIVersion
+	secure  bool
 }
 }
 
 
 // Get the formated URL for the root of this registry Endpoint
 // Get the formated URL for the root of this registry Endpoint
@@ -95,7 +108,7 @@ func (e Endpoint) Ping() (RegistryInfo, error) {
 		return RegistryInfo{Standalone: false}, err
 		return RegistryInfo{Standalone: false}, err
 	}
 	}
 
 
-	resp, _, err := doRequest(req, nil, ConnectTimeout)
+	resp, _, err := doRequest(req, nil, ConnectTimeout, e.secure)
 	if err != nil {
 	if err != nil {
 		return RegistryInfo{Standalone: false}, err
 		return RegistryInfo{Standalone: false}, err
 	}
 	}
@@ -134,3 +147,19 @@ func (e Endpoint) Ping() (RegistryInfo, error) {
 	log.Debugf("RegistryInfo.Standalone: %t", info.Standalone)
 	log.Debugf("RegistryInfo.Standalone: %t", info.Standalone)
 	return info, nil
 	return info, nil
 }
 }
+
+// IsSecure returns false if the provided hostname is part of the list of insecure registries.
+// Insecure registries accept HTTP and/or accept HTTPS with certificates from unknown CAs.
+func IsSecure(hostname string, insecureRegistries []string) bool {
+	if hostname == IndexServerAddress() {
+		return true
+	}
+
+	for _, h := range insecureRegistries {
+		if hostname == h {
+			return false
+		}
+	}
+
+	return true
+}

+ 1 - 1
registry/endpoint_test.go

@@ -12,7 +12,7 @@ func TestEndpointParse(t *testing.T) {
 		{"0.0.0.0:5000", "https://0.0.0.0:5000/v1/"},
 		{"0.0.0.0:5000", "https://0.0.0.0:5000/v1/"},
 	}
 	}
 	for _, td := range testData {
 	for _, td := range testData {
-		e, err := newEndpoint(td.str)
+		e, err := newEndpoint(td.str, true)
 		if err != nil {
 		if err != nil {
 			t.Errorf("%q: %s", td.str, err)
 			t.Errorf("%q: %s", td.str, err)
 		}
 		}

+ 55 - 43
registry/registry.go

@@ -14,6 +14,7 @@ import (
 	"strings"
 	"strings"
 	"time"
 	"time"
 
 
+	log "github.com/Sirupsen/logrus"
 	"github.com/docker/docker/utils"
 	"github.com/docker/docker/utils"
 )
 )
 
 
@@ -35,7 +36,7 @@ const (
 	ConnectTimeout
 	ConnectTimeout
 )
 )
 
 
-func newClient(jar http.CookieJar, roots *x509.CertPool, cert *tls.Certificate, timeout TimeoutType) *http.Client {
+func newClient(jar http.CookieJar, roots *x509.CertPool, cert *tls.Certificate, timeout TimeoutType, secure bool) *http.Client {
 	tlsConfig := tls.Config{
 	tlsConfig := tls.Config{
 		RootCAs: roots,
 		RootCAs: roots,
 		// Avoid fallback to SSL protocols < TLS1.0
 		// Avoid fallback to SSL protocols < TLS1.0
@@ -46,6 +47,10 @@ func newClient(jar http.CookieJar, roots *x509.CertPool, cert *tls.Certificate,
 		tlsConfig.Certificates = append(tlsConfig.Certificates, *cert)
 		tlsConfig.Certificates = append(tlsConfig.Certificates, *cert)
 	}
 	}
 
 
+	if !secure {
+		tlsConfig.InsecureSkipVerify = true
+	}
+
 	httpTransport := &http.Transport{
 	httpTransport := &http.Transport{
 		DisableKeepAlives: true,
 		DisableKeepAlives: true,
 		Proxy:             http.ProxyFromEnvironment,
 		Proxy:             http.ProxyFromEnvironment,
@@ -86,69 +91,76 @@ func newClient(jar http.CookieJar, roots *x509.CertPool, cert *tls.Certificate,
 	}
 	}
 }
 }
 
 
-func doRequest(req *http.Request, jar http.CookieJar, timeout TimeoutType) (*http.Response, *http.Client, error) {
-	hasFile := func(files []os.FileInfo, name string) bool {
-		for _, f := range files {
-			if f.Name() == name {
-				return true
-			}
-		}
-		return false
-	}
-
-	hostDir := path.Join("/etc/docker/certs.d", req.URL.Host)
-	fs, err := ioutil.ReadDir(hostDir)
-	if err != nil && !os.IsNotExist(err) {
-		return nil, nil, err
-	}
-
+func doRequest(req *http.Request, jar http.CookieJar, timeout TimeoutType, secure bool) (*http.Response, *http.Client, error) {
 	var (
 	var (
 		pool  *x509.CertPool
 		pool  *x509.CertPool
 		certs []*tls.Certificate
 		certs []*tls.Certificate
 	)
 	)
 
 
-	for _, f := range fs {
-		if strings.HasSuffix(f.Name(), ".crt") {
-			if pool == nil {
-				pool = x509.NewCertPool()
-			}
-			data, err := ioutil.ReadFile(path.Join(hostDir, f.Name()))
-			if err != nil {
-				return nil, nil, err
+	if secure && req.URL.Scheme == "https" {
+		hasFile := func(files []os.FileInfo, name string) bool {
+			for _, f := range files {
+				if f.Name() == name {
+					return true
+				}
 			}
 			}
-			pool.AppendCertsFromPEM(data)
+			return false
 		}
 		}
-		if strings.HasSuffix(f.Name(), ".cert") {
-			certName := f.Name()
-			keyName := certName[:len(certName)-5] + ".key"
-			if !hasFile(fs, keyName) {
-				return nil, nil, fmt.Errorf("Missing key %s for certificate %s", keyName, certName)
+
+		hostDir := path.Join("/etc/docker/certs.d", req.URL.Host)
+		log.Debugf("hostDir: %s", hostDir)
+		fs, err := ioutil.ReadDir(hostDir)
+		if err != nil && !os.IsNotExist(err) {
+			return nil, nil, err
+		}
+
+		for _, f := range fs {
+			if strings.HasSuffix(f.Name(), ".crt") {
+				if pool == nil {
+					pool = x509.NewCertPool()
+				}
+				log.Debugf("crt: %s", hostDir+"/"+f.Name())
+				data, err := ioutil.ReadFile(path.Join(hostDir, f.Name()))
+				if err != nil {
+					return nil, nil, err
+				}
+				pool.AppendCertsFromPEM(data)
 			}
 			}
-			cert, err := tls.LoadX509KeyPair(path.Join(hostDir, certName), path.Join(hostDir, keyName))
-			if err != nil {
-				return nil, nil, err
+			if strings.HasSuffix(f.Name(), ".cert") {
+				certName := f.Name()
+				keyName := certName[:len(certName)-5] + ".key"
+				log.Debugf("cert: %s", hostDir+"/"+f.Name())
+				if !hasFile(fs, keyName) {
+					return nil, nil, fmt.Errorf("Missing key %s for certificate %s", keyName, certName)
+				}
+				cert, err := tls.LoadX509KeyPair(path.Join(hostDir, certName), path.Join(hostDir, keyName))
+				if err != nil {
+					return nil, nil, err
+				}
+				certs = append(certs, &cert)
 			}
 			}
-			certs = append(certs, &cert)
-		}
-		if strings.HasSuffix(f.Name(), ".key") {
-			keyName := f.Name()
-			certName := keyName[:len(keyName)-4] + ".cert"
-			if !hasFile(fs, certName) {
-				return nil, nil, fmt.Errorf("Missing certificate %s for key %s", certName, keyName)
+			if strings.HasSuffix(f.Name(), ".key") {
+				keyName := f.Name()
+				certName := keyName[:len(keyName)-4] + ".cert"
+				log.Debugf("key: %s", hostDir+"/"+f.Name())
+				if !hasFile(fs, certName) {
+					return nil, nil, fmt.Errorf("Missing certificate %s for key %s", certName, keyName)
+				}
 			}
 			}
 		}
 		}
 	}
 	}
 
 
 	if len(certs) == 0 {
 	if len(certs) == 0 {
-		client := newClient(jar, pool, nil, timeout)
+		client := newClient(jar, pool, nil, timeout, secure)
 		res, err := client.Do(req)
 		res, err := client.Do(req)
 		if err != nil {
 		if err != nil {
 			return nil, nil, err
 			return nil, nil, err
 		}
 		}
 		return res, client, nil
 		return res, client, nil
 	}
 	}
+
 	for i, cert := range certs {
 	for i, cert := range certs {
-		client := newClient(jar, pool, cert, timeout)
+		client := newClient(jar, pool, cert, timeout, secure)
 		res, err := client.Do(req)
 		res, err := client.Do(req)
 		// If this is the last cert, otherwise, continue to next cert if 403 or 5xx
 		// If this is the last cert, otherwise, continue to next cert if 403 or 5xx
 		if i == len(certs)-1 || err == nil &&
 		if i == len(certs)-1 || err == nil &&

+ 2 - 2
registry/registry_test.go

@@ -21,7 +21,7 @@ const (
 
 
 func spawnTestRegistrySession(t *testing.T) *Session {
 func spawnTestRegistrySession(t *testing.T) *Session {
 	authConfig := &AuthConfig{}
 	authConfig := &AuthConfig{}
-	endpoint, err := NewEndpoint(makeURL("/v1/"))
+	endpoint, err := NewEndpoint(makeURL("/v1/"), false)
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -33,7 +33,7 @@ func spawnTestRegistrySession(t *testing.T) *Session {
 }
 }
 
 
 func TestPingRegistryEndpoint(t *testing.T) {
 func TestPingRegistryEndpoint(t *testing.T) {
-	ep, err := NewEndpoint(makeURL("/v1/"))
+	ep, err := NewEndpoint(makeURL("/v1/"), false)
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}

+ 14 - 9
registry/service.go

@@ -13,12 +13,15 @@ import (
 //  'pull': Download images from any registry (TODO)
 //  'pull': Download images from any registry (TODO)
 //  'push': Upload images to any registry (TODO)
 //  'push': Upload images to any registry (TODO)
 type Service struct {
 type Service struct {
+	insecureRegistries []string
 }
 }
 
 
 // NewService returns a new instance of Service ready to be
 // NewService returns a new instance of Service ready to be
 // installed no an engine.
 // installed no an engine.
-func NewService() *Service {
-	return &Service{}
+func NewService(insecureRegistries []string) *Service {
+	return &Service{
+		insecureRegistries: insecureRegistries,
+	}
 }
 }
 
 
 // Install installs registry capabilities to eng.
 // Install installs registry capabilities to eng.
@@ -32,15 +35,12 @@ func (s *Service) Install(eng *engine.Engine) error {
 // and returns OK if authentication was sucessful.
 // and returns OK if authentication was sucessful.
 // It can be used to verify the validity of a client's credentials.
 // It can be used to verify the validity of a client's credentials.
 func (s *Service) Auth(job *engine.Job) engine.Status {
 func (s *Service) Auth(job *engine.Job) engine.Status {
-	var (
-		err        error
-		authConfig = &AuthConfig{}
-	)
+	var authConfig = new(AuthConfig)
 
 
 	job.GetenvJson("authConfig", authConfig)
 	job.GetenvJson("authConfig", authConfig)
-	// TODO: this is only done here because auth and registry need to be merged into one pkg
+
 	if addr := authConfig.ServerAddress; addr != "" && addr != IndexServerAddress() {
 	if addr := authConfig.ServerAddress; addr != "" && addr != IndexServerAddress() {
-		endpoint, err := NewEndpoint(addr)
+		endpoint, err := NewEndpoint(addr, IsSecure(addr, s.insecureRegistries))
 		if err != nil {
 		if err != nil {
 			return job.Error(err)
 			return job.Error(err)
 		}
 		}
@@ -49,11 +49,13 @@ func (s *Service) Auth(job *engine.Job) engine.Status {
 		}
 		}
 		authConfig.ServerAddress = endpoint.String()
 		authConfig.ServerAddress = endpoint.String()
 	}
 	}
+
 	status, err := Login(authConfig, HTTPRequestFactory(nil))
 	status, err := Login(authConfig, HTTPRequestFactory(nil))
 	if err != nil {
 	if err != nil {
 		return job.Error(err)
 		return job.Error(err)
 	}
 	}
 	job.Printf("%s\n", status)
 	job.Printf("%s\n", status)
+
 	return engine.StatusOK
 	return engine.StatusOK
 }
 }
 
 
@@ -89,7 +91,10 @@ func (s *Service) Search(job *engine.Job) engine.Status {
 	if err != nil {
 	if err != nil {
 		return job.Error(err)
 		return job.Error(err)
 	}
 	}
-	endpoint, err := NewEndpoint(hostname)
+
+	secure := IsSecure(hostname, s.insecureRegistries)
+
+	endpoint, err := NewEndpoint(hostname, secure)
 	if err != nil {
 	if err != nil {
 		return job.Error(err)
 		return job.Error(err)
 	}
 	}

+ 1 - 1
registry/session.go

@@ -65,7 +65,7 @@ func NewSession(authConfig *AuthConfig, factory *utils.HTTPRequestFactory, endpo
 }
 }
 
 
 func (r *Session) doRequest(req *http.Request) (*http.Response, *http.Client, error) {
 func (r *Session) doRequest(req *http.Request) (*http.Response, *http.Client, error) {
-	return doRequest(req, r.jar, r.timeout)
+	return doRequest(req, r.jar, r.timeout, r.indexEndpoint.secure)
 }
 }
 
 
 // Retrieve the history of a given image from the Registry.
 // Retrieve the history of a given image from the Registry.