Docker镜像构建原理解析(不装docker也能构建镜像)

在devops流程里面 构建镜像是一个非常重要的过程,一般构建镜像是写dockerfile文件然后通过docker client来构建的image。
docker client 会先检查本地有没有image,如果没有帮你 从镜像仓库 pull 下来
然后解析你写的dockerfile构建新的image。
本文带你了解
- pull 命令 背后是怎么做的?
- build 命令 背后是怎么做的?
下篇文章带你解析:
- 如果我不用docker 我如何构建一个镜像?
我们以微软的aspnet2.2为基础构建一个aspnetcore项目的镜像为例子
mcr.microsoft.com/dotnet/core/aspnet:2.2
根据基础镜像REGISTRY去获取mainfest信息

https://mcr.microsoft.com/v2/dotnet/core/aspnet/manifests/2.2
Accept:
application/vnd.oci.image.manifest.v1+json,application/vnd.docker.distribution.manifest.v2+json,application/vnd.docker.distribution.manifest.v1+json
获取到的内容如下:
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 4039,
"digest": "sha256:e7e3b238011ce0f2b9350153535fe273caa01f0e7188d0b91f965b3802ddc600"
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 22524609,
"digest": "sha256:804555ee037604c40de144f9f8da0d826d38db82f15d74cded32790fe279a8f6"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 17692725,
"digest": "sha256:970251047358aea56ba6db6975b14ff12470b75de0c2477f4445240ddd727fd4"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 2978257,
"digest": "sha256:f3d4c41a4fd13f35c0b46f19a4e27845f4695163cc7174d908ff84836bbc2f5a"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 62145592,
"digest": "sha256:bd391c46585f9f8d84992bbaa9087189148c1601968eaaf097d5b3ed60840e5e"
}
]
}
mainfest文件里面都是摘要(digest)记录
- config信息摘要
- 每个layer的摘要 (上面的例子有4个)
根据上面的config信息摘要获取config详情

