Skip to content

Commit 28ca2a6

Browse files
author
sophia parafina
committed
edited tutorial
1 parent d829aef commit 28ca2a6

File tree

3 files changed

+91
-92
lines changed

3 files changed

+91
-92
lines changed

registry/part-1.md

+45-56
Original file line numberDiff line numberDiff line change
@@ -2,111 +2,103 @@
22

33
There are several ways to run a registry container. The simplest is to run an insecure registry over HTTP, but for that we need to configure Docker to explicitly allow insecure access to the registry.
44

5-
## Testing the Registry Image
5+
Docker expects all registries to run on HTTPS. The next section of this lab will introduce a secure version of our registry container, but for this part of the tutorial we will run a version on HTTP. When registering a image, Docker returns an error message like this:
6+
```
7+
http: server gave HTTP response to HTTPS client
8+
```
9+
The Docker Engine needs to be explicitly setup to use HTTP for the insecure registry. Edit or create `/etc/docker/docker` file:
10+
```
11+
$ sudo vi /etc/docker/docker
612
7-
First we'll test that the registry image is working correctly, by running it without any special configuration:
13+
# add this line
14+
DOCKER_OPTS="--insecure-registry <localhost>:5000"
15+
```
16+
- where `localhost`0 is the name of your machine, which can be found with the `hostname` command
817

918
```
10-
docker run -d -p 5000:5000 --name registry registry:latest
19+
$ hostname
1120
```
12-
## Understanding Image Names
1321

22+
Close and save the file, then restart the docker daemon.
23+
```
24+
$ sudo service docker restart
25+
```
26+
## Testing the Registry Image
27+
First we'll test that the registry image is working correctly, by running it without any special configuration:
28+
```
29+
$ sudo docker run -d -p 5000:5000 --name registry registry:2
30+
```
31+
## Understanding Image Names
1432
Typically we work with images from the Docker Hub, which is the default registry for the Docker Engine. Commands using just the image repository name work fine, like this:
15-
1633
```
17-
docker pull nginx
34+
$ sudo docker pull hello-world
1835
```
19-
20-
`nginx` is the repository name, which we are using as a short form of the full image name. The full name is `docker.io/nginx:latest`. That breaks down into three parts:
36+
`hello-world` is the repository name, which we are using as a short form of the full image name. The full name is `docker.io/hello-world:latest`. That breaks down into three parts:
2137

2238
- `docker.io` - the hostname of the registry which stores the image;
23-
- `nginx` - the repository name, in this case in `{userName}/{imageName}` format;
39+
- `hello-world` - the repository name, in this case in `{imageName}` format;
2440
- `latest` - the image tag.
2541

2642
If a tag isn't specified, then the default `latest` is used. If a registry hostname isn't specified then the default `docker.io` for Docker Hub is used. If you want to use images with any other registry, you need to explicitly specify the hostname - the default is always Docker Hub, you can't change to a different default registry.
2743

28-
With a local registry, the hostname is the IP address or `localhost`, and the custom port used by the registry. The full registry address is `localhost:5000`.
44+
With a local registry, the hostname and the custom port used by the registry is the full registry address, e.g. `<hostname>:5000`.
45+
```
46+
$ hostname
47+
```
2948

3049
## Pushing and Pulling from the Local Registry
3150

3251
Docker uses the hostname from the full image name to determine which registry to use. We can build images and include the local registry hostname in the image tag, or use the `docker tag` command to add a new tag to an existing image.
3352

34-
These commands pull a public image from Docker Hub, tag it for use in the private registry with the full name `localhost:5000/labs/nginx`, and then push it to the registry:
53+
These commands pull a public image from Docker Hub, tag it for use in the private registry with the full name `<hostname>:5000/hello-world`, and then push it to the registry:
3554

3655
```
37-
docker pull nginx
38-
docker tag nginx localhost:5000/labs/nginx:latest
39-
docker push localhost:5000/labs/nginx:latest
56+
$ sudo docker tag hello-world <hostname>:5000/hello-world
57+
$ sudo docker push <hostname>:5000/hello-world
4058
```
4159

4260
When you push the image to your local registry, you'll see similar output to when you push a public image to the Hub:
4361

