Docker入门——保姆级

Docker概述

—— Notes from WAX through KuangShen

准确来说,这是一篇学习笔记!!!

Docker为什么出现

一款产品:开发—上线 两套环境!应用环境如何铜鼓?

开发 – 运维。避免“在我的电脑米问题呀!!!”

环境配置十分麻烦,没一个机器都要部署环境(集群Redis、ES…)!费时费力。

发布一个项目(jar + (Redis、Mysql、jdk、ES))能否带上安装环境进行打包发布。

Windows开发,最后发布到Linux:

传统:开发项目,运维来做。

现在:开发打包部署上线,一套流程做完。

例:

java – apk – 发布(应用商店) – 张三使用apk – 安装即可使用!

java – jar(环境) – 打包项目带上环境(镜像)-- (Docker仓库:商店)-- 下载发布的镜像 – 直接运行即可!

Docker给出以上问题的解决方案!

Docker的思想来自于集装箱!

隔离:Docker核心思想,打包装箱!每个箱子是互相隔离的

Docker通过隔离机制,可以将服务器利用到极致!

Docker的历史

2010年,几个搞IT的年轻人,就在没美国成立了一家公司dotCloud

做一些pass的云计算服务,LXC有关的容器技术!

他们将自己的技术(容器话技术)命名 就是Docker!

Docker刚刚诞生的时候,没有引起行业注意!公司举步维艰,于是决定开源!!!

2013,Docker开源!

Docker越来越多的人发现Docker的有点!火了,每个月都会更新一个版本!

2014年4月9日,Docker1.0发布!

Docker为什么这么火?极其轻巧

在容器技术出来之前,我们都是使用虚拟技术!

虚拟机:在Windows中装一个Vmware,通过这个软件可以虚拟化出来一个或多个电脑,但是十分笨重。

虚拟机也是属于虚拟化技术,Docker容器技术,也是一种虚拟化技术

vm:linux centos原生镜像(一个电脑) 隔离,需要开启多个虚拟机! 几个G大小
docker:隔离,镜像(最核心的环境4m + jdk + mysql)十分轻巧,运行镜像就可以了,几 M Kb  秒级启动

到现在,所有开发人员都必须会的工具 Docker。

聊聊docker

Docker是基于 Go 语言开发的,开源项目!

官网:https://www.docker.com

文档:https://docs.docker.com 超详细

仓库地址:https://hub.docker.com

Docker的作用

虚拟机技术缺点:

1、资源占用多

2、冗余步骤多

3、启动慢

Docker和虚拟技术的不同:

  • 统虚拟机,虚拟出一切硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件

  • 容器内的应用直接运行再宿主机的内核,容器是没有自己的内核的,也没有虚拟我们的硬件,所以轻便

  • 每个容器内是相互隔离的,每个容器内都有一个属于自己的文件系统,互不影响

DevOps(开发/运维)

应用更快速的交付和部署

  • 传统方式:一堆帮助文档,安装程序

  • Docker:打包镜像发布测试,意见运行

更快捷的升级和扩缩容

  • 使用Docker以后,我们不熟应用就类似搭积木简单

  • 项目打包为一个镜像,扩容 服务器A 服务器B

更简单的系统运维

  • 在容器化之后,开发、测试测试环境都是高度一致的。

更高效的计算资源利用:

  • Docker是内核级的虚拟化,可以在一个物理机上运行很多个容器实例。服务器的性能能利用到极致。

docker的安装

docker的基本组成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cXdU4l9R-1691285233022)(C:\Users\wax\AppData\Roaming\Typora\typora-user-images\image-20210424153809962.png)]

镜像(image):

Docker镜像好比一个模板,可以通过这个模板来创建容器服务。

通过这个镜像可以创建多个容器(最终服务运行或项目运行就是在容器中的)

容器(container):

Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建。

虽然不是很准确,但是可以粗略的连接容器就是一个简单的LInux系统

仓库(repository):

仓库就是存放镜像的地方

仓库分为公有仓库和私有仓库

Docker Hub

阿里云…都有容器服务器

安装docker

安装环境

  1. 需要会一点Linux的基础
  2. CentOS(本次用例)

环境查看

#系统版本是3.10以上的
[root@sa ~]# uname -r
3.10.0-957.el7.x86_64
[root@sa ~]# 
#系统版本
[root@sa ~]# cat /etc/os-release 
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

安装docker

帮助文档:https://docs.docker.com/engine/install/

# 1、删除旧的版本
sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine
# 2、依赖包
sudo yum install -y yum-utils# 3、设置镜像的仓库,当然也可以设置阿里云的
sudo yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.repo              官方
sudo yum-config-manager \--add-repo \https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo     阿里云#更新yum软件包索引
yum makecache fast# 4、安装docekr  -ce表示社区版    -ee表示企业版
yum install docker-ce docker-ce-cli containerd.io# Ubuntu 安装sudo apt install docker.io# 5、运行docker
sudo systemctl start docker# 6、查看版本信息,有则是安装成功
docker version# 7、查看启动是否成功
docker run hello-world   # 会打印“Hello from Docker!” 则成功

卸载docker

# 1、卸载依赖
sudo yum remove docker-ce docker-ce-cli containerd.io# 2、删除资源
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

hello world流程

此处就不画图了:

docker run 开始,docker就会在本地查找镜像,

有,则直接运行该镜像。没有,就会在docker Hub(官方镜像仓库)上去下载,下载到本地后直接运行,没有下载到则返回错误

底层原理

docker是怎么工作的

Docker是一个 Client - Server结构的系统,Docker的守护进程运行在主机上。通过Socket从客户端访问!

DockerServer 接收到Docekr Client的指令执行!
在这里插入图片描述

Docker 为什么比 VM 快

  1. Docker有着比虚拟机更少的抽象层
  2. Docker利用的是宿主机的内核,VM需要的是 Guest OS。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kr2YNtvt-1691285233023)(Docker-入门.assets/95a51974f5cb22bbf85a4650fe3a901f.png)]

所以说,新建一容器的时候,Docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载Guest OS,分钟级别,而Docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级启动。

