Docker 镜像操作

获取镜像

一般镜像通过 Docker Hub 来获取。

搜索镜像

通过 docker search 命令可以搜索公共仓库 Docker Hub 中的镜像:

[root@server4 ~]$ docker search python
NAME                       DESCRIPTION               STARS     OFFICIAL   AUTOMATED
python                     Python is an interpreted, 6632      [OK]       
pypy                       PyPy is a fast, compliant 290       [OK]       
nikolaik/python-nodejs     Python with Node.js       86                   [OK]

搜索结果以 STARS 排序,默认显示 25 个结果。其字段说明如下:

  • NAME:镜像名称。
  • DESCRIPTION:创建者对镜像的简单描述。
  • STARS:镜像在官方镜像仓库中受欢迎程度。
  • OFFICIAL:是否由 Docker 官方提供。
  • AUTOMATED:镜像是否使用了自动构建。

设置搜索结果数目限制到 100 个:

[root@server4 ~]$ docker search --limit 100 centos

使用 --filter 参数来限制搜索结果只显示官方构建的 nginx 镜像:

[root@server4 ~]$ docker search --filter=is-official=true nginx
NAME      DESCRIPTION                STARS     OFFICIAL   AUTOMATED
nginx     Official build of Nginx.   15666     [OK]    

过滤收藏数小于 10 的镜像:

[root@server4 ~]$ docker search --filter=stars=10 linux

拉取镜像

在运行 Docker 容器之前,需要在本地获取相应的镜像,可以使用 docker pull 命令进行镜像拉取。

例如,从 Docker Hub 拉取 Ubuntu 18.04 系统的基础镜像:

[root@server4 ~]$ docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
284055322776: Pull complete 
Digest: sha256:0fedbd5bd9fb72089c7bbca476949e10593cebed9b1fb9edf5b79dbbacddd7d6
Status: Downloaded newer image for ubuntu:18.04
docker.io/library/ubuntu:18.04

Docker 利用镜像的分层机制,将镜像分为多个包进行下载。当所有镜像层的下载和解压等操作完成后,镜像会出现在本地镜像仓库中。

如果不指定标签,默认使用 latest 标签。例如,从网易镜像站下载最新版本的 Ubuntu 镜像:

[root@server4 ~]$ docker pull hub-mirror.c.163.com/public/ubuntu

此外,可以使用 -a 参数一次性下载所有标签版本的镜像。

管理镜像

镜像管理命令和容器管理命令类似。

创建镜像

可以使用 docker commit 将容器转换为镜像,以保存容器中所做的更改:

[root@server4 ~]$ docker commit c238293 newimage:v1
sha256:392f66f55bace6d10def28028edc90eebc3bb1e23e8e30a030aeb8f96e98ac8e
[root@server4 ~]$ docker images
REPOSITORY                TAG       IMAGE ID       CREATED         SIZE
newimage                  v1        392f66f55bac   4 seconds ago   63.1MB

这种手动创建镜像的方法容易出错且可重复性较差,因此最好使用 docker build 命令结合 Dockerfile 来构建镜像。

默认情况下,docker build 命令会自动在指定目录下查找名为 Dockerfile 的文件,并使用该文件进行构建。也可以通过 -f 参数指定要使用的文件名:

[root@server4 ~]$ vi Dockerfile
FROM ubuntu:18.04
CMD echo "Hello Dockerfile"
[root@server4 ~]$ docker build .
Sending build context to Docker daemon  5.938MB
Step 1/2 : FROM ubuntu:18.04
 ---> 5a214d77f5d7
Step 2/2 : CMD echo "Hello Dockerfile"
 ---> Running in 2fe4d2fa8be2
Removing intermediate container 2fe4d2fa8be2
 ---> 4e73bed1428a
Successfully built 4e73bed1428a
[root@server4 ~]$ docker images
REPOSITORY                TAG       IMAGE ID       CREATED          SIZE
<none>                    <none>    4e73bed1428a   12 seconds ago   63.1MB
[root@server4 ~]$ docker run --rm 4e73
Hello Dockerfile

使用 -t 参数可以指定构建镜像的名称和标签:

[root@server4 ~]$ docker build -t assassing/redis:2.3 .

删除镜像

要删除本地镜像,可以使用 docker rmi 命令。如果一个镜像有多个标签,只有在最后一个标签被删除时,镜像才会被真正删除:

[root@server4 ~]$ docker rmi 5a214d77
Error response from daemon: conflict: unable to delete 5a214d77f5d7 (must be forced) - image is referenced in multiple repositories
[root@server4 ~]$ docker rmi base:1.0
Untagged: base:1.0

如果镜像中包含与其他镜像共享的镜像层,那些层将被保留下来,只删除未被使用的层。

当镜像被容器使用时,可以使用 -f 参数强制删除镜像:

[root@server4 ~]$ docker rmi -f nginx
Untagged: nginx:latest
Untagged: nginx@sha256:644a70516a26004c97d0d85c7fe1d0c3a67ea8ab7ddf4aff193d9f301670cf36

但是,强制删除镜像不会自动停止或删除使用该镜像的容器,这可能会导致一些难以处理的问题。最好先停止或清理使用该镜像的容器,然后再删除镜像。

清理镜像

