Introduction
Table of Contents
Without images there is no reason of running Docker. Images are integral part of infrastructure like virtual machines on hypervisor environment. In this article we are covering basic container operations (search, pull, push, list,) public and private registries and tagging operation. Docker by default is accessing official Docker Hub site (hub.docker.com). But you can always switch access to other public or your private registry. It is very important to know how to search, pull, push and tag container images. So let’s see how it works.
Public registries
Public registries are easiest and most straightforward way to access and download images. You have to consider if your environment includes production services because public images are not known by its secure nature. Everybody with account can push and publish images. Reports say that 70% of images on Docker Hub are not secure. Our recommendation is to be careful with public images and use them in test environment only. One of the trusted sources for public images is Red Hat image repository. Check the Docker security for more details.
Basic image operations
Search
To search for particular image you can use Docker search command:
[root@swmanager Docker]# Docker search mysql
NAME DESCRIPTION STARS OFFICIAL mysql MySQL is a widely used, open-source relation… 9609 [OK] mariadb is a community-developed fork of MyS… 3493 [OK] mysql/mysql-server Optimized MySQL Server Docker images. Create… 702 [OK] centos/mysql-57-centos7 MySQL 5.7 SQL database server 76 mysql/mysql-cluster Experimental MySQL Cluster Docker images. Cr… 69 centurylink/mysql Image containing mysql. Optimized to be link… 61 [OK] deitch/mysql-backup REPLACED! Please use http://hub.docker.com/r… 41 [OK] |
There are few handy switches you can use to filter the search:
–filter=is-automated (images built with Dockerfile)
–stars=N (number of stars, i.e. image ratings by user experience)
Let’s check for automated builds with stars more than 500:
[root@swmanager Docker]# Docker search mysql –filter=is-automated=true –filter=stars=500
NAME DESCRIPTION STARS OFFICIAL mysql/mysql-server Optimized MySQL Server Docker images. Create… 702 [OK] |
Pull command
Use the pull command to retrieve images from the defined registry. Leave the default configuration Docker automatically pulls images from Docker Hub.
[root@swmanager Docker]# Docker pull mysql
Using default tag: latest latest: Pulling from library/mysql 8559a31e96f4: Pull complete d51ce1c2e575: Pull complete ….. |
Pull images with all tags included:
[root@swmanager /]# Docker pull Redis –all-tags=true
2-32bit: Pulling from library/Redis 51f5c6a04d83: Pull complete ….. 2.6-32bit: Pulling from library/Redis d4bce7fd68df: Download complete …. 2.6.17-32bit: Pulling from library/Redis …. 2.8-32bit: Pulling from library/Redis …. |
Docker images are stored locally on same system where Docker is installed. To check local images use Docker images command:
[root@swmanager /]# Docker images
REPOSITORY TAG IMAGE ID CREATED SIZE nginx <none> 602e111c06b6 6 weeks ago 127MB ubuntu latest 72300a873c2c 3 months ago 64.2MB centos latest 470671670cac 4 months ago 237MB hello-world latest fce289e99eb9 17 months ago 1.84kB Redis 2-32bit 19865a7ae96c 4 years ago 203MB Redis 2.8-32bit 19865a7ae96c 4 years ago 203MB Redis 2.6-32bit 62b0a5c3ea45 4 years ago 158MB Redis 2.6.17-32bit 62b0a5c3ea45 4 years ago 158MB Redis 2.6 a081f7d44c38 4 years ago 150MB Redis 2.6.17 a081f7d44c38 4 years ago 150MB Redis 2.8.18 5f9a9a936de2 5 years ago 111MB Redis 2.8.17 01aaba7226f1 5 years ago 111MB Redis 2.8.16 8b6103fd7b3e 5 years ago 111MB Redis 2.8.15 dbb560009c50 5 years ago 111MB Redis 2.8.14 4aad650df84a 5 years ago 111MB Redis 2.8.13 c4f8a05f3aff 5 years ago 111MB Redis 2.8.12 98bc726ecd17 5 years ago 111MB Redis 2.8.11 2fb854cb3f76 5 years ago 111MB Redis 2.8.10 33fe9dbeb30c 5 years ago 111MB |
You can see various image version of Redis which was used by command before.
Docker tag image
Command is used to distinguish the image versions like any other software. If no tag is defined then the latest version of image is used. For example let’s pull the mysql version 5.5:
[root@swmanager ~]# Docker pull mysql:5.5
5.5: Pulling from library/mysql 743f2d6c1f65: Downloading [======================> ] 10.34MB/22.49MB 3f0c413ee255: Download complete aef1ef8f1aac: Download complete f9ee573e34cb: Download complete 3f237e01f153: Download complete …. |
Saving and loading images
Images can be saved in two ways: save command or push to public/private registry.
Saving images is easy and done in classic tar format:
[root@swmanager ~]# Docker save -o mysql.tar mysql |
Notice the o parameter, if not used save will go to standard output. We defined name mysql.tar and local image mysql.
Tar format can be compressed with gzip to save more space:
[root@swmanager ~]# Docker save -o mysql.tar mysql | gzip > mysql.tar.gz
[root@swmanager ~]# ls -la | grep mysql -rw——- 1 root root 2688 Mar 31 08:51 .mysql_history -rw——- 1 root root 209714176 Jun 12 23:06 mysql.tar -rw-r–r– 1 root root 20 Jun 12 23:06 mysql.tar.gz |
Image in tar or gzip format can be transferred anywhere where Docker is installed and loaded with load option:
[root@swmanager ~]# Docker load -i mysql.tar
Loaded image: mysql:5.5 |
Push to public registry
Other way to save image is to push image to public or private registry. In this example we will cover public registry Docker Hub.
If you have account on Docker Hub first step is authentication:
[root@swmanager ~]# Docker login –username=username –password=password
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 |
Check local image cache:
[root@swmanager ~]# Docker images
[root@swmanager ~]# Docker images
REPOSITORY TAG IMAGE ID CREATED SIZE nginx <none> 602e111c06b6 7 weeks ago 127MB ubuntu latest 72300a873c2c 3 months ago 64.2MB centos latest 470671670cac 4 months ago 237MB mysql 5.5 d404d78aa797 13 months ago 205MB hello-world latest fce289e99eb9 17 months ago 1.84kB |
Tag image with your username:
[root@swmanager ~]# Docker tag d404d78aa797 username/mysql |
Push image:
[root@swmanager ~]# Docker push username/mysql |
Docker delete image
To keep your local image cache simple and clean you have to delete old and unused image. Each time image is pulled from registry it is stored on your local system. Before image deletion, make sure that there is no container which is running and using particular image. Container should be off to successfully delete image. If image is referenced use the –force=true parameter.
Let’s delete local mysql images with Docker delete image. First write mysql image id.
[root@swmanager ~]# Docker images
REPOSITORY TAG IMAGE ID CREATED SIZE nginx <none> 602e111c06b6 7 weeks ago 127MB ubuntu latest 72300a873c2c 3 months ago 64.2MB centos latest 470671670cac 4 months ago 237MB mysql 5.5 d404d78aa797 13 months ago 205MB |
Use Docker delete command:
[root@swmanager ~]# Docker rmi d404d78aa797
Error response from daemon: conflict: unable to delete d404d78aa797 (must be forced) – image is referenced in multiple repositories |
Unfortunately we must use –force=true because image is referenced:
[root@swmanager ~]# Docker rmi d404d78aa797 –force=true
Untagged username/mysql:latest Untagged: jadranmestrovic/mysql@sha256:c9c671d0c959183154313d6830d46f9a00d5937f97415c15ebd3c6844f6f1467 Untagged: mysql:5.5 Untagged: mysql@sha256:12da85ab88aedfdf39455872fb044f607c32fdc233cd59f1d26769fbf439b045 |
There is handy command to delete all unused images:
Docker rmi $(Docker images -q)
[root@swmanager ~]# Docker rmi $(Docker images -q) |
Modifying images
When Docker images are up and running you can save image current state to the new image with command Docker commit. However, this is not recommended approach because you will saturate new image with log, process ID files and it will not be a clean way to build new image. Recommended way is always to use Docker file. But let check example with Docker commit.
Check running containers:
[root@swmanager ~]# Docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5a01497cce2d nginx:latest “nginx -g ‘daemon of…” 3 minutes ago Up 2 minutes 80/tcp nginx.1.n1zzqfn5qa3iigbod9cbipfoa bb024f708fa2 nginx:latest “nginx -g ‘daemon of…” 3 minutes ago Up 2 minutes 80/tcp nginx.2.x7hnb7kv8cq9sdb2bfqi2ywd9 |
Run diff command to check differences between original and current nginx image:
[root@swmanager ~]# Docker diff nginx.1.n1zzqfn5qa3iigbod9cbipfoa
C /run A /run/nginx.pid C /var C /var/cache C /var/cache/nginx A /var/cache/nginx/proxy_temp A /var/cache/nginx/scgi_temp A /var/cache/nginx/uwsgi_temp A /var/cache/nginx/client_temp A /var/cache/nginx/fastcgi_temp |
Changed file is tagged with C label while new file is tagged with A label.
Commit current running image to new image:
[root@swmanager ~]# Docker commit nginx.1.n1zzqfn5qa3iigbod9cbipfoa nginx3
sha256:b778cd9e1fff6ecf36b8359768fc91bfacb71b4cba986398e425f86b3a3201b6 |
Check new image:
[root@swmanager ~]# Docker images
REPOSITORY TAG IMAGE ID CREATED SIZE nginx3 latest b778cd9e1fff About a minute ago 127MB |
Docker tag image
Docker tag image is used to tag images based on the same software in order to distinguish software versions. If tag is not provided, the latest software release is used. The latest software release does not necessarily mean the latest build.
Tag the local Ubuntu image:
[root@swmanager ~]# Docker tag ubuntu devel/ubuntu:1.1 |
Remove the tag:
[root@swmanager ~]# docker rmi devel/ubuntu:1.1
Untagged: devel/ubuntu:1.1 |
Docker local registry
It is time to setup you own local registry and procedure is pretty simple because there is already image which provides local registry services. In the following example we will set up the local registry, pull the image from public registry, tag it with our own local tag and push it to the local registry. In order to test the local registry, all Ubuntu images will be removed and pulled from local registry. Private registry can be a good choice if you want your own independent and secure registry. It is a pretty easy procedure that involves installing the pre-built container-registry. The hardest part of the installation is securing the registry from remote access. Let’s see how to do it:
- Pull the registry container
- Install the registry container
- Securing the private registry
Just run the container with registry image:
[root@swmanager ~]# Docker run -p 5000:5000 -dit –restart=always –name registry registry:2
fc97bb77df4c5316b645682e82ec9f32343e4fc12f41ecb75c00afca54d4a5d9 |
New container with private registry image is started on port 5000. Parameter restart=always is used to container to start each time Docker starts.
Pull the Ubuntu image from public registry:
[root@swmanager ~]# Docker pull ubuntu
Using default tag: latest latest: Pulling from library/ubuntu …. |
To use local registry it is very important to tag the local image with following format:
registryserver:portnumber/image name:tag
Otherwise Docker will operate with default option and that is public registry.
Tag the Ubuntu image with local tag:
[root@swmanager ~]# Docker tag ubuntu swmanager.local:5000/mylocalubuntu:16.1 |
Check that image is in the list:
[root@swmanager ~]# Docker images
REPOSITORY TAG IMAGE ID CREATED SIZE swmanager.local:5000/mylocalubuntu 16.1 adafef2e596e 6 days ago 73.9MB |
Push the Ubuntu image to your local registry:
[root@swmanager ~]# Docker push swmanager.local:5000/mylocalubuntu
The push refers to repository [swmanager.local:5000/mylocalubuntu] 8891751e0a17: Pushed 2a19bd70fcd4: Pushed 9e53fd489559: Pushed 7789f1a3d4e9: Pushed latest: digest: sha256:5747316366b8cc9e3021cd7286f42b2d6d81e3d743e2ab571f55bcd5df788cc8 size: 1152 |
Remove Ubuntu from public registry and local ubuntu image:
[root@swmanager ~]# Docker image remove ubuntu
Untagged: ubuntu:latest Untagged: ubuntu@sha256:747d2dbbaaee995098c9792d99bd333c6783ce56150d1b11e333bbceed5c54d7 [root@swmanager ~]# Docker image remove localhost:5000/mylocalubuntu Untagged: localhost:5000/mylocalubuntu:latest Untagged: localhost:5000/mylocalubuntu@sha256:5747316366b8cc9e3021cd7286f42b2d6d81e3d743e2ab571f55bcd5df788cc8 Deleted: sha256:1d622ef86b138c7e96d4f797bf5e4baca3249f030c575b9337638594f2b63f01 Deleted: sha256:279e836b58d9996b5715e82a97b024563f2b175e86a53176846684f0717661c3 Deleted: sha256:39865913f677c50ea236b68d81560d8fefe491661ce6e668fd331b4b680b1d47 Deleted: sha256:cac81188485e011e56459f1d9fc9936625a1b62cacdb4fcd3526e5f32e280387 Deleted: sha256:7789f1a3d4e9258fbe5469a8d657deb6aba168d86967063e9b80ac3e1154333f |
Pull image from your local registry:
[root@swmanager ~]# Docker pull swmanager.local:5000/mylocalubuntu
Using default tag: latest latest: Pulling from mylocalubuntu d51af753c3d3: Pull complete fc878cd0a91c: Pull complete 6154df8ff988: Pull complete fee5db0ff82f: Pull complete Digest: sha256:5747316366b8cc9e3021cd7286f42b2d6d81e3d743e2ab571f55bcd5df788cc8 Status: Downloaded newer image for localhost:5000/mylocalubuntu:latest localhost:5000/mylocalubuntu:latest |
Choosing the right storage location
By default registry images are stored on predefined Docker volume stored in following path: var/lib/Docker. But what if you want to store your private image data on external source? Then only option is to use bind mount. Example mounts host path /mnt/external to Docker registry /var/lib/registry.
Docker run -d -p 5000:5000 –restart=always –name registry -v /mnt/registry:/var/lib/registry registry:2 |
Note:
Using the storage drivers private registry can be stored in any cloud like Google, AWS or IBM.
Setting the secure private registry for remote access
By default Docker use secure TLS connection. We will demonstrate the configuration of secure connection with self-signed certificate:
Create directory for self-signed certificate:
[root@swmanager ~]# mkdir -p /Docker/certs |
Start private registry with configured certificate and key:
[root@swmanager certs]# Docker run -d -p 5000:5000 –restart=always –name registry -v /Docker/certs:/Docker/certs -e REGISTRY_HTTP_TLS_CERTIFICATE=/Docker/certs/docker.crt -e REGISTRY_HTTP_TLS_KEY=/Docker/certs/Docker. Key registry |
Generate the self-signed certificate with open SSL command:
[root@swmanager ~]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout /docker/certs/docker.ca -x509 -days 365 -out /Docker/certs/docker.key
Generating a RSA private key …………………………++++ …………………………………………………………………………………………………..++++ writing new private key to ‘/Docker/certs/docker.ca’ —– 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]:GB State or Province Name (full name) []:GB Locality Name (eg, city) [Default City]:GB Organization Name (eg, company) [Default Company Ltd]:localhost Organizational Unit Name (eg, section) []:IT Common Name (eg, your name or your server’s hostname) []:swmanager.local Email Address []:swmanager@local |
Copy the certificate from server to client:
[root@swworker1 ~]# scp -pr root@swmanager.local:/docker/certs/docker.ca /etc/Docker/certs.d/swmanager.local:5000/
The authenticity of host ‘swmanager.local (192.168.78.3)’ can’t be established. ECDSA key fingerprint is SHA256:iNe0xpuyJDPtmCQIp+jg5oR18BcvidZRpuX8qltm1tg. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added ‘swmanager.local,192.168.78.3’ (ECDSA) to the list of known hosts. root@swmanager.local’s password: /etc/dokcer/certs.d/swmanager.local:5000/: Not a directory |
Restart Docker service:
[root@swworker1 ~]# systemctl restart Docker |
Push the previosuly tagged Redis image to your private registry:
[root@swworker1 swmanager.local:5000]# Docker push swmanager.local:5000/Redis:v1
The push refers to repository [swmanager.local:5000/Redis] 7b9c5be81844: Pushed 67c707dbd847: Pushed 72d3a7e6fe02: Pushed cdaf0fb0082b: Pushed e6b49c7dcaac: Pushed 13cb14c2acd3: Pushed v1: digest: sha256:76ff608805ca40008d6e0f08180d634732d8bf4728b85c18ab9bdbfa0911408d size: 1572 |
Check image on private registry server:
[root@swmanager certs]# Docker images
REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest adafef2e596e 8 days ago 73.9MB swmanager.local:5000/mylocalubuntu 16.1 adafef2e596e 8 days ago 73.9MB registry latest 2d4f4b5309b1 3 weeks ago 26.2MB nginx3 latest b778cd9e1fff 4 weeks ago 127MB Redis latest 235592615444 5 weeks ago 104MB swmanager.local:5000/Redis v1 235592615444 5 weeks ago 104MB |
Let’s test the image pull from private registry. First delete local copy of Redis image:
[root@swworker1 swmanager.local:5000]# Docker image rm swmanager.local:5000/Redis:v1
Untagged: swmanager.local:5000/Redis:v1 Untagged: swmanager.local:5000/Redis@sha256:76ff608805ca40008d6e0f08180d634732d8bf4728b85c18ab9bdbfa0911408d [root@swworker1 swmanager.local:5000]# |
And pull the Redis image from private registry:
[root@swworker1 swmanager.local:5000]# Docker pull swmanager.local:5000/Redis:v1
v1: Pulling from Redis Digest: sha256:76ff608805ca40008d6e0f08180d634732d8bf4728b85c18ab9bdbfa0911408d Status: Downloaded newer image for swmanager.local:5000/Redis:v1 swmanager.local:5000/Redis:v1 |
Check that image is now on local server:
[root@swworker1 swmanager.local:5000]# Docker images
REPOSITORY TAG IMAGE ID CREATED SIZE Redis latest 235592615444 5 weeks ago 104MB swmanager.local:5000/Redis v1 235592615444 5 weeks ago 104MB |
[root@swworker1 ~]# systemctl restart Docker |