在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对比与基础镜像

我们来复习下构建镜像的过程

    1. 根据镜像名称拉取mainfest
    1. 根据mainfest拉取config
    1. 根据config拉取layers
    1. 下载各个layer
    1. 修改到基础镜像的配置(config.json和mainfest.json)
    1. 加入我们要加入的文件layer

知道原理后我们可以自己写一个工具来实现整个过程

我开源的docker镜像构建,让你不用装docker也能快速构建容器镜像

支持以下镜像仓库作为基础镜像构建

  • docker hub
  • aliyun
  • 腾讯云

Docker镜像构建原理解析(不装docker也能构建镜像)的更多相关文章

  1. [原][Docker]特性与原理解析

    Docker特性与原理解析 文章假设你已经熟悉了Docker的基本命令和基本知识 首先看看Docker提供了哪些特性: 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上, ...

  2. Docker网络管理机制实例解析+创建自己Docker网络

    实例解析Docker网络管理机制(bridge network,overlay network),介绍Docker默认的网络方式,并创建自己的网络桥接方式,将开发的容器添加至自己新建的网络,提高Doc ...

  3. 一篇不一样的docker原理解析

    转自:https://zhuanlan.zhihu.com/p/22382728 https://zhuanlan.zhihu.com/p/22403015 在学习docker的过程中,我发现目前do ...

  4. 8天入门docker系列 —— 第三天 使用aspnetcore小案例熟悉对镜像的操控

    上一篇我们聊到了容器,现在大家应该也知道了,没有镜像就没有容器,所以镜像对docker来说是非常重要的,关于镜像的特性和原理作为入门系列就不阐 述了,我还是通过aspnetcore的小sample去熟 ...

  5. Docker 基本核心原理

    Docker内核知识 namespace资源隔离 namespace的6项隔离 NameSpace 系统调用参数 隔离内容 UTS CLONE_NEWUTS 主机名与域名 IPC CLONE_NEWI ...

  6. Docker学习笔记之Docker的Build 原理

    0x00 概述 使用 Docker 时,最常用的命令无非是 docker container 和 docker image 相关的子命令,当然最初没有管理类命令(或者说分组)的时候,最常使用的命令也无 ...

  7. 操作系统-容器-Docker:如何将应用打包成为 Docker 镜像?

    ylbtech-操作系统-容器-Docker:如何将应用打包成为 Docker 镜像? 1.返回顶部 1. 虽然 DockerHub 提供了大量的镜像,但是由于企业环境的多样性,并不是每个应用都能在 ...

  8. Docker容器的原理与实践(上)

    本文来自网易云社区. 虚拟化 是一种资源管理技术,将计算机的各种资源予以抽象.转换后呈现出来, 打破实体结构间的不可切割的障碍,使用户可以比原本更好的方式来应用这些资源. Hypervisor 一种运 ...

  9. Docker容器的原理与实践 (下)

    欢迎访问网易云社区,了解更多网易技术产品运营经验. Docker原理分析 Docker架构 镜像原理 镜像是一个只读的容器模板,含有启动docker容器所需的文件系统结构及内容Docker以镜像和在镜 ...

随机推荐

  1. CF 1288 E. Messenger Simulator

    CF 1288 E. Messenger Simulator 题目传送门 官方题解 题意想必大家都明白了这里就不赘述了,这里只想重点记录一下几种实现方法 分析 设向前移动的序列为\(a\)序列 对于没 ...

  2. Codeforces Round #657 (Div. 2) A. Acacius and String(字符串)

    题目链接:https://codeforces.com/contest/1379/problem/A 题意 给出一个由 '?' 和小写字母组成的字符串,可以将 '?' 替换为小写字母,判断是否存在一种 ...

  3. C语言实现--静态链表的操作

    1,我们研究数据结构的操作,第一要弄懂它的结构体表示(也就是结构体特点).第二要清楚它的初始化和撤销过程.对于静态链表首先分析它的特点:一是采用静态存储方式,二是没有指针.静态链表就是不用指针来表示链 ...

  4. Codeforces Global Round 7 D1. Prefix-Suffix Palindrome (Easy version)(字符串)

    题意: 取一字符串不相交的前缀和后缀(可为空)构成最长回文串. 思路: 先从两边取对称的前后缀,之后再取余下字符串较长的回文前缀或后缀. #include <bits/stdc++.h> ...

  5. Codeforces Round #647 (Div. 2) - Thanks, Algo Muse! C. Johnny and Another Rating Drop (规律,二进制)

    题意:有一个正整数\(n\),要求写出所有\(1\)~\(n\)的二进制数,统计相邻的两个二进制同位置上不同数的个数. 题解:打表找规律,不难发现: ​ \(00000\) ​ \(00001\) ​ ...

  6. Spring Cloud实战 | 第十一篇:Spring Cloud Gateway 网关实现对RESTful接口权限控制和按钮权限控制

    一. 前言 hi,大家好,这应该是农历年前的关于开源项目 的最后一篇文章了. 有来商城 是基于 Spring Cloud OAuth2 + Spring Cloud Gateway + JWT实现的统 ...

  7. OpenStack Train版-1.安装基础环境&服务

    1. 服务组件的密码 密码名称 描述 ADMIN_PASS admin用户密码 CINDER_DBPASS 块设备存储服务的数据库密码 CINDER_PASS 块设备存储服务的 cinder 密码 D ...

  8. 1.初识Redis

    作者 微信:tangy8080 电子邮箱:914661180@qq.com 更新时间:2019-08-14 20:35:36 星期三 欢迎您订阅和分享我的订阅号,订阅号内会不定期分享一些我自己学习过程 ...

  9. 鸟哥的linux私房菜——第七章学习(Linux 磁盘与文件系统管理)

    1.1).文件系统特征 我们称呼一个可被挂载的数据为一个文件系统而不是一个分区! 文件系统通常会将这两部份的数据分别存放在不同的区块,权限与属性放置到 inode 中,至于实际数据则放置到 data ...

  10. VScode 配置c++环境

    参考 https://code.visualstudio.com/docs/cpp/config-mingw https://zhuanlan.zhihu.com/p/77645306 主要 http ...