热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

docker文件系统镜像篇

学习docker的本地存储系统结构首先我们明白docker镜像具有分层的架构,也就是说一个镜像由n个子镜像组成。比如我们下载一个docker镜像(mysql:5.7),可以看到,这



学习docker的本地存储系统结构
首先我们明白docker镜像具有分层的架构,也就是说一个镜像由n个子镜像组成。比如我们下载一个docker镜像(mysql:5.7),可以看到,这里它是一层层去下载的,本地有的层就不会重复去下载。
在这里插入图片描述
在pull完镜像之后,我们就会产生一个问题,镜像在本地是怎么存储的?是不是一个文件的方式直接存储在本地?带着问题,一起了解一下镜像在本地的存储方式。

/var/lib/docker,这是docker在本地存储镜像和容器的目录。查看一下目录的结构:
在这里插入图片描述
这篇博客主要的内容就在 image/ 子文件中讨论。
在这里插入图片描述
进入image文件夹,只有一个子文件夹overlay2,这代表着我本地的docker使用的文件驱动系统是overlay,早期的时候使用的是aufs,也就是说这里文件夹就是对应docker使用的文件的类型了。继续往里进,ls一下:

root@ubuntu:overlay2# ls
distribution imagedb layerdb repositories.json

一共有三个文件夹和一个json文件。先看json文件(python -m json.tool 是格式化命令行输出,便于查看):

root@ubuntu:overlay2# cat repositories.json |python -m json.tool
{
"Repositories": {
"10.1.21.39:48080/virtual-experiment/hdu_ubuntu18.04": {
"10.1.21.39:48080/virtual-experiment/hdu_ubuntu18.04:1.0": "sha256:62c28f359ff8118ef8ced0aea6e8516c4cac721024b5d90f57494f939b0f4eb8",
"10.1.21.39:48080/virtual-experiment/hdu_ubuntu18.04:juyiwang": "sha256:40620aa96ad8aeec60fdcdf195ab2722ce6979621b3f49d6f5d4938e60239bdf",
"10.1.21.39:48080/virtual-experiment/hdu_ubuntu18.04@sha256:2c828d609231bce40039f9d0e68f474edfd5454b3488183c1ae1c0f2d36b89f4": "sha256:40620aa96ad8aeec60fdcdf195ab2722ce6979621b3f49d6f5d4938e60239bdf",
"10.1.21.39:48080/virtual-experiment/hdu_ubuntu18.04@sha256:c6c05dbc439c6ba29487cd341f92348d5cf63f2a251e3d88f16ad2ac981b3be3": "sha256:62c28f359ff8118ef8ced0aea6e8516c4cac721024b5d90f57494f939b0f4eb8"
},
"hyperledger/fabric-tools": {
"hyperledger/fabric-tools:1.4.1": "sha256:432c24764fbbc8e2546b0e46d470dd090a459ecd33a4d7c2acca2df734b7906c",
"hyperledger/fabric-tools@sha256:c458ddc3109d3519b209baaf9abff113641267ec2adb01dfdcf8f4c9e77a2fa0": "sha256:432c24764fbbc8e2546b0e46d470dd090a459ecd33a4d7c2acca2df734b7906c"
},
"jenkins/jenkins": {
"jenkins/jenkins:lts-centos": "sha256:8a93d9bb527e66a91d974c4b9a1ca312f90b24742266238098cd9fafdb825405",
"jenkins/jenkins@sha256:8b9ccc6797dcfc2513f5d2bf0a0a89a2cc7750e27d72423588989bd6187f22b8": "sha256:8a93d9bb527e66a91d974c4b9a1ca312f90b24742266238098cd9fafdb825405"
},
"mongo": {
"mongo:latest": "sha256:ba0c2ff8d3620c0910832424efef02787214013b1c5b1d9dc9d87d638e2ceb71",
"mongo@sha256:a4448eb5f6e6097353d0ab97eb50aeb0238bb4e60c37e401920d3c2c4fc73eb9": "sha256:ba0c2ff8d3620c0910832424efef02787214013b1c5b1d9dc9d87d638e2ceb71"
},
"mysql": {
"mysql:5.7": "sha256:f07dfa83b5283f486f1fa1628cb8b4a18a4d071a486708acc5c06243ca7f592a",
"mysql@sha256:c3a567d3e3ad8b05dfce401ed08f0f6bf3f3b64cc17694979d5f2e5d78e10173": "sha256:f07dfa83b5283f486f1fa1628cb8b4a18a4d071a486708acc5c06243ca7f592a"
},
"nginx": {
"nginx:1.17.9": "sha256:6678c7c2e56c970388f8d5a398aa30f2ab60e85f20165e101053c3d3a11e6663"
}
……
……
……
}
}

