|  |  |  | @ -16,13 +16,17 @@ deployment process. This registry image is sufficient for running local tests | 
		
	
		
			
				|  |  |  |  | but is insufficient for production. For production you should configure and | 
		
	
		
			
				|  |  |  |  | build your own custom registry image from the `docker/distribution` code. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | >**Note**: The examples on this page were written and tested using Ubuntu 14.04.  | 
		
	
		
			
				|  |  |  |  | >If you are running Docker in a different OS, you may need to "translate" | 
		
	
		
			
				|  |  |  |  | >the commands to meet the requirements of your own environment.  | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | ## Simple example with the official image | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | In this section, you create a local registry using Docker's official image. You | 
		
	
		
			
				|  |  |  |  | push an image to, and then pull the same image from, the registry. This a good | 
		
	
		
			
				|  |  |  |  | exercise for understanding the basic interactions a client has with a | 
		
	
		
			
				|  |  |  |  | local registry. | 
		
	
		
			
				|  |  |  |  | In this section, you create a container running Docker's official registry | 
		
	
		
			
				|  |  |  |  | image. You push an image to, and then pull the same image from, this registry. | 
		
	
		
			
				|  |  |  |  | This a good exercise for understanding the basic interactions a client has with | 
		
	
		
			
				|  |  |  |  | a local registry. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 1. Install Docker. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -30,7 +34,8 @@ local registry. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		$ docker run hello-world | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	The `run` command automatically pulls the image from Docker's official images. | 
		
	
		
			
				|  |  |  |  | 	The `run` command automatically pulls a `hello-world` image from Docker's | 
		
	
		
			
				|  |  |  |  | 	official images. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 3. Start a registry service on your localhost. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -68,11 +73,40 @@ local registry. | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	 You should see your new image in your listing. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 5. Push this new image to your local registry. | 
		
	
		
			
				|  |  |  |  | 6. Push this new image to your local registry. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		$ docker push localhost:5000/hello-mine:latest | 
		
	
		
			
				|  |  |  |  | 		The push refers to a repository [localhost:5000/hello-mine] (len: 1) | 
		
	
		
			
				|  |  |  |  | 		e45a5af57b00: Image already exists  | 
		
	
		
			
				|  |  |  |  | 		31cbccb51277: Image successfully pushed  | 
		
	
		
			
				|  |  |  |  | 		511136ea3c5a: Image already exists  | 
		
	
		
			
				|  |  |  |  | 		Digest: sha256:a1b13bc01783882434593119198938b9b9ef2bd32a0a246f16ac99b01383ef7a | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 7. Use the `curl` command and the Docker Registry Service API v2 to list your | 
		
	
		
			
				|  |  |  |  |    image in the registry: | 
		
	
		
			
				|  |  |  |  |     | 
		
	
		
			
				|  |  |  |  | 		$ curl -v -X GET http://localhost:5000/v2/hello-mine/tags/list | 
		
	
		
			
				|  |  |  |  | 		* Hostname was NOT found in DNS cache | 
		
	
		
			
				|  |  |  |  | 		*   Trying 127.0.0.1... | 
		
	
		
			
				|  |  |  |  | 		* Connected to localhost (127.0.0.1) port 5000 (#0) | 
		
	
		
			
				|  |  |  |  | 		> GET /v2/hello-mine/tags/list HTTP/1.1 | 
		
	
		
			
				|  |  |  |  | 		> User-Agent: curl/7.35.0 | 
		
	
		
			
				|  |  |  |  | 		> Host: localhost:5000 | 
		
	
		
			
				|  |  |  |  | 		> Accept: */* | 
		
	
		
			
				|  |  |  |  | 		>  | 
		
	
		
			
				|  |  |  |  | 		< HTTP/1.1 200 OK | 
		
	
		
			
				|  |  |  |  | 		< Content-Type: application/json; charset=utf-8 | 
		
	
		
			
				|  |  |  |  | 		< Docker-Distribution-Api-Version: registry/2.0 | 
		
	
		
			
				|  |  |  |  | 		< Date: Sun, 12 Apr 2015 01:29:47 GMT | 
		
	
		
			
				|  |  |  |  | 		< Content-Length: 40 | 
		
	
		
			
				|  |  |  |  | 		<  | 
		
	
		
			
				|  |  |  |  | 		{"name":"hello-mine","tags":["latest"]} | 
		
	
		
			
				|  |  |  |  | 		* Connection #0 to host localhost left intact | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 	You can also get this information by entering the | 
		
	
		
			
				|  |  |  |  | 	`http://52.10.125.146:5000/v2/hello-mine/tags/list` address in your browser. | 
		
	
		
			
				|  |  |  |  | 			 | 
		
	
		
			
				|  |  |  |  | 6. Remove all the unused images from your local environment: | 
		
	
		
			
				|  |  |  |  | 8. Remove all the unused images from your local environment: | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		$ docker rmi -f $(docker images -q -a ) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -86,7 +120,7 @@ local registry. | 
		
	
		
			
				|  |  |  |  | 		 registry         2.0     bbf0b6ffe923  3 days ago    545.1 MB | 
		
	
		
			
				|  |  |  |  | 		 golang           1.4     121a93c90463  5 days ago    514.9 MB | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 7. Try running `hello-mine`. | 
		
	
		
			
				|  |  |  |  | 9. Try running `hello-mine`. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		$ docker run hello-mine | 
		
	
		
			
				|  |  |  |  | 		Unable to find image 'hello-mine:latest' locally | 
		
	
	
		
			
				
					|  |  |  | @ -96,7 +130,7 @@ local registry. | 
		
	
		
			
				|  |  |  |  | 	The `run` command fails because your new image doesn't exist in the Docker public | 
		
	
		
			
				|  |  |  |  | 	registry. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 8. Now, try running the image but specifying the image's registry: | 
		
	
		
			
				|  |  |  |  | 10. Now, try running the image but specifying the image's registry: | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		$ docker run localhost:5000/hello-mine | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -128,7 +162,7 @@ factors: | 
		
	
		
			
				|  |  |  |  |   		access and/or authentication | 
		
	
		
			
				|  |  |  |  |   	</th> | 
		
	
		
			
				|  |  |  |  |   	<td> | 
		
	
		
			
				|  |  |  |  |   		Do users should have full or controlled access? This can depend on whether | 
		
	
		
			
				|  |  |  |  |   		Should users have full or controlled access? This can depend on whether | 
		
	
		
			
				|  |  |  |  |   		you are serving images to the public or internally to your company only. | 
		
	
		
			
				|  |  |  |  |   	</td> | 
		
	
		
			
				|  |  |  |  |   </tr> | 
		
	
	
		
			
				
					|  |  |  | @ -156,7 +190,7 @@ You can configure your registry features to adjust for these factors. You do | 
		
	
		
			
				|  |  |  |  | this by specifying options on the command line or, more typically, by writing a | 
		
	
		
			
				|  |  |  |  | registry configuration file. The configuration file is in YAML format. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | Docker's official repository image it is preconfigured using the following | 
		
	
		
			
				|  |  |  |  | Docker's official repository image is preconfigured using the following | 
		
	
		
			
				|  |  |  |  | configuration file: | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | ```yaml | 
		
	
	
		
			
				
					|  |  |  | @ -203,7 +237,6 @@ notifications: | 
		
	
		
			
				|  |  |  |  |         disabled: true | 
		
	
		
			
				|  |  |  |  | ``` | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | This configuration is very basic and you can see it would present some problems | 
		
	
		
			
				|  |  |  |  | in a production. For example, the `http` section details the configuration for | 
		
	
		
			
				|  |  |  |  | the HTTP server that hosts the registry. The server is not using even the most | 
		
	
	
		
			
				
					|  |  |  | @ -213,10 +246,10 @@ minimal transport layer security (TLS). Let's configure that in the next section | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | In this section, you configure TLS on the server to enable communication through | 
		
	
		
			
				|  |  |  |  | the `https` protocol. Enabling TLS on the server is the minimum layer of | 
		
	
		
			
				|  |  |  |  | security recommended for running a registry behind a corporate firewall. The | 
		
	
		
			
				|  |  |  |  | easiest way to do this is to build your own registry image.   | 
		
	
		
			
				|  |  |  |  | security recommended for running a registry behind a corporate firewall. One way | 
		
	
		
			
				|  |  |  |  | to do this is to build your own registry image.   | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | ### Download the registry source and generated certificates | 
		
	
		
			
				|  |  |  |  | ### Download the source and generate certificates | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 1. [Download the registry | 
		
	
		
			
				|  |  |  |  | source](https://github.com/docker/distribution/releases/tag/v2.0.0). | 
		
	
	
		
			
				
					|  |  |  | @ -241,55 +274,21 @@ source](https://github.com/docker/distribution/releases/tag/v2.0.0). | 
		
	
		
			
				|  |  |  |  | 				 -newkey rsa:2048 -nodes -keyout certs/domain.key \ | 
		
	
		
			
				|  |  |  |  | 				 -x509 -days 365 -out certs/domain.crt | 
		
	
		
			
				|  |  |  |  | 				  | 
		
	
		
			
				|  |  |  |  | 	This command prompts you for basic information it needs to create the certificates. | 
		
	
		
			
				|  |  |  |  | 				  | 
		
	
		
			
				|  |  |  |  | ### Add the certificates to the image | 
		
	
		
			
				|  |  |  |  | 6. List the contents of the `certs` directory. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | In this section, you copy the certifications from your `certs` directory into | 
		
	
		
			
				|  |  |  |  | your base image. | 
		
	
		
			
				|  |  |  |  | 							  | 
		
	
		
			
				|  |  |  |  | 1. Edit the `Dockerfile` and add a `CERTS_PATH` environment variable. | 
		
	
		
			
				|  |  |  |  |   | 
		
	
		
			
				|  |  |  |  | 		ENV CERTS_PATH  /etc/docker/registry/certs | 
		
	
		
			
				|  |  |  |  | 		$ ls certs | 
		
	
		
			
				|  |  |  |  | 		domain.crt  domain.key | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 2. Add a line to make the `CERTS_PATH` in the filesystem. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		RUN mkdir -v $CERTS_PATH | 
		
	
		
			
				|  |  |  |  | 		  | 
		
	
		
			
				|  |  |  |  | 3. Add `RUN` instructions to hard link your new certifications into this path: | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		RUN cp -lv ./certs/domain.crt $CERTS_PATH | 
		
	
		
			
				|  |  |  |  | 		RUN cp -lv ./certs/domain.key $CERTS_PATH | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		This copies your certifications into your container. | 
		
	
		
			
				|  |  |  |  |  			 | 
		
	
		
			
				|  |  |  |  | 4. Save your work. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	 At this point your Dockerfile should look like the following: | 
		
	
		
			
				|  |  |  |  | 	  | 
		
	
		
			
				|  |  |  |  | 		FROM golang:1.4 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		ENV CONFIG_PATH /etc/docker/registry/config.yml | 
		
	
		
			
				|  |  |  |  | 		ENV CERTS_PATH	/etc/docker/registry/certs | 
		
	
		
			
				|  |  |  |  | 		ENV DISTRIBUTION_DIR /go/src/github.com/docker/distribution | 
		
	
		
			
				|  |  |  |  | 		ENV GOPATH $DISTRIBUTION_DIR/Godeps/_workspace:$GOPATH | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		WORKDIR $DISTRIBUTION_DIR | 
		
	
		
			
				|  |  |  |  | 		COPY . $DISTRIBUTION_DIR | 
		
	
		
			
				|  |  |  |  | 		RUN make PREFIX=/go clean binaries | 
		
	
		
			
				|  |  |  |  | 		RUN mkdir -pv "$(dirname $CONFIG_PATH)" | 
		
	
		
			
				|  |  |  |  | 		RUN mkdir -v $CERTS_PATH | 
		
	
		
			
				|  |  |  |  | 		RUN cp -lv ./certs/domain.crt $CERTS_PATH | 
		
	
		
			
				|  |  |  |  | 		RUN cp -lv ./certs/domain.key $CERTS_PATH | 
		
	
		
			
				|  |  |  |  | 		RUN cp -lv ./cmd/registry/config.yml $CONFIG_PATH | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 5. Before you close the Dockerfile look for an instruction to copy the `config.yml` file. | 
		
	
		
			
				|  |  |  |  | 	When you build this container, the `certs` directory and its contents | 
		
	
		
			
				|  |  |  |  | 	automatically get copied also. | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 		RUN cp -lv ./cmd/registry/config.yml $CONFIG_PATH | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 	This is the default registry configuration file. You'll need to edit the file | 
		
	
		
			
				|  |  |  |  | 	to add TLS. | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | ### Add TLS to the registry configuration | 
		
	
		
			
				|  |  |  |  | ### Add TLS to the configuration | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | The `distribution` repo includes sample registry configurations in the `cmd` | 
		
	
		
			
				|  |  |  |  | subdirectory. In this section, you edit one of these configurations to add TLS | 
		
	
		
			
				|  |  |  |  | support.  | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 1. Edit the `./cmd/registry/config.yml`  file. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -311,8 +310,8 @@ your base image. | 
		
	
		
			
				|  |  |  |  | 				debug: | 
		
	
		
			
				|  |  |  |  | 						addr: localhost:5001 | 
		
	
		
			
				|  |  |  |  | 				tls: | 
		
	
		
			
				|  |  |  |  | 					certificate: /etc/docker/registry/certs/domain.crt | 
		
	
		
			
				|  |  |  |  | 					key: /etc/docker/registry/certs/domain.key	 | 
		
	
		
			
				|  |  |  |  | 					certificate: /go/src/github.com/docker/distribution/certs/domain.crt | 
		
	
		
			
				|  |  |  |  | 					key: /go/src/github.com/docker/distribution/certs/domain.key	 | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 	You provide the paths to the certificates in the container. If you want | 
		
	
		
			
				|  |  |  |  | 	two-way authentication across the layer, you can add an optional `clientcas` | 
		
	
	
		
			
				
					|  |  |  | @ -321,7 +320,7 @@ your base image. | 
		
	
		
			
				|  |  |  |  | 4. Save and close the file. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | ### Run your new image | 
		
	
		
			
				|  |  |  |  | ### Build and run your registry image | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 1. Build your registry image. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -329,138 +328,238 @@ your base image. | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 2. Run your new image. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		$ docker run -p 5000:5000 secure_registry | 
		
	
		
			
				|  |  |  |  | 		$ docker run -p 5000:5000 registry_local:latest | 
		
	
		
			
				|  |  |  |  | 		time="2015-04-12T03:06:18.616502588Z" level=info msg="endpoint local-8082 disabled, skipping" environment=development instance.id=bf33c9dc-2564-406b-97c3-6ee69dc20ec6 service=registry  | 
		
	
		
			
				|  |  |  |  | 		time="2015-04-12T03:06:18.617012948Z" level=info msg="endpoint local-8083 disabled, skipping" environment=development instance.id=bf33c9dc-2564-406b-97c3-6ee69dc20ec6 service=registry  | 
		
	
		
			
				|  |  |  |  | 		time="2015-04-12T03:06:18.617190113Z" level=info msg="using inmemory layerinfo cache" environment=development instance.id=bf33c9dc-2564-406b-97c3-6ee69dc20ec6 service=registry  | 
		
	
		
			
				|  |  |  |  | 		time="2015-04-12T03:06:18.617349067Z" level=info msg="listening on :5000, tls" environment=development instance.id=bf33c9dc-2564-406b-97c3-6ee69dc20ec6 service=registry  | 
		
	
		
			
				|  |  |  |  | 		time="2015-04-12T03:06:18.628589577Z" level=info msg="debug server listening localhost:5001"  | 
		
	
		
			
				|  |  |  |  | 		2015/04/12 03:06:28 http: TLS handshake error from 172.17.42.1:44261: remote error: unknown certificate authority | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		Watch the messages at startup. You should see that `tls` is running: | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		ubuntu@ip-172-31-34-181:~/repos/distribution$ docker run -p 5000:5000 secure_registry | 
		
	
		
			
				|  |  |  |  | 		time="2015-04-05T23:56:47Z" level=info msg="endpoint local-8082 disabled, skipping" app.id=3dd802ad-3bd4-4413-b56d-90c4acff41c7 environment=development service=registry  | 
		
	
		
			
				|  |  |  |  | 		time="2015-04-05T23:56:47Z" level=info msg="endpoint local-8083 disabled, skipping" app.id=3dd802ad-3bd4-4413-b56d-90c4acff41c7 environment=development service=registry  | 
		
	
		
			
				|  |  |  |  | 		time="2015-04-05T23:56:47Z" level=info msg="using inmemory layerinfo cache" app.id=3dd802ad-3bd4-4413-b56d-90c4acff41c7 environment=development service=registry  | 
		
	
		
			
				|  |  |  |  | 		time="2015-04-05T23:56:47Z" level=info msg="listening on :5000, tls" app.id=3dd802ad-3bd4-4413-b56d-90c4acff41c7 environment=development service=registry  | 
		
	
		
			
				|  |  |  |  | 		time="2015-04-05T23:56:47Z" level=info msg="debug server listening localhost:5001"  | 
		
	
		
			
				|  |  |  |  | 		2015/04/05 23:57:23 http: TLS handshake error from 172.17.42.1:52057: remote error: unknown certificate authority | 
		
	
		
			
				|  |  |  |  | 		Watch the messages at startup. You should see that `tls` is running. | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 3. Use `curl` to verify that you can connect over `https`. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		$ curl https://localhost:5000 | 
		
	
		
			
				|  |  |  |  | 		$ curl -v https://localhost:5000 | 
		
	
		
			
				|  |  |  |  | 		* Rebuilt URL to: https://localhost:5000/ | 
		
	
		
			
				|  |  |  |  | 		* Hostname was NOT found in DNS cache | 
		
	
		
			
				|  |  |  |  | 		*   Trying 127.0.0.1... | 
		
	
		
			
				|  |  |  |  | 		* Connected to localhost (127.0.0.1) port 5000 (#0) | 
		
	
		
			
				|  |  |  |  | 		* successfully set certificate verify locations: | 
		
	
		
			
				|  |  |  |  | 		*   CAfile: none | 
		
	
		
			
				|  |  |  |  | 			CApath: /etc/ssl/certs | 
		
	
		
			
				|  |  |  |  | 		* SSLv3, TLS handshake, Client hello (1): | 
		
	
		
			
				|  |  |  |  | 		* SSLv3, TLS handshake, Server hello (2): | 
		
	
		
			
				|  |  |  |  | 		* SSLv3, TLS handshake, CERT (11): | 
		
	
		
			
				|  |  |  |  | 		* SSLv3, TLS alert, Server hello (2): | 
		
	
		
			
				|  |  |  |  | 		* SSL certificate problem: self signed certificate | 
		
	
		
			
				|  |  |  |  | 		* Closing connection 0 | 
		
	
		
			
				|  |  |  |  | 		curl: (60) SSL certificate problem: self signed certificate | 
		
	
		
			
				|  |  |  |  | 		More details here: http://curl.haxx.se/docs/sslcerts.html | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | ## Configure Nginx with a v1 and v2 registry | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | This sections describes how to  user `docker-compose` to run a combined version | 
		
	
		
			
				|  |  |  |  | 1 and version 2.0 registry behind an `nginx` proxy. The combined registry is | 
		
	
		
			
				|  |  |  |  | accessed at `localhost:5000`. If a `docker` client has a version less than 1.6, | 
		
	
		
			
				|  |  |  |  | Nginx will route its requests to the 1.0 registry. Requests from newer clients | 
		
	
		
			
				|  |  |  |  | will route to the 2.0 registry. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | This procedure uses the same `distribution` directory you created in the last | 
		
	
		
			
				|  |  |  |  | procedure. The directory includes an example `compose` configuration.  | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | ### Install Docker Compose | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 1. Open a new terminal on the host with your `distribution` directory. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 2. Get the `docker-compose` binary. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		$ sudo wget https://github.com/docker/compose/releases/download/1.1.0/docker-compose-`uname  -s`-`uname -m` -O /usr/local/bin/docker-compose | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	This command installs the binary in the `/usr/local/bin` directory.  | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 3. Add executable permissions to the binary. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		$  sudo chmod +x /usr/local/bin/docker-compose | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | ## Adding a middleware configuration | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | This section describes how to configure storage middleware in a registry. | 
		
	
		
			
				|  |  |  |  | Middleware allows the registry to server layers via a content delivery network | 
		
	
		
			
				|  |  |  |  | (CDN). This is useful for reducing requests to the storage layer.   | 
		
	
		
			
				|  |  |  |  | ### Do some housekeeping | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | Currently, the registry supports [Amazon | 
		
	
		
			
				|  |  |  |  | Cloudfront](http://aws.amazon.com/cloudfront/).  You can only use Cloudfront in | 
		
	
		
			
				|  |  |  |  | conjunction with the S3 storage driver. | 
		
	
		
			
				|  |  |  |  | 1. Remove any previous images. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | <table> | 
		
	
		
			
				|  |  |  |  |   <tr> | 
		
	
		
			
				|  |  |  |  |     <th>Parameter</th> | 
		
	
		
			
				|  |  |  |  |     <th>Description</th> | 
		
	
		
			
				|  |  |  |  |   </tr> | 
		
	
		
			
				|  |  |  |  |   <tr> | 
		
	
		
			
				|  |  |  |  |     <td><code>name</code></td> | 
		
	
		
			
				|  |  |  |  |     <td>The storage middleware name. Currently <code>cloudfront</code> is an accepted value.</td> | 
		
	
		
			
				|  |  |  |  |   </tr> | 
		
	
		
			
				|  |  |  |  |   <tr> | 
		
	
		
			
				|  |  |  |  |     <td><code>disabled<code></td> | 
		
	
		
			
				|  |  |  |  |     <td>Set to <code>false</code> to easily disable the middleware.</td> | 
		
	
		
			
				|  |  |  |  |   </tr> | 
		
	
		
			
				|  |  |  |  |   <tr> | 
		
	
		
			
				|  |  |  |  |     <td><code>options:</code></td> | 
		
	
		
			
				|  |  |  |  |     <td>  | 
		
	
		
			
				|  |  |  |  |     A set of key/value options to configure the middleware. | 
		
	
		
			
				|  |  |  |  |     <ul> | 
		
	
		
			
				|  |  |  |  |     <li><code>baseurl:</code> The Cloudfront base URL.</li> | 
		
	
		
			
				|  |  |  |  |     <li><code>privatekey:</code> The location of your AWS private key on the filesystem. </li> | 
		
	
		
			
				|  |  |  |  |     <li><code>keypairid:</code> The ID of your Cloudfront keypair. </li> | 
		
	
		
			
				|  |  |  |  |  		<li><code>duration:</code> The duration in minutes for which the URL is valid. Default is 20. </li> | 
		
	
		
			
				|  |  |  |  |  		</ul> | 
		
	
		
			
				|  |  |  |  |     </td> | 
		
	
		
			
				|  |  |  |  |   </tr> | 
		
	
		
			
				|  |  |  |  | </table> | 
		
	
		
			
				|  |  |  |  | 		$ docker rmi -f $(docker images -q -a ) | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 	 This step is a house keeping step. It prevents you from mistakenly picking up | 
		
	
		
			
				|  |  |  |  | 	 an old image as you work through this example. | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 2. Edit the `distribution/cmd/registry/config.yml` file and remove the `tls` block. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | The following example illustrates these values: | 
		
	
		
			
				|  |  |  |  | 	If you worked through the previous example, you'll have a `tls` block.  | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | ``` | 
		
	
		
			
				|  |  |  |  | middleware: | 
		
	
		
			
				|  |  |  |  |     storage: | 
		
	
		
			
				|  |  |  |  |         - name: cloudfront | 
		
	
		
			
				|  |  |  |  |           disabled: false | 
		
	
		
			
				|  |  |  |  |           options: | 
		
	
		
			
				|  |  |  |  |              baseurl: http://d111111abcdef8.cloudfront.net | 
		
	
		
			
				|  |  |  |  |              privatekey: /path/to/asecret.pem | 
		
	
		
			
				|  |  |  |  |              keypairid: asecret | 
		
	
		
			
				|  |  |  |  |              duration: 60 | 
		
	
		
			
				|  |  |  |  | ``` | 
		
	
		
			
				|  |  |  |  | 4. Save any changes and close the file. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | ### Configure SSL | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | >**Note**: Cloudfront keys exist separately to other AWS keys.  See | 
		
	
		
			
				|  |  |  |  | >[the documentation on AWS credentials](http://docs.aws.amazon.com/AWSSecurityCredentials/1.0/ | 
		
	
		
			
				|  |  |  |  | >AboutAWSCredentials.html#KeyPairs) for more information. | 
		
	
		
			
				|  |  |  |  | 1. Change to the `distribution/contrib/compose/nginx` directory. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	This directory contains configuration files for Nginx and both registries. | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 2. Use SSL to generate some self-signed certificates. | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 		$ openssl req \ | 
		
	
		
			
				|  |  |  |  | 				 -newkey rsa:2048 -nodes -keyout domain.key \ | 
		
	
		
			
				|  |  |  |  | 				 -x509 -days 365 -out domain.crt | 
		
	
		
			
				|  |  |  |  | 				  | 
		
	
		
			
				|  |  |  |  | 	 This command prompts you for basic information it needs to create certificates. | 
		
	
		
			
				|  |  |  |  | 				  | 
		
	
		
			
				|  |  |  |  | 3. Edit the `Dockerfile`and add the following lines. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | **TODO(stevvooe): Need a "best practice" configuration overview. Perhaps, we can point to a documentation section. | 
		
	
		
			
				|  |  |  |  | 		COPY domain.crt /etc/nginx/domain.crt | 
		
	
		
			
				|  |  |  |  | 		COPY domain.key /etc/nginx/domain.key | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 	When you are done, the file looks like the following. | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 		FROM nginx:1.7 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		COPY nginx.conf /etc/nginx/nginx.conf | 
		
	
		
			
				|  |  |  |  | 		COPY registry.conf /etc/nginx/conf.d/registry.conf | 
		
	
		
			
				|  |  |  |  | 		COPY docker-registry.conf /etc/nginx/docker-registry.conf | 
		
	
		
			
				|  |  |  |  | 		COPY docker-registry-v2.conf /etc/nginx/docker-registry-v2.conf | 
		
	
		
			
				|  |  |  |  | 		COPY domain.crt /etc/nginx/domain.crt | 
		
	
		
			
				|  |  |  |  | 		COPY domain.key /etc/nginx/domain.key | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | # Configure nginx to deploy alongside v1 registry | 
		
	
		
			
				|  |  |  |  | 4. Save and close the `Dockerfile` file. | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 5. Edit the `registry.conf` file and add the following configuration.  | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | This sections describes how to configure nginx to proxy to both a v1 and v2 | 
		
	
		
			
				|  |  |  |  | registry. Nginx will handle routing of to the correct registry based on the | 
		
	
		
			
				|  |  |  |  | URL and Docker client version. | 
		
	
		
			
				|  |  |  |  | 		 ssl on; | 
		
	
		
			
				|  |  |  |  | 			ssl_certificate /etc/nginx/domain.crt; | 
		
	
		
			
				|  |  |  |  | 			ssl_certificate_key /etc/nginx/domain.key; | 
		
	
		
			
				|  |  |  |  | 			 | 
		
	
		
			
				|  |  |  |  | 	This is an `nginx` configuration file. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | ## Example configuration | 
		
	
		
			
				|  |  |  |  | With v1 registry running at `localhost:5001` and v2 registry running at | 
		
	
		
			
				|  |  |  |  | `localhost:5002`.  Add this to `/etc/nginx/conf.d/registry.conf`. | 
		
	
		
			
				|  |  |  |  | ``` | 
		
	
		
			
				|  |  |  |  | server { | 
		
	
		
			
				|  |  |  |  |   listen 5000; | 
		
	
		
			
				|  |  |  |  |   server_name localhost; | 
		
	
		
			
				|  |  |  |  | 6. Save and close the `registry.conf` file. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   ssl on; | 
		
	
		
			
				|  |  |  |  |   ssl_certificate /etc/docker/registry/certs/domain.crt; | 
		
	
		
			
				|  |  |  |  |   ssl_certificate_key /etc/docker/registry/certs/domain.key; | 
		
	
		
			
				|  |  |  |  | ### Build and run | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   client_max_body_size 0; # disable any limits to avoid HTTP 413 for large image uploads | 
		
	
		
			
				|  |  |  |  | 1. Go up to the `distribution/contrib/compose` directory | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   # required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486) | 
		
	
		
			
				|  |  |  |  |   chunked_transfer_encoding on; | 
		
	
		
			
				|  |  |  |  | 	This directory includes a single `docker-compose.yml` configuration. | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 		nginx: | 
		
	
		
			
				|  |  |  |  | 			build: "nginx" | 
		
	
		
			
				|  |  |  |  | 			ports: | 
		
	
		
			
				|  |  |  |  | 				- "5000:5000" | 
		
	
		
			
				|  |  |  |  | 			links: | 
		
	
		
			
				|  |  |  |  | 				- registryv1:registryv1 | 
		
	
		
			
				|  |  |  |  | 				- registryv2:registryv2 | 
		
	
		
			
				|  |  |  |  | 		registryv1: | 
		
	
		
			
				|  |  |  |  | 			image: registry | 
		
	
		
			
				|  |  |  |  | 			ports: | 
		
	
		
			
				|  |  |  |  | 				- "5000" | 
		
	
		
			
				|  |  |  |  | 		registryv2: | 
		
	
		
			
				|  |  |  |  | 			build: "../../" | 
		
	
		
			
				|  |  |  |  | 			ports: | 
		
	
		
			
				|  |  |  |  | 				- "5000" | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   location /v2/ { | 
		
	
		
			
				|  |  |  |  |     # Do not allow connections from docker 1.5 and earlier | 
		
	
		
			
				|  |  |  |  |     # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents | 
		
	
		
			
				|  |  |  |  |     if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) { | 
		
	
		
			
				|  |  |  |  |       return 404; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  This configuration builds a new `nginx` image as specified by the | 
		
	
		
			
				|  |  |  |  |  `nginx/Dockerfile` file. The 1.0 registry comes from Docker's official public | 
		
	
		
			
				|  |  |  |  |  image. Finally, the registry 2.0 image is built from the | 
		
	
		
			
				|  |  |  |  |  `distribution/Dockerfile` you've used previously. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     proxy_pass                       http://localhost:5002; | 
		
	
		
			
				|  |  |  |  |     proxy_set_header  Host           $http_host;   # required for docker client's sake | 
		
	
		
			
				|  |  |  |  |     proxy_set_header  X-Real-IP      $remote_addr; # pass on real client's IP | 
		
	
		
			
				|  |  |  |  |     proxy_read_timeout               900; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 2. Get a registry 1.0 image. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   location / { | 
		
	
		
			
				|  |  |  |  |     proxy_pass                       http://localhost:5001; | 
		
	
		
			
				|  |  |  |  |     proxy_set_header  Host           $http_host;   # required for docker client's sake | 
		
	
		
			
				|  |  |  |  |     proxy_set_header  X-Real-IP      $remote_addr; # pass on real client's IP | 
		
	
		
			
				|  |  |  |  |     proxy_set_header  Authorization  ""; # see https://github.com/docker/docker-registry/issues/170 | 
		
	
		
			
				|  |  |  |  |     proxy_read_timeout               900; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | ``` | 
		
	
		
			
				|  |  |  |  | 		$ docker pull registry:0.9.1  | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | ## Running nginx without a v1 registry | 
		
	
		
			
				|  |  |  |  | When running a v2 registry behind nginx without a v1 registry, the `/v1/` endpoint should | 
		
	
		
			
				|  |  |  |  | be explicitly configured to return a 404 if only the `/v2/` route is proxied. This | 
		
	
		
			
				|  |  |  |  | is needed due to the v1 registry fallback logic within Docker 1.5 and 1.6 which will attempt | 
		
	
		
			
				|  |  |  |  | to retrieve content from the v1 endpoint if no content was retrieved from v2. | 
		
	
		
			
				|  |  |  |  | 	The Compose configuration looks for this image locally. If you don't do this | 
		
	
		
			
				|  |  |  |  | 	step, later steps can fail. | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 3. Build `nginx`, the registry 2.0 image, and  | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		$ docker-compose build | 
		
	
		
			
				|  |  |  |  | 		registryv1 uses an image, skipping | 
		
	
		
			
				|  |  |  |  | 		Building registryv2... | 
		
	
		
			
				|  |  |  |  | 		Step 0 : FROM golang:1.4 | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		... | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		Removing intermediate container 9f5f5068c3f3 | 
		
	
		
			
				|  |  |  |  | 		Step 4 : COPY docker-registry-v2.conf /etc/nginx/docker-registry-v2.conf | 
		
	
		
			
				|  |  |  |  | 		 ---> 74acc70fa106 | 
		
	
		
			
				|  |  |  |  | 		Removing intermediate container edb84c2b40cb | 
		
	
		
			
				|  |  |  |  | 		Successfully built 74acc70fa106 | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 	The commmand outputs its progress until it completes. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 4. Start your configuration with compose. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		$ docker-compose up | 
		
	
		
			
				|  |  |  |  | 		Recreating compose_registryv1_1... | 
		
	
		
			
				|  |  |  |  | 		Recreating compose_registryv2_1... | 
		
	
		
			
				|  |  |  |  | 		Recreating compose_nginx_1... | 
		
	
		
			
				|  |  |  |  | 		Attaching to compose_registryv1_1, compose_registryv2_1, compose_nginx_1 | 
		
	
		
			
				|  |  |  |  | 		... | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 5. In another terminal, display the running configuration. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		$ docker ps | 
		
	
		
			
				|  |  |  |  | 		CONTAINER ID        IMAGE                       COMMAND                CREATED             STATUS              PORTS                                     NAMES | 
		
	
		
			
				|  |  |  |  | 		a81ad2557702        compose_nginx:latest        "nginx -g 'daemon of   8 minutes ago       Up 8 minutes        80/tcp, 443/tcp, 0.0.0.0:5000->5000/tcp   compose_nginx_1         | 
		
	
		
			
				|  |  |  |  | 		0618437450dd        compose_registryv2:latest   "registry cmd/regist   8 minutes ago       Up 8 minutes        0.0.0.0:32777->5000/tcp                   compose_registryv2_1    | 
		
	
		
			
				|  |  |  |  | 		aa82b1ed8e61        registry:latest             "docker-registry"      8 minutes ago       Up 8 minutes        0.0.0.0:32776->5000/tcp                   compose_registryv1_1    | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | ### Explore a bit | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 1. Check for TLS on your `nginx` server. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		$ curl -v https://localhost:5000 | 
		
	
		
			
				|  |  |  |  | 		* Rebuilt URL to: https://localhost:5000/ | 
		
	
		
			
				|  |  |  |  | 		* Hostname was NOT found in DNS cache | 
		
	
		
			
				|  |  |  |  | 		*   Trying 127.0.0.1... | 
		
	
		
			
				|  |  |  |  | 		* Connected to localhost (127.0.0.1) port 5000 (#0) | 
		
	
		
			
				|  |  |  |  | 		* successfully set certificate verify locations: | 
		
	
		
			
				|  |  |  |  | 		*   CAfile: none | 
		
	
		
			
				|  |  |  |  | 			CApath: /etc/ssl/certs | 
		
	
		
			
				|  |  |  |  | 		* SSLv3, TLS handshake, Client hello (1): | 
		
	
		
			
				|  |  |  |  | 		* SSLv3, TLS handshake, Server hello (2): | 
		
	
		
			
				|  |  |  |  | 		* SSLv3, TLS handshake, CERT (11): | 
		
	
		
			
				|  |  |  |  | 		* SSLv3, TLS alert, Server hello (2): | 
		
	
		
			
				|  |  |  |  | 		* SSL certificate problem: self signed certificate | 
		
	
		
			
				|  |  |  |  | 		* Closing connection 0 | 
		
	
		
			
				|  |  |  |  | 		curl: (60) SSL certificate problem: self signed certificate | 
		
	
		
			
				|  |  |  |  | 		More details here: http://curl.haxx.se/docs/sslcerts.html | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 2. Tag the `v1` registry image. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		 $ docker tag registry:latest localhost:5000/registry_one:latest | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 2. Push it to the localhost. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		 $ docker push localhost:5000/registry_one:latest | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 	If you are using the 1.6 Docker client, this pushes the image the `v2 `registry. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 4. Use `curl` to list the image in the registry. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 			$ curl -v -X GET http://localhost:32777/v2/registry1/tags/list | 
		
	
		
			
				|  |  |  |  | 			* Hostname was NOT found in DNS cache | 
		
	
		
			
				|  |  |  |  | 			*   Trying 127.0.0.1... | 
		
	
		
			
				|  |  |  |  | 			* Connected to localhost (127.0.0.1) port 32777 (#0) | 
		
	
		
			
				|  |  |  |  | 			> GET /v2/registry1/tags/list HTTP/1.1 | 
		
	
		
			
				|  |  |  |  | 			> User-Agent: curl/7.36.0 | 
		
	
		
			
				|  |  |  |  | 			> Host: localhost:32777 | 
		
	
		
			
				|  |  |  |  | 			> Accept: */* | 
		
	
		
			
				|  |  |  |  | 			>  | 
		
	
		
			
				|  |  |  |  | 			< HTTP/1.1 200 OK | 
		
	
		
			
				|  |  |  |  | 			< Content-Type: application/json; charset=utf-8 | 
		
	
		
			
				|  |  |  |  | 			< Docker-Distribution-Api-Version: registry/2.0 | 
		
	
		
			
				|  |  |  |  | 			< Date: Tue, 14 Apr 2015 22:34:13 GMT | 
		
	
		
			
				|  |  |  |  | 			< Content-Length: 39 | 
		
	
		
			
				|  |  |  |  | 			<  | 
		
	
		
			
				|  |  |  |  | 			{"name":"registry1","tags":["latest"]} | 
		
	
		
			
				|  |  |  |  | 			* Connection #0 to host localhost left intact | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 	This example refers to the specific port assigned to the 2.0 registry. You saw | 
		
	
		
			
				|  |  |  |  | 	this port earlier, when you used `docker ps` to show your running containers. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | Add this location block to explicitly block v1 requests. | 
		
	
		
			
				|  |  |  |  | ``` | 
		
	
		
			
				|  |  |  |  | localhost /v1/ { | 
		
	
		
			
				|  |  |  |  | 	return 404; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | ``` | 
		
	
	
		
			
				
					|  |  |  | 
 |