4462
```
45-
The push refers to a repository [localhost:5000/labs/nginx]
63+
The push refers to a repository [<hostname>:5000/hello-world]
4664
a55ad2cda2bf: Pushed
4765
cfbe7916c207: Pushed
4866
fe4c16cbf7a4: Pushed
4967
latest: digest: sha256:79e028398829da5ce98799e733bf04ac2ee39979b238e4b358e321ec549da5d6 size: 948
5068
```
51-
5269
On the local machine, you can remove the new image tag and the original image, and pull it again from the local registry to verify it was correctly stored:
53-
5470
```
55-
docker rmi localhost:5000/labs/nginx:latest
56-
docker rmi nginx:latest
57-
docker pull localhost:5000/labs/nginx:latest
71+
$ sudo docker rmi <hostname>:5000/hello-world
72+
$ sudo docker rmi hello-world
73+
$ sudo docker pull <hostname>:5000/hello-world
5874
```
59-
6075
That exercise shows the registry works correctly, but at the moment it's not very useful because all the image data is stored in the container's writable storage area, which will be lost when the container is removed. To store the data outside of the container, we need to mount a host directory when we start the container.
6176

6277
## Running a Registry Container with External Storage
63-
6478
Remove the existing registry container by removing the container which holds the storage layer. Any images pushed will be deleted:
65-
6679
```
67-
docker kill registry
68-
docker rm registry
80+
$ sudo docker kill registry
81+
$ sudo docker rm registry
6982
```
70-
7183
In this example, the new container will use a host-mounted Docker volume. When the registry server in the container writes image layer data, it appears to be writing to a local directory in the container but it will be writing to a directory on the host.
7284

73-
The IP address needs to be specified to use the same IP the previous registry had, because that's what Docker Engine is configured to use, and it's how the images are tagged. The `-v` option maps the host folder, and the `--ip` option specifies an IP address. First, create a network to assign an IP address to the container:
74-
75-
```
76-
docker network create --driver=bridge \
77-
--subnet=192.168.127.0/24 --gateway=192.168.127.1 \
78-
--ip-range=192.168.127.128/25 testbridge
79-
```
8085
Create the registry:
8186
```
82-
mkdir registry-data
83-
docker run -d -p 5000:5000 \
87+
$ mkdir registry-data
88+
$ sudo docker run -d -p 5000:5000 \
8489
--name registry \
85-
-v registry-data:/var/lib/registry \
86-
--network testbridge \
87-
--ip 192.168.127.128 \
90+
-v `pwd`/registry-data:/var/lib/registry \
8891
registry
8992
```
90-
91-
Docker expects all registries to run on HTTPS. The next section of this lab will introduce a secure version of our registry container, but the current version runs on HTTP. When registering a image, Docker returns an error message like this:
92-
```
93-
http: server gave HTTP response to HTTPS client
94-
```
95-
The Docker Engine needs to be explicitly setup to use HTTP for the insecure registry. This can be set by clicking on ![](images/moby.png)
96-
97-
`Preferences`
98-
![](images/preferences.png)
99-
`Daemon` > `Insecure registries` and enter the IP address and port of the registry.
100-
![](images/config_insecure_registry_osx.png)
10193
Tag and push the container with the new IP address of the registry.
10294
```
103-
docker tag nginx 192.168.127.128:5000/labs/nginx:latest
104-
docker push 192.168.127.128:5000/labs/nginx:latest
95+
docker tag hello-world <hostname>:5000/hello-world
96+
docker push <hostname>:5000/hellow-world
10597
```
106-
Repeating the previous `docker push` command uploads an image to the registry container, and the layers will be stored in the container's `/var/lib/registry` directory, which is actually mapped to the `$(pwd)/registry-data` directory on you local machine. The `tree` command will show the directory structure the registry server uses (if `tree` is not installed in OS X, `find` with also work):
98+
Repeating the previous `docker push` command uploads an image to the registry container, and the layers will be stored in the container's `/var/lib/registry` directory, which is actually mapped to the `$(pwd)/registry-data` directory on you local machine. The `tree` command will show the directory structure the registry server uses:
10799

108100
```
109-
registry-data find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
101+
$ tree registry-data
110102
.
111103
|____docker
112104
| |____registry
@@ -118,11 +110,8 @@ registry-data find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
118110
119111
...
120112
```
121-
122113
Storing data outside of the container means we can build a new version of the registry image and replace the old container with a new one using the same host mapping - so the new registry container has all the images stored by the previous container.
123114