这里我删去了很多的镜像信息,只留下了一部分,可以看到,刚刚下载的mysql镜像信息为:

"mysql": {
"mysql:5.7": "sha256:f07dfa83b5283f486f1fa1628cb8b4a18a4d071a486708acc5c06243ca7f592a",
"mysql@sha256:c3a567d3e3ad8b05dfce401ed08f0f6bf3f3b64cc17694979d5f2e5d78e10173": "sha256:f07dfa83b5283f486f1fa1628cb8b4a18a4d071a486708acc5c06243ca7f592a"
}

这个 repositories.json文件记载了机器上所有的镜像的信息。相同的镜像不同的tag会放在一个镜像里面存储。存储的具体信息有:第一行存储的是镜像的ID,这个ID在所有的机器上都是统一的。另外一个hash值还不清楚,但是在每个机器上相同镜像也是相同的。

接下来看一下imagedb文件夹:

[root@k8s-master overlay2]# tree imagedb/
imagedb/
├── content
│ └── sha256
│ ├── 06298d9e08f809fa1e0d1d8aed6b45c91b06263ae2bf79facc254709a0816b61
│ ├── 0633993b5dfcc12185995f44ee2ed14b2182851a88d1c604c5b043be27c6f112
│ ├── 133283c0dd722f69ca6c136a2403581dcce7be09a907b2915c1029087b159119
│ ├── 219ee5171f8006d1462fa76c12b9b01ab672dbc8b283f186841bf2c3ca8e3c93
│ ├── 22c70bba8283cb87951743be5fa043bec56ade01ceee079e6c2357a10b44159a
│ ├── 2c4adeb21b4ff8ed3309d0e42b6b4ae39872399f7b37e0856e673b13c4aba13d
│ ├── 40620aa96ad8aeec60fdcdf195ab2722ce6979621b3f49d6f5d4938e60239bdf
│ ├── 432c24764fbbc8e2546b0e46d470dd090a459ecd33a4d7c2acca2df734b7906c
│ ├── 4e9f801d2217e98e94de72cefbcb010a7f2caccf03834dfd12a8e60abcaaecfd
│ ├── 5ac750b5261527d0720f0926183a76f52e33eb0f71368b05c2fe4a481415108f
│ ├── 62c28f359ff8118ef8ced0aea6e8516c4cac721024b5d90f57494f939b0f4eb8
│ ├── 6678c7c2e56c970388f8d5a398aa30f2ab60e85f20165e101053c3d3a11e6663
│ ├── 68c3eb07bfc3fc02f468d9e56564fd97fb4d75879b5f7c3ce1d8af4f60d32865
│ ├── 76d11bb7c38696065071971f6019154132158da2f23546c20c8c359272920aa0
│ ├── 7c926cb4c20c8b4b60ac552cc475714b8a2d7df8830a470c119e94a8ff8425c2
│ ├── 7ffcec7b8dd8dd08855040f59871264dc3ca034556e06bfa245c9df98eef1572
│ ├── 8205975e0c5a3bc1d0cb38979933e97f68644146f8ead9901befe089f5fb88b2
│ ├── 82719e1ce60dc59ffeba849f2e5cb56e6e53eabd09afd41c661c9633e580303a
│ ├── 89a062da739d3774b51a5ad4f0876f6d732dc4f15df92b839e433b302968abb6
│ ├── 8a93d9bb527e66a91d974c4b9a1ca312f90b24742266238098cd9fafdb825405
│ ├── 9a4b698bff47c4b3df9a053e82e4eda633fffcfe8399c5fc8fa0358fc8e12546
│ ├── 9bdad03644c77f646425c50ea4aacfb146ee40dfeee6a40eff031c044deee5de
│ ├── 9f3a39d15fb92be6ccd28cbae89d4edf100ec7968cf437aa43a93b5e77ddcd0d
│ ├── aa45bdd3887e43c0adafcef5edbe6132f90b1e4995177d9450208da30dd4b4b6
│ ├── ac1c9c4c950cec6546482146f1ea5f9aa94437d917710cbba139ff4875c71713
│ ├── ae0f2e7ff3511927689a4031d96d674553f6d9694a0787284221aaa165deadf3
│ ├── b0b3c4c404da51002078e80e59d63221bdf1aeae86317a5ebeed39a58ce94877
│ ├── ba0c2ff8d3620c0910832424efef02787214013b1c5b1d9dc9d87d638e2ceb71
│ ├── bec9f481115c600b7a89684d6c7df852c8a3044106593bc780152fc8e864f36e
│ ├── bf756fb1ae65adf866bd8c456593cd24beb6a0a061dedf42b26a993176745f6b
│ ├── d3c94e01ac0d2850ce9c2506204aa408b54a692f231683aab74b9e2a62192067
│ ├── d75082f1d121636c8a2546a2183597a239feb585bf0f6d3367468baca17f103a
│ ├── da86e6ba6ca197bf6bc5e9d900febd906b133eaa4750e6bed647b0fbe50ed43e
│ ├── e3dd0e49bca555d559ca2e97f06a1efa108ebd230fddcb17606723994f18ae3b
│ ├── eb516548c180f8a6e0235034ccee2428027896af16a509786da13022fe95fe8c
│ ├── f07dfa83b5283f486f1fa1628cb8b4a18a4d071a486708acc5c06243ca7f592a
│ └── f87615ada079b93259b5e8e3bf354439373cfcbf41f8385df9afda9105c455f9
└── metadata
└── sha256
├── 06298d9e08f809fa1e0d1d8aed6b45c91b06263ae2bf79facc254709a0816b61
│ └── parent
├── 0633993b5dfcc12185995f44ee2ed14b2182851a88d1c604c5b043be27c6f112
│ └── parent
├── 40620aa96ad8aeec60fdcdf195ab2722ce6979621b3f49d6f5d4938e60239bdf
│ ├── lastUpdated
│ └── parent
├── 5ac750b5261527d0720f0926183a76f52e33eb0f71368b05c2fe4a481415108f
│ └── parent
├── 62c28f359ff8118ef8ced0aea6e8516c4cac721024b5d90f57494f939b0f4eb8
│ └── lastUpdated
├── 6678c7c2e56c970388f8d5a398aa30f2ab60e85f20165e101053c3d3a11e6663
│ └── lastUpdated
├── 7c926cb4c20c8b4b60ac552cc475714b8a2d7df8830a470c119e94a8ff8425c2
│ └── parent
├── 7ffcec7b8dd8dd08855040f59871264dc3ca034556e06bfa245c9df98eef1572
│ └── parent
├── 9a4b698bff47c4b3df9a053e82e4eda633fffcfe8399c5fc8fa0358fc8e12546
│ └── parent
├── 9bdad03644c77f646425c50ea4aacfb146ee40dfeee6a40eff031c044deee5de
│ └── lastUpdated
├── 9f3a39d15fb92be6ccd28cbae89d4edf100ec7968cf437aa43a93b5e77ddcd0d
│ └── parent
├── d3c94e01ac0d2850ce9c2506204aa408b54a692f231683aab74b9e2a62192067
│ ├── lastUpdated
│ └── parent
└── f87615ada079b93259b5e8e3bf354439373cfcbf41f8385df9afda9105c455f9
└── parent
17 directories, 52 files