当然,安全性方面,肯定还是VM虚拟机更安全,毕竟是一个完整的虚拟系统。

Docker的常用命令

帮助命令

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jIj51yeg-1691285233024)(Docker-入门.assets/image-20210524201159034.png)]

docker version				# 显示docker版本信息
docker info					# 显示docker的系统信息,包括镜像和容器的数量
docekr --help				# 帮助

帮助文档 https://docs.docker.com/reference/

镜像命令

Docker images 查看所有本地镜像

[root@sa ~]# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
hello-world             latest              d1165f221234        2 months ago        13.3kB
vue-docker-demo-image   latest              4835e3101950        8 months ago        135MB
docker-demo-image       latest              831b48a0447e        8 months ago        133MB# 含义
REPOSITORY		镜像的仓库源
TAG				镜像的标签
IMAGE ID		镜像的id
REPOSITORY		镜像创建时间
SIZE			镜像大小# 可选项-a, --all             Show all images (default hides intermediate images)		# 显示所有镜像--digests         Show digests 											# 显示摘要-f, --filter filter   Filter output based on conditions provided--format string   Pretty-print images using a Go template--no-trunc        Don't truncate output-q, --quiet           Only show numeric IDs									# 只显示id

docekr search 搜索镜像

[root@sa ~]# docker search mysql
NAME           DESCRIPTION 			         STARS  OFFICIAL            AUTOMATED
mysql                MySQL is a widely used, open-source relation…   10876  	 [OK] 
mariadb       		 MariaDB Server is a high performing open sou…   4102   	 [OK] 
mysql/mysql-server   Optimized MySQL Server Docker images. Create…   808       					 [OK]
...
[root@sa ~]# # 可选项,通过收藏来过滤-f, --filter filter   Filter output based on conditions provided--format string   Pretty-print search using a Go template--limit int       Max number of search results (default 25)--no-trunc        Don't truncate output
[root@sa ~]# docker search mysql --filter=STARS=3000
NAME                DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mysql               MySQL is a widely used, open-source relation…   10876               [OK]                
mariadb             MariaDB Server is a high performing open sou…   4102                [OK]     
[root@sa ~]#

**docker pull ** 下载镜像

# 下载镜像 docker pull 镜像名[:tag]
[root@sa ~]# docker pull mysql
Using default tag: latest				# 如果没有指定tag,默认就是latest
latest: Pulling from library/mysql
69692152171a: Pull complete 			# 分层下载,docker image的核心--联合文件系统
1651b0be3df3: Pull complete 
951da7386bc8: Pull complete 
0f86c95aa242: Pull complete 
37ba2d8bd4fe: Pull complete 
6d278bb05e94: Pull complete 
497efbd93a3e: Pull complete 
f7fddf10c2c2: Pull complete 
16415d159dfb: Pull complete 
0e530ffc6b73: Pull complete 
b0a4a1a77178: Pull complete 
cd90f92aa9ef: Pull complete 
Digest: sha256:d50098d7fcb25b1fcb24e2d3247cae3fc55815d64fec640dc395840f8fa80969		# 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest		# 真实地址
[root@sa ~]# # 以下两个命令等价
docker pull mysql
docker pull docekr.io/library/mysql:latest

docker images 查看镜像

[root@sa ~]# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
mysql                   latest              c0cdc95609f1        3 days ago          556MB
hello-world             latest              d1165f221234        2 months ago        13.3kB
vue-docker-demo-image   latest              4835e3101950        8 months ago        135MB
[root@sa ~]# 

docker rmi 删除镜像

# docker rmi 容器id  -f  强制删除(运行中的)
# docker rmi 容器id 容器id 容器id  删除多个容器
[root@sa ~]# docker rmi d11
Untagged: hello-world:latest
Untagged: hello-world@sha256:5122f6204b6a3596e048758cabba3c46b1c937a46b5be6225b835d091b90e46c
Deleted: sha256:d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726
Deleted: sha256:f22b99068db93900abe17f7f5e09ec775c2826ecfe9db961fea68293744144bd
[root@sa ~]# # 批量删除
# -f 强制删除,-aq 仅显示所有的镜像id
[root@sa ~]# docker rmi -f $(docker images -aq)

容器命令

有了镜像才可以创建容器

以centOS镜像为例:

docker pull centos

新建容器并启动

docekr run [可选参数] image# 参数说明
--name="name"			# 容器名称 name01  name02,用来区分容器
-d 						# 后台方式运行
-it						# 使用交互方式运行,进入容器查看内容
-p						# 指定容器的端口-p ip:主机端口:容器端口  映射-p 主机端口:容器端口(常用)-p 容器端口-P(大写p)				# 随机指定端口# 启动并进入容器,你会发现,现在的用户名就是容器的id
[root@sa ~]# 
[root@sa ~]# docker run -it centos /bin/bash
[root@74457211455c /]# 
[root@74457211455c /]# 
# 退出就是exit
...

列出所有运行的容器

docker ps	# 列出正在运行的容器-a 		# 列出所有容器,包含已经停止的-n=? 	# 列出最近创建的容器,带数字-q		# 只列出容器的id# 列出所有容器,包含已经停止的
[root@sa ~]# docker ps -a
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS                    PORTS               NAMES
74457211455c        centos                  "/bin/bash"              2 minutes ago       Up 2 minutes                                  happy_wilson

退出容器

exit		# 直接停止容器并退出
Ctrl +p +q  # 容器不停止退出

删除容器

docker rm 						# 容器id-f 	# 强制删除正在运行的容器docker rm -f $(docker ps -aq)	# 删除所有的容器
docker ps -aq |xargs docker rm	# 也可以删除所有容器

启动容器

docker start	容器id		# 启动容器
docker restart	容器id		# 重启容器
docker stop		容器id		# 停止当前正在运行的容器
docker kill		容器id		# 轻质停止当前容器

其他常用命令

后台启动

# 命令 docker run -d 镜像名
[root@sa ~]# docker run -d centos
26e18764513a7ebf03f73dda143d5b1bb73054cbf74bae10d8f22ba16d4c4ea9
[root@sa ~]# 
# 会产生的问题:ps发现centos 直接停了
# 原因:docke容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止

