突破难关:Docker镜像和容器的区别以及构建的最佳实践

本文详细介绍了Docker镜像的构成,包括manifest.json、RepoTags、Config和Layers,以及Docker镜像和容器的区别。讨论了如何构建Docker镜像,包括从容器创建和从Dockerfile创建,并分享了6个最佳实践,如利用缓存、部分拷贝和选择合适的基础镜像,以提升构建效率。
摘要由CSDN通过智能技术生成

大家好,我是张晋涛。

本周 Docker 就发布 10 周年了,为了庆祝这个里程碑,我将会发布一系列文章,涉及 Docker,CI/CD, 容器等各个方面。

Docker 可谓是开启了容器化技术的新时代,现在无论大中小公司基本上都对容器化技术有不同程度的尝试,或是已经进行了大量容器化的改造。伴随着 Kubernetes 和 Cloud Native 等技术和理念的普及,也大大增加了业务容器化需求。而这一切的推进,不可避免的技术之一便是构建容器镜像。

Docker 镜像是什么

在真正实践之前,我们需要先搞明白几个问题:

  • Docker 镜像是什么

  • Docker 镜像的作用

  • 容器和镜像的区别及联系

Docker 镜像是什么

这里,我们以一个 Debian 系统的镜像为例。通过 docker run --it debian 可以启动一个 debian 的容器,终端会有如下输出:

/ # docker run -it debian
Unable to find image 'debian:latest' locally
latest: Pulling from library/debian
c5e155d5a1d1: Pull complete 
Digest: sha256:f81bf5a8b57d6aa1824e4edb9aea6bd5ef6240bcc7d86f303f197a2eb77c430f
Status: Downloaded newer image for debian:latest
root@860f21595fb6:/# cat /etc/os-release 
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

看终端的日志,Docker CLI 首先会查找本地是否有 debian 的镜像,如果没有则从镜像仓库(若不指定,默认是 DockerHub)进行 pull; 将镜像 pull 到本地后,再以此镜像来启动容器。

我们可以先退出此容器,来看看 Docker 镜像到底是什么。用 docker image ls 来查看已下载好的镜像:

(MoeLove) ➜ docker image ls debian
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
debian       latest    72b624312240   2 weeks ago   124MB

docker image save 命令将镜像保存成一个 tar 文件:

(MoeLove) ➜ mkdir debian-image
(MoeLove) ➜ docker image save -o debian-image/debian.tar debian
(MoeLove) ➜ ls debian-image/
debian.tar

将镜像文件进行解压:

(MoeLove) ➜ tar -C debian-image/ -xf debian-image/debian.tar 
(MoeLove) ➜ tree -I debian.tar debian-image/
debian-image/
├── 72b6243122405be2c5c5e7e20d410f4c8fe301e1ce84cc60ea591b63167750e6.json
├── 7a66e59f40fd03d0e7bfaebe419af6a2c409ef8f513d037e3b1ebb8cbc803ec2
│   ├── VERSION
│   ├── json
│   └── layer.tar
├── manifest.json
└── repositories

1 directory, 6 files

可以看到将镜像文件解压后,包含的内容主要是一些配置文件和 tar 包。

接下来我们来具体看看其中的内容,并通过这些内容来理解镜像的组成。

manifest.json

(MoeLove) ➜ cd debian-image/
(MoeLove) ➜ cat manifest.json | jq
[
  {
    "Config": "72b6243122405be2c5c5e7e20d410f4c8fe301e1ce84cc60ea591b63167750e6.json",
    "RepoTags": [
      "debian:latest"
    ],
    "Layers": [
      "7a66e59f40fd03d0e7bfaebe419af6a2c409ef8f513d037e3b1ebb8cbc803ec2/layer.tar"
    ]
  }
]

注意:在实际存储时,是不包含换行的,这里为了便于展示所以使用了 jq 工具进行格式化。

manifest.json 包含了镜像的顶层配置,它是一系列配置按顺序组织而成的;以现在我们的 debian 镜像为例,它至包含了一组配置,这组配置中包含了 3 个主要的信息,我们由简到繁进行说明。

RepoTags

RepoTags 表示镜像的名称和 tag ,这里简要的对此进行说明:RepoTags 其实分为两部分:

  • Repo: Docker 镜像可以存储在本地或者远端镜像仓库内,Repo 其实就是镜像的名称。 Docker 默认提供了大量的官方镜像存储在 Docker Hub 上,对于我们现在在用的这个 Docker 官方的 debian 镜像而言,完整的存储形式其实是 docker.io/library/debian,只不过 docker 自动帮我们省略掉了前缀。

  • Tag: 我们可以通过 repo:tag 的方式来引用一个镜像,默认情况下,如果没有指定 tag (像我们上面操作的那样),则会 pull 下来最新的镜像(即:latest)

Config

Config 字段包含的内容是镜像的全局配置。我们来看看具体内容:

(MoeLove) ➜ cat 72b6243122405be2c5c5e7e20d410f4c8fe301e1ce84cc60ea591b63167750e6.json | jq                                                                                    
{                                                                                      
  "architecture": "amd64",                                                             
  "config": {                                                                          
    "Hostname": "",                                                                    
    "Domainname": "",                                                                  
    "User": "",                                                                        
    "AttachStdin": false,                                                              
    "AttachStdout": false,                                                             
    "AttachStderr": false,                                                             
    "Tty": false,                                                                      
    "OpenStdin": false,                                                                
    "StdinOnce": false,                                                                
    "Env": [                                                                           
      "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"                                                                                                     
    ],                                                                                 
    "Cmd": [                                                                           
      "bash"                                                                           
    ],                                                                                 
    "Image": "sha256:f8f185aa88c5b07710b327c1c8fd02c8d264bdcce11877d337b9d5c739015cea",                                                                                       
    "Volumes": null,                                                                   
    "WorkingDir": "",                                                                  
    "Entrypoint": null,                                                                
    "OnBuild": null,                                                                   
    "Labels": null                                                                     
  },                                                                                   
  "container": "f41eadbc246cbece89086679da07f3b0d1508234aab4932acab7cbdc8ae63a9c",                                                                                            
  "container_config": {                                                                
    "Hostname": "f41eadbc246c",                                                        
    "Domainname": "",                                                                  
    "User": "",                                                                        
    "AttachStdin": false,                                                              
    "AttachStdout": false,                                                             
    "Attac
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张晋涛-MoeLove

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值