先看imagedb/content/sha256/{镜像ID}文件:

[root@k8s-master overlay2]# cat imagedb/content/sha256/f07dfa83b5283f486f1fa1628cb8b4a18a4d071a486708acc5c06243ca7f592a|python -m json.tool
{
"architecture": "amd64",
"config": {
……
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
……
],
"Cmd": [
"mysqld"
],
"Image": "sha256:eeb4574531bba5f416e424e5af5f8833b1731cadddd08547366817a2099dee96",
"Volumes": {
"/var/lib/mysql": {}
},
"WorkingDir": "",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": null
},
"container": "000ffa68848b6e618b1d24f5e906d14ff2123afd224ff28a67a8aaa1b6cbfa18",
"container_config": {
……
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
……
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"mysqld\"]"
],
"Image": "sha256:eeb4574531bba5f416e424e5af5f8833b1731cadddd08547366817a2099dee96",
"Volumes": {
"/var/lib/mysql": {}
},
"WorkingDir": "",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {}
},
"created": "2020-12-21T20:34:44.202492422Z",
"docker_version": "19.03.12",
"history": [……
],
"os": "linux",
"rootfs": {
"type": "layers",
"diff_ids": [
"sha256:87c8a1d8f54f3aa4e05569e8919397b65056aa71cdf48b7f061432c98475eee9",
"sha256:8d77519601a52080d6e1e48d455df3b2646ec839a41f4566116c4058d1612eac",
"sha256:cb1c4d92429ddcbcbe3c43d2f4b8cea706cb47485f833c22aeb78725b593c8be",
"sha256:614fbc08d1b2e529d6a4b6975b7d193a232efc49f3359923d7efb2cfa6d73e3e",
"sha256:d4a3e8c51d197f372f9e1bba89eefe1c20e51ccb349211f9efbecc22ca64c95d",
"sha256:d0425b5c07f61692b1720f23afd5cd9b07f0bbf2e8cb2e52dcb971c81524436f",
"sha256:7d338559a103f8537c06b60bbda893b519f1d5f6ea7d79f2bd83a0cdee3c6120",
"sha256:d8e44f98a95fceeba96085ff4c9661e0cddde510f44b8dfb6bf8be0296d2f198",
"sha256:937609480ea5519ed11458ef62228d00d1948b8ecc98e2641f747799b3c65028",
"sha256:7888c0a868da47885502aebf582a918a3d04cf670feea9281d990bf05239097f",
"sha256:e3c6570b4ce19a9fb95d1e0e85ae22bcd46c8a6f13297b451774bf48ff4ae7f3"
]
}
}

