参考原文:http://www.dockerinfo.net/image%e9%95%9c%e5%83%8f

基本概念

基础镜像

在 Docker 的术语里,一个只读层被称为镜像,一个镜像是永久不会变的。镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件。
由于 Docker 使用一个统一文件系统,Docker 进程认为整个文件系统是以读写方式挂载的。 但是所有的变更都发生顶层的可写层,而下层的原始的只读镜像文件并未变化。由于镜像不 可写,所以镜像是无状态的。

父镜像

每一个镜像都可能依赖于由一个或多个下层的组成的另一个镜像。我们有时说,下层那个 镜像是上层镜像的父镜像。

基础镜像

一个没有任何父镜像的镜像,谓之基础镜像。

镜像ID

所有镜像都是通过一个 64 位十六进制字符串 (内部是一个 256 bit 的值)来标识的。 为简化使用,前 12 个字符可以组成一个短ID,可以在命令行中使用。短ID还是有一定的 碰撞机率,所以服务器总是返回长ID。

如何得到一个镜像

  1. 从远程仓库 pull 一个
  2. 从其他人处 copy 一个
  3. 自己制作docker file build 一个镜像

    镜像的分层下载

    当我们去 pull 一个镜像的时候,会下载许多个镜像。
    这个类似于 git 存在的控制版本
    安装了 centos 第一层
    安装了 docker 第二层
    1. [root@localhost ~]# docker pull redis
    2. Using default tag: latest
    3. latest: Pulling from library/redis
    4. 7d63c13d9b9b: Pull complete
    5. a2c3b174c5ad: Pull complete
    6. 283a10257b0f: Pull complete
    7. 7a08c63a873a: Pull complete
    8. 0531663a7f55: Pull complete
    9. 9bf50efb265c: Pull complete
    10. Digest: sha256:a89cb097693dd354de598d279c304a1c73ee550fbfff6d9ee515568e0c749cfe
    11. Status: Downloaded newer image for redis:latest
    12. docker.io/library/redis:latest
    13. [root@localhost ~]#
    UnionFS(联合文件系统) 是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加。同时可以将不同物理位置的目录挂在到同一个虚拟文件系统下。union文件系统是docker镜像的基础。镜像可以通过分层来进行继承。基于基础镜像可以制作各种镜像。
    特性:一次同事加载多个文件系统,从外面看起来只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
    UFS参考:https://blog.csdn.net/songcf_faith/article/details/82787946

看一下这张图
第一层是一个内核
第二层是一个debian的镜像
第三层是安装了一个 emacs 叠加在内核之上
第四层是安装了一个apache2 的中间件
image.png
上文中说到的 UFS
最底层是bootfs(boot file system),主要包含了bootloader 和 kernel, bootloader 主要是引导加载 kernel,linux刚启动时会加载 bootfs文件系统。在docker镜像最底层的 bootfs。这一层与我们典型的 LINUX、UNIX系统是一样的,包含 boot 加载器和内核。当 boot加载完成之后整个内核就都在内存中了。此时内存的使用权已由bootsf 转交给 kernel。系统也会卸载 bootfs。

rootfs(root file system)。在bootfs之上。包含的就是典型的 linux 系统中的 /dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版。

注:如果某个镜像需要修改内核中的参数,则牵一发而动全身。因为docker 共用 宿主机的内核。

在下载的时候,可以看到之前下载过的镜像,不需要再下载了
image.png
相对详细的解答:
image.png
image.png
image.png
image.png

总结:
docker镜像是只读的,当容器启动的时候,一个新的可写层会被加载到镜像的顶部。
这一层就是容器层,其它层都是镜像层。

当你丛 hub 上 pull 一个镜像的时候。
你的新操作就在一个可写的容器层上开辟了,你发布一个自己的docker 镜像时,就意味着 你需要把前面的镜像和你自己添加的内容打包到一个镜像!
下面一层一层的那个就叫 layer
image.png

如何发布自己的一个镜像

  1. docker commit 提交容器成为一个新的副本
  2. docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
  1. [root@localhost ~]# docker run -it --name mynginx nginx
  2. /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
  3. /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
  4. /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
  5. 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
  6. 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
  7. /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
  8. /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
  9. /docker-entrypoint.sh: Configuration complete; ready for start up
  10. 2021/10/21 14:00:06 [notice] 1#1: using the "epoll" event method
  11. 2021/10/21 14:00:06 [notice] 1#1: nginx/1.21.3
  12. 2021/10/21 14:00:06 [notice] 1#1: built by gcc 8.3.0 (Debian 8.3.0-6)
  13. 2021/10/21 14:00:06 [notice] 1#1: OS: Linux 3.10.0-1160.el7.x86_64
  14. 2021/10/21 14:00:06 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
  15. 2021/10/21 14:00:06 [notice] 1#1: start worker processes
  16. 2021/10/21 14:00:06 [notice] 1#1: start worker process 32
  17. 2021/10/21 14:00:06 [notice] 1#1: start worker process 33
  18. ^P
  19. [root@localhost ~]#
  20. [root@localhost ~]#
  21. [root@localhost ~]#
  22. [root@localhost ~]# docker ps
  23. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  24. 9821cf90d1ba nginx "/docker-entrypoint.…" 19 seconds ago Up 19 seconds 80/tcp mynginx
  25. [root@localhost ~]# docker exec -it 9821cf90d1ba /bin/bash
  26. root@9821cf90d1ba:/# ls
  27. bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
  28. root@9821cf90d1ba:/# mkdir 1
  29. root@9821cf90d1ba:/# ls
  30. 1 bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
  31. [root@localhost ~]# docker commit -m="add a files" -a"waiting4" ^C
  32. [root@localhost ~]# docker ps
  33. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  34. 9821cf90d1ba nginx "/docker-entrypoint.…" 10 minutes ago Up 10 minutes 80/tcp mynginx
  35. [root@localhost ~]# docker commit -m="add a files" -a="waiting4" 9821cf90d1ba jginx:1.0
  36. sha256:99250f27e4f729b31fd7d6097555ff749921a8351267bef8a81ef948549c9f2e
  37. [root@localhost ~]# docker images
  38. REPOSITORY TAG IMAGE ID CREATED SIZE
  39. jginx 1.0 99250f27e4f7 9 seconds ago 133MB
  40. redis latest 7faaec683238 9 days ago 113MB
  41. nginx latest 87a94228f133 9 days ago 133MB
  42. centos latest 5d0da3dc9764 5 weeks ago 231MB
  43. [root@localhost ~]#