124-
This container is still limited though. The container is accessible externally using the host's IP address, but that's different from the container's IP address - so you need to use different tags and a different engine configuration for external clients.
125-
126115
Using an insecure registry also isn't practical in multi-user scenarios. Effectively there's no security so anyone can push and pull images if they know the registry hostname. The registry server supports authentication, but only over a secure SSL connection. We'll run a secure version of the registry server in a container next.
127116

128117
## Next

registry/part-2.md

+23-12
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22

33
We saw how to run a simple registry container in [Part 1](part-1.md), using the official Docker registry image. The registry server con be configured to serve HTTPS traffic on a known domain, so it's straightforward to run a secure registry for private use with a self-signed SSL certificate.
44

5-
## Generating the SSL Certificate
5+
## Generating the SSL Certificate in Linux
66

7-
### Create an SSL Certificate in Linux
87
The Docker docs explain how to [generate a self-signed certificate](https://docs.docker.com/registry/insecure/#/using-self-signed-certificates) on Linux using OpenSSL:
98

109
```
@@ -29,9 +28,22 @@ State or Province Name (full name) [Some-State]:
2928
Locality Name (eg, city) []:
3029
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Docker
3130
Organizational Unit Name (eg, section) []:
32-
Common Name (e.g. server FQDN or YOUR name) []:<host name>
31+
Common Name (e.g. server FQDN or YOUR name) []:<hostname>
3332
Email Address []:
3433
```
34+
If you are running the registry locally, be sure to use your host name as the CN.
35+
36+
To get the docker daemon to trust the certificate, copy the domain.crt file.
37+
```
38+
$ sudo su
39+
$ mkdir /etc/docker/certs.d
40+
$ mkdir /etc/docker/certs.d/<localhost>:5000
41+
$ cp `pwd`/certs/domain.crt /etc/docker/certs.d/<localhost>:5000/ca.crt
42+
```
43+
Make sure to restart the docker daemon.
44+
```
45+
$ sudo service docker restart
46+
```
3547
Now we have an SSL certificate and can run a secure registry.
3648

3749
## Running the Registry Securely
@@ -41,15 +53,15 @@ The registry server supports several configuration switches as environment varia
4153
If you have an insecure registry container still running from [Part 2](part-2.md), remove it:
4254

4355
```
44-
> docker kill registry
45-
> docker rm registry
56+
$ docker kill registry
57+
$ docker rm registry
4658
```
4759

4860
For the secure registry, we need to run a container which has the SSL certificate and key files available, which we'll do with an additional volume mount (so we have one volume for registry data, and one for certs). We also need to specify the location of the certificate files, which we'll do with environment variables:
4961

5062
```
51-
> mkdir registry-data
52-
> docker run -d -p 5000:5000 --name registry \
63+
$ mkdir registry-data
64+
$ docker run -d -p 5000:5000 --name registry \
5365
--restart unless-stopped \
5466
-v $(pwd)/registry-data:/var/lib/registry -v $(pwd)/certs:/certs \
5567
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
@@ -68,12 +80,11 @@ We'll let Docker assign a random IP address to this container, because we'll be
6880

6981
## Accessing the Secure Registry
7082

71-
We're ready to run a secure registry now.
83+
We're ready to push an image into our secure registry.
84+
```
85+
$ docker push <hostname>:5000/hello-world
86+
$ docker pull <hostname>:5000/hello-world
7287
```
73-
> docker tag hello-world mylocalregistry:5000/hello-world
74-
> docker push mylocalregistry:5000/hello-world
75-
> docker pull mylocalregistry:5000/hello-world
76-
7788
We can go one step further with the open-source registry server, and add basic authentication - so we can require users to securely log in to push and pull images.
7889

7990
## Next

registry/part-3.md

+23-24
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,23 @@ From [Part 2](part-2.md) we have a registry running in a Docker container, which
44

55
## Usernames and Passwords
66

7-
The registry server and the Docker client support [basic authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) over HTTPS. The server uses a file with a collection of usernames and encrypted passwords. The file uses a common standard from the Linux world - [Apache htpasswd].
7+
The registry server and the Docker client support [basic authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) over HTTPS. The server uses a file with a collection of usernames and encrypted passwords. The file uses Apache's htpasswd.
88

9-
Create the password file with an entry for user "moby" with password "DockerRules";
9+
Create the password file with an entry for user "moby" with password "gordon";
1010
```
11-
> mkdir auth
12-
> docker run --entrypoint htpasswd registry:latest -bn moby DockerRules > auth/htpasswd
11+
$ mkdir auth
12+
$ sudo docker run --entrypoint htpasswd registry:latest -bn moby gordon > auth/htpasswd
1313
```
1414
The options are:
1515

1616
- --entrypoint Overwrite the default ENTRYPOINT of the image
1717
- -b run in batch mode
1818
- -n display results
1919

20-
We can verify the entries have been written by checking the file contents - which should show the usernames in plain text and a cipher text password:
20+
We can verify the entries have been written by checking the file contents - which shows the user names in plain text and a cipher text password:
2121

22-
```PowerShell
23-
> cat auth/htpasswd
22+
```
23+
$ cat auth/htpasswd
2424
moby:$apr1$xnxYmr0O$S4HXd0ACkZkpp40YCw/lW/
2525
```
2626

@@ -31,23 +31,22 @@ Adding authentication to the registry is a similar process to adding SSL - we ne
3131
As before, we'll remove the existing container and run a new one with authentication configured:
3232

3333
```
34-
> docker kill registry
35-
> docker rm registry
36-
37-
> docker run -d -p 5000:5000 --name registry \
34+
$ sudo docker kill registry
35+
$ sudo docker rm registry
36+
$ sudo docker run -d -p 5000:5000 --name registry \
3837
--restart unless-stopped \
3938
-v $(pwd)/registry-data:/var/lib/registry \
4039
-v $(pwd)/certs:/certs \
4140
-v $(pwd)/auth:/auth \
4241
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
4342
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
4443
-e REGISTRY_AUTH=htpasswd \
45-
-e REGISTRY_AUTH_HTPASSWD_REALM='Registry Realm' \
46-
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
44+
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
45+
-e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
4746
registry
4847
```
4948

50-
The new options for this container are:
49+
The options for this container are:
5150

5251
- `-v $(pwd)/auth:/auth` - mount the local `auth` folder into the container, so the registry server can access `htpasswd` file;
5352
- `-e REGISTRY_AUTH=htpasswd` - use the registry's `htpasswd` authentication method;
@@ -60,17 +59,17 @@ Now the registry is using secure transport and user authentication.
6059

6160
With basic authentication, users cannot push or pull from the registry unless they are authenticated. If you try and pull an image without authenticating, you will get an error:
6261

63-
```PowerShell
64-
> docker pull registry.local:5000/labs/hello-world
62+
```
63+
$ sudo docker pull <hostname>:5000/hello-world
6564
Using default tag: latest
66-
Error response from daemon: Get https://registry.local:5000/v2/labs/hello-world/manifests/latest: no basic auth credentials
65+
Error response from daemon: Get https://<hostname>:5000/v2/hello-world/manifests/latest: no basic auth credentials
6766
```
6867

6968
The result is the same for valid and invalid image names, so you can't even check a repository exists without authenticating. Logging in to the registry is the same `docker login` command you use for Docker Hub, specifying the registry hostname:
7069

71-
```PowerShell
72-
> docker login registry.local:5000
73-
Username: elton
70+
```
71+
$ sudo docker login registry.local:5000
72+
Username: moby
7473
Password:
7574
Login Succeeded
7675
```
@@ -83,12 +82,12 @@ Error response from daemon: login attempt to https://registry.local:5000/v2/ fai
8382

8483
Now you're authenticated, you can push and pull as before:
8584

86-
```PowerShell
87-
> docker pull registry.local:5000/labs/hello-world
85+
```
86+
$ sudo docker pull <hostname>:5000/hello-world
8887
Using default tag: latest
89-
latest: Pulling from labs/hello-world
88+
latest: Pulling from hello-world
9089
Digest: sha256:961497c5ca49dc217a6275d4d64b5e4681dd3b2712d94974b8ce4762675720b4
91-
Status: Image is up to date for registry.local:5000/labs/hello-world:latest
90+
Status: Image is up to date for registry.local:5000/hello-world:latest
9291
```
9392

9493
> Note. The open-source registry does not support the same authorization model as Docker Hub or Docker Trusted Registry. Once you are logged in to the registry, you can push and pull from any repository, there is no restriction to limit specific users to specific repositories.

0 commit comments

Comments
 (0)