此文件主要内容为镜像的基本信息、环境变量、创建时间等。目前我们关注最后的rootfs这个key,可以看到这里他把镜像所涉及到的层都罗列出来了,使用的是diff_ids作为valus。
这里介绍一下相关的四个ID:


  • cacheID
      由宿主机随即生成的一个uuid,根镜像层文件一一对应,用于宿主机标志和索引镜像层。文件镜像内容实际存放的位置,是一个随机值。

  • diffID
      镜像每层次内容的摘要,反映了单个层次内容的信息镜像层校验ID、根据该镜像层的打包文件校验获得

  • parent
      父镜像层的chainID(最底层不含该文件)

  • chainID
      docker内容寻址机制采用的索引ID,其值根据当前层和所有祖先层的diffID算得:若该镜像层是最底层,那么其chainID 和 diffID 相同否则,chainID=sha256(父层chainID+" "+本层diffID)

这里各种ID比较多,不要记混了,注意区分,多去文件夹里看一下,多做区别。回到上面文件中的rootfskey中来:

"rootfs": {
"type": "layers",
"diff_ids": [
"sha256:87c8a1d8f54f3aa4e05569e8919397b65056aa71cdf48b7f061432c98475eee9",
"sha256:8d77519601a52080d6e1e48d455df3b2646ec839a41f4566116c4058d1612eac",
"sha256:cb1c4d92429ddcbcbe3c43d2f4b8cea706cb47485f833c22aeb78725b593c8be",
"sha256:614fbc08d1b2e529d6a4b6975b7d193a232efc49f3359923d7efb2cfa6d73e3e",
"sha256:d4a3e8c51d197f372f9e1bba89eefe1c20e51ccb349211f9efbecc22ca64c95d",
"sha256:d0425b5c07f61692b1720f23afd5cd9b07f0bbf2e8cb2e52dcb971c81524436f",
"sha256:7d338559a103f8537c06b60bbda893b519f1d5f6ea7d79f2bd83a0cdee3c6120",
"sha256:d8e44f98a95fceeba96085ff4c9661e0cddde510f44b8dfb6bf8be0296d2f198",
"sha256:937609480ea5519ed11458ef62228d00d1948b8ecc98e2641f747799b3c65028",
"sha256:7888c0a868da47885502aebf582a918a3d04cf670feea9281d990bf05239097f",
"sha256:e3c6570b4ce19a9fb95d1e0e85ae22bcd46c8a6f13297b451774bf48ff4ae7f3"
]
}

