1.1 今日课程介绍
1.2 初始docker - 什么是docker
项目部署的问题
大型项目组件较多, 运行环境也较为复杂,部署时会碰到一些问题.
特别是微服务, 各种各样的微服务,而且这些微服务还会依赖于各种各样的应用; 比如说,前端部分肯定依赖node.js吧, 而我们服务端还需要数据库mysql,缓存系统redis,还有我们后面会学习到的异步通信(mq,rabbitmq?)等等这些,更多,这些只是其中一些,
所有这些应用将来都需要部署到我们的服务器上,而大多数的服务器都会采用Linux系统;
应用在安装在操作系统上面之前,要做一些准备工作,因为这些应用依赖都会有自己所需要的依赖和函数库;
每一个不同的应用,它们所需要的依赖和函数库可能有差异,也可能一样,但是版本不同(不同应用);
这个时候,如此复杂的一个依赖关系,很容易产生兼容性的问题,而且当兼容性问题解决,发现只是开始, 因为开发,测试和生产环境有差异,预发布,可怕的是这些操作环境的linux操作系统还可能不同,
比如,装了个centos系统,另外环境装的是Fedora系统,还有装的是Ubuntu系统,那怎么办?
一个操作系统里面配好的东西放到另外操作系统,还能正常运行吗?no
以前开发部署时的效率非常的低,这个问题docker是如何解决的呢?
既然每个应用都有自己所需的依赖和函数库,why not打包应用的Libs函数库,deps依赖,配置与应用一起打包,docker就干了这件事情,
Nodejs需要什么依赖,打包起来,形成一个整体,还将每个应用放到一个隔离容器去运行,避免互相干扰,每个应用需要什么我都这么去做(打包依赖和函数库到一个隔离容器去运行)
打一个包,一起扔过去,不用考虑依赖和函数库问题,有同学说,把他们扔到一台机器上,它们之间(隔离容器们)的依赖难道没有干扰吗? 不会,因为docker会把这些打包好的程序,用一个隔离的容器去运行,会用到一种沙箱的技术,它们相互之间不可见,这个问题不就解决了吗?这只是解决了混乱依赖的问题
有了docker,应用程序随时都可以运行.仅限于同样的一个操作系统,因为打包时,肯定基于某种操作系统去打包.
比如这个应用(node.js)是鲁班图ubuntu version,那它的依赖和函数库也肯定是ubuntu乌班图的;
你把这个打包好的程序(eg, node.js)扔到centos上去;程序运行不了;docker怎么来解决这个问题呢?
要想了解docker跨系统运行,我们得先知道OS的structure;
这儿以ubuntu为例,给大家讲一下OS structure;别着急; 没那么复杂,
所有的Linux内核的操作系统, 都可以分成两层;一层是大家共享的内核(Linux内核),
不管是ubuntu,centos,fedora,redhat,他们的内核都是linux; 区别是上层系统应用的不同; ubuntu和centos它们的应用是不一样的, (它们的))内核是相同的;
内核干什么事呢? 内核负责与计算机硬件进行交互,eg, 我去调用一下CPU, 调用一下内存, 读一下文件,开辟一个进程之类的; 这些都是内核要做的, 而内核会把这些事情变成一个一个的指令;
你调用这些指令就可以操作计算机硬件了,但可惜的是这些指令大多比较简陋; 如果你要基于这些指令去开发应用,那可就太麻烦,所以说我们就有了系统应用;
系统应用, 比如说ubuntu,它干了什么? 它会将内核的指令进行一个组装, 再封装, 形成函数, 区域多的函数形成了函数库.
那么程序员可以基于这些函数库进行开发,程序调用我们的函数/函数库, 函数库调用内核指令去调用我们的计算机硬件,从而实现我们这个应用的执行;
这就是我们linux系统的一个结构,以及应用的执行原理.
问题来了, 一个ubuntu系统上的应用,为什么不能在centos上运行,两个系统内核一样,系统应用不同,也就是说函数库不同;
可能ubuntu上的函数库centos上不一定有,或者名字不一样;
这个时候我们把一个ubuntu上的mysql应用迁移到centos上,尝试去执行, 你会发现,当他去调用一个函数库,因为代码写死了, 函数库(ubuntu)在centos上根本不存在; 那肯定会程序报错; 这就是为什么我们应用不能跨系统运行原因.
那针对这样一个问题, 我们docker干了什么事情?
既然每个应用都依赖于系统函数库, 我为什么不把它的系统函数库跟它一起打包呢? 这样一来,不愁找不到函数库了吗?
所以docker的解决方案就是将用户程序与系统调用的这个函数库一起打包.
也就是说(for instance/sample)我来打包一个这个需要自己的一些依赖的mysql, 同时mysql需要一些比如ubutu的系统函数库;
然后我们就把mysql自己的依赖和ubuntu的函数库打包成一个整体, 我们的mysql, nodojs等应用,你随便放在任何的只要是linux内核的linux操作系统上,
通过这种方式,docker就解决了应用执行跨系统的问题
docker沙箱,不同应用组件依赖之间看不到,接触不到,就没有相互影响;,
docker沙箱隔离,依赖,函数库和配置等等; 因此(不同应用)只需要依赖linux内核,可以在任何Linux操作系统运行了.
到这为止,讲完了docker的工作原理. docker就是一个快速交付应用,运行应用的技术; docker(程序应用,依赖(防止不同应用依赖的相互干扰),函数库,环境,等等)打包一个到镜像,可以迁移到任意Linux OS
docker启动,移除只需要一行命令完成,方便快捷; 因此docker(含有程序应用,依赖,函数库)做部署和运行都非常快,
1.3 Docker和虚拟机
Docker可以实现在不同的linux操作系统上去运行好部署(避免不同应用依赖干扰和跨LinuxOS平台运行), 同时VM virtual machine也可以达到类似的效果;
它们两个的实现,又有什么样的差别呢?
docker把应用所需要的依赖及其应用函数库,甚至与操作系统函数库一起打包(不同操作系统不同的函数库一起打包)
那VM又是一种什么样的情况呢? vm大家不陌生,我们都在自己的WIn电脑上安装过, (VM系统)类似于centos或者Ubuntu这样的一个操作系统.
那么device是怎么实现在一个系统里面装了另一个系统的呢? 它(device or VM)其实用到一个名为hypervisor的技术, 这种技术可以模拟出计算机的各种各样硬件,比如cpu,内存等等.
然后在模拟出的计算机上, 你就可以安装任意你想要的操作系统了.
(VM里面)操作系统可以任意安装, 那么就可以安装任何适合的依赖; 函数库以及应用等等, 这样就实现了跨系统的一种应用部署;
VM是系统里面装了另外的系统,应用–>内置的操作系统–>hypervisor交互–>web操作系统(OS的一部分?!)–>调用计算机硬件调用. (调用链关系,VM部署程序性能效率很差)
VM应用调用经过了层层传递,所以速度等性能相对docker来讲是差了一点; docker直接调用操作系统底层的内核,性能速度效率好很多.
VM使用时,先要启动虚拟的操作系统,而后再启动虚拟操作系统上面的应用, 相当于重启了计算机, 但是docker只需要在OS操作系统上把一个进程给启动起来,
1.4)docker架构
理解了docker原理, 更好使用docker,还需理解docker架构,docker架构中,有几个重要的概念,镜像就是硬盘中的文件
镜像image: docker将应用程序及其所需的依,函数库,环境,配置等文件打包在一起,称为镜像; 镜像就是硬盘中的文件
容器又是什么回事?简单理解, 把mysql的应用给它跑起来就, 形成的这个进程就是容器;
只不过,在docker里边,容器还要做隔离; 也就是说, 我们的容器可以看做是这样一个小盒子, 这个盒子里边将来会利用我们linux手段,将它形成隔离空间, 里面有自己独立的cpu资源,内存资源甚至还有独立的文件系统,
那么在这个容器内运行的这个进程, 以为是这台计算机上唯一进程了, 从而起到隔离的效果
将来我们mysql镜像不管是启动成一个容器,还是启动成多个容器,它们之间都是相互隔离的;
容器运行过程中,必然会做一种数据读写操作, 比如mysql将来肯定要去存数据, 存到data目录, ,容器里面的数据能不能写到镜像的data目录里面去? 不能, 等于对镜像产生了污染 (写了很多可能导致镜像污染不可用了)
镜像都是只能读的, 也就是说容器在运行时,你不能往镜像里面写东西 你可以基于镜像去创建容器, 然后容器可以去镜像里面读数据,但不能写;
啊将来mysql容器我往哪里写呢,很简单,你可以拷贝一份文件到自己的独立文件系统中,写数据到自己空间里,不会对别的容器和镜像产生影响,日志也如此,大家各写各, ,
镜像怎么共享给被人去使用呢? 给同事或者网络中其它的程序员. 用到第二个概念, dockerhub是一个docker镜像的托管平台,这样的平台(阿里云,腾讯云,etc)我们统称为docker registry,也就是镜像服务器,
程序员可以利用docker提供的一些命令,去完成镜像的构建; 构建出mysql,redis各种各样的镜像,而后将这些镜像上传到dockerhub(统称dockerhub registery)这样的服务器上去;
docker官方也写了很多很多优良镜像,把它都放到docker hub这样的服务器上,;;; 阿里云, 网易云都有这样的服务器docker hub,
如果你觉得这些服务器在外网公开太危险, 公司内部的这种东西, 你不想公开, 可以搭建私有的云服务器,这些都叫docker registry
这就是镜像构建的方案,如何利用docker完成镜像构建,或者是从远端拉取镜像呢? 怎样运行容器呢?
部署就完成了, ,mysql, nginx等镜像建议使用官方镜像(在docker registry里面拉取),没必要自己构建;
只有我们自己的微服务,或者深度定制的镜像才需要构建;
一般使用docker: 就是向docker server发命令–>得到镜像–>创建容器–>完成部署;
一个镜像启动多个容器,形成集群(容器集群??)
1.5) 初始docker-docker的安装
docker可以安装在各种OS上, 企业用的最多的是linuxOS, Centos distro的发行版占比最重, ,在centos下如何安装docker,
1.uninstall docker which may be not very right:
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine \
docker-ce
2.虚拟机联网,安装yum工具
yum install -y yum-utils \
device-mapper-persistent-data \
lvm2 --skip-broken
- 更新本地镜像源(不用去国外地址安装,没有vpn会很慢):
1.6) Docker basic operations
1.6.1 docker mirror operations
before learning docker mirror operations (mirror commands), we have a look at mirror naming convention;
two parts for a mirror name (naming convention): [repository]:[tag] ---- 仓库和版本 eg: mysql:5.7
if nono for tag, resembling the latest version of mirror,
mirror operation barely CRUD,
两种获取镜像的方式:
我想知道本地有那些镜像,我该怎么办? 使用docker images 命令去查看镜像 images就是镜像的意思
我想删一两个多余的镜像, docker rmi remove images
学会了获取,查看和删除镜像了, ,
如何分享镜像给别人,怎么办? 两种方式,
- docker push推送镜像到服务
2)u盘拷给同事
(要有一个文件来拷贝, docker save保存镜像为一个压缩包, 同时拿着U盘来拷贝这个压缩包,–>同事再用一个docker load加载/解压 压缩包为镜像, 就可以将压缩包加载成一个本地镜像)
这些就是docker操作中的镜像操作的常见命令, ,记不住,查看帮助文档就行, docker --help就可以查看到docker中的所有命令了,命令不一定会记,只要会帮助文档
then case on mirror operations: 从dockerhub中拉取一个nginx镜像并查看
- List item 访问首先dockerhub镜像仓库搜索nginx镜像, 比如镜像仓库dockerhub,搜索慢,
-
拉取镜像了,
每一个镜像都有一个自己唯一的ID,完成了拉取和查看镜像,
case 2: 通过docker save将nginx镜像导出磁盘,然后再通过load加载回来,
docker save会把镜像变成一个压缩包,
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker save -o nginx1.tar nginx:1.25.5-perl
[root@iZ2vc5lqzt23aweti4j777Z ~]# ll
total 235632
-rw------- 1 root root 241286144 Apr 25 11:46 nginx1.tar
导出成功了, 接下来演示导入,–>先删除本地我们自己导入的镜像
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker rmi nginx:1.25.5-perl
Untagged: nginx:1.25.5-perl
Untagged: nginx@sha256:bff5a5a6e7da905c69fdb81888d6f50ba12b10a9cd4bac09686b2f42108635e2
接下来通过load加载这个nginx的tar文件
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker load --help
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker load -i nginx1.tar
52ec5a4316fa: Loading layer [>] 77.88MB/77.88MB
bbde741e108b: Loading layer [>] 113.8MB/113.8MB
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx 1.25.5-perl ae6a0c82fff6 30 hours ago 236MB
hello-world latest d2c94e258dcb 11 months ago 13.3kB
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker pull nginx:1.25.5-perl
镜像重新加载回来了, docker pull docker save docker rmi docker load docker images,
perception/bond/curiosity for positive side all the way/documentary/practice/team spirit/critical thinking for all, first of all on self/ perseverance/pain
1.6.2 container operation
1.6.3 data volumn (container data anagement)
1.7) docker 镜像命令练习
search and pull redis mirror from dockerhub
刚刚学习了docker常见命令,还有一些未演示的命令,后期的学习中再去给大家演示,
1.8) docker container introduction
如何基于镜像创建容器? 完成容器的各种操作,–>首先create container (docker run)
docker run不仅创建容器,还可以让容器处于一个运行状态–>除了run,容器还会有pause和stop状态,–>简单几个命令,就可以实现三个状态之间的切换
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fd9c16c31406 ae6a0c82fff6 "/docker-entrypoint.…" About an hour ago Up About an hour (Paused) 0.0.0.0:80->80/tcp, :::80->80/tcp myNginx
运行到暂停,该怎么办呢? docker pause --> 暂停恢复运行 docker unpause
运行到停止 docker stop --> 停止恢复运行 docker start
pause status: OS将容器内进程挂起, 容器关联内存暂存起来,CPU不在执行这个进程,
unpause恢复: 内存空间恢复, 程序接着被CPU运行>>>程序就进入运行状态了
stop: OS kill the progress/tenor/course, 容器所占的内存回收, 保留下来的仅限容器的文件系统,也就是那些静态的东西
停止后进程被终止,无法被恢复,不能起死回生,但是可以重新生一个,docker start,创建全新的进程,
docker ps查看所有运行的容器和状态>>>docker logs查看容器运行的日志,查看运行过程中,产生的一些细节, container运行中有没有什么错误,都可以通过log来查看,
不满足从表面观察容器,想深入内部了解container,–>docker exec 进入容器内部执行命令,做我们想做的事,
容器完全明白理解了–> docker rm 可以删掉容器,不是rmi >>>删容器,不仅仅是把进程干掉, 内存回收,包括硬盘上的文件系统彻底干掉,(干干净净的,没有这个东西了,容器硬盘上干干净净?!)
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker rm myNgin
1.9) demo container frequently used commands
demo: 创建运行Nginx container>>>去docker hub查看Nginx容器运行命令
不仅仅是nginx以后碰到新的镜像要去运行,>建议都去dockerhub上查看一下帮助文档,
每一个容器都要有一个唯一名称,>>>>宿主机(服务器??) 有很多端口, like 80
客户想要访问容器,那就去访问centos服务器,
端口映射作用是, 把一个本来完全隔离的容器, 暴露一个小口,透过它你来访问,—端口映射的作用,
左侧宿主机端口,右侧容器内端口,>>>宿主机端口可以任意被占用,只要端口没有被占用,容器内端口往往取决于这个应用本身,
nginx一般监听的都是80端口,容器内端口一般不变,可变的是宿主机端口,宿主机8080:80, 也可以
-d 代表后台运行,不加-d他就是前台运行,(前台就是展示在desktop,后台就是没在desktop,而是在后台进程运行,前面看不到,)>>>一般都加上-d,在后台运行
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker unpause myNginx
myNginx
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fd9c16c31406 ae6a0c82fff6 "/docker-entrypoint.…" 2 hours ago Up 2 hours 0.0.0.0:80->80/tcp, :::80->80/tcp myNginx
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker stop myNginx
myNginx
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker start myNginx
myNginx
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fd9c16c31406 ae6a0c82fff6 "/docker-entrypoint.…" 2 hours ago Up 1 second 0.0.0.0:80->80/tcp, :::80->80/tcp myNginx
先stop image, 再-f 强制关掉image,
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
522ce2195461 redis "docker-entrypoint.s…" 18 hours ago Up 18 hours 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp myRedis
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker rmi ae6a0c82fff6
Error response from daemon: conflict: unable to delete ae6a0c82fff6 (must be forced) - image is being used by stopped container 2f99ade879ca
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker rmi -f ae6a0c82fff6
Deleted: sha256:ae6a0c82fff6648733ec5b3e5d8905dd63e907d4a57c1dbc92ee29a39e3be254
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
522ce2195461 redis "docker-entrypoint.s…" 18 hours ago Up 18 hours 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp myRedis
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d2c94e258dcb 11 months ago 13.3kB
redis latest 7614ae9453d1 2 years ago 113MB
1.10) 使用docker,修改nginx里面的文件内容
用到之前的一个命令docker exec -it myNginx bash >>>在这个过程中我们可以加一些参数,>>>加-it, 进入容器时创建标准输入输出终端,
我们以前学习java基础io流的时候,已经接触过标准输入输出了吧,就是利用键盘的一种录入, 或者是控制台的输出实现一种容器交互,>>> 加了it(??initial terminal 创建终端)
bash 进入容器后执行的linux终端交互命令
Hosting some simple static content
$ docker run --name some-nginx -v /some/content:/usr/share/nginx/html:ro -d nginx
Alternatively, a simple Dockerfile can be used to generate a new image that includes the necessary content (which is a much cleaner solution than the bind mount above):
FROM nginx
COPY static-html-directory /usr/share/nginx/html
place to find and change index page:
cd /usr/share/nginx/html
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker exec -it myNginx bash
root@fd9c16c31406:/#
root@fd9c16c31406:/# pwd
/
root@fd9c16c31406:/# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
容器内部有自己的一套类似linux系统目录,(nginx精简版目录系统结构,) >>>镜像都已经封装了命令和deps,函数库,运行环境等等,
sed -i ‘s###g’ index.html
sed -i ‘s#Welcome to nginx#传智教育欢迎你#g’ index.html
root@fd9c16c31406:/usr/share/nginx/html# sed -i 's#Welcome to nginx#\344\274\240\346\231\272\346\225\231\350\202\2
62\346\254\242\350\277\216\344\275\240#g' index.html
root@fd9c16c31406:/usr/share/nginx/html# sed -i 's#<head>#<meta charset="utf-8">#g' index.html
root@fd9c16c31406:/usr/share/nginx/html# sed -i 's#Welcome to nginx#\344\274\240\346\231\272\346\225\231\350\202\2
62\346\254\242\350\277\216\344\275\240#g' index.html
案例做完后,如何停掉容器,先退出容器 exit (linux->>images>>container)
root@fd9c16c31406:/usr/share/nginx/html# exit
exit
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fd9c16c31406 ae6a0c82fff6 "/docker-entrypoint.…" 2 hours ago Up 27 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp myNginx
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker stop myNginx
myNginx
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps --help
Usage: docker ps [OPTIONS]
List containers
Aliases:
docker container ls, docker container list, docker container ps, docker ps
Options:
-a, --all Show all containers (default shows just running)
-f, --filter filter Filter output based on conditions provided
--format string Format output using a custom template:
'table': Print output in table format with column headers (default)
'table TEMPLATE': Print output in table format using the given Go template
'json': Print in JSON format
'TEMPLATE': Print output using the given Go template.
Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates
-n, --last int Show n last created containers (includes all states) (default -1)
-l, --latest Show the latest created container (includes all states)
--no-trunc Don't truncate output
-q, --quiet Only display container IDs
-s, --size Display total file sizes
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fd9c16c31406 ae6a0c82fff6 "/docker-entrypoint.…" 2 hours ago Exited (0) 3 minutes ago myNginx
c665f7066f4d hello-world "/hello" 21 hours ago Exited (0) 21 hours ago nifty_keller
3919e662fe0e hello-world "/hello" 21 hours ago Exited (0) 21 hours ago sharp_banach
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker start myNginx
myNginx
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fd9c16c31406 ae6a0c82fff6 "/docker-entrypoint.…" 2 hours ago Up 4 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp myNginx
c665f7066f4d hello-world "/hello" 21 hours ago Exited (0) 21 hours ago nifty_keller
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker stop myNginx
myNginx
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker rm myNginx
myNginx
容器里修改命令vi不能用,不推荐大家在容器内做修改,下节课讲解修改文件的正确姿势
设置宿主机服务器端口和容器端口对应
Last login: Thu Apr 25 17:48:50 2024 from 47.96.60.214
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker run --name myRedis -p 6379:6379 -d redis redis-server --appendonly yes
522ce2195461951e1b84a0f2a797bf16e2946264acadb4ef34c13d37ca3d3841
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
522ce2195461 redis "docker-entrypoint.s…" 41 seconds ago Up 40 seconds 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp myRedis
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker exec -it myRedis bash
root@522ce2195461:/data# redis-cli
连接redis, 查看没有任何数据
root@522ce2195461:/data# redis-cli
通过keys *查看没有任何数据
127.0.0.1:6379> keys *
(empty array)
通过set num 666存一个数据进去
127.0.0.1:6379> set num 666
OK
root@522ce2195461:/data# redis-cli
127.0.0.1:6379> set num 666
OK
127.0.0.1:6379> get num
"666"
127.0.0.1:6379> exit
root@522ce2195461:/data# exit
exit
第一次退出redis,第二次退出容器container,
直接进入myRedis容器的客户端,一步到位
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker exec -it myRedis redis-cli
127.0.0.1:6379> keys *
1) "backup4"
2) "backup1"
3) "num"
4) "backup3"
5) "backup2"
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> get num
"666"
127.0.0.1:6379> exit
[root@iZ2vc5lqzt23aweti4j777Z ~]#
一次退出到了宿主机(liux服务器,)
1.11) 数据卷: 容器和数据耦合的问题
问题: docker里面文件和数据也好,都是和容器耦合在一起的,
在容器里面一顿改,随着时间迁移, 改的越来越多,自己都不知道改了什么,将来有创建了新的容器,也希望与原来容器达到相同效果时,你会发现,需要把原来所有动作重复再做一遍,…就是说,你所做的哪些修改对其它容器来讲是不可复用的,----你不得不重复劳动,
容器数据耦合,升级时,要先删除旧容器,没有好的方式实现数据迁移升级,
使用数据卷知识解决上面问题,>>>数据卷是虚拟的,并不真实存在,真正指向的是硬盘上的一个文件夹,
nginx的html目录在/usr/share/nginx/html,容器内目录.,配置放在上面/etc/nginx
/conf
让nginx内部目录和数据卷相关联,通过数据卷,为宿主机文件系统和容器文件系统达起桥梁,
两个容器挂载同一个数据卷,那么原来conf目录里做的一切修改,那我这个新的容器也能看到,这就是数据共享
将来某一天,容器删了,数据卷没有删,因为数据卷挂载在容器目录之上,卷还在,硬盘数据/宿主机文件还在,
将来来了一个新的新版本容器,只要挂载在这两个数据卷之上,共享以前旧数据
操作数据卷?
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker volume --help
Usage: docker volume COMMAND
Manage volumes
Commands:
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove unused local volumes
rm Remove one or more volumes
Run 'docker volume COMMAND --help' for more information on a command.
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker volume create html
html
[root@iZ2vc5lqzt23aweti4j777Z ~]# ls
nginx1.tar redis.tar
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker volume ls
DRIVER VOLUME NAME
local 47f756d77edcf552cac4819cb53d7024726b383d4ea351664931510b3a4add0a
local html
存储地点,挂载地方,/var/lib/docker
查看数据卷详细信息,
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker volume inspect html
[
{
"CreatedAt": "2024-04-26T10:37:35+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/html/_data",
"Name": "html",
"Options": null,
"Scope": "local"
}
]
删除数据卷两种办法, prune(删除未使用的数据,no effect now)和rm
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker volume prune
WARNING! This will remove anonymous local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker volume ls
DRIVER VOLUME NAME
local 47f756d77edcf552cac4819cb53d7024726b383d4ea351664931510b3a4add0a
local html
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker volume prune
WARNING! This will remove anonymous local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker volume ls
DRIVER VOLUME NAME
local 47f756d77edcf552cac4819cb53d7024726b383d4ea351664931510b3a4add0a
local html
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker volume rm html
html
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker volume ls
DRIVER VOLUME NAME
local 47f756d77edcf552cac4819cb53d7024726b383d4ea351664931510b3a4add0a
数据卷: 解耦合, 方便操作,数据安全,可以不用因为升级容器版本等被删除数据
1.12)数据卷挂载case 1 | 如何将数据卷挂载到容器当中
create 建立在nginx镜像上的新容器:, 通过数据卷,将容器数据挂载到宿主机服务器系统文件目录上面, ,
docker run --name myNginx -p 80:80 -v html:/usr/share/nginx/html -d nginx
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
522ce2195461 redis "docker-entrypoint.s…" 18 hours ago Up 18 hours 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp myRedis
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2f99ade879ca nginx:1.25.5-perl "/docker-entrypoint.…" 28 minutes ago Exited (0) 18 minutes ago myNginx
522ce2195461 redis "docker-entrypoint.s…" 18 hours ago Up 18 hours 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp myRedis
c665f7066f4d hello-world "/hello" 40 hours ago Exited (0) 40 hours ago nifty_keller
3919e662fe0e hello-world "/hello" 40 hours ago Exited (0) 40 hours ago sharp_banach
6b329a28900e hello-world "/hello" 2 days ago Exited (0) 2 days ago happy_bartik
4e3735b9d957 hello-world "/hello" 2 days ago Exited (0) 2 days ago happy_archimedes
18027c590230 hello-world "/hello" 2 days ago Exited (0) 2 days ago kind_leavitt
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker start myNginx
myNginx
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2f99ade879ca nginx:1.25.5-perl "/docker-entrypoint.…" 29 minutes ago Up 3 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp myNginx
522ce2195461 redis "docker-entrypoint.s…" 18 hours ago Up 18 hours 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp myRedis
c665f7066f4d hello-world "/hello" 40 hours ago Exited (0) 40 hours ago nifty_keller
3919e662fe0e hello-world "/hello" 40 hours ago Exited (0) 40 hours ago sharp_banach
6b329a28900e hello-world "/hello" 2 days ago Exited (0) 2 days ago happy_bartik
4e3735b9d957 hello-world "/hello" 2 days ago Exited (0) 2 days ago happy_archimedes
18027c590230 hello-world "/hello" 2 days ago Exited (0) 2 days ago kind_leavitt
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2f99ade879ca nginx:1.25.5-perl "/docker-entrypoint.…" 29 minutes ago Up 9 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp myNginx
522ce2195461 redis "docker-entrypoint.s…" 18 hours ago Up 18 hours 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp myRedis
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker volume inspect html
[
{
"CreatedAt": "2024-04-26T10:51:36+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/html/_data",
"Name": "html",
"Options": null,
"Scope": "local"
}
]
[root@iZ2vc5lqzt23aweti4j777Z ~]# docker inspect html
[
{
"CreatedAt": "2024-04-26T10:51:36+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/html/_data",
"Name": "html",
"Options": null,
"Scope": "local"
}
]
[root@iZ2vc5lqzt23aweti4j777Z _data]# docker run --name myNginx -p 80:80 -v html:/usr/share/nginx/html -d nginx
删除的数据卷不存在还能成功显示挂载吗?重新创建后,自动生成新的卷,容器挂载到系统文件
1.13) 数据卷挂载case 2
刚刚演示了数据卷挂载到容器目录,而事实上不仅仅是数据卷,我们的宿主机目录可以直接与容器进行挂载
宿主机目录直接挂载容器,与通过数据卷,宿主机目录挂载容器,有什么区别呢?
![在这里插入图片描述](https://img-blog.****img.cn/direc
t/0c0a9aef587042598251559dd8c49428.png)
文件直接覆盖, 数据卷挂载没有的内容
docker run \
--name mysql \
-e MYSQL_ROOT_PASSWORD=123 \
-p 3306:3306 \
-v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf \
-v /tmp/mysql/data:/var/lib/mysql \
-d \
mysql:latest