查看日志

docker logs -tf --tail# 显示日志
-tf				# 显示日志 -t时间戳 -f Follow log output(不断输出日志)
--tail number	# 要显示的日志条数,后接数字

查看容器中的进程信息

# 命令 docker top 容器id
[root@sa ~]# docker top 8b
UID    PID        PPID    C   STIME        TTY       TIME        CMD
root   21913     21895    0     04:28     pts/0    00:00:00     /bin/bash
[root@sa ~]# 

查看镜像的元数据

# 命令 docker inspect 容器id[root@sa ~]# docker inspect 8b
[{"Id": "8bdbd34f37a64afa4e80eaafdaa517bd98a8ed1b3be178b2fb386865d4df7f05","Created": "2021-05-18T20:28:55.704722287Z","Path": "/bin/bash","Args": [],"State": {"Status": "running","Running": true,"Paused": false,"Restarting": false,"OOMKilled": false,"Dead": false,"Pid": 21913,"ExitCode": 0,"Error": "","StartedAt": "2021-05-18T20:28:56.270071675Z","FinishedAt": "0001-01-01T00:00:00Z"},"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55","ResolvConfPath": "/var/lib/docker/containers/8bdbd34f37a64afa4e80eaafdaa517bd98a8ed1b3be178b2fb386865d4df7f05/resolv.conf","HostnamePath": "/var/lib/docker/containers/8bdbd34f37a64afa4e80eaafdaa517bd98a8ed1b3be178b2fb386865d4df7f05/hostname","HostsPath": "/var/lib/docker/containers/8bdbd34f37a64afa4e80eaafdaa517bd98a8ed1b3be178b2fb386865d4df7f05/hosts","LogPath": "/var/lib/docker/containers/8bdbd34f37a64afa4e80eaafdaa517bd98a8ed1b3be178b2fb386865d4df7f05/8bdbd34f37a64afa4e80eaafdaa517bd98a8ed1b3be178b2fb386865d4df7f05-json.log","Name": "/interesting_black","RestartCount": 0,"Driver": "overlay2","Platform": "linux","MountLabel": "","ProcessLabel": "","AppArmorProfile": "","ExecIDs": null,"HostConfig": {"Binds": null,"ContainerIDFile": "","LogConfig": {"Type": "json-file","Config": {}},"NetworkMode": "default","PortBindings": {},"RestartPolicy": {"Name": "no","MaximumRetryCount": 0},"AutoRemove": false,"VolumeDriver": "","VolumesFrom": null,"CapAdd": null,"CapDrop": null,"Capabilities": null,"Dns": [],"DnsOptions": [],"DnsSearch": [],"ExtraHosts": null,"GroupAdd": null,"IpcMode": "private","Cgroup": "","Links": null,"OomScoreAdj": 0,"PidMode": "","Privileged": false,"PublishAllPorts": false,"ReadonlyRootfs": false,"SecurityOpt": null,"UTSMode": "","UsernsMode": "","ShmSize": 67108864,"Runtime": "runc","ConsoleSize": [0,0],"Isolation": "","CpuShares": 0,"Memory": 0,"NanoCpus": 0,"CgroupParent": "","BlkioWeight": 0,"BlkioWeightDevice": [],"BlkioDeviceReadBps": null,"BlkioDeviceWriteBps": null,"BlkioDeviceReadIOps": null,"BlkioDeviceWriteIOps": null,"CpuPeriod": 0,"CpuQuota": 0,"CpuRealtimePeriod": 0,"CpuRealtimeRuntime": 0,"CpusetCpus": "","CpusetMems": "","Devices": [],"DeviceCgroupRules": null,"DeviceRequests": null,"KernelMemory": 0,"KernelMemoryTCP": 0,"MemoryReservation": 0,"MemorySwap": 0,"MemorySwappiness": null,"OomKillDisable": false,"PidsLimit": null,"Ulimits": null,"CpuCount": 0,"CpuPercent": 0,"IOMaximumIOps": 0,"IOMaximumBandwidth": 0,"MaskedPaths": ["/proc/asound","/proc/acpi","/proc/kcore","/proc/keys","/proc/latency_stats","/proc/timer_list","/proc/timer_stats","/proc/sched_debug","/proc/scsi","/sys/firmware"],"ReadonlyPaths": ["/proc/bus","/proc/fs","/proc/irq","/proc/sys","/proc/sysrq-trigger"]},"GraphDriver": {"Data": {"LowerDir": "/var/lib/docker/overlay2/1664d1df131ceec26e30d5f1288e4a76104ba149a4e2ed91df49cbae1d5b5c95-init/diff:/var/lib/docker/overlay2/85c0301341e0be53f9854cc3148968bb232564ca6cac942efebc0b9328ec192c/diff","MergedDir": "/var/lib/docker/overlay2/1664d1df131ceec26e30d5f1288e4a76104ba149a4e2ed91df49cbae1d5b5c95/merged","UpperDir": "/var/lib/docker/overlay2/1664d1df131ceec26e30d5f1288e4a76104ba149a4e2ed91df49cbae1d5b5c95/diff","WorkDir": "/var/lib/docker/overlay2/1664d1df131ceec26e30d5f1288e4a76104ba149a4e2ed91df49cbae1d5b5c95/work"},"Name": "overlay2"},"Mounts": [],"Config": {"Hostname": "8bdbd34f37a6","Domainname": "","User": "","AttachStdin": true,"AttachStdout": true,"AttachStderr": true,"Tty": true,"OpenStdin": true,"StdinOnce": true,"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd": ["/bin/bash"],"Image": "centos","Volumes": null,"WorkingDir": "","Entrypoint": null,"OnBuild": null,"Labels": {"org.label-schema.build-date": "20201204","org.label-schema.license": "GPLv2","org.label-schema.name": "CentOS Base Image","org.label-schema.schema-version": "1.0","org.label-schema.vendor": "CentOS"}},"NetworkSettings": {"Bridge": "","SandboxID": "f90c37e119e8231aee5aed42652c64393959cd87f061092347b98b21a5764f8e","HairpinMode": false,"LinkLocalIPv6Address": "","LinkLocalIPv6PrefixLen": 0,"Ports": {},"SandboxKey": "/var/run/docker/netns/f90c37e119e8","SecondaryIPAddresses": null,"SecondaryIPv6Addresses": null,"EndpointID": "d3f5369c06fc9c93af1b5bfbc45617ee24b7900e88a33ac66793b80712912f88","Gateway": "172.17.0.1","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"IPAddress": "172.17.0.2","IPPrefixLen": 16,"IPv6Gateway": "","MacAddress": "02:42:ac:11:00:02","Networks": {"bridge": {"IPAMConfig": null,"Links": null,"Aliases": null,"NetworkID": "d29efb6707572fecd8ccaadfb2f011525f39fa0a9fb0a7732be8af61baf34003","EndpointID": "d3f5369c06fc9c93af1b5bfbc45617ee24b7900e88a33ac66793b80712912f88","Gateway": "172.17.0.1","IPAddress": "172.17.0.2","IPPrefixLen": 16,"IPv6Gateway": "","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"MacAddress": "02:42:ac:11:00:02","DriverOpts": null}}}}
]
[root@sa ~]# 