接下来就去找到这些层,最上面的层是底层。cd /var/lib/docker/image/overlay2/layerdb/sha256 ,我们发现在这个文件夹下有很多的文件夹,他们的结构是:

.
├── chainID
│ ├── cache-id //本镜像层在本地存储的位置
│ ├── diff //本镜像层的diffID
│ ├── parent //存储父镜像层的chainID
│ ├── size //本镜像层的大小
│ └── tar-split.json.gz //layer层数据tar压缩包的split文件该文件生成需要依赖tar-split,通过这个文件可以还原layer的tar包。

在这里,我们前面介绍的四种ID全都出现了。在这个文件夹下,我们开始寻找最上层的ID:e3c6570b4ce19a9fb95d1e0e85ae22bcd46c8a6f13297b451774bf48ff4ae7f3,但是却没有找到。只有最底层的ID:87c8a1d8f54f3aa4e05569e8919397b65056aa71cdf48b7f061432c98475eee9。这里涉及到一个存储的原理,在本地docker并不是使用diffID进行相关内容的存储,而是根据chainID进行存储,而chainID和diffID之间有一个计算的公式(没有父层则 chainID= diffID)。






c


h


a


i


n


I


D


=


s


h


a


256


(


p


a


r


e


n


t





c


h


a


i


n


I


d


+








+


d


i


f


f


I


D


)



chainID = sha256(parent-chainId +空格+ diffID)


chainID=sha256(parent−chainId+空格+diffID)

而在这个/layerdb/sha256文件夹下都是以chainId为文件夹名保存的。所以我们找不到除最底层之外的层对应文件夹。为了验证这个说法下面进行一次hash计算得到文件夹的名称:

root@ubuntu:sha256# cat aff48ce4678f78d83d7e9bfb9e88cd951c3da52da08779e99b6082edd1cc66f3/diff
sha256:8d77519601a52080d6e1e48d455df3b2646ec839a41f4566116c4058d1612eac

首先我们找到含有第二个层的文件夹(根据diffID去找)。


  • 第二层的diffid:sha256:8d77519601a52080d6e1e48d455df3b2646ec839a41f4566116c4058d1612eac
  • 第二层的chainID:aff48ce4678f78d83d7e9bfb9e88cd951c3da52da08779e99b6082edd1cc66f3
  • 第一层的chainID:87c8a1d8f54f3aa4e05569e8919397b65056aa71cdf48b7f061432c98475eee9
    接下来我们要验证的就是第一层的chainID+空格+第二层的diffdID做sha256=第二层的chainID。
    在这里插入图片描述
    经过验证,这个确实是成立的。
    最后我们还剩下了layerdb/mounts文件夹内容。

root@ubuntu:layerdb# tree mounts/
mounts/
├── 47e5e13e4f692d5f6870de031d3bb1ffc3f99a9fa6e0931d62721f5cae0b8fca
│ ├── init-id // init层在本地的存储位置
│ ├── mount-id // 容器层在本地的存储位置
│ └── parent
└── c128b7ba12a5a208819b54b8c93e9cf4be289d3c9eb5fdfe243ee9845fde8389
├── init-id
├── mount-id
└── parent
2 directories, 6 files

我运行了两个容器(做MySQL主从复制),所以这个文件夹下只有两个文件夹。
未完……



