一、Docker概述 1.Docker的作用 一款产品的开发往往需要多个开发环境,在以前,开发人员将项目打包好之后,经常会出现在我的电脑上能够正常运行,而在他的电脑上不能使用,原因就是产品开发所需要的环境不一样。
而现在,开发人员将产品以及它所对应的开发环境一起打包,这种就被称为镜像。这样就省去了开发环境的麻烦。
而docker的出现就是为了解决以上的问题,docker就相当于一个箱子(镜像),把每一个镜像隔离开来,互不干扰。
1.镜像 镜像就相当于一个印刷机的模板,可以通过镜像来创建多个容器,也就是可以靠印刷机的模板印刷出很多相同的书籍,各个容器之间相互独立。
2.容器 容器就是一个一个独立的应用,每个应用之间相互独立 可以被启用、开始、停止、删除。足够安全 可以把容器看作是一个简易版的Linux系统(包括root用户权限,进程空间,用户空间和网络空间等)和运行在其中的应用程序。
3.仓库 仓库是集中存放镜像文件的地方。 仓库和仓库注册服务器(Registry)是有区别的,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签 仓库分为公开仓库(public)和私有仓库(private)两种形式 最大的仓库是国外的Docker Hub,存放了大量的镜像文件。
二、Docker工作原理 1.Docker的工作原理 Dokcer是一个Client-Server结构:Docker守护进程运行在主机上,通过Socket从客户端来访问这个守护进程,而守护进程接收到来自客户端的命令后,管理运行在主机上的容器以及进行资源的分配。
三、命令 容器命令 有了镜像才可以创建容器
说明:我们有了镜像才可以创建容器,Linux 下载一个centos镜像来测试学习
新建容器并启动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 docker run[可选参数] image# 参数说明 --name= "NAME" 容器名字 tomcat1 tomcat2,用来进行区分容器 -d 后台方式运行 -it 使用交互方式运行,进入容器查看内容 -P 指定容器的端口 -p 8080:8080 -p主机端口:容器端口(常用) -p容器端口 容器端口 -p 随机指定端口# 启动并进入容器 PS C:\Users\17083\Desktop> docker run -it centos [root@6c35f43ce5c2 /]# exit exit PS C:\Users\17083\Desktop> docker run -it centos /bin/bash [root@9e59d793d8dc /]#
docker 中创建容器的两种方式(交互式与守护式)
当使用Docker时,有两种常见的方式来创建容器:交互式方式和守护(后台)式方式。
交互式方式创建容器
交互式方式创建容器是指在容器内部启动一个交互式会话,类似于在终端中登录到一个虚拟机 。您可以直接与容器进行交互,并在容器内部执行命令。
守护(后台)式方式创建容器
守护式方式创建容器是指在后台运行容器,无需进入容器内部进行交互。这种方式适用于长期运行的服务或应用程序。
列出所有运行的镜像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # 列出当前正在运行的容器 + 带出历史运行过的容器 PS C:\Users\17083\Desktop> docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9e59d793d8dc centos "/bin/bash" 4 minutes ago Exited (127) 8 seconds ago agitated_shtern 6c35f43ce5c2 centos "/bin/bash" 4 minutes ago Exited (0) 4 minutes ago elastic_brahmagupta 63684c89095b jenkins/jenkins:jdk11 "/usr/bin/tini -- /u…" 10 days ago Exited (255) 6 days ago 50000/tcp, 0.0.0.0:9090->8080/tcp jks# 列出当前正在运行的容器 PS C:\Users\17083\Desktop> docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES# 列出最近创建的容器 PS C:\Users\17083\Desktop> docker ps -a -n=1 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9e59d793d8dc centos "/bin/bash" 7 minutes ago Exited (127) 3 minutes ago agitated_shtern# -q只显示容器的编号 PS C:\Users\17083\Desktop> docker ps -aq 9e59d793d8dc 6c35f43ce5c2 63684c89095b
退出容器
1 2 3 exit #容器停止并退出 Ctrl + P + Q #容器不停止退出 docker exec -it [容器NAMES] /bin/bash #容器不停止退出,重新进入这个容器
删除容器
1 2 3 docker rm [容器id] #删除指定的容器,不能删除正在运行的容器 docker rm -f $(docker ps -aq) #删除所有的容器 docker ps -a -q|xargs docker rm #删除所有的容器
启动和停止容器的操作
1 2 3 4 docker start[容器id] #启动容器 docker restart[容器id] #重启容器 docker stop[容器id] #停止容器 docker kill[容器id] #杀死容器
常用的其他命令 后台启动容器
1 2 3 4 # docker run -d 镜像名 docker run -d centos # 问题:docker ps -a 发现centos停止了 #
查看日志的命令
1 2 3 4 5 6 7 8 9 10 11 docker logs -t -f --tail #如果容器中没有日志# 自己写一个脚本 docker run -d centos /bin/bash -c "while true;do echo yll;sleep 1;done" PS C:\Users\17083\Desktop> docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7df27afdfd97 centos "/bin/bash -c 'while…" 30 seconds ago Up 29 seconds elegant_pascal# 显示日志 -tf --tail [number] #要显示的日志数量 + 容器id docker logs -t -f --tail 10 7df27afdfd97
查看容器中的进程信息ps
1 2 3 4 5 # top命令 PS C:\Users\17083\Desktop> docker top 7df27afdfd97 UID PID PPID C STIME TTY root 25077 24273 0 06:35 ?
查看镜像元数据
1 2 3 # 命令 docker inspect [容器id] PS C:\Users\17083\Desktop> docker inspect 7df27afdfd97
进入当前正在运行的容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # 我们通常容器都是使用 后台的方式进行运行的,需要进入容器修改一些配置 # 命令1 # -it以交互模式执行 docker exec -it [容器id] [bashshell]# 测试 PS C:\Users\17083\Desktop> docker exec -it 7df27afdfd97 /bin/bash [root@7df27afdfd97 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var# 命令2 dcoker attach [容器id] 正在执行当前的代码......# docker exec # docker attach
从容器中拷贝文件到主机上
1 2 3 4 docker cp 容器id: 容器内的路径 目的主机的路径 root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop# docker cp d574485cf29a:/home/test.java /mnt/c/Users/17083/Desktop Successfully copied 1.54kB to /mnt/c/Users/17083/Desktop# 拷贝是一个手动的过程,未来我们使用-v卷的技术,可以实现自动同步 /home /home
练习
Docker安装nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # 1、搜索镜像 docker search nginx# 2、下载镜像 dcoker pull nginx# 3、运行测试 # -d 后台运行 # --name 给容器命名 # -p 宿主机端口,容器内部的端口 root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop# docker run -d --name nginx01 -p 3344:80 nginx a92da888d3aa44846b8dcbd278e530b443c4e46af7852078a780e0bde101b6ac root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a92da888d3aa nginx "/docker-entrypoint.…" 8 seconds ago Up 7 seconds 0.0.0.0:3344->80/tcp nginx01 root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop# curl localhost:3344# 进入容器 root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a92da888d3aa nginx "/docker-entrypoint.…" 7 minutes ago Up 7 minutes 0.0.0.0:3344->80/tcp nginx01 root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop# docker exec -it nginx01 /bin/bash root@a92da888d3aa:/# whereis nginx nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx root@a92da888d3aa:/# cd /etc/nginx root@a92da888d3aa:/etc/nginx# ls conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
每次改动nginx配置文件,都需要进入容器的里面,十分麻烦,我要是可以在容器外提供映射路径,达到在容器外面修改文件,容器内部就可以自动修改。-v:数据卷
docker安装一个tomcat
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 官方的使用方法 docker run -it --rm tomcat:9.0# 我们之前的启动都是后台,停止了容器之后,容器还可以再查得到 docker -it --rm tomcat:9.0,一般用来进行测试,用完就删除 # 先下载,再启动 docker pull tomcat# 启动运行 docker run -d -p 3355:8080 --name tomcat01 tomcat # 测试访问没有问题 cp -r webapps.dist/* webapps # 进入容器 root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop # docker exec -it tomcat01 /bin/bash # 发现它没有webapps,镜像的原因,默认是最小的镜像,所有不必要的都会剔除,保证最小的可运行的环境!
如果每次进入容器都会非常的麻烦,我们要是可以在容器的外面提供一个映射的路径,webapps,我们再外面放置项目,就自动同步到内部就很好了。
部署es + kibana
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 # elasticsearch 暴露的端口很多 # elasticsearch 十分的消耗内存 # elasticsearch 的数据一般要放置到安全的目录下!挂载 # --net somenetwork ?网络配置 # 启动 docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2# 它是非常消耗内存的 localhost:9200 { "name": "4cd6c3d1f871", "cluster_name": "docker-cluster", "cluster_uuid": "XU3rNb8-T6Cu-NSzBd7ykA", "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" }# 增加内存限制,修改配置文件 -e环境配置修改 docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "ES_JAVA_OPTS=-Xms64m -Xmx512m" elasticsearch:7.6.2
使用kibana连接elasticsearch
四、可视化面板
portainer(先用这个)
Rancher(CI/CD)
什么是portainer Docker图形化界面管理工具!提供一个后台面板供我们操作
1 2 Docker run -d -p 8088:9000 \ --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
访问测试:Portainer ,可以看到
五、Docker 镜像讲解 1、镜像是什么? 镜像是一种轻量级的、可执行的独立的软件包,用来打包软件运行环境开发的软件,它包含某个软件所需要的所有内容,包括代码、运行时、库、环境变量和配置文件。
将所有的应用和环境,直接打包为Docker镜像,就可以直接运行。
如何得到镜像 ?
从远程仓库下载
拷贝
自己制作一个DockerFile
2、Docker镜像加载原理
UnionFs(联合文件系统)
UnionFs(联合文件系统):Union文件系统(UnionFs)是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下( unite several directories into a single virtual filesystem)。Union文件系统是 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等等。
平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?
对于个精简的OS,rootfs可以很小,只需要包合最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的Linux发行版, boots基本是一致的, rootfs会有差別,因此不同的发行版可以公用bootfs.
虚拟机是分钟级别,容器是秒级!
3、分层理解 我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层层的在下载 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop# docker pull redis Using default tag: latest latest: Pulling from library/redis 09f376ebb190: Already exists # 明显这一层已经下载了 9ae6a7172b01: Pull complete 2c310454138b: Pull complete 3eba9ec960aa: Pull complete 3d36c165ff0a: Pull complete 493d196d734f: Pull complete 4f4fb700ef54: Pull complete 484e0560ae90: Pull complete Digest: sha256:01afb31d6d633451d84475ff3eb95f8c48bf0ee59ec9c948b161adb4da882053 Status: Downloaded newer image for redis:latest docker.io/library/redis:latest
思考: 为什么Docker镜像要采用这种分层的结构呢?
最大的好处,我觉得莫过于资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过docker image inspect 命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 "RootFS": { "Type": "layers", "Layers": [ # 第一步已经下载过了,剩下的再一步一步安装,每次安装一部就是一个记录 "sha256:5d4427064ecc46e3c2add169e9b5eafc7ed2be7861081ec925938ab628ac0e25", "sha256:12c0b39a3b9d0dab1c5cbcb18cb220ee002110f1afedad16e2d7ff206aef3c9e", "sha256:304555e2fff0c025082f15d5c33cb2497e128032db726375739930040e044863", "sha256:8af05c1dad089b41305326247dbd3b10e83f667c74f80cc289ca081f5c7448c3", "sha256:56c72ac4e9c6d764f3f7cecbde503aefe6a5fb6e6d354074013a9dd55722c1d1", "sha256:1f3cf62067a933ee78a2cd500fb3fc7434cf99cdcebf062d099f0d57df01972b", "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef", "sha256:d1b598028f26907d399516f3957eed2c6dd8f21c6c3772385de74b0b54031b6d" ] }, "Metadata": { "LastTagTime": "0001-01-01T00:00:00Z"
所有的 Docker镜像都起始于一个基础镜像层,当进行修改或培加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于 Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创健第三个镜像层该像当 前已经包含3个镜像层。例如:在外部看来整个镜像只有6个文件,这是因为最上层中的文件7 是文件5的一个更新版,这种情況下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新 镜像层添加到镜像当中。Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。Linux上可用的存储引撃有AUFS、 Overlay2、 Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于 Linux中对应的。件系统或者块设备技术,井且每种存储引擎都有其独有的性能特点。Docker在 Windows上仅支持 windowsfilter 一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW [1]。
特点
Docker 镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层!
如何提交一个自己的镜像
4、Commit镜像 1 2 docker commit 提交容器成为一个新的副本 docker commit -m "提交的描述信息" -a="作者" 容器id 目标镜像名,[tag]
实战测试
1 2 3 4 5 6 7 8 9 # 1、启动一个默认的tomcat docker run -d -p 8080:8080 tomcat# 2、发现这个默认的tomcat 是没有webapps应用,官方的镜像默认webapps下面是没有文件的! docker exec -it 容器id# 3、我自己拷贝文件进去 cp -r webapps.dis/* webapps# 4、将操作过的容器通过commit提交为一个镜像!我们以后就使用我们修改过的镜像即可,这就是我们自己的一个修改的镜像。 docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[TAG] docker commit -a="kuangshen" -m="add webapps app" 容器id tomcat02:1.0
如果你想要保存当前容器的状态,就可以通过commit来提交,获得一个镜像,就好比我们我使用虚拟机的时候,快照!,到了这里Docker才算入门