进入正在运行的容器

# 进入正在运行的容器# 方式一:
docker exec -it 容器id bashShell# 方式二:
docker attch 容器id# docker exec	进入容器后开启一个新的终端
# docker attch	进入容器正在执行的终端,不会开启新的进程

容器和主机之间的拷贝

# 从容器内拷贝文件到主机
docker cp 容器id:/路径 /主机路径  # 建议使用绝对路径# 进入容器
[root@sa ~]# docker exec -it f2 /bin/sh
sh-4.4# 
sh-4.4# touch 123.txt
sh-4.4# ls
123.txt  ks-script-esd4my7v  ks-script-eusq_sc5
sh-4.4# exit
[root@sa ~]# # 将容器内的文件拷贝至主机
[root@sa ~]# docker cp  f2:/tmp/123.txt ./
[root@sa ~]# 
[root@sa ~]# docker ps 					 # 说明只要容器还在,启不启动数据都在
CONTAINER ID   IMAGE    COMMAND    CREATED      STATUS      PORTS     NAMES
[root@sa ~]# 
[root@sa ~]# docker ps -a
CONTAINER ID  IMAGE COMMAND   				 CREATED  	STATUS  PORTS   NAMES
f24dcc07e0e5 centos "/bin/sh -c 'while t…"   15 ago     Exited      vigilant_hypatia
[root@sa ~]# 

Docker 镜像讲解

镜像是什么

镜像是一种轻量级、可执行的独立软件包(类似于免安装),用来打包软件运行环境和基于运行环境开发的软件,他包含运行某个软件所需的所有内容,包括代码、运行是所需的库、环境变量及配置文件等等。

Docker镜像加载原理

UnionFS(联合文件系统)

UnionFS:Union文件系统是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂在到同一个虚拟文件系统(unite several directories into a single virtual filesystem)下。Union文件系统时Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:以此同时加载多个文件系统,单对外表现,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

Docker镜像加载原理

Docker的镜像实际上有一层一层的文件系统组成,这种层级的文件系统叫联合文件系统

Bootfs(boot file system)主要包含bootloader 和kernel,BootLoader主要是引导加载kerner,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们经典的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs(root file system),在bootfs之上。包含的就是典型Linux系统中的/dev, /proc, /etc等标准目录文件。rootfs就是各种不同的操作系统发行版,例如:Ubuntu、CentOS等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JUvjsVsI-1691285233025)(Docker-入门.assets/image-20210605100943326.png)]

平时安装的虚拟机CentOS都是好几个G,但是Docker这里的才几百兆,为什么?

因为Docker镜像一般都是非常精简的,不要忘了,他用的宿主机的内核,自己只需要提供rootfs就可以了。所以镜像只需提供最基本的命令、工具和程序即可。由此,对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以共用bootfs。

分层理解

分层的镜像

​ 在下载镜像时,可以注意到下载日志输出的是一层层下载的

分层的好处:

最大的好处莫过于资源共享!例如,有多个镜像都是相同的Base镜像构建而来,那么宿主机只需要在磁盘上保留一份Base镜像,同时,内存中也只需要加载一份Base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

查看镜像分层的方式可以通过 docker inspect 命令查看

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WIBMsGcc-1691285233026)(Docker-入门.assets/image-20210605150403314.png)]

理解:

所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上创建一个新的镜像层。

例如:基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层,如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层,如果继续添加,则依次往上新建。

这里其实忽略了一个重要的概念,那就是层,怎样的添加才能构成所谓的 “层"

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X08F9UvE-1691285233026)(Docker-入门.assets/image-20210605164534407.png)]

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!这一层就是我们通常说的容器层,容器之下的都叫镜像层。

分层理解2(理论更清晰)

比较好的理解:

Docker的镜像分层

接下来,我们来看看 Docker的镜像分层机制。

Docker镜像是分层构建的,Dockerfile 中每条指令都会新建一层。例如以下 Dockerfile:

FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py

以上四条指令会创建四层,分别对应基础镜像、复制文件、编译文件以及入口文件,每层只记录本层所做的更改,而这些层都是只读层。当你启动一个容器,Docker 会在最顶部添加读写层,你在容器内做的所有更改,如写日志、修改、删除文件等,都保存到了读写层内,一般称该层为容器层,如下图所示:

> [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9brxJaJt-1691285233027)(Docker-入门.assets/v2-4b2318880b12c3220fa59a9d9992dc90_720w.jpg)]docker layer

事实上,容器(container)和镜像(image)的最主要区别就是容器加上了顶层的读写层。所有对容器的修改都发生在此层,镜像并不会被修改,也即前面说的 COW(copy-on-write)技术。容器需要读取某个文件时,直接从底部只读层去读即可,而如果需要修改某文件,则将该文件拷贝到顶部读写层进行修改,只读层保持不变。