推荐阅读
  • 0157.K 升级 kubeadm 集群_一主两从
    升级kube ... [详细]
  • 大类|电阻器_使用Requests、Etree、BeautifulSoup、Pandas和Path库进行数据抓取与处理 | 将指定区域内容保存为HTML和Excel格式
    大类|电阻器_使用Requests、Etree、BeautifulSoup、Pandas和Path库进行数据抓取与处理 | 将指定区域内容保存为HTML和Excel格式 ... [详细]
  • 在《Cocos2d-x学习笔记:基础概念解析与内存管理机制深入探讨》中,详细介绍了Cocos2d-x的基础概念,并深入分析了其内存管理机制。特别是针对Boost库引入的智能指针管理方法进行了详细的讲解,例如在处理鱼的运动过程中,可以通过编写自定义函数来动态计算角度变化,利用CallFunc回调机制实现高效的游戏逻辑控制。此外,文章还探讨了如何通过智能指针优化资源管理和避免内存泄漏,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • 本文深入探讨了 hCalendar 微格式在事件与时间、地点相关活动标记中的应用。作为微格式系列文章的第四篇,前文已分别介绍了 rel 属性用于定义链接关系、XFN 微格式增强链接的人际关系描述以及 hCard 微格式对个人和组织信息的描述。本次将重点解析 hCalendar 如何通过结构化数据标记,提高事件信息的可读性和互操作性。 ... [详细]
  • 前言: 网上搭建k8s的文章很多,但很多都无法按其说明在阿里云ecs服务器成功搭建,所以我就花了些时间基于自己成功搭建k8s的步骤写了个操作手册,希望对想搭建k8s环境的盆友有所帮 ... [详细]
  • 以下内容|尾部_quarkus实战之一:准备工作
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了quarkus实战之一:准备工作相关的知识,希望对你有一定的参考价值。欢迎访问我的GitHub ... [详细]
  • Spring – Bean Life Cycle
    Spring – Bean Life Cycle ... [详细]
  • 在CentOS 7环境中安装配置Redis及使用Redis Desktop Manager连接时的注意事项与技巧
    在 CentOS 7 环境中安装和配置 Redis 时,需要注意一些关键步骤和最佳实践。本文详细介绍了从安装 Redis 到配置其基本参数的全过程,并提供了使用 Redis Desktop Manager 连接 Redis 服务器的技巧和注意事项。此外,还探讨了如何优化性能和确保数据安全,帮助用户在生产环境中高效地管理和使用 Redis。 ... [详细]
  • 在Linux系统中,网络配置是至关重要的任务之一。本文详细解析了Firewalld和Netfilter机制,并探讨了iptables的应用。通过使用`ip addr show`命令来查看网卡IP地址(需要安装`iproute`包),当网卡未分配IP地址或处于关闭状态时,可以通过`ip link set`命令进行配置和激活。此外,文章还介绍了如何利用Firewalld和iptables实现网络流量控制和安全策略管理,为系统管理员提供了实用的操作指南。 ... [详细]
  • 求助:在CentOS 5.8系统上安装PECL扩展遇到问题
    在 CentOS 5.8 系统上尝试安装 APC 扩展时遇到了问题,具体表现为 PECL 工具无法正常工作。为了确保顺利安装,需要解决 PECL 的相关依赖和配置问题。建议检查 PHP 和 PECL 的版本兼容性,并确保所有必要的库和开发工具已正确安装。此外,可以尝试手动下载 APC 扩展的源代码并进行编译安装,以绕过 PECL 工具的限制。 ... [详细]
  • MySQL索引详解及其优化策略
    本文详细解析了MySQL索引的概念、数据结构及管理方法,并探讨了如何正确使用索引以提升查询性能。文章还深入讲解了联合索引与覆盖索引的应用场景,以及它们在优化数据库性能中的重要作用。此外,通过实例分析,进一步阐述了索引在高读写比系统中的必要性和优势。 ... [详细]
  • CentOS 7环境下Jenkins的安装与前后端应用部署详解
    CentOS 7环境下Jenkins的安装与前后端应用部署详解 ... [详细]
  • 技术日志:Ansible的安装及模块管理详解 ... [详细]
  • BIEE中的最终用户界面被称为Presentation Layer(展现层)。展现层呈现的内容与用户在Web报表开发界面中看到的一致,使用业务语言进行描述,隐藏了技术细节,如星型模型。本文将详细介绍展现层的设计要点及其与业务模型层的关系。 ... [详细]
  • 本书《.NET Core 2.* 开发者指南》是面向开发者的全面学习与实践手册,涵盖了从基础到高级的各个层面。书中详细解析了 .NET Core 的核心概念,包括如何创建 .NET Core 网站,并通过视频教程直观展示操作过程。此外,还深入探讨了 Startup 类的作用、项目目录结构的组织方式以及如何在应用中使用静态文件等内容。对于希望深入了解 .NET Core 架构和开发技巧的开发者来说,本书提供了丰富的实践案例和详尽的技术指导。 ... [详细]
author-avatar
黑糖老姜茶
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有