[docker]七、docker镜像的制作(超详细)、docker镜像结构原理、镜像的分享——harbor
目录
1、镜像(images)
1.1、Dockerfile:是制作镜像的文件
2、镜像结构原理
2.1、base 镜像
2.1.1、rootfs和bootfs
2.1.2、base 镜像提供的是最小安装的 Linux 发行版
2.2、镜像分层
2.2.1、为什么 Docker 镜像要采用这种分层结构呢?
2.3、容器可写层
3、制作镜像
3.1、制作镜像的过程
3.1.1、练习
3.2、Minimize the number of layers,减少层数
3.3、制作镜像的流程中可能会出现的问题
3.4、copy和add的区别
4、若是今后开发人员开发了新的代码,容器里的代码是否会自动更新?
5、为什么有些容器启动的时候需要使用 -it 有些不需要?
5.1、daemon off
6、使用容器跑一个go程序
7、harbor
1、镜像(images)
是打包好的软件,由程序代码、基础系统、依赖关系的软件包、系统库和工具组成 。
官方解释:
A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries and settings.
Docker容器映像是一个轻量级的、独立的、可执行的软件包,包含了运行应用程序所需的一切:代码、运行时、系统工具、系统库和设置。
[区分一下之前我们提到的centos镜像]
我们之前在linux安装centos提到的镜像是镜像站点的centos镜像,也叫映像文件。因为centos的官方是在国外,若是我们国内用户访问到国外的话,网速就特别慢。这个时候中国的企业就在中国搞一个镜像站点,把国外的东西复制一份放到国内来。那么国内的这个服务器就成为了国外服务器的镜像站点了。而我们现在要讲的这个镜像叫images,是docker容器里的镜像可以理解为是打包好的软件,是一个app的封装。
1.1、Dockerfile:是制作镜像的文件
参考文献:Docker Hub
点开里边的任意一个版本就能看到它的dockerfile
2、镜像结构原理
转载部分内容:第八篇:Docker镜像结构原理_Linux运维开发的技术博客_51CTO博客
2.1、base 镜像
base 镜像有两层含义:
- 不依赖其他镜像,从 scratch 构建。
scratch:是最基础的docker镜像,相当于一个地基。
- 其他镜像可以在此基础上进行扩展。
用别的镜像做基础镜像---》站在巨人的肩膀
base 镜像的通常都是各种 Linux 发行版的 Docker 镜像,比如 Ubuntu, Debian, CentOS 等,以 CentOS 为例学习 base 镜像包含哪些内容。
这里拉了很多镜像,是因为这个镜像就是在一些基础镜像的基础上加一些镜像组成了python这个镜像
使用docker pull centos下载最新版本的Centos镜像也就207M左右,而我们平时下载一个原生的centos镜像都是4G,对于 Docker 初学者都会有这个疑问。
下载python镜像:
下面来了解下Linux 操作系统由内核空间和用户空间组成,如下图所示:
2.1.1、rootfs和bootfs
bootfs和rootfs里面就是一些程序和文件
bootfs:容器启动的时候需要的内容,是linux kernel 提供了bootfs
内核空间是 kernel,Linux 刚启动时会加载 bootfs 文件系统,之后 bootfs 会被卸载掉。用户空间的文件系统是 rootfs,包含我们熟悉的 /dev, /proc, /bin 等目录。对于 base 镜像来说,底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。而对于一个精简的 OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了。相比其他 Linux 发行版,CentOS 的 rootfs 已经算臃肿的了,alpine 还不到 10MB。我们平时安装的 CentOS 除了 rootfs 还会选装很多软件、服务、图形桌面等,需要好几个 GB 就不足为奇了。
即我们的容器全部用宿主机的内核kernel,而容器提供的只是不同的系统文件。bootfs,容器启动的时候需要的内容;rootfs,容器内部的操作系统
2.1.2、base 镜像提供的是最小安装的 Linux 发行版
下面是 CentOS 镜像的 Dockerfile 的内容:
第二行 ADD 指令添加到镜像的 tar 包就是 CentOS 7 的 rootfs。在制作镜像时,这个 tar 包会自动解压到 / 目录下,生成 /dev, /porc, /bin 等目录。
2.2、镜像分层
Docker 支持通过扩展现有镜像,创建新的镜像。
实际上,Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。比如我们现在制作一个镜像
root@dockerserever:~# docker pull debian # 下载一个debian的镜像
① 新镜像不再是从 scratch 开始,而是直接在 Debian base 镜像上构建。
② 安装 emacs 编辑器。
③ 安装 apache2。
④ 容器启动时运行 bash。
构建过程如下图所示:
可以看到,新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。
2.2.1、为什么 Docker 镜像要采用这种分层结构呢?
最大的一个好处就是 - 共享资源。
比如:若是有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
这时可能就有人会问了:如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是否也会被修改?
答:不会!因为修改会被限制在单个容器内。因为它有Copy-on-Write特性。
2.3、容器可写层
当容器启动时,一个新的可写层被加载到镜像的顶部。
这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。
只有容器层是可写的,容器层下面的所有镜像层都是只读的。
下面我们深入讨论容器层的细节。
镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a0.。在容器层中,用户看到的是一个叠加之后的文件系统。
1.添加文件
在容器中创建文件时,新文件被添加到容器层中。
2. 读取文件
在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,打开并读入内存。
3. 修改文件
在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。
4. 删除文件
在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。
只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。
这样就解释了我们前面提出的问题:容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。
3、制作镜像
[为什么要制作镜像?docker hub上不是有很多镜像吗?]
- 不能满足我们的需求
- 不够安全,有安全隐患
[谁去制作镜像?]
一般都是由开发人员去制作,也可以运维人员去制作或者权力比较大的工作人员,因为镜像里边涉及了公司里的机密代码等。
3.1、制作镜像的过程
第一步:新建一个空文件夹并pull一个python镜像
[root@centos7-docker ~]# mkdir /mydocker
[root@centos7-docker ~]# cd /mydocker/
第二步:新建Dockerfile
这里要注意,不要把注释放在代码的后边,不然待会run的时候运行不出来。
FROM python
# 我们在docker容器的工作目录。即进入docker容器的时候,所在的目录
WORKDIR /app # 复制当前目录下的所有内容到容器里边/app目录下
ADD . /app # 定义一个数据卷
VOLUME ["/data_flask"]# requirements.txt会写明我这个项目会需要一些什么python库;\
# 这条命令是告诉容器把requirements.txt里需要的库到pypi.python.org这个网站里边下载
# 这条命令是在制作镜像的时候要运行的,而不是在启动容器的时候运行的,这个要记住很容易混淆
RUN pip install --trusted-host pypi.python.org -r requirements.txt# 暴露我们的端口号,即容器对外开放哪个端口
EXPOSE 80# 定义环境变量
ENV NAME World
ENV AUTHOR fan# 容器起来之后运行的第一个程序,这个是容器启动的时候运行,要和上边区分开来
CMD ["python", "app.py"]
另外的一些解释
第三步:新建requirements.txt文件
Flask
Redis
第四步:新建app.py文件
from flask import Flask
from redis import Redis,RedisError
import os
import socket# Connect to Redis 连接redis数据库
redis = Redis(host="redis", db=0,socket_connect_timeout=2, socket_timeout=2)app = Flask(__name__)# 访问这台机器的根"/"
@app.route("/")
def hello():try:# 若是有人访问,会往redis数据库里增加一个值visits = redis.incr("counter")except RedisError:# 这个visits是从redis数据库里获取的visits = "<i>cannot connect to REdis, counter disabled</i>"html = "<h3>Hello {name}!</h3>" \"<b>Hostname:</b>{hostname}<br/>" \"<b>Visits:</b> {visits}"# 返回这个主机名(socket.gethostname())和访问的次数(visits)return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(),visits=visits)if __name__ == "__main__":app.run(host='0.0.0.0', port=80)
第五步:生成镜像,需要一点时间,因为要下载很多东西
# -t,打个标记,等于给这个镜像取个名字
[root@centos7-docker mydocker]# docker build -t friendlyhello_1 .
生成镜像的时候,背后会自动生成临时的容器去执行Dockerfile里的命令,检测这个命令是否可以运行
[查看结果]
[root@centos7-docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
friendlyhello_1 latest 82dda8055795 7 hours ago 935MB
第六步:运行容器
[root@centos7-docker docker]# docker run -d -p 5080:80 --name hello-1 friendlyhello_1
[root@centos7-docker docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c6dbd5383c7a friendlyhello_1 "python app.py" 7 minutes ago Up 7 minutes 0.0.0.0:5080->80/tcp, :::5080->80/tcp hello-1
# 一定要做端口映射,不然到时候我们无法访问应用程序
[注意]: 若是我们使用"daocker ps"没有看到我们创建的容器在启动,那么就是我们之前编辑app.py Dockerfile requirements.txt,这三个文件有误。我们可以使用"docker logs + 容器名字"来看运行这个容器的时候出现了什么错误。
[root@centos7-docker mydocker]# docker logs hello-2* Serving Flask app 'app' (lazy loading)* Environment: productionWARNING: This is a development server. Do not use it in a production deployment.Use a production WSGI server instead.* Debug mode: off* Running on all addresses (0.0.0.0)WARNING: This is a development server. Do not use it in a production deployment.* Running on http://127.0.0.1:80* Running on http://172.17.0.3:80 (Press CTRL+C to quit)
192.168.29.1 - - [22/Apr/2022 13:19:18] "GET / HTTP/1.1" 200 -
192.168.29.1 - - [22/Apr/2022 13:19:18] "GET /favicon.ico HTTP/1.1" 404 -# 我这是执行成功了的情况
[结果查看]
因为redis服务没有安装,所以连接不到redis数据库,可以启动一个redis的容器,链接到现在这个容器
第七步:起一个redis容器
[root@centos7-docker docker]# docker run -d -p 6379:80 --name fan-redis-1 redis
a2b9a2ec08fa9efa1276efbefed4beaef25033bd56d8d888f3e61bfa46afad8b
[root@centos7-docker docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a2b9a2ec08fa redis "docker-entrypoint.s…" 4 seconds ago Up 3 seconds 6379/tcp, 0.0.0.0:6379->80/tcp, :::6379->80/tcp fan-redis-1
c6dbd5383c7a friendlyhello_1 "python app.py" 22 minutes ago Up 22 minutes 0.0.0.0:5080->80/tcp, :::5080->80/tcp hello-1
起完之后,页面还是没有变化。因为我们虽然起了reids容器,但是不知道redis服务的IP地址是多少,所以连不过去。
[root@centos7-docker docker]# docker exec -it hello-1 /bin/bash
root@c6dbd5383c7a:/app# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 c6dbd5383c7a # 这里可以看到这个机器只知道自己的IP地址
因为这个镜像的命令太过于少了,所以没有vim和vi命令能够直接修改这个文件。但是我感觉直接修改这个文件,添加一条标明redis容器的IP地址的内容就可以访问到了。这里我们直接新建一个容器吧。
[root@centos7-docker mydocker]# docker run -d --name hello-2 -p 5081:80 --link fan-redis-1:redis friendlyhello_1
ad7d079f9aa87da741303fc366311166b020617d4b5729916444881c75983647
[root@centos7-docker mydocker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ad7d079f9aa8 friendlyhello_1 "python app.py" 6 seconds ago Up 6 seconds 0.0.0.0:5081->80/tcp, :::5081->80/tcp hello-2
a2b9a2ec08fa redis "docker-entrypoint.s…" About an hour ago Up 6 minutes 6379/tcp, 0.0.0.0:6379->80/tcp, :::6379->80/tcp fan-redis-1# 这里我们可以看到新建的hello-2有redis的IP地址
root@ad7d079f9aa8:/app# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 redis a2b9a2ec08fa fan-redis-1
172.17.0.3 ad7d079f9aa8
[docker]七、docker镜像的制作(超详细)、docker镜像结构原理、镜像的分享——harbor相关推荐
- 了解MySQL(超详细的MySQL工作原理 体系结构)
了解MySQL(超详细的MySQL工作原理 体系结构) 1.MySQL体系结构 2.MySQL内存结构 3.MySQL文件结构 4.innodb体系结构 一.了解MySQL前你需要知道的 引擎是什么: ...
- 超详细的MySQL工作原理 体系结构
超详细的MySQL工作原理 体系结构 妖精的杂七杂八 2020-08-13 13:54:12 了解MySQL(超详细的MySQL工作原理 体系结构) 1.MySQL体系结构 2.MySQL内存结构 3 ...
- 超详细Docker部署SpringBoot+Vue项目(三更博客项目部署)
文章目录 1.项目部署规划 2.前置工作 2.1修改后端配置文件ip 2.2修改前端Vue项目运行端口 2.3修改前端对应的服务器ip 2.4后端项目打包 2.4.1解决打包问题 2.4.2项目打包, ...
- 超详细Docker容器化自动部署(纯手打)
微服务容器化自动部署 1. 传统手动部署: 首先基于源码打包生成jar包(或war包),将jar包(或war包)上传至虚 拟机并拷贝至JDK容器. 2. 通过Maven插件自动部署: 对于数量众多的微 ...
- 超详细docker入门级教程
何夜息随笔录-docker入门级教程 文章目录 何夜息随笔录-docker入门级教程 什么是docker docker的组成 安装docker 卸载docker 阿里云镜像加速 docker的运行流程 ...
- Linux下Docker如何挂载启动nginx(超详细)
前言:随着docker越来越火爆,很多东西都可以部署在docker上面:使用docker方便管理我们的应用:这篇博客将教会你如何使用docker部署nginx! 准备工作:部署好docker联网的li ...
- java+maven项目+tapd+jenkins+gitlab+sonarqube+docker实现自动化持续部署(超详细)
文章目录 前言 相关介绍 一.准备 环境 二.安装docker 开放docker 2375端口 三.docker安装gitlab 修改gitlab.rb配置文件 进入容器重启配置 修改http的clo ...
- mysql主从配置duxi_手把手超详细Docker部署MongoDB集群
Mongodb集群搭建 mongodb 集群搭建的方式有三种:主从备份(Master - Slave)模式,或者叫主从复制模式. 副本集(Replica Set)模式. 分片(Sharding)模式. ...
- 2023年CentOS镜像下载地址,包括CentOS官网、国内镜像下载,超详细教学,小白也能学会。
目录 1.CentOS官网镜像下载 1.1进入CentOs官网镜像下载地址 1.2找到需要下载的版本 1.3选择isos镜像文件夹 1.4选择架构 1.5下载种子文件 2.阿里云开源镜像站下载 2.1 ...
- 超详细的Vue渲染原理讲解
目录 一.Vue简介 1. MVVM.MVP和MVC 2. Vue的基本配置 二.Vue渲染原理 1. HTML与模板 2. Vue组件的完整渲染过程 (1). Vue自身的初始化阶段 (2). 组件 ...
最新文章
- Windows Phone 7、XNA的旋转的背景
- 对比3家平台,我总结了疫情数据可视化的8点经验
- HelloWorld 和相关设置
- js网页文件资源加载器
- Redis未授权访问漏洞记录(端口:6379)
- Vue基本操作及运行截图总结
- mysql case quchong_处理mysql的查询语句去重案例一则
- java jpanel对齐_java – 如何使用GridBagLayout在JPanel中对齐组件中心?
- 毕业设计不要再做 XX 管理系统了
- 移动流量转赠给好友_中国移动怎么才能转赠手机流量
- Java Poi 根据文字内容 插入 word 图片
- 中国人保为易集康健康科技承保产品责任险,为消费者保驾护航!
- 《管理学》第一章 管理与管理学
- 干货:如何打造一个直播平台
- 禁止APP录屏和截屏
- word2013插入excel对象报错_excel插入对象文件夹 Excel2013中插入对象文件的方法
- 学习表——受任于败军之际,奉命于危难之间(11.28-12.4)
- Java学习网站 [摘自互联网]
- Python学习笔记之网络爬虫
- 面对客户的“佩奇”需求,顶级外贸业务员该怎么做
热门文章
- 激活函数Relu 及 leakyRelu
- 车辆出险保险索赔技巧
- 怎么修改服务器图片存储路径,linux服务器存储图片路径
- vue3中使用swiper8 实现缩略图(thumbs的使用)
- 软件本地化测试比功能测试都有哪些方面需要注意?
- 易车买过车之后如何省钱
- 第十六届(2017)中国政府网站绩效评估结果发布 暨经验交流会在京顺利召开
- mysql技能特长怎么写_自我介绍性格技能兴趣特长.doc
- WinLicense 2.4.6.30 x86 / x64强大的技术和灵活性相结合
- 【UE4】【技巧】物体绕圆心转动(适用于转盘,旋转开关等)