每个容器都有自己的读写层,因此多个容器可以使用同一个镜像,另外容器被删除时,其对应的读写层也会被删除(如果你希望多个容器共享或者持久化数据,可以使用 Docker volume)。

最后,执行命令 docker ps -s,可以看到最后有两列 size 和 virtual size。其中 size就是容器读写层占用的磁盘空间,而 virtual size 就是读写层加上对应只读层所占用的磁盘空间。如果两个容器是从同一个镜像创建,那么只读层就是 100%共享,即使不是从同一镜像创建,其镜像仍然可能共享部分只读层(如一个镜像是基于另一个创建)。因此,docker 实际占用的磁盘空间远远小于 virtual size 的总和。

> [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w4oP9qIz-1691285233028)(Docker-入门.assets/v2-b71caf2dbcc2fa95e8545cb7c97998ac_720w.png)]

以上就是 Docker 镜像分层的主要内容,至于这些层的交互、管理就需要存储驱动程序,也即联合文件系统(UnionFS)。Docker 可使用多种驱动,如目前已经合并入 Linux 内核、官方推荐的overlay, 曾在 Ubuntu、Debian等发行版中得到广泛使用的 AUFS,以及devicemapper、zfs等等,需要根据 Docker以及宿主机系统的版本,进行合适的选择。

commit 镜像

docker commit 提交容器成为一个新的副本(镜像)# 命令和git类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]

容器数据卷

什么是容器数据卷

数据如果只保存在容器中,那么容器删除,则数据丢失。

有没有什么方式可以将容器中的数据同步或者说映射至本地/宿主机的长期保存所想要的数据。

容器之间也可以共享数据。

于是,有了卷技术。简单理解就是目录的挂载,将容器内的目录挂载到宿主机上,并且容器间也是可以数据共享的。

使用数据卷

方式一: 直接使用命令挂载 -v

# docker run -it -v 宿主机目录:容器内目录,宿主机目录可以不存在,会自动创建,最好使用绝对路径-it # 交互式启动-v  # 卷volume  挂载[root@sa ~]# docker run  -it -v ~/mont_volume:/home centos /bin/bash# 启动之后可根据 docker inspect 容器id 查看挂载结果
[root@sa ~]# docker inspect 0601e8ee0ec6

# 挂载以后基本上就理解成容器内核宿主机共用这个目录。
# 测试可发现,当容器停止后,在宿主机向mont_volume目录写入文件,然后重新启动容器,容器home目录可直接看到写入文件
# 即使,容器被删除,然后重新起一个容器,挂载宿主机目录还是mont_volume,那么,新容器也是可以直接看到写入文件。这也说明了,容器删除不会影响挂载的目录
# 总结,可用该方法将配置类的文件挂载出来,当我们需要修改容器配置时,无需进入容器即可修改

安装MySQL

# 1、获取镜像
[root@sa ~]# docker pull mysql# 2、安装mysql一定要注意配置密码
# Starting a MySQL instance is simple:
#
[root@sa ~] # docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# ... where some-mysql is the name you want to assign to your container, my-secret-pw # is the password to be set for the MySQL root user and tag is the tag specifying the # MySQL version you want. See the list above for relevant tags.
# from  https://hub.docker.com/_/mysql# 3、启动镜像
[root@sa ~]# docker run -d -p 3310:3306 -v /home/myspl/conf:/etc/mysql/conf.d -v /home/mysql/date:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql ac4ca43eb68bc7bfadbd6da4cef7fa81f83d79eb10b9639cf8b7cbc016e50c9a-d 后台运行-p 端口映射-v 卷挂载-e 环境配置--name 容器名字(容器名字mysql01,而mysql是镜像名)
[root@sa ~]# 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UjMETaWf-1691285233028)(Docker-入门.assets/image-20210626114415095.png)]

具名和匿名挂载

