DockerHub provides us with many official images and images uploaded by individuals, or we can download images provided by institutions or individuals or upload our own local images using a third-party image warehouse, but the disadvantages are:
- Due to the network, downloading and uploading images from DockerHub may be slow;
- The Docker image used in production may contain our code, configuration information, etc. it does not want to be obtained by external personnel, but can only be downloaded by developers on the intranet.
In order to solve the above problems, Docker officially provides an image called registry for building a local private warehouse. The Docker private warehouse built on the internal network can enable intranet personnel to download and upload very quickly, which is not affected by external network bandwidth and other factors. At the same time, people who are not on the internal network can not download our image, and the private warehouse also supports the configuration of warehouse authentication function.
1, Establishment of registry private warehouse
Create a private warehouse container using the registry image
After installing Docker, you can simply build a local private warehouse environment through the registry image provided by the official:
[root@docker ~]# docker run -d --name myregistry -p 5000:5000 -v /mnt/my_registry:/var/lib/registry registry ad2a3a85f7f4fa1ad059250f566e2e51dbb4d837a7c533f36b5eb60dd2cfe34f # Parameters: -d Background operation --name Name the container you created -p Port mapping, the service runs with 5000 port communication by default -v The data volume is mounted. By default, the warehouse will be created in the container /var/lib/registry Directory. Can pass -v Parameter to store the image file in the specified local path. [root@docker ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ad2a3a85f7f4 registry "/entrypoint.sh /etc..." 24 seconds ago Up 22 seconds 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp myregistry
Open the browser and enter:
http://192.168.126.20:5000/v2/_catalog
Display {"repositories": []} indicates that the private warehouse is built successfully and the content is empty.
2, Push image to private warehouse
Perform the following steps on any host that installs Docker service and can connect to the private warehouse host (including installing the local machine of the private warehouse host) to push the image to the private warehouse
Modify configuration
Modify the daemon JSON file
[root@docker ~]# vim /etc/docker/daemon.json { "registry-mirrors": [ "https://e9hk8fzj.mirror.aliyuncs.com", "https://docker.mirrors.ustc.edu.cn" ], "insecure-registries": ["192.168.126.20:5000"] # The content added in this behavior is the IP address of the host running the warehouse container, and the port is consistent with the host port specified when using the registry image to run the container }
Reload the configuration information and restart the Docker service
[root@docker ~]# systemctl daemon-reload && systemctl restart docker
Image labeling
You must first set a label for the image to be pushed and uploaded
Usage: docker tag SOURCE_IMAGE[:TAG] IP:PORT/TARGET_IMAGE[:TAG] [root@docker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE registry latest 1fd8e1b0bb7e 2 months ago 26.2MB busybox 1.31.1 1c35c4412082 13 months ago 1.22MB [root@docker ~]# docker tag busybox:1.31.1 192.168.126.20:5000/busybox_v1:1.31.1 [root@docker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE registry latest 1fd8e1b0bb7e 2 months ago 26.2MB 192.168.126.20:5000/busybox_v1 1.31.1 1c35c4412082 13 months ago 1.22MB busybox 1.31.1 1c35c4412082 13 months ago 1.22MB
Push image to private warehouse
Usage: docker push IP:PORT/TARGET_IMAGE[:TAG] [root@docker ~]# docker push 192.168.126.20:5000/busybox_v1:1.31.1 The push refers to repository [192.168.126.20:5000/busybox_v1] 1be74353c3d0: Pushed 1.31.1: digest: sha256:fd4a8673d0344c3a7f427fe4440d4b8dfd4fa59cfabbd9098f9eb0cb4ba905d0 size: 527
3, View images in the warehouse
Usage:
# Query image curl -XGET http://IP:PORT/v2/_catalog # Query image tag (version) curl -XGET http://IP:PORT/v2/IMAGE_NAME/tags/list # Get image digest_hash curl http://IP:PORT/v2/IMAGE_NAME/manifests/TAG_NAME --header "Accept: application/vnd.docker.distribution.manifest.v2+json"
View on the host where the warehouse is built
# View data volumes [root@docker ~]# ls /mnt/my_registry/ docker [root@docker ~]# ls /mnt/my_registry/docker/registry/v2/repositories/busybox_v1/ _layers _manifests _uploads # View in container [root@docker ~]# docker exec -it myregistry /bin/sh / # ls /var/lib/registry/docker/registry/v2/repositories/ busybox_v1 [root@docker ~]# curl -XGET http://192.168.126.20:5000/v2/_catalog {"repositories":["busybox_v1"]} [root@docker ~]# curl -XGET http://192.168.126.20:5000/v2/busybox_v1/tags/list {"name":"busybox_v1","tags":["1.31.1"]} # Or access in the browser http://192.168.126.20:5000/v2/_catalog
Or view it on the client where the image is uploaded
[root@k8s-master ~]# curl -XGET http://192.168.126.20:5000/v2/_catalog {"repositories":["busybox_v1"]} [root@k8s-master ~]# curl -XGET http://192.168.126.20:5000/v2/busybox_v1/tags/list {"name":"busybox_v1","tags":["1.31.1"]} # Or access in the browser http://192.168.126.20:5000/v2/_catalog
[root@k8s-master ~]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I -X HEAD http://192.168.126.20:5000/v2/hello_test/manifests/v1 [root@k8s-master ~]# curl -v -X DELETE http://192.168.126.20:5000/v2/hello_test/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792
4, Deletion of image in private warehouse
At first, when installing the private warehouse, I didn't think about deleting the image. When I want to delete the uploaded image, the image can't be deleted. It's more troublesome, so I have to run the private warehouse container again
In version 2.1, Docker warehouse supports the API for deleting images, but this deletion operation will only delete image metadata, not layer data. In version 2.4, this problem is solved by adding a garbage collection command to delete unreferenced layer data
First, the registry needs to enable deletion
Because the default Docker private registry does not allow you to delete images, if you encounter a "405 Unsupported" error, you need to modify the relevant parameters in the configuration file when running the registry container
# Enable delete (add delete: enabled: true) [root@docker ~]# docker exec -it myregistry sh -c "sed -i '/storage:/a\ delete:' /etc/docker/registry/config.yml" [root@docker ~]# docker exec -it myregistry sh -c "sed -i '/delete:/a\ enabled: true' /etc/docker/registry/config.yml" # see [root@docker ~]# docker exec -it myregistry cat /etc/docker/registry/config.yml version: 0.1 log: fields: service: registry storage: delete: # Added by this behavior enabled: true # Added by this behavior cache: blobdescriptor: inmemory filesystem: rootdirectory: /var/lib/registry http: addr: :5000 headers: X-Content-Type-Options: [nosniff] health: storagedriver: enabled: true interval: 10s threshold: 3
Restart private warehouse container
[root@docker ~]# docker restart myregistry myregistry
View images in the warehouse
[root@docker ~]# curl -XGET http://192.168.126.20:5000/v2/_catalog {"repositories":["busybox_v1","hello_test"]} # View version [root@docker ~]# curl -XGET http://192.168.126.20:5000/v2/hello_test/tags/list {"name":"hello_test","tags":["v1"]} [root@docker ~]# curl -XGET http://192.168.126.20:5000/v2/busybox_v1/tags/list {"name":"busybox_v1","tags":["1.31.1"]}
Get image digest_hash
[root@docker ~]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I -X HEAD http://192.168.126.20:5000/v2/hello_test/manifests/v1 HTTP/1.1 200 OK Content-Length: 525 Content-Type: application/vnd.docker.distribution.manifest.v2+json Docker-Content-Digest: sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 Docker-Distribution-Api-Version: registry/2.0 Etag: "sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792" X-Content-Type-Options: nosniff Date: Mon, 28 Jun 2021 08:19:30 GMT [root@docker ~]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I -X HEAD http://192.168.126.20:5000/v2/busybox_v1/manifests/1.31.1 HTTP/1.1 200 OK Content-Length: 527 Content-Type: application/vnd.docker.distribution.manifest.v2+json Docker-Content-Digest: sha256:fd4a8673d0344c3a7f427fe4440d4b8dfd4fa59cfabbd9098f9eb0cb4ba905d0 Docker-Distribution-Api-Version: registry/2.0 Etag: "sha256:fd4a8673d0344c3a7f427fe4440d4b8dfd4fa59cfabbd9098f9eb0cb4ba905d0" X-Content-Type-Options: nosniff Date: Mon, 28 Jun 2021 08:24:17 GMT
Delete mirrored API
Usage:
DELETE /v2/<name>/manifests/<reference> # Usage: curl -v -X DELETE http://IP : PORT/v2/IMAGE_NAME/manifests/REFERENCE # Name: image name # reference: image corresponding sha256 value
delete mirror
[root@docker ~]# curl -v -X DELETE http://192.168.126.20:5000/v2/hello_test/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 * About to connect() to 192.168.126.20 port 5000 (#0) * Trying 192.168.126.20... * Connected to 192.168.126.20 (192.168.126.20) port 5000 (#0) > DELETE /v2/hello_test/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 HTTP/1.1 > User-Agent: curl/7.29.0 > Host: 192.168.126.20:5000 > Accept: */* > < HTTP/1.1 202 Accepted < Docker-Distribution-Api-Version: registry/2.0 < X-Content-Type-Options: nosniff < Date: Mon, 28 Jun 2021 08:29:58 GMT < Content-Length: 0 < * Connection #0 to host 192.168.126.20 left intact
The delete image here only deletes some metadata. You need to perform garbage collection to really delete the image data from the hard disk
Perform garbage collection: registry garbage-collect /etc/docker/registry/config.yml
garbage collection
Usage:
registry garbage-collect /etc/docker/registry/config.yml
Enter private warehouse containers for garbage collection
[root@docker ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ad2a3a85f7f4 registry "/entrypoint.sh /etc..." 2 hours ago Up 7 minutes 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp myregistry [root@docker ~]# docker exec -it myregistry /bin/sh / # registry garbage-collect /etc/docker/registry/config.yml busybox_v1 busybox_v1: marking manifest sha256:fd4a8673d0344c3a7f427fe4440d4b8dfd4fa59cfabbd9098f9eb0cb4ba905d0 busybox_v1: marking blob sha256:1c35c441208254cb7c3844ba95a96485388cef9ccc0646d562c7fc026e04c807 busybox_v1: marking blob sha256:76df9210b28cbd4bc127844914d0a23937ed213048dc6289b2a2d4f7d675c75e hello_test 3 blobs marked, 3 blobs and 0 manifests eligible for deletion blob eligible for deletion: sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/1b/1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 go.version=go1.11.2 instance.id=3e01bf0b-8ca7-4b3f-9114-9290839edb2d service=registry blob eligible for deletion: sha256:b8dfde127a2919ff59ad3fd4a0776de178a555a76fff77a506e128aea3ed41e3 INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/b8/b8dfde127a2919ff59ad3fd4a0776de178a555a76fff77a506e128aea3ed41e3 go.version=go1.11.2 instance.id=3e01bf0b-8ca7-4b3f-9114-9290839edb2d service=registry blob eligible for deletion: sha256:d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726 INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/d1/d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726 go.version=go1.11.2 instance.id=3e01bf0b-8ca7-4b3f-9114-9290839edb2d service=registry
Deleted successfully.
5, Private warehouse authentication function
To ensure the security of the private warehouse, you also need a security certificate to prevent unexpected things. Therefore, you need to create a self signed certificate on the Docker host where the private warehouse is built.
Create certificate store directory
[root@docker ~]# mkdir -p /usr/local/registry/certs
Generate self signed certificate
Mr. openssl generates a self signed certificate. After running the command, you need to fill in some certificate information. The most critical part is: Common Name (eg, your name or your server's hostname) []:192.168.126.20. Here is the address of the private warehouse
[root@docker ~]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/registry/certs/domain.key -x509 -days 365 -out /usr/local/registry/certs/domain.crt Generating a 2048 bit RSA private key ...............+++ ...................................+++ writing new private key to '/usr/local/registry/certs/domain.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:cn State or Province Name (full name) []:sx Locality Name (eg, city) [Default City]:sl Organization Name (eg, company) [Default Company Ltd]:test Organizational Unit Name (eg, section) []:it Common Name (eg, your name or your server's hostname) []:192.168.126.20 # Here is the address of the private warehouse Email Address []:1234567@163.com openssl req: Create certificate signing request and other functions; -newkey: establish CSR Certificate signature file and RSA Private key file; rsa:2048: Specify the created RSA The length of the private key is 2048; -nodes: Do not encrypt the private key; -sha256: use SHA256 Algorithm; -keyout: Name and location of the created private key file; -x509: Form of self issued certificate; -days: Validity period of certificate; -out: appoint CSR Name and location of output file;
Generate authentication password file
# Create a directory to store authentication password files [root@docker ~]# mkdir -p /usr/local/registry/auth # If there is no htpasswd function, you need to install httpd [root@docker ~]# yum install -y httpd # Create user and password [root@docker ~]# htpasswd -Bbn zhangsan 123456 > /usr/local/registry/auth/htpasswd # Htpasswd is the basic authentication file of apache http. You can use htpasswd command to generate user and password files. User name zhangsan, password 123456
Create private warehouse container
[root@docker ~]# docker run -di --name myregistry -p 5000:5000 \ -v /mydata/docker_registry:/var/lib/registry \ -v /usr/local/registry/certs:/certs \ -v /usr/local/registry/auth:/auth \ -e "REGISTRY_AUTH=htpasswd" \ -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \ -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \ registry d7d612a0c914f0bcf68ac0a9447bdc79ab43e404c2584a48dc1f0ccb19ed1fdc [root@docker ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d7d612a0c914 registry "/entrypoint.sh /etc..." 14 seconds ago Up 12 seconds 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp myregistry
Modify the daemon of Docker client JSON file
[root@docker-client ~]# vim /etc/docker/daemon.json { "registry-mirrors": [ "https://e9hk8fzj.mirror.aliyuncs.com", "https://docker.mirrors.ustc.edu.cn" ], "insecure-registries": ["192.168.126.20:5000"] # The content added in this behavior is the IP address of the host running the warehouse container, and the port is consistent with the host port specified when using the registry image to run the container }
Label the local image on the Docker client
[root@docker-client ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos 7 8652b9f0cb4c 7 months ago 204MB [root@docker-client ~]# docker tag centos:7 192.168.126.20:5000/centos_test:v1 [root@k8s-docker-client ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE 192.168.126.20:5000/centos_test v1 8652b9f0cb4c 7 months ago 204MB centos 7 8652b9f0cb4c 7 months ago 204MB 7 8652b9f0cb4c 7 months ago 204MB
Failed to push image to private warehouse
[root@k8s-docker-client ~]# docker push 192.168.126.20:5000/centos_test:v1 The push refers to repository [192.168.126.20:5000/centos_test] 174f56854903: Preparing no basic auth credentials # Because there is no login authentication.
If you directly push the image, it will certainly fail, and the error of no basic auth credentials appears, because there is no login authentication.
Login account
Log in to the private warehouse by entering the account and password through the docker login command
[root@k8s-docker-client ~]# docker login 192.168.126.20:5000 -u zhangsan -p 123456 WARNING! Using --password via the CLI is insecure. Use --password-stdin. WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded
Push image to private warehouse succeeded
push the image again and find that it can be pushed successfully.
[root@k8s-master ~]# docker push 192.168.126.20:5000/centos_test:v1 The push refers to repository [192.168.126.20:5000/centos_test] 174f56854903: Pushed v1: digest: sha256:e4ca2ed0202e76be184e75fb26d14bf974193579039d5573fb2348664deef76e size: 529
see
View via browser
The construction of private image warehouse can also be realized through harbor. Harbor is an enterprise Docker Registry management project open source by VMware company. It includes rights management (RBAC), LDAP, log audit, management interface, self registration, image replication, Chinese support and other functions.