GET:https://mcr.microsoft.com/v2/dotnet/core/aspnet/blobs/sha256:e7e3b238011ce0f2b9350153535fe273caa01f0e7188d0b91f965b3802ddc600
{
"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",
"ASPNETCORE_URLS=http://+:80",
"DOTNET_RUNNING_IN_CONTAINER=true",
"ASPNETCORE_VERSION=2.2.8"
],
"Cmd": [
"bash"
],
"ArgsEscaped": true,
"Image": "sha256:5ecfe4016ac8e911a94aa601a675f7204e9ccab00cbb08e7067c184ad40f34e9",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null
},
"container": "14196c2f9c327d41e26682d32c7c89c4e7c78aa32f8b7501a23192035a9f4844",
"container_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",
"ASPNETCORE_URLS=http://+:80",
"DOTNET_RUNNING_IN_CONTAINER=true",
"ASPNETCORE_VERSION=2.2.8"
],
"Cmd": [
"/bin/sh",
"-c",
"curl -SL --output aspnetcore.tar.gz https://dotnetcli.azureedge.net/dotnet/aspnetcore/Runtime/$ASPNETCORE_VERSION/aspnetcore-runtime-$ASPNETCORE_VERSION-linux-x64.tar.gz && aspnetcore_sha512='954072376698be69acb7e277df2c243f931e10529def21dcbf9ce277609b30d462126bf8b8b3cab36476bec3d63a927b8e44e59e4d4cade23eef45956fba1ffd' && echo \"$aspnetcore_sha512 aspnetcore.tar.gz\" | sha512sum -c - && mkdir -p /usr/share/dotnet && tar -zxf aspnetcore.tar.gz -C /usr/share/dotnet && rm aspnetcore.tar.gz && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet"
],
"Image": "sha256:5ecfe4016ac8e911a94aa601a675f7204e9ccab00cbb08e7067c184ad40f34e9",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null
},
"created": "2019-12-28T08:12:05.676492579Z",
"docker_version": "3.0.8",
"history": [
{
"created": "2019-12-28T04:23:47.4966447Z",
"created_by": "/bin/sh -c #(nop) ADD file:90a2c81769a336bed3f731f44a385f2a65b0916f517a0b77c06c224579bf9a9a in / "
},
{
"created": "2019-12-28T04:23:47.719507596Z",
"created_by": "/bin/sh -c #(nop) CMD [\"bash\"]",
"empty_layer": true
},
{
"created": "2019-12-28T08:11:05.607009582Z",
"created_by": "/bin/sh -c apt-get update && apt-get install -y --no-install-recommends ca-certificates libc6 libgcc1 libgssapi-krb5-2 libicu57 liblttng-ust0 libssl1.0.2 libstdc++6 zlib1g && rm -rf /var/lib/apt/lists/*"
},
{
"created": "2019-12-28T08:11:07.64336022Z",
"created_by": "/bin/sh -c #(nop) ENV ASPNETCORE_URLS=http://+:80 DOTNET_RUNNING_IN_CONTAINER=true",
"empty_layer": true
},
{
"created": "2019-12-28T08:11:16.475068844Z",
"created_by": "/bin/sh -c apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*"
},
{
"created": "2019-12-28T08:11:43.814078508Z",
"created_by": "/bin/sh -c #(nop) ENV ASPNETCORE_VERSION=2.2.8",
"empty_layer": true
},
{
"created": "2019-12-28T08:12:05.676492579Z",
"created_by": "/bin/sh -c curl -SL --output aspnetcore.tar.gz https://dotnetcli.azureedge.net/dotnet/aspnetcore/Runtime/$ASPNETCORE_VERSION/aspnetcore-runtime-$ASPNETCORE_VERSION-linux-x64.tar.gz && aspnetcore_sha512='954072376698be69acb7e277df2c243f931e10529def21dcbf9ce277609b30d462126bf8b8b3cab36476bec3d63a927b8e44e59e4d4cade23eef45956fba1ffd' && echo \"$aspnetcore_sha512 aspnetcore.tar.gz\" | sha512sum -c - && mkdir -p /usr/share/dotnet && tar -zxf aspnetcore.tar.gz -C /usr/share/dotnet && rm aspnetcore.tar.gz && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet"
}
],
"os": "linux",
"rootfs": {
"type": "layers",
"diff_ids": [
"sha256:814c70fdae62bc26c603bfae861f00fb1c77fc0b1ee8d565717846f4df24ae5d",
"sha256:0cf75cb98eb2e0a82631d4aff71b40ba79ff7f83e0361f696875e592a1a4cefc",
"sha256:15e45d99c92686fb1fd61a41431d8400d7a0e8381595d09d666b0809c4f5d993",
"sha256:579a8f1d6a123f98095c0b1a1395079f7504391fd2a8bc529dede305a2072a36"
]
}
}
根据diff_ids里面去下载对应layers
下载完后对比摘要一致,确保镜像文件合法性
路径规则:
https://mcr.microsoft.com/v2/dotnet/core/aspnet/blobs/sha256:XXXXXX




构建我们的镜像
在基础镜像的配置基础上加入我们的自定义配置
- Entrypoint
- Cmd
- Ports
- Environment
- ImageWorkingDirectory
- Volumes
- Labels
在基础镜像的所有的layers把我们要打包到镜像也做成一个layer
生成的镜像tar包解压出来

多了一个 tar.gz文件,解压之后 就是我们打包放进去的文件

- 原来基础镜像有4个layer 加上我们的 共5个
- config.json
- manifest.json
manifest.json对比与基础镜像

config.json对比与基础镜像

