Docker概述
Docker为什么出现?
一款产品∶
开发–上线两套环境!应用环境,应用配置!
开发—运维。问题︰我在我的电脑上可以运行!版本更新,导致服务不可用!对于运维来说,考验就十分大?环境配置是十分的麻烦,每一个机器都要部署环境(集群Redis、ES、Hadoop…)”!费时费力。
发布一个项目( jar + ( Redis MySQL jdk ES ) ),项目能不能都带上环境安装打包!
之前在服务器配置一个应用的环境(Redis MySQL jdk ES Hadoop),配置超麻烦了,不能够跨平台。Windows,最后发布到Linux !
传统:开发jar,运维来做!
现在:开发打包部署上线,一套流程做完!
java – apk --发布(应用商店)—张三使用apk —安装即可用!
一
java.- jar (环境)…打包项目带上环境(镜像)-- ( Docker仓库:商店)-下载我们发布的镜像—直接运行即可
Docker的思想就来自于集装箱!
JRE–多个应用(端口冲突) —原来都是交叉的!
隔离:Docker核心思想!打包装箱!每个箱子是互相隔离的。水果生化武器
Docker通过隔离机制,可以将服务器利用到极致!
Docker能干啥
之前的虚拟机技术
虚拟机技术的缺点:
1.资源占用太多
2.冗余步骤太多
3.启动很慢
现在的容器化技术
容器化技术不是模拟的一个完整的操作系统
比较Docker和虚拟机技术的不同:
①传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
②容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了
③每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响。
应用更快速的交付和部署
传统: 一堆帮助文档,安装程序
Docker: 打包镜像发步测试,一键运行
更便捷的升级和扩缩
容使用了Docker之后,我们部署应用就和搭积木一样!
项目打包为一个镜像,扩展服务器A!服务器B
更简单的系统运维
在容器化之后,我们的开发,测试环境都是高度一致的。更高效的计算资源利用:
Docker是内核级别的虚拟化,可以再一个物理机上可以运行很多的容器实例!服务器的性能可以被压榨到极致。
Docker的名词概念
镜像:(image):
docker镜像如同一个模板,可以通过这个模板创建容器服务。
容器:(container)
docker利用容器技术,独立运行一个或一组应用,通过对象创建的
基本命令:启动,停止,删除
目前可将容器理解成一个简易的linux系统
仓库:(repository)
仓库是存放镜像的地方
仓库分为共有仓库和私有仓库
安装docker
#需要的安装包
yum install -y yum-utils
#设置镜像仓库
yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#安装docker核心
yum install docker-ce docker-ce-cli containerd.io
#启动docker
systemctl start docker
#运行helloworld
docker run hello-world
#查看hello-world镜像
docker images
卸载docker
#1、卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
#2、制除资源
rm -rf /var /lib/docker #docker的工作目录
回顾helloworld的流程
运行流程图
Docker的运行原理
Docker为什么比VM快
1.Docker比虚拟机有更少的抽象层
2.docker利用的宿主机的内核,vm是guestOs
所以说新建一个容器,docker不需要像虚拟机一样重新加载一个操作系统的内核,虚拟机要加载guestOs,docker利用宿主机的核心省略了这个过程
Docker的常用命令
帮助命令
docker version #显示docker版本
docker info #显示docker的信息
docker 命令 --help #显示docker的帮助文档
镜像命令
docker images
[root@iZwz923fx7de74e5pc1tgoZ ~] #docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 5 months ago 13.3kB
REPOSITORY:镜像的仓库源
TAG:镜像的标签
IMAGE ID:镜像的id
CREATED:镜像创建时间
SIZE:镜像大小
#可选项
Options:
-a, --all 列出所有镜像
-q, --quiet 只显示镜像的id
docker search
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11225 [OK]
mariadb MariaDB Server is a high performing open sou… 4265 [OK]
#可选项,通过搜索过滤
--filter=STARS=3000 搜索3000以上star的源
docker pull
#下载镜像
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker pull mysql
Using default tag: latest # 如果不写tag,默认就是latest(最近的)
latest: Pulling from library/mysql
33847f680f63: Pull complete # 分层下载 docker images的核心 联合文件系统
5cb67864e624: Pull complete
1a2b594783f5: Pull complete
b30e406dd925: Pull complete
48901e306e4c: Pull complete
603d2b7147fd: Pull complete
802aa684c1c4: Pull complete
715d3c143a06: Pull complete
6978e1b7a511: Pull complete
f0d78b0ac1be: Pull complete
35a94d251ed1: Pull complete
36f75719b1a9: Pull complete
Digest: sha256:8b928a5117cf5c2238c7a09cd28c2e801ac98f91c3f8203a8938ae51f14700fd #签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真实地址
# 指定版本下载
docker pull mysql:5.7
红框中是刚刚安装latest版本中相同的依赖,docker对其做了处理,让我们不需要重复的下载相同的依赖。
docker rmi
#删除镜像
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 8cf625070931 2 weeks ago 448MB
mysql latest c60d96bd2b77 2 weeks ago 514MB
hello-world latest d1165f221234 5 months ago 13.3kB
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker rmi -f c60d96bd2b77 #删除id为c60d96bd2b77的镜像
Untagged: mysql:latest
Untagged: mysql@sha256:8b928a5117cf5c2238c7a09cd28c2e801ac98f91c3f8203a8938ae51f14700fd
Deleted: sha256:c60d96bd2b771a8e3cae776e02e55ae914a6641139d963defeb3c93388f61707
Deleted: sha256:5c8c91273faab368a6d659156f2569fa9f40b0e0139222fdf9eef073df4b3797
Deleted: sha256:33d8196a776f42a16f10395b66f10f91443b1fb194bca2a9b8dfb0deff5babb8
Deleted: sha256:3ec63323025213e3cabf17ac7933506dc5520ec49226a9764418f77ea60d35c8
Deleted: sha256:1f129b005b51b049ac84ed0775b82096d480b7d9308a9a137697f37346562266
Deleted: sha256:80ed209bd0434faa1ce31fbaab8508124dddf8f6502c5736ee4b8e46697a8477
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 8cf625070931 2 weeks ago 448MB
hello-world latest d1165f221234 5 months ago 13.3kB
#递归删除命令
docker rmi -f $(docker images -aq)
容器命令
有了镜像我们才能创建容器,下载一个centos来学习
docker pull centos
新建容器并启动
docker run [可选参数] image
#参数说明
--name="Name" 容器名字 tomcat01 tomcat02 用来区分容器
-d 后台运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口
-p 容器端口
容器端口
-p 随机端口
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker run -it centos
[root@d11af9403852 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@d11af9403852 /]# exit
exit #退出命令
列出所有运行中的容器
#docker ps命令
#列出当前正在运行的容器
-a #列出当前正在运行的容器+带出历史运行过的容器
-n=? #显示最近创建的容器
-q #只显示id
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker ps #查看运行中的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker ps -a #查看历史运行中的容器 + 当前正在运行的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d11af9403852 centos "/bin/bash" 2 minutes ago Exited (0) About a minute ago vigilant_ardinghelli
9ca3796f40aa hello-world "/hello" About an hour ago Exited (0) About an hour ago beautiful_hermann
退出容器
exit #停止容器并且退出
Ctrl + P + Q #容器不停止退出
删除容器
docker rm 容器id
docker rm -f $(docker ps -aq) 删除所有容器
启动或者停止容器
docker start 容器id #启动容器
docker restart 容器id #重启容器
docker stop 容器id #停止当前正在运行的容器
docker kil 容器id #强制停止当前容器
docker run 和 docker start的区别是前者是第一次启动创建容器并且运行,后者是运行现有的容器
其他的命令
后台启动容器
#后台启动容器
docker run -d centos
#常见的坑: docker容器使用后台运行,就必须要有要一个前台进程,docker发现没有应用,就会自动停止
#nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
查看日志
docker logs
#显示日志
-tf #显示日志
--tail number#要显示日志条数
[root@kuangshen / ]# docker logs -tf --tai1 10 dce7b86171bf
查看容器中的进程信息
docker top 容器id
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker top 427d8b6a1e42
UID PID PPID C STIME TTY TIME CMD
root 22129 22110 0 09:29 pts/0 00:00:00 /bin/bash
查看容器的元数据
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker inspect 8cf625070931
[
{
"Id": "sha256:8cf6250709314f2fcd2669e8643f5d3bdebfe715bddb63990c8c96e5d261d6fc",
"RepoTags": [
"mysql:5.7"
],
"RepoDigests": [
"mysql@sha256:be70d18aedc37927293e7947c8de41ae6490ecd4c79df1db40d1b5b5af7d9596"
],
"Parent": "",
"Comment": "",
"Created": "2021-07-22T09:46:58.633532241Z",
"Container": "55c80e6cae67918a0f23a3e89d1fb67567180c0fa14be584f72a634f26018bd3",
"ContainerConfig": {
"Hostname": "55c80e6cae67",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"3306/tcp": {},
"33060/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOSU_VERSION=1.12",
"MYSQL_MAJOR=5.7",
"MYSQL_VERSION=5.7.35-1debian10"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"mysqld\"]"
],
"Image": "sha256:db75bc17dd0f7a6fc62da7c4ad423276262ac089d6baf875af2f099f3a384718",
"Volumes": {
"/var/lib/mysql": {}
},
"WorkingDir": "",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {}
},
"DockerVersion": "20.10.7",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"3306/tcp": {},
"33060/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOSU_VERSION=1.12",
"MYSQL_MAJOR=5.7",
"MYSQL_VERSION=5.7.35-1debian10"
],
"Cmd": [
"mysqld"
],
"Image": "sha256:db75bc17dd0f7a6fc62da7c4ad423276262ac089d6baf875af2f099f3a384718",
"Volumes": {
"/var/lib/mysql": {}
},
"WorkingDir": "",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 448231635,
"VirtualSize": 448231635,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/7b9260c0abd246be572d1f30e255e57a7e6ad3260f83252582f3698421b9b602/diff:/var/lib/docker/overlay2/44994b9bd6bd8355976f8f92c390f72444dc68e9334e59d697654e5022209aca/diff:/var/lib/docker/overlay2/410f7ca5510958929b5f732d6c48ea463eabd8b5266bcfc232fe4fb21758e1fd/diff:/var/lib/docker/overlay2/90b2ec06c320fd23651efc43a461011b18409affa354633099d31ece4145ac42/diff:/var/lib/docker/overlay2/566b76bb20e5891177b195007896d2015a341c9b63e896ababdc766e1186a5a4/diff:/var/lib/docker/overlay2/fd0648d2a59f4f3adabcd23297143c36edb91930fc759c6cae1c2ddae06c4174/diff:/var/lib/docker/overlay2/fb30191819232b24e68f35bf7af053678216b4efbb2a457e74da2b4212b04de4/diff:/var/lib/docker/overlay2/ae976dd3c5747768aa5eb22525cb81801254201eac88cdb337628bbb99ec49f3/diff:/var/lib/docker/overlay2/044119402a0929300900b5df1fce539572e303e8f052a01eb478b100cd74d89b/diff:/var/lib/docker/overlay2/8d0c84ccceee3e657b91cd3272d4095ab1a7861e4e09bce9dbc61025d39b8326/diff",
"MergedDir": "/var/lib/docker/overlay2/bdd29e2762d98a38a48aa4bfebf6e63b7690206937202dc9072cc3e7280fa058/merged",
"UpperDir": "/var/lib/docker/overlay2/bdd29e2762d98a38a48aa4bfebf6e63b7690206937202dc9072cc3e7280fa058/diff",
"WorkDir": "/var/lib/docker/overlay2/bdd29e2762d98a38a48aa4bfebf6e63b7690206937202dc9072cc3e7280fa058/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:814bff7343242acfd20a2c841e041dd57c50f0cf844d4abd2329f78b992197f4",
"sha256:7075fc380548c52cc2a5c67d0ad62ca2d6b4e1a8d3648f803c5c3ce1f184e27e",
"sha256:147b6eb160c4df8032ec4929c0c8381f63745bee5d0d1c648ca6b4618211b619",
"sha256:b4419c864ffe6a264ba82bec875b19ee2fa08dbe1f92070901affb5ca1d4c8e9",
"sha256:719288c1485f6918cc94c98ec325374de8fbe0f254c8c810bd49c4dfd9097ed2",
"sha256:418c960a3eca900d4b4b1669d8f5c1fe5dd99f65d97e7243630f31b81f492805",
"sha256:104ecd74e4e4c89524a3b93f8f97ef8f8574aaa52f9d9163f6a94aabe2f3fa1f",
"sha256:5952cb12b9ed756f79fe1ed2b6c0bafb246e737cc0aa9f787771f4ef4f616b26",
"sha256:7fa793435ff13e4dd013df0e54f68bbe110210af023359473e0bb7cfb85519c8",
"sha256:8cb73d42958e5e83119036193e5e2f3c2564b76f06c02019d20c3dc9f923eb72",
"sha256:9885efd52d6f8f5da69beef0cdea85066553fd2434c9dbfa1f13c7274188eeb6"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
进入容器
#方式一
docker exec -it 容器id baseshell
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker exec -it 427d8b6a1e42 /bin/bash
[root@427d8b6a1e42 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@427d8b6a1e42 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 01:29 pts/0 00:00:00 /bin/bash
root 16 0 0 01:34 pts/1 00:00:00 /bin/bash
root 31 16 0 01:34 pts/1 00:00:00 ps -ef
#方式二
docker attach 容器id
attach和exec的区别
exec会进入当前容器并开启一个新的终端
attach就会直接进入当前终端不会重新开启
从容器内拷贝
docker cp 容器id:容器内路径 目的的主机路径
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker cp 427d8b6a1e42:/home/test.java /
[root@iZwz923fx7de74e5pc1tgoZ /]# ls
bin boot dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys test.java tmp usr var
#拷贝是一个手动过程,以后用-v卷的技术可以实现自动同步
实战:docker 安装nginx
#1、搜索镜像search建议大家去docker搜索,可以看到帮助文档
#2、下载镜像pull
#3、运行测试
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker pull nginx
-d:后台运行
--name:给容器命名
-p:宿主机端口:容器内部端口
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker run -d --name nginx1 -p 3344:80 nginx
65c03bbac600695bb8c496dd85585ad10088265196e82865d31ad12409e277e1
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
65c03bbac600 nginx "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 0.0.0.0:3344->80/tcp nginx1
[root@iZwz923fx7de74e5pc1tgoZ ~]# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
端口暴露
当我们启动容器后,便可以用进入容器的命令,对该容器运行的nginx的配置文件进行修改,但是我们每次要修改nginx的配置文件都得进入容器吗?可不可以自动同步? -v
实战:docker安装tomcat
#官方的使用
docker -run -it --rm tomcat 9.0
#我们之前的启动都是后台,停止了容器后,容器还是能够查到
--rm代表用完即删除
安装完tomcat后,会跑tomcat的日志,ctrl+c停止后执行查看容器命令
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
65c03bbac600 nginx "/docker-entrypoint.…" 18 minutes ago Up 18 minutes 0.0.0.0:3344->80/tcp nginx1
发现找不到tomcat,说明已经被删除了
#先下载在启动
docker pull tomcat
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker run -d --name tomcat01 -p 3345:8080 tomcat
ca7f06dda761579b2dcca71e986bbbe8ffa6556f31320f35203478a07f52b61e
root@ca7f06dda761:/usr/local/tomcat# ls
BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist
root@ca7f06dda761:/usr/local/tomcat# ll
bash: ll: command not found
#发现问题1、linux命令少了 2、没有webapps 阿里云镜像的原因。
#默认用最小的镜像,将其他不需要的剔除
实战:部署es+kibana
#es暴露的端口很多
#es耗内存
#es的数据需要放在安全目录
--net somenetwork?网络配置
#启动了linux就卡住了docker stats查看cpu的状态
# es是十分耗内存的,1.xG ,1核2G
[root@iZwz923fx7de74e5pc1tgoZ ~]# curl localhost:9200
{
"name" : "3fb90b526277",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "fmzwfnluTgGfN45duhYzUg",
"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"
}
可视化
portainer
#端口访问9000
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce
Docker镜像讲解
Dock镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
所有的应用,直接打包docker镜像,就可以直接跑起来!
如何得到镜像︰
·从远程仓库下载
·朋友拷贝给你
· 自己制作一个镜像DockerFile
Docker镜像加载原理
UnionFS(联合文件系统)
UnionFS (联合文件系统):Union文件系统(UnionFS )是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtualfilesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。特性︰一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
roots (root file system),在bootfs之上。包含的就是典型Linux系统中的/dev, /proc, /bin, /etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu , Centos等等。
分层理解
分层的镜像
我们去下载一个镜像的时候,观察日志,发现是一层一层在下载
思考:为什么Docker镜像要采用这种分层的结构呢?
最大的好处,我觉得莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过docker image inspect命令!
理解:
所有的Docker[镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层.
举一个简单的例子,假如基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。
上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统.
Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及zFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker在Windows上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1].
下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
特点
Docker镜像都是只读的,当容器启动后,一个新的可写层被加载到镜像的顶部!这一层通常被我们叫做容器层,容器之下就是镜像层
如何提交自己的镜像
docker commit 提交容器成为一个新的副本
docker commit -m="提交的信息" -a="作者" 容器id 目标镜像名字:Tag
实战:
#启动一个默认的tomcat
#发现这个默认的tomcat是没有webapps应用,镜像的原因,官方的镜像默认 webapps下面是没有文件的!
#我自己拷贝进去了基本的文件
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker commit -a="penghaomin" -m="add webapps" 5c454d00dded tomcat1:1.0
sha256:11a27901896e58c041885df62d029693c2c607b09375004ea2bdf72e22f69d3d
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat1 1.0 11a27901896e 10 seconds ago 673MB
tomcat 9.0 710ec5c56683 3 hours ago 668MB
tomcat latest 710ec5c56683 3 hours ago 668MB
portainer/portainer-ce latest dfac2df13044 8 days ago 210MB
redis latest aa4d65e670d6 2 weeks ago 105MB
nginx latest 08b152afcfae 2 weeks ago 133MB
mysql 5.7 8cf625070931 2 weeks ago 448MB
hello-world latest d1165f221234 5 months ago 13.3kB
centos latest 300e315adb2f 8 months ago 209MB
elasticsearch 7.6.2 f29a1ee41030 16 months ago 791MB
容器数据卷
什么是容器数据卷
docker的理念回顾
将应用和环境打包成一个镜像!
数据?如果数据都在容器中,那么我们容器删除,数据就会丢失 !需求∶数据可以持久化
MySQL,容器删了,删库跑路 需求:Mysql数据存在本地
容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!
这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux上面
使用容器数据卷
方式一:直接使用命令挂载 -v
docker run -it -v 主机目录:容器内端口
反向操作
实战:mysql数据同步
docker run --name mysql4 -e MYSQL_ROOT_PASSWORD=123456 -v /home/mysql/conf:/etc/my.cnf -v /home/mysql/data:/var/lib/mysql -p 3310:3306 -d mysql:5.7
具名挂载和匿名挂载
#匿名挂载
docker run -d --name nginx -v 容器内路径
#查看所有卷的情况
[root@iZwz923fx7de74e5pc1tgoZ mysql]# docker volume ls
DRIVER VOLUME NAME
local 6b2209c890e1b3631efc68e19019d749e0dd7ad922e71afc7b8f4094c84c0bbb
local 7b720be37f88f110d50c0fe85764661280d807123c0d2cc751899561c7880325
local 678e293904a49a8e7f1feae876ac86a7f0891a141e70a637656c0e0e015e43e0
local 58255b78e82441600bb8cf7a325f22e500d61a41eb01ae9ee27ab8359609e591
local c5964c817d4afed84e04ec27d2d2ff63fe837b27d87b875e9681413561b94674
local e5ae42beca5cb33c96a2e6f665a21416ca2167e0be6bcbe5e1769d4477200c6e
local f611d08defde2257ab7ef01b8dd1c613a2efb9cde63c912881f447caaa5ed1b8
local fde187080f79f2c74b229f8c29867fa41e455887616936e772e0879defffab4b
local portainer_data
#听过-v 卷名:容器路径 来为数据卷命名
#查看卷的详情
[root@iZwz923fx7de74e5pc1tgoZ mysql]# docker volume inspect 6b2209c890e1b3631efc68e19019d749e0dd7ad922e71afc7b8f4094c84c0bbb
[
{
"CreatedAt": "2021-08-07T17:12:48+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/6b2209c890e1b3631efc68e19019d749e0dd7ad922e71afc7b8f4094c84c0bbb/_data",
"Name": "6b2209c890e1b3631efc68e19019d749e0dd7ad922e71afc7b8f4094c84c0bbb",
"Options": null,
"Scope": "local"
}
]
所有的卷没有指定目录的话,都是在/var/lib/docker/volumes /卷名字/ _data存储的
#如何确定是具名挂载还是匿名挂载呢
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载
通过-v 容器内路径:ro rw改变读写权限
ro readonly#只读
rw readwrite#可读可写
docker run -d -p--name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -p--name nginx02 -v juming-nginx:/etc/nginx:rw nginx
#ro 说明这个路径只可以通过宿主机操作,无法在容器内操作
初识DockerFile
DockerFile就是用来构建docker镜像的构建文件,命令脚本
这个脚本可以生成一个镜像,镜像是一层一层的,脚本的每一个命令都是一层
方式二:
vim dockerfile
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "end"
CMD /bin/bash
[root@iZwz923fx7de74e5pc1tgoZ volume]# docker build -f /home/volume/dockerfile -t phm/centos:7.0 .
注意最后有个点
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 300e315adb2f
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in 736834fbd9a4
Removing intermediate container 736834fbd9a4
---> b9f5c2a242fc
Step 3/4 : CMD echo "end"
---> Running in a9c2d94b224d
Removing intermediate container a9c2d94b224d
---> d5d4f294337d
Step 4/4 : CMD /bin/bash
---> Running in f8627be75051
Removing intermediate container f8627be75051
---> e6895c6fc05e
Successfully built e6895c6fc05e
Successfully tagged phm/centos:7.0
成功构建镜像
我们进入容器中,ls发现了好玩的东西,在/下生成了我们自动挂载的数据卷目录
这些卷肯定和外部有目录是连接的。
进入该数据卷目录,新建一个文件,因为我们知道,内部容器中做出的改变,外部容器是同步的,我们就可以通过这个来找到目录,还是匿名挂载
数据卷容器
#先启动三个容器
[root@iZwz923fx7de74e5pc1tgoZ /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
341bc81f4311 e6895c6fc05e "/bin/bash" 11 seconds ago Up 10 seconds phm3
690301013bed e6895c6fc05e "/bin/bash" 18 seconds ago Up 18 seconds phm2
841dbdd78779 e6895c6fc05e "/bin/bash" 40 seconds ago Up 39 seconds phm1
9eb416d9fb1b mysql:5.7 "docker-entrypoint.s…" 52 minutes ago Up 52 minutes 33060/tcp, 0.0.0.0:3310->3306/tcp mysql4
[root@iZwz923fx7de74e5pc1tgoZ /]# docker run -it --name=phm2 --volumes-from phm1 e6895c6fc05e /bin/bash
利用–volumes-from将phm1和phm2同步
可以看到在phm2中touch了一个a.txt,在phm1的volume01中也出现了
[root@kuangshen home]# docker run -d -p 3310:3306 -v/etc/mysq1/conf.d -v /var/1ib/mysq1 -eYsQL_ROOT_PASSWORD=123456--name mysq101 mysq1:5.7
[root@kuangshen home]# docker run -d -p 3310:3306 -e MYSQL_R00T_PASSWORD=123456 --name mysq102 --olumes-form mysq101 mysq1:5.7
# 这个时候,可以实现两个容器数据同步!
结论∶容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!
DockerFile
dockerfile是用来构建dokcer镜像的文件!命令参数脚本!构建步骤:
1、编写一个dockerfile 文件
2、docker build构建成为一个镜像
3、docker run运行镜像
4、docker push 发布镜像(DockerHub、阿里云镜像仓库!)
很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!官方既然可以制作镜像,那我们也可以!
DockerFile的创建过程
基础知识:
1、每个保留关键字(指令)都必须是大写
2、指令从上到下执行
3、#表示注释
4、每一个指令都会创建提交一个新的镜像层
dockerfile是面向开发的,我们以后要发布项目,作镜像,就要编写dockerfile文件,这个文件特别简单
Docker镜像已经逐渐成为了企业交接的标准
DockerFile :构建文件,定义了一切的步骤,源代码
Dockerlmages:通过DockerFile构建生成的镜像,最终发布和运行的产品!
Docker容器︰容器就是镜像运行起来提供服务器
DockerFile的指令说明
FROM
#基础镜镜像,一切从这里开始构建
MAINTAINER
#镜像是谁写的,姓名+邮箱
RUN
#镜像构建的时候需要运行的命令
ADD
#步骤: tomcat镜像,这个tomcat压缩包!添加内容
WORKDIR
#镜像的工作目录
VOLUME
#挂载的目录
CMD
#指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT
#指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD
#当构建一个被继承的dockerFile就会运行ONBUILD
COPY
#类似add,将文件拷贝到目录中
ENV
#构建环境变量
实战构建自己的centos
Docker Hub中99%镜像都是从这个基础镜像过来的FROM scratch,然后配置需要的软件和配置来进行的构建
创建一个目录,然后创建dockerFile文件
FROM centos
MAINTAINER phm<892552140@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH #设置工作目录
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD "echo " ----end-
CMD /bin/bashl
通过build命令构建
docker build -f dockerfile -t mycentos:1 .
CMD和ENTRYPOINT的区别
#编写dockerfile 文件
[root@kuangshen dockerfile]# vim dockerfile-cmd-testFROM centos
CMD ["ls ", "-a"]
#构件镜像
[root@kuangshen dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .
#run运行,发现我们的-a命令生效
[root@kuangshen dockerfile]# docker run dd8e4401d72f -l
docker: Error. response from daemon: OCI runtime create failed: container_linux. g0:349: starting
container process caused "exec: \"-1\": executab7e file not found in $PATH": unknown.
#cmd的情况下 -l替换成了CMD["ls","-a"]命令,但是没有单个-l的命令,所以会报错,下列就不报错
[root@kuangshen dockerfile]# docker run dd8e4401d72f ls -al
但是我们如果用ENTRYPOINT就不会报错,因为ENTRYPOINT是可以追加的
Docker制作tomcat镜像
1、准备tomcat镜像的压缩包,jdk的压缩包
2、dockerfile文件,官方命名Dockerfile,这样就不需要-f绑定了
FRoM centos
MAINTAINET kuangshen<24736743@qq.com:COPY readme.txt /usr/local/readme.txt
ADD jdk-8u11-linux-x64.tar.gz /usr/local/ADD apache-tomcat-9.0.22.tar.gz /usr/local/RUN yum -y install vim
ENV MYPATH /usr/localwORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarENV CATALINA_HOME/usr/local/apache-tomcat-9.0.22
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.22
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CND/usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.22/bin/logs/catalina.out
3、构建镜像
#docker build -t diytomcat .
4、启动镜像
5、访问测试
6、发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了! )
发布至dockerhub
DockerHub
1、首先得注册一个账号
2、在服务器上登录账号
[root@iZwz923fx7de74e5pc1tgoZ ~]# docker login --help
Usage: docker login [OPTIONS] [SERVER]
Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.
Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username
我的docker账号:wohenlaijin
3、登陆完毕就可以提交镜像了
docker push 作者/项目:标签
找不到可以
docker tag id kuangshen/tomcat: 1.0
阿里云容器
1、登录阿里云
2、找到容器镜像服务
3、创建命名空间
4、创建镜像仓库
后边基本一致