要清理系统中残留的临时镜像文件或未使用的镜像,可以使用 docker image prune 命令进行清理:

[root@server4 ~]$ docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B

导出镜像

要导出镜像,可以使用 docker save 命令。例如,将 alpine 镜像导出到本地的 a.tar 文件:

[root@server4 ~]$ docker images alpine
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
alpine       latest    14119a10abf4   7 weeks ago   5.6MB
[root@server4 ~]$ docker save -o a.tar alpine
[root@server4 ~]$ ll a.tar 
-rw-------. 1 root root 5874688 Oct 20 23:22 a.tar

也可以使用输出重定向将导出内容保存到指定文件:

[root@server4 ~]$ docker save alpine > a1.tar

可以一次将多个镜像导出到单个文件中:

[root@server4 ~]$ docker save -o docker.tar alpine hello-world

导入镜像

可以使用 docker load 命令从文件中导入镜像:

[root@server4 ~]$ docker load -i docker.tar 
e2eb06d8af82: Loading layer [========================================>]  5.865MB/5.865MB
Loaded image: alpine:latest
e07ee1baac5f: Loading layer [========================================>]  14.85kB/14.85kB
Loaded image: hello-world:latest

也可以使用输入重定向符号从文件中导入镜像:

[root@server4 ~]$ docker load < 2.tar 
2653d992f4ef: Loading layer [==================================================>]  216.5MB/216.5MB
Loaded image ID: sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55

查询镜像

镜像以分层文件的形式存储在文件系统中。

查询镜像列表

使用 docker images 命令可以列出本地镜像列表:

[root@server4 ~]$ docker images
REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
ubuntu        18.04     5a214d77f5d7   2 weeks ago   63.1MB
hello-world   latest    feb5d9fea6a5   3 weeks ago   13.3kB

结果显示字段的含义如下:

  • REPOSITORY: 镜像名或镜像来源仓库。如果有 Namespace,也会一同显示。
  • TAG: 镜像标签,用于标记不同的版本信息。
  • IMAGE ID: 镜像的 ID,也是镜像的唯一标识。可以使用前几个字符代替完整的 ID。
  • CREATED: 镜像的创建时间。
  • SIZE: 镜像的大小,包括共享的镜像层。实际占用的存储空间可能较小。

可以使用通配符来过滤镜像列表:

[root@server4 ~]$ docker images ubu*
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
ubuntu       18.04     5a214d77f5d7   2 weeks ago   63.1MB

查询镜像详情

可以使用 docker inspect 命令获取镜像的详细信息:

[root@server4 ~]$ docker inspect ubuntu:18.04
[
    {
        "Id": "sha256:5a214d77f5d747e6ed81632310baa6190301feeb875cf6bf9da560108fa09972",
        "RepoTags": [
            "base:1.0",
            "ubuntu:18.04"
        ],
        "RepoDigests": [
            "ubuntu@sha256:0fedbd5bd9fb72089c7bbca476949e10593cebed9b1fb9edf5b79dbbacddd7d6"
        ],

也可以通过镜像的 ID 进行查询:

[root@server4 ~]$ docker inspect 5a21

查询结果以 JSON 格式返回,可以使用输出格式化工具进行过滤:

[root@server4 ~]$ docker inspect -f {{".ContainerConfig.Hostname"}} alpine
330289c649db

查询镜像修改历史

可以使用 docker history 命令查看镜像的每一层具体内容:

[root@server4 ~]$ docker history --no-trunc alpine
IMAGE          CREATED       CREATED BY                            SIZE      COMMENT
14119a10abf4   7 weeks ago   /bin/sh -c #(nop)  CMD ["/bin/sh"]    0B        
<missing>      7 weeks ago   /bin/sh -c #(nop) ADD file:aad4290d   5.6MB 

操作镜像

涉及到镜像操作的内容包括镜像改名和上传镜像。

镜像改名

可以使用 docker tag 命令为本地镜像添加标签,并删除原始镜像,从而实现改名的目的。

例如,为 ubuntu:18.04 镜像添加一个新标签 base:1.0

[root@server4 ~]$ docker tag ubuntu:18.04 base:1.0
[root@server4 ~]$ docker images
REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
base          1.0       5a214d77f5d7   2 weeks ago   63.1MB
ubuntu        18.04     5a214d77f5d7   2 weeks ago   63.1MB
hello-world   latest    feb5d9fea6a5   3 weeks ago   13.3kB

现在可以看到多了一个名为 base:1.0 的镜像,其镜像 ID 与 ubuntu:18.04 相同。通过添加标签,类似于创建文件的硬链接。

上传镜像

要将镜像上传到仓库,可以使用 docker push 命令。在上传之前,需要为目标镜像打上标签。如果要上传到 Docker Hub,则目标镜像的命名空间为用户的用户名;如果要上传到私有仓库,则命名空间变为仓库的地址:

[root@server4 ~]$ docker tag alpine:latest assassing/a1:latest
[root@server4 ~]$ docker push assassing/a1:latest
The push refers to repository [docker.io/assassing/a1]
e2eb06d8af82: Mounted from library/alpine 
latest: digest: sha256:69704ef328d05a9f806b6b8502915e6a0a4faa4d72018dc42343f511490daf8a size: 528