我们来复习下构建镜像的过程
- 根据镜像名称拉取mainfest
- 根据mainfest拉取config
- 根据config拉取layers
- 下载各个layer
- 修改到基础镜像的配置(config.json和mainfest.json)
- 加入我们要加入的文件layer
知道原理后我们可以自己写一个工具来实现整个过程
我开源的docker镜像构建,让你不用装docker也能快速构建容器镜像
支持以下镜像仓库作为基础镜像构建
- docker hub
- aliyun
- 腾讯云
Docker镜像构建原理解析(不装docker也能构建镜像)的更多相关文章
- [原][Docker]特性与原理解析
Docker特性与原理解析 文章假设你已经熟悉了Docker的基本命令和基本知识 首先看看Docker提供了哪些特性: 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上, ...
- Docker网络管理机制实例解析+创建自己Docker网络
实例解析Docker网络管理机制(bridge network,overlay network),介绍Docker默认的网络方式,并创建自己的网络桥接方式,将开发的容器添加至自己新建的网络,提高Doc ...
- 一篇不一样的docker原理解析
转自:https://zhuanlan.zhihu.com/p/22382728 https://zhuanlan.zhihu.com/p/22403015 在学习docker的过程中,我发现目前do ...
- 8天入门docker系列 —— 第三天 使用aspnetcore小案例熟悉对镜像的操控
上一篇我们聊到了容器,现在大家应该也知道了,没有镜像就没有容器,所以镜像对docker来说是非常重要的,关于镜像的特性和原理作为入门系列就不阐 述了,我还是通过aspnetcore的小sample去熟 ...
- Docker 基本核心原理
Docker内核知识 namespace资源隔离 namespace的6项隔离 NameSpace 系统调用参数 隔离内容 UTS CLONE_NEWUTS 主机名与域名 IPC CLONE_NEWI ...
- Docker学习笔记之Docker的Build 原理
0x00 概述 使用 Docker 时,最常用的命令无非是 docker container 和 docker image 相关的子命令,当然最初没有管理类命令(或者说分组)的时候,最常使用的命令也无 ...
- 操作系统-容器-Docker:如何将应用打包成为 Docker 镜像?
ylbtech-操作系统-容器-Docker:如何将应用打包成为 Docker 镜像? 1.返回顶部 1. 虽然 DockerHub 提供了大量的镜像,但是由于企业环境的多样性,并不是每个应用都能在 ...
- Docker容器的原理与实践(上)
本文来自网易云社区. 虚拟化 是一种资源管理技术,将计算机的各种资源予以抽象.转换后呈现出来, 打破实体结构间的不可切割的障碍,使用户可以比原本更好的方式来应用这些资源. Hypervisor 一种运 ...
- Docker容器的原理与实践 (下)
欢迎访问网易云社区,了解更多网易技术产品运营经验. Docker原理分析 Docker架构 镜像原理 镜像是一个只读的容器模板,含有启动docker容器所需的文件系统结构及内容Docker以镜像和在镜 ...
随机推荐
- Scala数据结构(数组,Map和Tuple)
package com.zy import scala.collection.mutable import scala.collection.mutable.ArrayBuffer object te ...
- HDU-4773 Problem of Apollonius (圆的反演)
参考: https://oi-wiki.org/geometry/inverse/ https://blog.csdn.net/acdreamers/article/details/16966369 ...
- 2019icpc徐州站 Cat 计蒜客 - 42540 && The Answer to the Ultimate Question of Life, The Universe, and Everything. 计蒜客 - 42545
VJ链接:https://vjudge.net/contest/412095#problem/A Cat 计蒜客 - 42540 题意: 给你一个区间[L,R],给你现在拥有的钱S.你需要从[L,R] ...
- 【poj 1961】Period(字符串--KMP 模版题)
题意:给你一个字符串,求这个字符串到第 i 个字符为止的重复子串的个数. 解法:判断重复子串的语句很重要!!if (p && i%(i-p)==0) printf("%d % ...
- 【noi 2.6_2988】计算字符串距离(DP)
题意: 给两个字符串,可以增.删.改,问使这两个串变为相同的最小操作数. 解法:(下面2种的代码主要区别在初始化和,而状态转移方程大家可挑自己更容易理解的方法打) 1.f[i][j]表示a串前i个和b ...
- Linux 设置简单密码
centos: echo 密码 | passwd --stdin 用户名 ubuntu:(需先设置一个密码) sudo passwd username https://blog.csdn.net/mi ...
- Python——Django框架——Model数据库模型
一.设置 1.Django的setting中配置数据库(MySQL配置) DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql' ...
- MySQL数据库系列(四)- InnoDB下的共享表空间和独立表空间详解
一.概念 共享表空间: Innodb的所有数据保存在一个单独的表空间里面,而这个表空间可以由很多个文件组成,一个表可以跨多个文件存在,所以其大小限制不再是文件大小的限制,而是其自身的限制.从Innod ...
- 关于Matlab GUI的一些经验总结
注:此文来自转载,侵删去年做了一些关于Matlab GUI的程序,现在又要做相关的东西,回想起来,当时很多经验没有记录下来,现在回顾起来始终觉得不爽,所以从现在开始,一定要勤写记录. 从简单的例子说起 ...
- 记一次 Raven2 渗透(phpmailer漏洞+UDF提权)
目录: 1. 寻找IP 2.dirb目录爆破 2.PHPMailer漏洞反弹得到shell 3.python版本的exp修改 4.查看wordpress的wp-config.php配置文件得到数据库账 ...