# 匿名挂载
-v 容器内目录
[root@sa ~]# docker run -d -P --name nginx -v /etc/nginx nginx# 查看所有的 volume 的情况
[root@sa ~]# docker volume ls
DRIVER              VOLUME NAME
local               ed11f4eedfbbdff94704282111ffe0d6a8bad21171f4c6af0be255f8a649ab27
[root@sa ~]## VOLIME NAME 实际上是一些具体的目录# 现在为了对比,起一个具名的挂在容器
[root@sa ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
42ca9c1cd1447c2d6f79caa9c9197cd7083a597ce01abec60c0109018cc69b06
[root@sa ~]# 
[root@sa ~]# docker volume ls
DRIVER              VOLUME NAME
local               ed11f4eedfbbdff94704282111ffe0d6a8bad21171f4c6af0be255f8a649ab27
local               juming-nginx# 通过 -v 卷名:容器内路径
# 查看这个卷
[root@sa ~]# docker volume inspect ed11f4eedfbbdff94704282111ffe0d6a8bad21171f4c6af0be255f8a649ab27
[{"CreatedAt": "2021-05-29T23:21:35+08:00","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/ed11f4eedfbbdff94704282111ffe0d6a8bad21171f4c6af0be255f8a649ab27/_data","Name": "ed11f4eedfbbdff94704282111ffe0d6a8bad21171f4c6af0be255f8a649ab27","Options": null,"Scope": "local"}
]
[root@sa ~]#  
[root@sa ~]# docker volume inspect juming-nginx
[{"CreatedAt": "2021-06-26T21:55:36+08:00","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data","Name": "juming-nginx","Options": null,"Scope": "local"}
]
[root@sa ~]# 
[root@sa juming-nginx]# cd _data/
[root@sa _data]# ls
conf.d  fastcgi_params  koi-utf  koi-win  mime.types  modules  nginx.conf  scgi_params  uwsgi_params  win-utf

总结:

所有的Docker容器的卷,在没有指定挂在目录的情况下都在 /var/lib/docker/volumes/xxxxx/_data

我们通过具名挂载可以方便的找到我们的一个卷,大多数情况下使用 具名挂载

# 如何确定是具名还是匿名挂载
-v	容器内路径				# 匿名挂载
-v  卷名:容器内路径		  # 具名挂载
-v  宿主机路径:容器内路径		# 指定路径挂载

拓展:(下面所说的权限都是针对容器而言,也就是如果在容器上是只读的,但,在宿主机上是可以进行写操作的)

# 通过 -v 容器内路径  :ro  :rw 来改变读写权限
# ro 只读
# rw 可读可写# 凡是设置了这个容器权限,容器对挂载的内容的权限就被限定了
[root@sa ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
[root@sa ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx# 上面所说的权限都是针对容器而言,也就是如果在容器上是只读的,但是可以在宿主机上进行写操作(当然,宿主机本身对该路径可写)

数据卷之DockerFile

Dockerfile是用来构建docker镜像的构建文件。命令脚本。

通过这个脚本可以生成镜像,镜像是一层一层的,脚本时一个个的命令,每个命令就是一层

# 创建一个dockerfile文件,名字可以任意,最好还是dockerfile
# 一般格式:指令(全大写)  参数
# 文件内容如下:
[root@sa Dockerfile-test]# cat dockerfile1  # 以下的每个指令就是镜像的一层
FROM centos							# 将centos作为基础镜像				VOLUME ["volume01", "volume02"]		# 挂载数据卷CMD echo "----is wax ---- first --- Dockerfile----"
CMD /bin/bash[root@sa Dockerfile-test]# # 查看镜像生成过程
[root@sa Dockerfile-test]# docker build -f dockerfile1  -t wax-centos:0.1 .-f 指定dockerfile文件-t tag 目标文件一定不要忘了生成的文件存放路径—— 末尾的那个 .(当前目录)Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos---> 300e315adb2f
Step 2/4 : VOLUME ["volume01", "volume02"]---> Running in 669152823e0d
Removing intermediate container 669152823e0d---> 5e192b1bef6d
Step 3/4 : CMD echo "----is wax ---- first --- Dockerfile----"---> Running in b65e28cc25db
Removing intermediate container b65e28cc25db---> cf5be1a83272
Step 4/4 : CMD /bin/bash---> Running in 8cb48405b199
Removing intermediate container 8cb48405b199---> 09081e56f27e
Successfully built 09081e56f27e
Successfully tagged wax-centos:0.1
[root@sa Dockerfile-test]# # 查看镜像
[root@sa Dockerfile-test]# docker images
REPOSITORY      TAG      IMAGE ID            CREATED             SIZE
wax-centos     0.1       09081e56f27e        5 minutes ago       209MB
redis          latest    fad0ee7e917a        3 weeks ago         105MB# 启动镜像
[root@sa Dockerfile-test]# docker run  -it 09081e56f27e /bin/bash
[root@93d0f80f1c21 /]# 
[root@93d0f80f1c21 /]#   可以看到已经成功进入
[root@93d0f80f1c21 /]# ls -l
total 0
...... # 篇幅问题省略
drwxr-xr-x.   2 root root   6 Nov  3  2020 srv
dr-xr-xr-x.  13 root root   0 May 15 10:53 sys
drwxrwxrwt.   7 root root 145 Dec  4  2020 tmp
drwxr-xr-x.  12 root root 144 Dec  4  2020 usr
drwxr-xr-x.  20 root root 262 Dec  4  2020 var
drwxr-xr-x.   2 root root   6 Jun 28 11:13 volume01    # 两个volume** 目录就是构建镜像时,
drwxr-xr-x.   2 root root   6 Jun 28 11:13 volume02	   # 自动挂载的数据卷目录# 可以看到两个volume实际上是匿名挂载,那么,查看其挂载的具体位置
[root@sa ~]# docker inspect 93d0f80f1c21
....."Mounts": [{"Type": "volume","Name": "c716f0d4f9*****bddf","Source": "/var/lib/docker/volumes/c716f0d4f9*****bddf/_data","Destination": "volume01","Driver": "local","Mode": "","RW": true,"Propagation": ""},{"Type": "volume","Name": "14e0ac65b55b5******d156e","Source": "/var/lib/docker/volumes/14e0ac65b55b5*****d156e/_data","Destination": "volume02","Driver": "local","Mode": "","RW": true,"Propagation": ""}],
......

实际上,这种方式为十分常用,因为我们的目的大多需要自己构建镜像。

假如,构建镜像没有自动挂载卷,那就要自己手动挂载了, -v 卷名:容器内路径 (手动当然 具名挂载 啦)

数据卷容器

作用:实现多个容器间的数据同步,共享。

命令: - -volumes - from container_name

一般把被挂载的容器也就是父容器 称之为数据卷容器

# 启动数据卷容器
[root@sa ~]# docker run  -it --name docker-father wax-centos:0.1 /bin/bash# 启动要和父容器共享的容器(为了简单,使用同一个镜像)
[root@sa ~]# docker run  -it --name docker-child01  --volumes-from docker-father wax-centos:0.1 /bin/bash# 在启动2个容器
[root@sa ~]# docker run  -it --name docker-child02  --volumes-from docker-father wax-centos:0.1[root@sa ~]# docker run  -it --name docker-child03  --volumes-from docker-child02 centos# 查看父容器 (123. 456是03创建的)
[root@8eb24755d5fd volume01]# ls
123.txt  456.txt  child01-create  child02-create# 查看03容器
[root@sa ~]# docker attach docker-child03
[root@f2eb5b35ae88 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume01  volume02
[root@f2eb5b35ae88 /]# 

直接给结论:

当我们删除任何一个容器时,其他容器的挂载目录不受影响。

可以看到,child03的镜像是基础的centos镜像,挂载到02上的,其自身并没有挂载volume01 、volume02,但是,使用了

–volumes-from 指令之后依然会挂载这两个目录。

另外,虽然03容器挂载的是02容器,但是停止并删除了02容器后,再在03中的volume01目录下创建文件在父容器、01中依然可以看到。另外,再把父容器删除,03中volume*目录下创建的文件,在01中还是可以看到。所以应该不是简单的拷贝。(原理我也不知奥)

另外,通过inspect可以看到,4个容器的挂载目录都是同一个地方,是不是突然明白了?也就是,即使,你把所有容器都删了,数据应该是还在的,都在宿主机上,需要注意的是,删除容器不影响数据(文件),但是在容器内删除文件是同步的,包括会同步到宿主机。其实这个比较好理解。

再另外,在宿主机上,删除宿主机上的被挂载目录,比如 /var/lib/docker/volumes/***/_data 的_data目录,那么已经启动的容器将无法在其挂载目录下进行操作——无法新建文件。就算手动将_data目录再创建出来,依然不能新建文件。需要停止后重启容器才可以新建。

Dockerfile

Dockerfile 介绍

Dockerfile 是用来构建docker镜像的文件,就是参数脚本!

构建步骤:

  1. 编写一个dockefile文件
  2. docker build 构建成一个镜像
  3. docker run 就可以运行镜像
  4. docker push 可以发布镜像

Dockerfile 构建过程

  1. 每个保留关键字(指令)都是大写
  2. 从上至下依次执行
  3. 使用 ‘#’ 注释
  4. 每一个指令都会创建提交一层新的镜像层

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iS8pNngJ-1691285233029)(Docker-入门.assets/image-20210724151251695.png)]

Dockerfile是面向开发的!

Dockerfile:构建文件,定义了所有步骤,源代码

Dockerimages:通过Dockerfile构建的镜像,做种发布和运行

Docker容器:容器就是镜像运行起来提供的服务

Dockerfile的指令

FROM 					# 基础镜像,一切从这里构建
MAINTAINER				# 镜像的作者、维护者
RUN						# 镜像构建的时候需要运行的命令
ADD						# 步骤:Ubuntu镜像,可以给他加vim配置文件啥的
WORKDIR					# 镜像的工作目录
VOLUME					# 挂载的目录
EXPOSE					# 保留端口配置
CMD						# 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT				# 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD					# 当构建一个被继承 Dockerfile,这个时候就会运行 ONBUILD 的指令
COPY					# 类似ADD,将文件拷贝至镜像中
ENV						# 构建的时候设置环境变量

实例

以ubuntu基础镜像为例

# 先通过 docker pull ubuntu  下载一个官方的最新的ubuntu基础镜像
#这里可以先尝试一下,刚下载的镜像是不支持vim 的,等下通过dockerFile制作一个带有vim的镜像#下面开始写dockerFile
root@wu:~/my_dockerfile# cat Dockerfile 
FROM ubuntuMAINTAINER wax<1123@qq.com>ENV MYPATH /usr/local
WORKDIR $MYPATHRUN apt-get update
RUN apt-get install -y vim
RUN apt-get install -y net-toolsEXPOSE 80CMD echo $MYPATHCMD echo "------end!-------"
CMD /bin/bash

这里需要注意一点,如果是在centos系统上安装的docker,那么大概率执行以上dockerFile将会是失败的。据说是,容器使用的资源库的源是来自宿主机的,也就是centos上不能执行atp-get,而是 yum install命令

接着,我们就来构建自己的镜像(删除了安装vim过程中的打印)

# dockerFile的构建命令 可以通过 docker build --help查看# -f 指定dockerFile文件  -t 指定目标镜像root@wu:~/my_dockerfile# docker build -f Dockerfile -t my_ubuntu:1.0 ./
Sending build context to Docker daemon  2.048kB
Step 1/11 : FROM ubuntu---> ff0fea8310f3
Step 2/11 : MAINTAINER wax<1123@qq.com>---> Using cache---> 350bceb3effd
Step 3/11 : ENV MYPATH /usr/local---> Using cache---> 792e5469839a
Step 4/11 : WORKDIR $MYPATH---> Using cache---> 1b2933c2de8f
Step 5/11 : RUN apt-get update---> Using cache---> cee70ef91575
Step 6/11 : RUN apt-get  install -y vim---> Using cache---> 628163e35047
Step 7/11 : RUN apt-get  install -y net-tools---> Using cache---> 66ceeb0d5a36
Step 8/11 : EXPOSE 80---> Using cache---> 1a3c9ff3333b
Step 9/11 : CMD echo $MYPATH---> Using cache---> b9007091be62
Step 10/11 : CMD echo "------end!--------"---> Using cache---> 1c85c73c79fe
Step 11/11 : CMD /bin/bash---> Using cache---> 66c8af1a3f90
Successfully built 66c8af1a3f90
Successfully tagged my_ubuntu:1.0
root@wu:~/my_dockerfile# 

完了之后就可以运行my_ubuntu镜像,并且可以直接执行vim 以及 ifconfg等命令。这里就不做演示了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/27179.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【肺炎分类数据集】数据量非常充足的新冠肺炎分类数据共享

一、肺炎数据集介绍&#x1f349;&#xff1a; 1.1 格式&#x1f388; 按照标准的格式分为了①训练集train&#xff08;134138575198张&#xff09;&#xff0c;②验证集val&#xff08;8816张&#xff09;&#xff0c;③测试集test&#xff08;234390624张&#xff09;&#…

C++学习笔记总结练习:正则表达式

正则表达式 目录 regex正则表达式的定义regex_match/search/replace正则表达式的三个操作smatch、sregex_iterator正则表达式的结果对象以及与其配套的迭代器。 参考文献 正则表达式总结 1 正则表达式基础 不考虑子表达式的内容 头文件 #include<regex>库组件 库组件作…

React Dva项目 简单引入models中的所有JS文件

我们前面接触的 Dva项目 models目录下的文件还要一个一个引入 其实体验并不是很好 而且如果项目很大那就比较麻烦了 我们可以在 models 下创建一个 index.js 文件 编写代码如下 const context require.context("./", false, /\.js$/); export default context.key…

冠达管理:A股三大指数震荡整理 机构看好反弹趋势延续

周一&#xff0c;沪深两市呈弱势震动格式&#xff0c;创业板指领跌。到收盘&#xff0c;上证综指跌0.59%&#xff0c;报3268.83点&#xff1b;深证成指跌0.83%&#xff0c;报11145.03点&#xff1b;创业板指跌1%&#xff0c;报2240.77点。 资金面上&#xff0c;沪深两市昨日合计…

梳理日常开发涉及的负载均衡

负载均衡是当前分布式微服务时代最能提及的词之一&#xff0c;出于对分层、解耦、弱依赖、可配置、可靠性等概念的解读&#xff0c;一对一的模式变得不再可信赖&#xff0c;千变万化的网络环境中&#xff0c;冗余和备份显得格外重要&#xff0c;稍大型的系统就会存在大量微服务…

docker小白第一天

docker小白第一天 docker是什么docker理念容器与虚拟机比较docker能干什么docker官网介绍docker的基本组成docker平台架构 docker是什么 系统平滑移植&#xff0c;容器虚拟化技术。即源代码配置环境版本&#xff0c;打个包形成一个镜像文件&#xff0c;即软件带环境一起安装&a…

【果树农药喷洒机器人】Part1:研究现状分析以及技术路线介绍

本专栏介绍&#xff1a;付费专栏&#xff0c;持续更新机器人实战项目&#xff0c;欢迎各位订阅关注。 关注我&#xff0c;带你了解更多关于机器人、嵌入式、人工智能等方面的优质文章&#xff01; 文章目录 一、项目背景二、国内外研究现状2.1 国内研究现状2.2 国外研究现状 三…

RISC-V架构的演变

随着苹果基于ARM的硅和新的RISC-V CPU的推出&#xff0c;对于CPU开发来说&#xff0c;这是一个令人兴奋的时刻&#xff0c;尽管开发人员的旅程目前对后者来说有点坎坷。 我最喜欢的理论是&#xff0c;没有发生是孤独的&#xff0c;而只是重复了以前发生过的事情&#xff0c;也…

Linux 远程登录

Linux 远程登录 Linux 一般作为服务器使用&#xff0c;而服务器一般放在机房&#xff0c;你不可能在机房操作你的 Linux 服务器。 这时我们就需要远程登录到Linux服务器来管理维护系统。 Linux 系统中是通过 ssh 服务实现的远程登录功能&#xff0c;默认 ssh 服务端口号为 2…

C++QT教程1——QT概述(下载与安装)

文章目录 1 Qt概述1.1 什么是Qt1.2 Qt的发展史1.3 Qt版本1.4 Qt的下载与安装下载地址&#xff1a;其实我是有点懵逼的&#xff0c;因为还有个qtcreator&#xff0c;我差点不知道下哪个。。。&#xff08;qt框架比qtcreator功能更多更强大&#xff09; 安装 1.5 Qt的优点1.6 QT成…

SpringBoot + Docker 实现一次构建到处运行~

一、容器化部署的好处 图片 Docker 作为一种新兴的虚拟化方式&#xff0c;它可以更高效的利用系统资源&#xff0c;不需要进行硬件虚拟以及运行完整操作系统等额外开销。 传统的虚拟机技术启动应用服务往往需要数分钟&#xff0c;而 Docker 容器应用&#xff0c;由于直接运行…

[数据分析大全]基于Python的数据分析大全——Numpy基础

目录 一、前言二、NumpyNumpy数组 二、创建数组初始化占位符 三、输入、输出3.1 保存与载入文本文件3.2 保存与载入磁盘上的文件 四、数据类型五、数组信息六、调用帮助七、数组计算7.1 算数运算7.2 比较7.3 聚集函数 八、数组复制九、数组排序十、子集、切片、索引相关实现10.…

深入大B行业,什么是最有力的敲门砖?

引言&#xff1a;2023上半年&#xff0c; 能扛过外部环境各种变化&#xff0c; 这样的科技公司就很不容易了。 【全球云观察 &#xff5c; 热点关注】在当前后疫情时代下&#xff0c;全球经济增长处于的低增长期&#xff0c;这对所有科技企业的发展带来了直接影响。 有业内人…

win10 2022unity设置中文

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言解决方法 前言 在Edit->preferences里找不到language选项。 解决方法 【1】打开下面地址 注意 :把{version}换成你当前安装的版本&#xff0c;比如说如果…

SpringBoot第33讲:SpringBoot集成ShardingJDBC - 基于JPA的读写分离

SpringBoot第33讲&#xff1a;SpringBoot集成ShardingJDBC - 基于JPA的读写分离 本文是SpringBoot第33讲&#xff0c;主要介绍分表分库&#xff0c;以及SpringBoot集成基于 ShardingJDBC 的读写分离实践 文章目录 SpringBoot第33讲&#xff1a;SpringBoot集成ShardingJDBC - 基…

天津最新python培训班就业形势 python能就业吗?

小编认为Python是一门非常适合学习的编程语言&#xff0c;无论性别如何。它易于学习、功能强大&#xff0c;并且在各个领域都有广泛的应用&#xff0c;因此&#xff0c;性别不应该成为学习Python的障碍&#xff0c;那么学习Python是否就能找到满意的工作呢&#xff1f; 这是一…

吃瓜教程-Task05

目录 支持向量机 间隔与支持向量 SVM基本型 对偶问题 kkt条件 例子 对偶问题 例子 对偶问题原理解释 软间隔与正则化 替代损失函数 支持向量回归 例子 支持向量机 间隔与支持向量 在样本空间中&#xff0c;划分超平面可通过如下线性方程来描述: 样本空间中任意点x到…

数据结构【哈夫曼树】

哈夫曼树 哈夫曼树的概念哈夫曼树的构造构造算法的实现哈夫曼树应用哈夫曼编码哈夫曼编码的算法实现 哈夫曼树的概念 最优二叉树也称哈夫曼 (Huffman) 树&#xff0c;是指对于一组带有确定权值的叶子结点&#xff0c;构造的具有最小带权路径长度的二叉树。权值是指一个与特定结…

[原创]从强化学习的本质推导到PPO

前言 这篇博客很久之前就想做了&#xff0c;一直在拖是因为觉得自己对知识点理解还没有足够的透彻。但是每当去复盘基本概念的时候又很难理清逻辑&#xff0c;所以觉得即便现在半吊子水平&#xff0c;但是也想通过博客记录一下自己肤浅的学习心得&#xff0c;权当是为自己巩固…