学习Docker,你可以熟练的操作命令,能够把你的项目构建成Docker镜像!
是后端开发人员必备的技能!下面是自己的学习笔记,希望能帮助到需要的你!
特别感谢哔哩哔哩狂神:【狂神说Java】Docker最新超详细版教程通俗易懂_哔哩哔哩_bilibili
开发 -- 款产品: 开发 – 上线 两套环境!每套环境都需要配置环境,部署组建!
开发 -- 运维总会存在的问题:
我在我的电脑上可以允许!
版本的更新,可能会导致服务不可用!对于运维来说考验十分大?
环境配置是十分的麻烦,每一个都要部署相关组件(集群Redis、ES、Hadoop…) !费事费力。那么,是不是可以发布一个项目( jar + (Redis MySQL JDK ES) ),项目能带上环境安装打包呢?
开发环境Windows/MAC,最后发布到Linux!
传统:开发提供jar包,运维去做生产部署!
现在:开发打包带环境,部署上线,一套流程做完!
安卓流程:java — ***.apk —发布(应用商店)一 张三使用apk 一 安装即可用!
Docker给以上的问题,提出了解决方案:
docker流程: java — jar — 打包jar+环境(镜像)— ( Docker仓库:商店)— 下载运行即可用!
Docker的思想就来自于集装箱!
隔离:隔离是Docker核心思想!打包装箱!每个箱子是互相隔离的。
JRE – 多个应用(端口冲突) – 原来都是交叉的!已通过docker做到了隔离!
Docker通过隔离机制,可以将服务器利用到极致!
docker产生的本质:
所有的技术都是因为出现了一些问题,我们需要去解决,才去学习!
2010 -- 美国几个搞IT的年轻人 -- 公司 -- dotCloud -- 做一些pass的和云计算服务!LXC有关的容器技术!他们将自己的技术(容器化技术)命名为Docker!
Docker刚诞生的时候,没有引起行业的注意!dotCloud就活不下去了!
开源:开放源代码!
2013年,Docker开源!
开源后,越来越多的人发现了Docker的优点!火了。Docker每个月都有一个版本更新!
2014年9月,Docker 1.0发布!
Docker为什么火?
十分的轻巧!
在容器技术出来之前,我们一直使用的都是虚拟机技术!
VM和Docker有啥不一样呢?
Docker是go语言开发的!
Docker官网:Empowering App Development for Developers | Docker
Docker仓库地址:Docker Hub
Docker文档地址:Docker Documentation | Docker Documentation
内核+库+应用 ==> 模拟了一台电脑
虚拟机技术缺点:
1. 模拟了一台电脑,内存消耗很大,资源占用十分多
2. 共用库(运行环境),交叉
3. 启动冗余步骤多,启动很慢
内核 + 容器(库+应用) ==> 容器化技术并不是一个完整的操作系统
容器化技术的优点:
1. 每个容器有自己的应用和库(运行环境)
2. 相互隔离
3. 各个容器直接运行在操作系统上
比较容器化技术和虚拟机技术的不同:
传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
容器内的应用直接运行在宿主机的内核,容器没有自己的内核,也没有虚拟我们的硬件,所以就轻便了
每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响
镜像(image):
docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,
tomcat镜像 ==> run ==> tomcat01容器(提供服务器),
通过这 镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。
容器(container):
Docker利用容器技术,独立运行一个 或者 一组应用,通过镜像来创建的。
启动,停止,删除,基本命令 目前就可以把这个容器理解为就是一个简易的 Linux系统。
仓库(repository):
仓库就是存放镜像的地方! 仓库分为公有仓库和私有仓库(很类似git)。
Docker Hub(默认是国外的) 阿里云,网易云,华为云…都有容器服务器(配置镜像加速!)
1. 准备
需要会一点点的Linux基础(个人要求)
CenOS8(系统举例)
使用工具连接远程服务器进行操作
2. 环境查看
# 系统内核是3.10以上的
$ uname -r
4.18.0-348.2.1.el8_5.x86_64
# 查看系统版本
$ cat /etc/os-release
NAME="CentOS Linux"
VERSION="8"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="8"
PLATFORM_ID="platform:el8"
PRETTY_NAME="CentOS Linux 8"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:8"
HOME_URL="https://centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-8"
CENTOS_MANTISBT_PROJECT_VERSION="8"
3. 安装
官方帮助文档很详细
帮助文档:Install Docker Engine | Docker Documentation
#1. 卸载旧版本
$ yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
#2. 需要的安装包
$ yum install -y yum-utils
#3. 设置镜像的仓库(官网默认是从国外的,不推荐)
$ yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
#3. 设置镜像的仓库(阿里云的,十分的快!推荐)
$ yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#4. centos 8更新yum软件包索引
$ yum makecache 或者 dnf makecache
#4. 安装docker docker-ce 社区版(官方推荐,一般使用的也是ce) 而ee是企业版
$ yum install docker-ce docker-ce-cli containerd.io
#5. 启动docker
$ systemctl start docker
#6. 使用docker version查看是否按照成功(如下图)
$ docker version
#7. 测试
$ docker run hello-world
#8. 查看一下下载的hello-word image
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 2 months ago 13.3kB
4. 了解:卸载docker
#1. 卸载依赖
$ yum remove docker-ce docker-ce-cli containerd.io
#2. 删除资源 /var/lib/docker 是docker的默认工作路径!
$ rm -rf /var/lib/docker
$ rm -rf /var/lib/containerd
1. 阿里云控制台中找到容器镜像服务
2. 找到镜像加速器
3. 配置使用
#1. 创建文件夹
$ sudo mkdir -p /etc/docker
#2. 编写配置文件
$ sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://by4nvkyd.mirror.aliyuncs.com"]
}
EOF
#3. 重启reload
$ sudo systemctl daemon-reload
#4. 重启docker
$ sudo systemctl restart docker
回顾hello-word流程
由run hello-world 推出 docker run 的流程图:
Docker是怎么工作的?
Docker是一个Client-Server结构的系统
Docker的守护进程(服务)运行在主机上。通过Socket从客户端访问!
Docker-Server接收到Docker-Client的指令,就会执行这个命令!
Docker为什么比Vm快?
docker有着比虚拟机更少的抽象层。
docker利用的是宿主机的内核,VM需要Guest OS(虚拟机操作系统)。
因此,新建容器时,docker不需要和虚拟机一样重新加载一个操作系统内核,避免引导。
虚拟机软件需要加载GuestOS,分钟级别的。
docker是直接利用宿主机的操作系统,省略了这个复杂的过程,秒级的。
$ docker version # 显示docker的版本信息。
$ docker info # 显示docker的系统信息,包括镜像和容器的数量
$ docker 命令 --help # 帮助命令
帮助文档地址:https://docs.docker.com/engine/reference/
docker images ==> 查看虽有本地的主机上的镜像
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 2 months ago 13.3kB
# 解释
#REPOSITORY # 镜像的仓库源
#TAG # 镜像的标签
#IMAGE ID # 镜像的id
#CREATED # 镜像的创建时间
#SIZE # 镜像的大小
# 可选项 docker images -aq
-a, --all Show all images(显示所有的镜像)
-q, --quiet Only show image IDs(只显示镜像的ID)
docker search 容器名 ==> 搜索镜像
$ docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11843 [OK]
mariadb MariaDB Server is a high performing open sou… 4514 [OK]
docker pull 容器名 ==> 下载镜像
$ docker pull mysql
Using default tag: latest # 如果不写tag,默认就是latest
latest: Pulling from library/mysql # 分层下载: docker image的核心 => 联合文件系统
72a69066d2fe: Pull complete
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
688ba7d5c01a: Pull complete
00e060b6d11d: Pull complete
1c04857f594f: Pull complete
4d7cfa90e6ea: Pull complete
e0431212d27d: Pull complete
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 # 签名 防伪
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址
#等价于(作用效果一样)
$ docker pull mysql
$ docker pull docker.io/library/mysql:latest
# 指定版本下载(确保版本在docker仓库中有)
$ docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Already exists # 已经存在的共用 联合文件系统
93619dbc5b36: Already exists
99da31dd6142: Already exists
626033c43d70: Already exists
37d5d7efb64e: Already exists
ac563158d721: Already exists
d2ba16033dad: Already exists
0ceb82207cd7: Pull complete
37f2405cae96: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
docker rmi 镜像id ==> 删除镜像 -f 强制删除
$ docker rmi -f 镜像ID # 删除指定的镜像
$ docker rmi -f 镜像ID 镜像ID .. # 删除多个镜像
$ docker rmi -f $(docker images -aq) # 删除全部镜像
# 特殊情况 镜像ID相同 采取镜像名:TAG的方式删除
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 8.0 3218b38490ce 27 hours ago 516MB
mysql latest 3218b38490ce 27 hours ago 516MB
hello-world latest feb5d9fea6a5 2 months ago 13.3kB
$ docker rmi -f mysql:8.0 # 当镜像ID 相同时,可以采取镜像名:TAG的方式删除
Untagged: mysql:8.0
说明:我们有了镜像才可以创建容器,下面使用centos镜像来学习
$ docker pull centos
容器启动
$ docker run [可选参数] 镜像名 ==> 容器启动
$ docker run [可选参数] 镜像名 /bin/bash ==> 容器启动并进入 (Redis进入使用/bin/sh)
$ docker run --help
# 参数说明
--name="Name" 容器名字 tomcat01 tomcat02 用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080(宿主机):8080(容器)
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
容器端口
-P(大写) 随机指定端口
# 启动并进入容器
$ docker run -it centos /bin/bash
[root@c3dbc8161e78 /]# ls # 查看容器内的centos,基础版本
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@c3dbc8161e78 /]# exit # 从容器中退出主机,关闭容器
exit
列出所有运行的容器
$ docker ps # 列出当前正在运行的容器
# 解释说明
-a, --all Show all containers (default shows just running)(列出当前正在运行的以及历史运行过的容器)
-n=?, --last int Show n last created containers (includes all states) (default -1)(显示最近创建的容器)
-q, --quiet Only display numeric IDs(只显示容器的编号)
退出容器
$ exit # 容器直接退出
control+p+q(ctrl+p+q) # 容器不停止退出
删除容器
$ docker rm 容器id # 删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm -f
$ docker rm -f $(docker ps -aq) # 删除指定的容器
$ docker ps -a -q|xargs docker rm # 删除所有的容器(xargs 默认的命令是 echo,这意味着通过管道传递给 xargs)
启动和停止容器的操作
$ docker ps -a # 搜索到的容器,可根据容器id进行以下操作:
$ docker start 容器id # 启动容器
$ docker restart 容器id # 重启容器
$ docker stop 容器id # 停止当前正在运行的容器
$ docker kill 容器id # 强制停止当前容器
后台启动命令
$ docker run -d 镜像名 # -d 后台启动
$ docker run -d centos
f591aae3bddc9247e264ba7eed93e581af41fe206786840251fc2f9b45660c64
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 问题 docker ps 发现centos停止了
# 常见的坑,docker容器使用后台运行,就必须要有要一个前台进程,docker发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
查看日志
$ docker logs -f -t -n 10 容器ID
# 自己编写一段shell脚本 模拟日志
$ docker run -d centos /bin/sh -c "while true;do echo Docker 哇哈哈--哇哈哈;sleep 1;done"
# 查看容器id
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9916737f6d15 centos "/bin/sh -c 'while t…" 23 seconds ago Up 19 seconds eloquent_herschel
# 显示日志
$ docker logs -t -f -n 10 9916737f6d15
2021-12-28T06:58:57.094992452Z Docker 哇哈哈--哇哈哈
2021-12-28T06:58:58.097004335Z Docker 哇哈哈--哇哈哈
2021-12-28T06:58:59.098918779Z Docker 哇哈哈--哇哈哈
# 解释说明
-tf # 显示日志信息(一直更新)
-n number # 需要显示日志条数
docker logs -t n 容器id # 查看n行日志
docker logs -ft 容器id # 跟着日志
查看容器中进程信息
$ docker top 容器id
# 查看容器id
# 查看容器id
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9916737f6d15 centos "/bin/sh -c 'while t…" 23 seconds ago Up 19 seconds eloquent_herschel
# 查看容器中进程信息
$ docker top 9916737f6d15
UID PID PPID C STIME TTY TIME CMD
root 57612 57591 0 14:58 ? 00:00:00 /bin/sh -c while true;do echo Docker 哇哈哈--哇哈哈;sleep 1;done
root 58057 57612 0 15:04 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
查看镜像的元数据
$ docker inspect 容器id
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9916737f6d15 centos "/bin/sh -c 'while t…" 7 minutes ago Up 7 minutes eloquent_herschel
# 查询处容器的元信息
$ docker inspect 9916737f6d15
......
进入当前正在运行的容器
# 我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
$ docker run -it centos /bin/bash
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
65dd0bc2d400 centos "/bin/bash" 3 minutes ago Up 3 minutes xenodochial_blackburn
# 方式一
$ docker exec -it 容器id 启动bash
# 测试
$ docker exec -it 65dd0bc2d400 /bin/bash
[root@65dd0bc2d400 /]#
# 方式二
$ docker attach 容器id
# 测试
$ docker attach 65dd0bc2d400
[root@65dd0bc2d400 /]#
# 区别
# docker exec # 进入当前容器后开启一个新的终端,可以在里面操作。(常用)
# docker attach # 进入容器正在执行的终端
从容器内拷贝到主机上
$ docker cp 容器id:容器内路径 主机目的路径
# 进入docker容器内部
# 1. 查看当前主机目录下文件
$ ls
# 2. 进入Docker主机内部
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
65dd0bc2d400 centos "/bin/bash" 15 minutes ago Exited (0) 2 minutes ago xenodochial_blackburn
$ docker attach 65dd0bc2d400
[root@65dd0bc2d400 home]# cd /home
# 3. 在容器内新建一个文件
[root@65dd0bc2d400 home]# touch test.java
[root@65dd0bc2d400 home]# ls
test.java
[root@65dd0bc2d400 home]# exit
exit
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 4. 将文件拷贝到主机上
$ docker cp 65dd0bc2d400:/home/test.java /home
$ ls
test.java
# 当前拷贝是一个手动过程,未来会使用 -v 卷的技术,可以实现自动同步
docker命令思维导图:
Docker安装nginx:暴漏端口的重要性
#1. 搜索镜像 search 建议大家去docker搜索,可以看到帮助文档
$ docker search nginx
#2. 拉取镜像 pull
$ docker pull nginx
#3. 启动nginx容器
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口:容器内部端口 端口映射
$ docker run -d --name nginx01 -p 80:80 nginx
2af2bfda90ee86d56d0d759aa4e8c36fa91e88263b5ad88509dfddfb529452d2
# 4. 查看容器
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2af2bfda90ee nginx "/docker-entrypoint.…" 3 seconds ago Up 1 second 0.0.0.0:80->80/tcp, :::80->80/tcp nginx01
9916737f6d15 centos "/bin/sh -c 'while t…" 24 minutes ago Up 24 minutes eloquent_herschel
#5. 服务器一定要开放80端口
$ curl localhost:80
......
Welcome to nginx!
......
# 进入容器内部
$ docker exec -it nginx01 /bin/bash
root@ca221a04d0f0:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@ca221a04d0f0:/# cd /etc/nginx/
root@ca221a04d0f0:/etc/nginx# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_param
# 看到nginx配置文件
浏览器访问:
nginx端口映射:
思考问题:
我们每次改动nginx配置文件,都需要进入容器内部,十分的麻烦。
要是可以在容器外部提供一个映射路径,达到在容器外修改文件,容器内部就可以自动修改就好了 ==> 数据卷 - v!
Docker 安装 tomcat:官方测试以及如何进入容器查看
# 官方:docker run -it --rm tomcat:9.0 用完就删,一般用来测试
#1. 搜索镜像 search 建议大家去docker搜索,可以看到帮助文档
$ docker search tomcat
#2. 拉取镜像 pull
$ docker pull tomcat
#3. 启动运行
$ docker run -d -p 8080:8080 --name tomcat01 tomcat
bbebff6b0626ee68282162a560944b9a80705f20551b0e107d05dde3b386531e
#4. 测试访问没有问题(404,找不到页面),那没有页面什么原因?
# 进入容器 查找原因
$ docker exec -it tomcat01 /bin/bash
$ ls
BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist
CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work
$ cd webapps
$ ls # 无文件
# 问题: 1. Linux命令少了
# 2. Tomcat-webapps中没有内容
# 原因:阿里云镜像的原因,默认最小的镜像,所有不必要的都剔除掉。保证最小的可运行环境!
# 解决:把webapps.dist下的文件copy到webapps下
$ cd webapps.dist/
$ ls
ROOT docs examples host-manager manager
$ cd ../
$ cp -r webapps.dist/* webapps
#再次访问,有页面展示
思考问题:
我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?
要是可以在容器外部提供一个映射路径,我们在外部放置项目,就自动同步内部就好了 ==> 数据卷 - v!
Docker部署es+kibana:如何看容器的存活状态以及如何属性修改
# 问题:
# 1. es 暴露的端口很多!
# 2. es 的数据一般需要放置到安全目录!挂载
# 1. 启动elasticsearch
$ docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# 2. 查看docker容器使用内存情况
$ docker stats
# 3. 查看ES是否启动成功
$ curl localhost:9200
{
"name" : "a224cd5434e2",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "ToRaOTtJQx6u2delO5Q1-g",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
# 4. 赶紧关闭
# 5. 增加内存的限制 修改配置文件 -e 环境配置修改
$ docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
思考问题:
使用kibana连接es?思考网络如何才能连接?
$ docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
什么是portainer?
Docker图形化界面管理工具!提供一个后台面板供我们操作!
portainer测试访问: 外网IP:8088
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,他包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
(白话:所有的应用,直接打包成docker镜像,就可以直接跑起来了)
如何得到镜像
从远程仓库下载
朋友copy给你
自己制作(DockerFile)
UnionFs (联合文件系统):我们下载时看到的一层一层的就是这个!
UnionFs(联合文件系统):UnionFs 是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。 UnionFs 是 Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
boots(boot file system)主要包含 bootloader和 Kernel,,bootloader主要是引导加 kernel,Linux刚启动时会加bootfs文件系统,在 Docker镜像的最底层是 boots。这一层与我们典型的Linux/Unix系统是一样的,包含boot加載器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs转交给内核,此时系统也会卸载bootfs。(白话:系统启动需要引导加载,加载完成以后,系统启动。启动过程就不会再改变,加载就不再需要了)
rootfs(root file system)在 bootfs之上。包含的就是典型 Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。 rootfs就是各种不同的操作系统发行版,比如 Ubuntu, Centos等等。(白话:系统启动之后,就会形成一个基本的Linux系统)
对于个精简的OS,rootfs可以很小,只需要包合最基本的命令,工具和程序库就可以了,因为底层直接用Host(主机)的kernel(内核),自己只需要提供rootfs就可以了。由此可见对于不同的Linux发行版, boots基本是一致的, rootfs会有差別,因此不同的发行版可以公用bootfs。
所以虚拟机是分钟级别,容器是秒级!
分层的镜像
我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层层的在下载
思考:为什么Docker镜像要采用这种分层的结构呢?
最大的好处,我觉得莫过于资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。
#命令:docker image inspect 镜像:版本 查看镜像分层的方式
$ docker image inspect redis:latest
[
//......
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f",
"sha256:9b24afeb7c2f21e50a686ead025823cd2c6e9730c013ca77ad5f115c079b57cb",
"sha256:4b8e2801e0f956a4220c32e2c8b0a590e6f9bd2420ec65453685246b82766ea1",
"sha256:529cdb636f61e95ab91a62a51526a84fd7314d6aab0d414040796150b4522372",
"sha256:9975392591f2777d6bf4d9919ad1b2c9afa12f9a9b4d260f45025ec3cc9b18ed",
"sha256:8e5669d8329116b8444b9bbb1663dda568ede12d3dbcce950199b582f6e94952"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
]
理解:
所有的 Docker镜像都起始于一个基础镜像层,当进行修改或培加新的内容时,就会在当前镜像层之上,创建新的镜像层。
特点
Docker 镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层!
$ docker commit 提交容器成为一个新的副本
# 命令和git原理类似
$ docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[TAG]
实战测试
# 1、启动一个默认的tomcat
$ docker run -d -p 8080:8080 tomcat
# 2、发现这个默认的tomcat 是没有webapps应用,官方的镜像默认webapps下面是没有文件的!
$ docker exec -it 容器id
# 3、拷贝文件进去
$ cp webapps.dist/* webapps
# 4、将操作过的容器通过commit调教为一个镜像!我们以后就使用我们修改过的镜像即可,这就是我们自己的一个修改的镜像。
$ docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[TAG]
$ docker commit -m="add webapps app" -a="xiao" b6540c1b270d tomcat1.0:1.0
如果你想要保存当前容器的状态,就可以通过commit来提交,获得一个镜像
就好比我们我们使用虚拟机的快照。
到此,docker入门成功!!!
Docker进阶:https://blog.csdn.net/Shen_Junxiao/article/details/122197029