当前位置: 首页 > news >正文

【Docker】基础篇

文章目录

  • Docker为什么出现
  • 容器和虚拟机
    • 关于虚拟机
    • 关于Docker
    • 二者区别:
  • Docker的基本组成
    • 相关概念-镜像,容器,仓库
    • 安装Docker
    • 卸载docker
    • 阿里云镜像加速
    • docker run的原理
    • **为什么容器比虚拟机快**
    • Docker的常用命令
      • 1.帮助命令
      • 2.镜像相关命令
      • 3.容器命令
        • 新建容器并启动
        • 列出所有运行的容器
        • 退出容器
        • 删除容器
        • 启动和停止容器
      • 4.常用其他命令
        • 后台启动命令(run -d选项)
        • 查看日志
        • 查看容器内部的进程信息
        • 查看镜像的元数据
        • 进入当前正在运行的容器
        • 从容器内的内容拷贝到主机上
    • **命令小结:**
    • 案例一:Docker安装Nginx
    • 案例二:Docker安装tomcat
      • 坑点:解决webapps目录为空
    • 案例三:部署elasticsearch+kibana
  • Portainer 可视化面板安装
  • 镜像原理之联合文件系统
    • **镜像是什么**
    • **如何得到镜像**
    • **Docker镜像加载原理**
    • 分层理解
      • 查看镜像分层命令
    • 实例理解分层
    • 案例:做一个镜像
      • 提交容器成为新镜像的命令

Docker为什么出现

一款产品从开发到上线,至少与两套环境,包括应用环境,应用配置,而环境配置是十分的麻烦,每一个机器都要部署一样的环境,费事费力

问题:发布一个项目,该项目能不能带上环境安装打包一起发布

Docker给以上的问题,提出了解决方案(Docker的思想就来自于集装箱
image-20231219230513884

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

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

容器和虚拟机

关于虚拟机

在容器技术出来之前,都是使用虚拟机技术,但是虚拟机和docker容器都是一种虚拟化技术

  • 虚拟机:在window中装一个VMware,通过这个软件我们可以虚拟出来一台或者多台电脑,比较笨重

虚拟机技术:

image-20231219230646116

虚拟机技术缺点:资源占用多 冗余步骤多 启动很慢

关于Docker

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

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

  • docker相关文档:https://docs.docker.com/

  • docker仓库:https://hub.docker.com/

容器化技术

容器化技术不是模拟一个完整的操作系统

image-20231219230701673

二者区别:

1.虚拟化级别不同

  • 虚拟机是基于硬件层面的虚拟化技术,它通过在物理服务器上创建虚拟硬件层来模拟完整的操作系统和硬件环境,传统虚拟机:虚拟出一套硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
  • 容器是在操作系统层面进行虚拟化,利用操作系统的隔离机制来创建独立的运行环境,容器内的应用直接运行在宿主机的内核当中容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了

2.资源利用效率

  • 由于虚拟机需要模拟完整的操作系统和硬件环境,因此每个虚拟机都需要独立的操作系统和额外的系统资源。这使得虚拟机在资源利用方面相对较低
  • 容器共享宿主机的操作系统,容器之间共享内核,因此容器可以更高效地利用系统资源,每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响

3.启动时间

  • 虚拟机启动需要较长的时间,因为它需要启动完整的操作系统
  • 容器启动通常更快,因为它们共享宿主机的操作系统和内核

4.隔离性

  • 虚拟机提供了更强的隔离性,因为每个虚拟机都有自己独立的操作系统和硬件模拟
  • 容器在隔离性方面相对较弱,因为它们共享操作系统和内核,容器之间的隔离依赖于容器技术本身提供的机制

5.迁移和扩展性

  • 虚拟机可以在不同的物理服务器之间迁移,但迁移过程相对较慢和复杂
  • 容器可以更快速地迁移和扩展,因为它们是轻量级的,且依赖于宿主机的操作系统

docker对于DevOps(开发、运维)的用途

1.应用更快速的交付和部署

  • 传统做法:一对帮助文档,安装程序。

  • Docker做法:打包镜像发布测试一键运行。

2.更便捷的升级和扩缩容:使用了 Docker之后,我们部署应用就和搭积木一样,项目打包为一个镜像,然后扩展服务器A,服务器B

3.更简单的系统运维:在容器化之后,我们的开发,测试环境都是高度一致的

4.更高效的计算资源利用Docker是内核级别的虚拟化,可以在物理机上可以运行很多的容器实例!服务器的性能可以被压榨到极致


Docker的基本组成

image-20231219230728034

相关概念-镜像,容器,仓库

**镜像(image):**docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,通过运行tomcat镜像=>得到tomcat容器(提供服务器),通过这个镜像可以创建多个容器(最终服务或者项目就是在容器中运行的)

**容器(container):**Docker利用容器技术,独立运行一个或者一组应用,容器是通过镜像来创建的,可以把容器理解为就是一个简易的 Linux系统

**仓库(repository):**仓库就是存放镜像的地方,仓库分为公有仓库和私有仓库。(很类似git),官方Docker Hub默认是国外的,阿里云等平台都有容器服务(需要配置镜像加速)

安装Docker

环境准备

1.Linux要求内核3.0以上 2.CentOS 7

环境查看

[root@Mango ~]# uname -r
3.10.0-514.26.2.el7.x86_64	# 要求3.0以上
[root@Mango ~]# 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.卸载旧版本
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
#上述方法默认是从国外的,不推荐#推荐使用国内的(使用阿里云镜像)
yum-config-manager \--add-repo \https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo#更新yum软件包索引
yum makecache fast#4.安装docker相关的 docker-ce是社区版,而docker-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.查看已经下载的镜像(从这里可以查看已有镜像的id)
[root@Mango ~]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
hello-world           latest              bf756fb1ae65        4 months ago      13.3kB

卸载docker

#1. 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io#2. 删除资源
rm -rf /var/lib/docker# /var/lib/docker 是docker的默认工作路径!

阿里云镜像加速

步骤1:登录阿里云找到容器服务

image-20231219230741147

步骤2:找到镜像加速器

image-20231219230753884

步骤3:配置使用

#1.创建一个目录
sudo mkdir -p /etc/docker#2.编写配置文件
sudo tee /etc/docker/daemon.json <<-'EOF'
{"registry-mirrors": ["https://t2wwyxhb.mirror.aliyuncs.com"]
}
EOF#3.重启服务
sudo systemctl daemon-reload
sudo systemctl restart docker

docker run的原理

底层原理

Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上,通过Socket和客户端进行通信,当Docker-Server接收到Docker-Client的指令,就会执行这个命令

image-20231219230802711

docker run 流程图

image-20231219230811835

例子:docker run hello

image-20231219230915028

1)检查本地是否存在 hello 镜像: Docker 首先会检查本地主机上是否存在名为 “hello” 的镜像,如果本地不存在该镜像,Docker 将会去远程仓库下载该镜像。

2)创建容器: 一旦 Docker 获得了 hello 镜像,它会在本地主机上创建一个容器。这个容器是hello镜像的一个实例,包含了运行 hello 应用程序所需的文件系统、代码和依赖项 (该容器是一个隔离的运行环境,与主机和其他容器隔离开来)

3)启动容器: 一旦容器创建成功,Docker 会启动它**,启动容器的过程包括分配资源(如 CPU、内存等)以及配置网络和存储等相关设置**

4)运行 hello 应用程序: 一旦容器启动,Docker 将在容器内部执行 hello 应用程序,这可能涉及到在容器中启动一个进程、执行相关指令或者运行脚本


为什么容器比虚拟机快

image-20231217213901503

一个很重要的原因就是:docker有着比虚拟机更少的抽象层

  • 由于docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源,因此在CPU、内存利用率上docker将会在效率上有明显优势
  • docker利用的是宿主机的内核,而不需要像虚拟机一样,需要虚拟化一个操作系统:Guest OS
    • GuestOS: VM(虚拟机)里的的系统(OS) HostOS:物理机里的系统(OS)

当新建一个虚拟机时,虚拟机软件需要虚拟化一个操作系统,:GuestOS,返个虚拟化新建过程是分钟级别的,而docker由于直接利用宿主机的操作系统,则省略了这个复杂的过程,因此新建一个docker容器只需要几秒钟(docker不需要和虚拟机一样重新加载一个操作系统内核)

Docker的常用命令

1.帮助命令

docker帮助文档的地址:https://docs.docker.com/engine/reference/commandline/build/

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

2.镜像相关命令

docker images #查看所有本地主机上的镜像 可以使用docker image ls代替
docker search 镜像名 #搜索镜像
docker pull 镜像名 #下载镜像 =>完整指令:docker image pull 镜像名
docker rmi 镜像名 #删除镜像 =>完整指令:  docker image rm 镜像名    (i代表image)

docker images查看所有本地的主机上的镜像

image-20231219230839609

[root@Mango ~]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED           SIZE
hello-world           latest              bf756fb1ae65        4 months ago     13.3kB
mysql                 5.7                 b84d68d0a7db        6 days ago       448MB# 解释 
#REPOSITORY			# 镜像的仓库源
#TAG				# 镜像的标签(版本)		---lastest 表示最新版本
#IMAGE ID			# 镜像的id
#CREATED			# 镜像的创建时间
#SIZE				# 镜像的大小# 可选项
Options:-a, --all         Show all images (default hides intermediate images) #列出所有镜像-q, --quiet       Only show numeric IDs # 只显示镜像的id[root@Mango ~]# docker images -a  #列出所有镜像详细信息
[root@Mango ~]# docker images -aq #列出所有镜像的id

docker search: 搜索镜像

image-20231219230938538

[root@Mango ~]# docker search mysql#如果加上 --filter=STARS=3000 #进行过程,表示搜索出来的镜像收藏STARS数量大于3000的
#docker search --help查看相关内容
Options:-f, --filter filter   Fi	lter 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@Mango ~]# docker search mysql --filter=STARS=3000
NAME        DESCRIPTION         STARS            OFFICIAL        AUTOMATED
mysql       MySQL IS ...        9520             [OK]                
mariadb     MariaDB IS ...      3456             [OK]   

docker pull 下载镜像

# 下载镜像 docker pull 镜像名[:tag]  
#可以版本(tag)的原因可以指定下载某个版本,否则都是下载最新版latest
[root@Mango ~]# docker pull tomcat:8
8: Pulling from library/tomcat #如果不写tag(docker pull tomcat)  默认就是latest   
90fe46dd8199: Already exists   #分层下载: docker的核心 => 联合文件系统
35a4f1977689: Already exists 
bbc37f14aded: Already exists 
74e27dc593d4: Already exists 
93a01fbfad7f: Already exists 
1478df405869: Pull complete 
64f0dd11682b: Pull complete 
68ff4e050d11: Pull complete 
f576086003cf: Pull complete 
3b72593ce10e: Pull complete 
Digest: sha256:0c6234e7ec9d10ab32c06423ab829b32e3183ba5bf2620ee66de866df # 签名防伪
Status: Downloaded newer image for tomcat:8
docker.io/library/tomcat:8 #真实地址#等价于
docker pull tomcat:8 => docker pull docker.io/library/tomcat:8

注意:版本不能瞎写,必须是存在的

image-20231219230945450

docker rmi 删除镜像

docker rmi -f 镜像id #删除指定id的镜像
[root@Mango ~]# docker rmi -f f19c56ce92a8docker rmi -f $(docker images -aq) #删除全部的镜像   docker images -aq #列出所有镜像的id

3.容器命令

docker ps #列出所有运行的容器  等价于docker container list
docker rm 容器id #删除指定容器
docker start 容器id	#启动指定容器
docker restart 容器id	#重启指定容器
docker stop 容器id	#停止当前正在运行的容器
docker kill 容器id	#强制停止当前容器

说明:有了镜像才可以创建容器,下述我们可以通过下载centos镜像来学习

镜像下载

#docker中下载centos
docker pull centos
docker run 镜像id #根据镜像新建容器并启动
新建容器并启动
docker run [可选参数] image | docker container run [可选参数] image 
#参书说明
--name="Name"		#容器名字Name tomcat01 tomcat02 用来区分容器
-d					#后台方式运行 
-it 				#使用交互方式运行,进入容器查看内容
-p					#指定容器的端口 -p 8080(宿主机):8080(容器)
#有下述4种指定端口的方式-p 指定ip:主机端口:容器端口-p 主机端口:容器端口          (常用)-p 容器端口容器端口     (不带-p选项,直接写端口)
-P(大写) 				随机指定端口# 测试、启动并进入容器
[root@Mango ~]# docker run -it centos /bin/bash
[root@241b5abce65e /]# ls  #注意此时的主机名变成了镜像id   查看容器内的centos
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@Mango /]# exit #从容器退回主机  (或者ctrl+d退出)
exit/*
docker run -it centos /bin/bash:这个命令在启动 centos 镜像的容器后,会立即执行 /bin/bash 命令,进入容器的交互式终端(bash shell)。这样你可以在容器内执行命令、浏览文件系统、安装软件等操作。docker run -it centos:这个命令在启动 centos 镜像的容器后,默认会执行容器内的默认命令,通常是启动容器内的主进程。对于 CentOS 镜像来说,它启动之后的默认命令是 /bin/bash,所以在这种情况下,它与上述命令的效果是一样的
但是,如果你使用的是其他镜像,它的默认命令可能是不同的,比如启动一个 Web 服务器进程或者数据库服务
*/

image-20231219165443862

列出所有运行的容器
docker ps 命令  		#列出当前正在运行的容器-a,      	 #列出当前正在运行的容器 + 历史运行过的容器-n=?       #列出最近创建的?个容器 ?为1则只列出最近创建的一个容器,为2则列出2个-q,        #只列出容器的编号

image-20231219165642817

退出容器
exit 		#容器直接退出  #1.容器停止。会导致容器停止运行,容器中的任何正在运行的进程将被中止,并且容器将不再处于运行状态 =>docker ps查看不到该容器的信息#2.数据丢失。如果在退出容器之前没有保存或持久化关键数据,那么退出容器将导致在下次启动容器时丢失这些数据。容器中的临时文件和运行时状态将丢失
ctrl +P +Q  #容器不停止退出 =>分离(detach)容器,使容器在后台运行,而无需终止容器进程 	---注意:这个很有用的操作!!!!
删除容器
docker rm 容器id   				#删除指定的容器,不能删除正在运行的容器,如果要强制删除,可以加上-rf选项#删除所有的容器
docker rm -f $(docker ps -aq)  	 #方式1
docker ps -aq|xargs docker rm  #方式2/*
xargs: 这是一个用于处理命令行参数的工具。它可以将前一个命令的输出作为后一个命令的参数
docker rm: 这是一个用于删除 Docker 容器的命令,它接受一个或多个容器的 ID(或名称)作为参数,并删除这些容器。
因此上述命令的含义是:列出所有容器的 ID,将它们传递给 docker rm 命令以删除这些容器
*/

image-20231219231026913

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

4.常用其他命令

后台启动命令(run -d选项)
# 命令 docker run -d 镜像名
[root@Mango ~]# docker run -d centos   #后台运行centos
a8f922c255859622ac45ce3a535b7a0e8253329be4756ed6e32265d2dd2fac6c[root@Mango ~]# docker ps    
CONTAINER ID      IMAGE       COMMAND    CREATED     STATUS   PORTS    NAMES

问题: docker ps(查看正在运行的容器) 发现centos容器 停止了

常见的坑:docker容器使用后台运行,就必须要有要一个前台进程,docker发现没有前台应用,就会自动停止

  • 容器启动后,docker发现自己没有提供服务,docker就会立刻停止,就是没有程序,使用docker ps查看不到,所以最好的就是: 启动后台应用的情况下,最好要有前台应用与之对应

注意:在docker run命令中使用-d标志创建容器时,容器将在后台以守护进程的形式运行,但是,如果没有指定一个持续运行的进程或命令或者前台进程,容器会在启动后立即退出


解决办法1:在后台运行的容器当中增加一个持续运行的前台进程

  • /bin/sh -c "while true;do echo 6666;sleep 1;done":作为容器的启动命令,这是一个用/bin/sh解释器执行的命令字符串。该命令字符串包含一个无限循环,每秒打印一次字符串"6666"
  • 在这种情况下,使用-d标志是重要的,希望容器在后台持续运行而不阻塞终端。如果不使用-d标志,则命令将在前台运行,将看到输出并且无法继续输入其他命令

image-20231219171633258

解决办法2:docker run -d centos tail -f /dev/null

  • tail -f /dev/null是一个常用的技巧,它提供了一个无限循环的命令,它会持续读取/dev/null(空设备)并保持容器处于运行状态。/dev/null是一个特殊的设备文件,它会将所有写入它的数据丢弃,而读取它将始终返回空值
  • 通过在容器中运行tail -f /dev/null,您实际上在容器中创建了一个持续运行的进程,该进程不会做任何实际的工作,但会阻止容器退出。这样,您就可以保持CentOS容器持续运行而不会立即退出
查看日志
docker logs --help
Options:--details        Show extra details provided to logs 
*  -f, --follow         Follow log output--since string   Show logs since timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)
*      --tail string    Number of lines to show from the end of the logs (default "all")
*  -t, --timestamps     Show timestamps--until string   Show logs before a timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)#示例
docker run -d centos /bin/sh -c "while true;do echo 6666;sleep 1;done" #在后台运行的容器当中,模拟日志打印   #显示日志
-tf		#显示日志信息(一直更新)
--tail number #需要显示日志条数
docker logs -t --tail n 容器id #查看n行日志
docker logs -tf 容器id #实时更新日志

实时查看日志:

image-20231219171955161

指定行数查看日志:

image-20231219172041146


查看容器内部的进程信息
docker top 容器id

image-20231219203652872

查看镜像的元数据
docker inspect 容器id#测试 
docker inspect 55321bcae33d  #可以发现这个容器id只是下面的Id的缩写[{"Id": "55321bcae33d15da8280bcac1d2bc1141d213bcc8f8e792edfd832ff61ae5066","Created": "2020-05-15T05:22:05.515909071Z","Path": "/bin/sh","Args": ["-c","while true;do echo 6666;sleep 1;done"],//........
]
进入当前正在运行的容器

我们通常启动容器都是使用后台方式运行的,但是有时需要进入容器,修改一些配置,docker exec命令可以让我们进入容器

方式1:

docker exec -it 容器id bashshell (/bin/shell)

测试

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES
d8010c37caaf   centos    "/bin/bash"   4 seconds ago   Up 3 seconds             tender_greider
[root@localhost ~]# docker exec -it d8010c37caaf /bin/bash
[root@d8010c37caaf /]# pwd
/
[root@d8010c37caaf /]# exit
exit
[root@localhost ~]# 

image-20231219204207038

# 方式二
docker attach 容器id

image-20231219204355200

docker attachdocker exec的区别

  • docker exec #进入当前容器后开启一个新的终端(进程),并与容器进行交互,而不会影响容器的原始进程
    • docker exec命令在容器中启动的进程是新的进程,与容器的主进程相互独立
  • docker attach # 进入容器正在执行的终端 不会启动新的进程

所以说:docker attach:连接到容器后,按下 Ctrl+C 将会导致容器停止(除非容器中有其他进程在运行),docker exec:在容器内部启动的进程是新的进程,与容器的主进程相互独立。当您在容器中执行命令并退出后,容器仍然保持运行状态


应用场景

docker attach命令在以下情况下:实时查看容器的输出:如果您需要实时查看容器的输出,例如日志或控制台输出,可以使用docker attach连接到容器的标准流。这允许您直接与容器的主进程进行交互,并查看输出。

docker exec命令适用于以下情况:在容器内执行一次性命令:如果您需要在容器内部执行一次性的命令,例如安装软件包、执行脚本或检查容器的状态,docker exec是更合适的选择。它启动一个新的进程在容器内执行命令,并返回结果


从容器内的内容拷贝到主机上
docker cp 容器id:容器内路径  主机目的路径  #注意是在主机执行该命令,而不是在容器内部执行[root@Mango ~]# docker ps
CONTAINER ID     IMAGE    COMMAND     CREATED         STATUS       PORTS      NAMES
56a5583b25b4     centos   "/bin/bash" 7seconds ago    Up 6 seconds      #1. 进入docker容器内部
[root@Mango ~]# docker exec -it 56a5583b25b4 /bin/bash
[root@55321bcae33d /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var #在容器内新建一个文件
[root@55321bcae33d /]# echo "hello" > hello.java
[root@55321bcae33d /]# cat hello.java 
hello
[root@55321bcae33d /]# exit
exit#将容器内的hello.java拷贝到主机的home文件夹下
[root@Mango /]# docker cp 56a5583b25b4:/hello.java /home 
[root@Mango /]# cd /home
[root@Mango home]# ls -l	#可以看见hello.java存在
total 8
-rw-r--r-- 1 root root    0 May 19 22:09 haust.java
-rw-r--r-- 1 root root    6 May 22 11:12 hello.java
drwx------ 3 www  www  4096 May  8 12:14 www

命令小结:

image-20231219231048916

attach      Attach local standard input, output, and error streams to a running container#将本地标准输入、输出和错误流连接到运行中的容器
build       Build an image from a Dockerfile # 通过Dockerfile定制镜像
commit      Create a new image from a container's changes #提交当前容器为新的镜像
cp          Copy files/folders between a container and the local filesystem #拷贝文件
create      Create a new container #创建一个新的容器
diff        Inspect changes to files or directories on a container's filesystem #查看docker容器的变化
events      Get real time events from the server # 从服务获取容器实时时间
exec        Run a command in a running container # 在运行中的容器上运行命令
export      Export a container's filesystem as a tar archive #导出容器文件系统作为一个tar归档文件[对应import]
history     Show the history of an image # 展示一个镜像形成历史
images      List images #列出系统当前的镜像
import      Import the contents from a tarball to create a filesystem image #从tar包中导入内容创建一个文件系统镜像
info        Display system-wide information # 显示全系统信息
inspect     Return low-level information on Docker objects #查看容器详细信息
kill        Kill one or more running containers # kill指定docker容器
load        Load an image from a tar archive or STDIN #从一个tar包或标准输入中加载一个镜像[对应save]
login       Log in to a Docker registry #登录到 Docker 注册表
logout      Log out from a Docker registry#从 Docker 注册表注销
logs        Fetch the logs of a container#获取容器的日志
pause       Pause all processes within one or more containers#暂停一个或多个容器内的所有进程
port        List port mappings or a specific mapping for the container#列出容器的端口映射或特定映射
ps          List containers#列出容器
pull        Pull an image or a repository from aregistry #从注册表拉取镜像或仓库
push        Push an image or a repository to a registry#将镜像或仓库推送到注册表
rename      Rename a container#重命名一个容器
restart     Restart one or more containers#重新启动一个或多个容器
rm          Remove one or more containers#删除一个或多个容器
rmi         Remove one or more images#删除一个或多个镜像 (image:镜像)
run         Run a command in a new container#在新容器中运行命令
save        Save one or more images to a tar archive (streamed to STDOUT by default)#将一个或多个镜像保存为 tar 归档(默认流式传输到 STDOUT)
search      Search the Docker Hub for images#在 Docker Hub 中搜索镜像
start       Start one or more stopped containers #启动一个或多个已停止的容器
stats       Display a live stream of container(s) resource usage statistics#显示容器的资源使用统计信息的实时流
stop        Stop one or more running containers #停止一个或多个正在运行的容器
tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE#创建一个指向源镜像的目标镜像的标签
top         Display the running processes of a container#显示一个容器内的运行进程
unpause     Unpause all processes within one or more containers#取消暂停一个或多个容器内的所有进程
update      Update configuration of one or more containers #更新一个或多个容器的配置
version     Show the Docker version information#显示 Docker 版本信息
wait        Block until one or more containers stop, then print their exit codes #阻塞直到一个或多个容器停止,然后打印它们的退出代码。

案例一:Docker安装Nginx

#1. 搜索镜像 search 建议大家去docker官网搜索,可以看到帮助文档
[root@Mango ~]# docker search nginx#2. 拉取下载镜像 pull
[root@Mango ~]# docker pull nginx#3. 查看是否下载成功镜像
[root@Mango ~]# docker images#3. 运行测试  docker run
#选项: -d 后台运行  --name 给容器命名-p 宿主机端口:容器内部端口   
[root@Mango ~]# docker run -d --name nginx01 -p 3344:80 nginx
aa664b0c8ed98f532453ce1c599be823bcc1f3c9209e5078615af416ccb454c2#4. 查看正在启动的镜像
[root@Mango ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
75943663c116        nginx               "nginx -g 'daemon of…"   41 seconds ago      Up 40 seconds       0.0.0.0:82->80/tcp   nginx00#可以使用本机进行测试:curl localhost:3344#5. 进入容器
[root@Mango ~]# docker exec -it nginx01 /bin/bash 
root@aa664b0c8ed9:/# whereis nginx	#找到nginx配置文件
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@aa664b0c8ed9:/# cd /etc/nginx/
root@aa664b0c8ed9:/etc/nginx# ls
conf.d	fastcgi_params	koi-utf  koi-win  mime.types  modules  nginx.conf  scgi_params	uwsgi_params  win-utf#6. 退出容器
root@aa664b0c8ed9:/etc/nginx# exit
exit#7. 停止容器
[root@Mango ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
aa664b0c8ed9        nginx               "nginx -g 'daemon of…"   10 minutes ago      Up 10 minutes       0.0.0.0:3344->80/tcp   nginx01
[root@Mango ~]# docker stop aa664b0c8ed9

宿主机端口容器内部端口 以及端口暴露(映射):(端口映射功能允许将容器内部的端口映射到主机上的端口

image-20231219231102366

  • 通过端口映射,可以轻松将容器内的服务暴露给外部网络,使得可以通过主机的 IP 地址和端口访问容器中的应用程序,这对于开发和部署应用程序非常有用
  • 此时访问主机的3344端口就相当于访问容器的80端口的nginx服务

image-20231219231110715

**问题:**我们每次改动nginx配置文件,都需要进入容器内部?

这是十分麻烦,我要是可以在容器外部提供一个映射路径,达到在容器外部修改文件,容器内部的文件就可以自动修改

  • 此时需要的是数据卷 技术!例如:docker run -v 主机内的目录:容器内的目录通过docker run命令的-v选项进行两个目录之间的挂载

案例二:Docker安装tomcat

坑点:解决webapps目录为空

# 例如:下载 tomcat9.0
# 之前的启动都是后台,停止了容器,虽然在docker ps查看不到,但是加上-a选项还是可以查到# docker run -it --rm 镜像名   如果加上--rm选项,那么一般是用来测试,用完就删除,不会存在历史记录
#           --rm       Automatically remove the container when it exits 用完即删# docker run 命令会在本地不存在指定镜像时自动下载该镜像
[root@Mango ~]# docker run -it --rm tomcat:9.0  #指定下载9.0版本#如果不指定版本,默认下载最新版latest
[root@Mango ~]# docker pull tomcat#查看下载的镜像
[root@Mango ~]# docker images#以后台方式-d,进行端口映射方式-p,指定启动之后的容器名字为tomcat-1(--name选项) 启动运行tomcat容器  主机的8080端口和容器内的8080端口映射
[root@Mango ~]# docker run -d -p 8080:8080 --name tomcat01 tomcat#本地测试访问有没有问题
curl localhost:8080#如果直接去浏览器上访问会出现404,原因是文件缺失,看下面的解决方案#根据容器id进入tomcat容器
[root@Mango ~]# docker exec -it 645596565d3f /bin/bash
root@645596565d3f:/usr/local/tomcat# 
#查看tomcat容器内部内容:
root@645596565d3f:/usr/local/tomcat# ls -l
total 152
-rw-r--r-- 1 root root 18982 May  5 20:40 BUILDING.txt
-rw-r--r-- 1 root root  5409 May  5 20:40 CONTRIBUTING.md
-rw-r--r-- 1 root root 57092 May  5 20:40 LICENSE
-rw-r--r-- 1 root root  2333 May  5 20:40 NOTICE
-rw-r--r-- 1 root root  3255 May  5 20:40 README.md
-rw-r--r-- 1 root root  6898 May  5 20:40 RELEASE-NOTES
-rw-r--r-- 1 root root 16262 May  5 20:40 RUNNING.txt
drwxr-xr-x 2 root root  4096 May 16 12:05 bin
drwxr-xr-x 1 root root  4096 May 21 11:04 conf
drwxr-xr-x 2 root root  4096 May 16 12:05 lib
drwxrwxrwx 1 root root  4096 May 21 11:04 logs
drwxr-xr-x 2 root root  4096 May 16 12:05 native-jni-lib
drwxrwxrwx 2 root root  4096 May 16 12:05 temp
drwxr-xr-x 2 root root  4096 May 16 12:05 webapps
drwxr-xr-x 7 root root  4096 May  5 20:37 webapps.dist
drwxrwxrwx 2 root root  4096 May  5 20:36 work
root@645596565d3f:/usr/local/tomcat# 
#进入webapps目录
root@645596565d3f:/usr/local/tomcat# cd webapps
root@645596565d3f:/usr/local/tomcat/webapps# ls
root@645596565d3f:/usr/local/tomcat/webapps# 
# 发现问题:1、linux命令少了。 2.webapps目录为空 
# 原因:安装docker的时候使用的是阿里云镜像
#而阿里云默认是最小的镜像,所以不必要的内容都剔除掉,保证最小可运行的环境!
# 解决方案:将webapps.dist下的文件都拷贝到webapps下即可
root@645596565d3f:/usr/local/tomcat#ls   #找到webapps.dist
BUILDING.txt	 LICENSE  README.md	 RUNNING.txt  conf  logs  temp     webapps.dist
CONTRIBUTING.md  NOTICE   RELEASE-NOTES  bin   lib   na	tive-jni-lib  webapps  workroot@645596565d3f:/usr/local/tomcat# cd webapps.dist/ # 进入webapps.dist 
root@645596565d3f:/usr/local/tomcat/webapps.dist# ls # 查看内容
ROOT  docs  examples  host-manager  managerroot@645596565d3f:/usr/local/tomcat/webapps.dist# cd ..
root@645596565d3f:/usr/local/tomcat# cp -r webapps.dist/* webapps # 拷贝webapps.dist 内容给webapps
root@645596565d3f:/usr/local/tomcat# cd webapps #进入webapps
root@645596565d3f:/usr/local/tomcat/webapps# ls #查看拷贝结果
ROOT  docs  examples  host-manager  manager

这样docker部署tomcat就可以访问了

image-20231219231125100
问题:我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?要是可以在容器外部提供一个映射路径,比如webapps,我们在外部放置项目,就自动同步内部就好了! 这同样使用到的是数据卷技术!


案例三:部署elasticsearch+kibana

image-20231219231138817

# es 暴露的端口很多!
# es 十分耗内存
# es 的数据一般需要放置到安全目录!挂载
# --net somenetwork  网络配置# 启动elasticsearch
[root@Mango ~]# docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2# 测试一下es是否成功启动
➜  ~ curl localhost:9200
{"name" : "d73ad2f22dd3","cluster_name" : "docker-cluster","cluster_uuid" : "atFKgANxS8CzgIyCB8PGxA","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"
}[root@Mango ~]# docker stats  # 显示正在运行的容器的实时资源使用情况 (查看内存使用情况)#测试成功就关掉elasticSearch,防止耗内存
[root@Mango ~]# docker stop d834ce2bd306
d834ce2bd306

image-20231219231203762

#测试成功就关掉elasticSearch,可以添加内存的限制,修改配置文件 -e选项:环境配置修改
#  -e ES_JAVA_OPTS="-Xms64m -Xmx512m  :最多只占512M空间
docker rm -f d73ad2f22dd3            # stop命令也行                               
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

image-20231219231212772

#进行本地测试:  curl localhost:9200
{"name" : "b72c9847ec48","cluster_name" : "docker-cluster","cluster_uuid" : "yNAK0EORSvq3Wtaqe2QqAg","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 可视化面板安装

  • portainer(先用这个)

  • Rancher(CI/CD再用 -持续集成持续交付)

什么是portainer?

Docker图形化界面管理工具!提供一个后台面板供我们操作!

# portainer安装命令
[root@Mango ~]# docker run -d -p 8088:9000 \
> --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainerUnable to find image 'portainer/portainer:latest' locally
latest: Pulling from portainer/portainer
d1e017099d17: Pull complete 
a7dca5b5a9e8: Pull complete 
Digest: sha256:4ae7f14330b56ffc8728e63d355bc4bc7381417fa45ba0597e5dd32682901080
Status: Downloaded newer image for portainer/portainer:latest
81753869c4fd438cec0e31659cbed0d112ad22bbcfcb9605483b126ee8ff306d
1234567891011

测试访问: 外网:8088

  • 要使用本地的8088,前提是把阿里云的安全组打开,并且容器内的portainer也要在运行

image-20231219231239936

image-20231219231250245

  • 选择Local,进入之后的面板

image-20231219231301079

镜像原理之联合文件系统

镜像是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,镜像包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件。所有的应用,直接打包成docker镜像,就可以直接跑起来

如何得到镜像

  • 从远程仓库下载
  • 别人拷贝给你
  • 自己制作一个镜像 (需要使用DockerFile)

Docker镜像加载原理

UnionFs (联合文件系统)

UnionFs(联合文件系统):是一种分层、轻量级并且高性能的文件系统,支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下

UnionFS文件系统是 Docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像可以制作各种具体的应用镜像

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

Docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统称为UnionFS

boots(boot file system)主要包含 bootloader和 Kernel, bootloader主要是引导加载kernel, Linux刚启动时会加bootfs文件系统,在 Docker镜像的最底层是 boots,当boots加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs转交给内核,此时系统也会卸载bootfs
rootfs(root file system),在 bootfs之上,包含的就是典型 Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件,rootfs就是各种不同的操作系统发行版,比如 Ubuntu, Centos等等

image-20231219231307961

内核 => 内核+image => 内核+image +image ,每一层不断的往上进行叠加

平时我们安装到虚拟机的CentOS都是好几个G,为什么Docker这里才200M

image-20231219231317061

对于精简的OS,rootfs可以很小,只需要包合最基本的命令,工具和程序库就可以了,因为docker底层直接用宿主机的kernel,docker容器本身只需要提供rootfs就可以了,虚拟机是分钟级别启动,容器是秒级启动!

由此可见对于不同的Linux发行版, boots基本是一致的, rootfs会有差別,因此不同的发行版可以公用bootfs


分层理解

分层的镜像

我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层层的在下载

image-20231219222800696

思考:为什么Docker镜像要采用这种分层的结构呢?

1.节省存储空间:分层结构允许镜像的不同层次之间共享相同的文件 (资源共享)

  • 对于多个镜像,如果它们具有相同的基础层,那么这些基础层只需要存储一次,从而节省了存储空间,这对于大规模部署和分布式系统尤其重要,因为可以减少大量相同文件的重复存储
  • 比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘当中保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享

2.加快镜像传输速度:当需要从一个地方传输镜像到另一个地方时,分层结构使得只需传输有进行更改的层,而不需要传输整个镜像。这可以显著减少传输所需的时间和带宽消耗

3.提高镜像的可复用性:分层结构使得镜像的不同层可以独立更新和管理,使得镜像更易于维护和更新

  • 通过修改和更新镜像的特定层,可以轻松创建新的镜像版本,而无需重新构建整个镜像

4.支持版本控制和回滚:通过分层结构,可以轻松管理和控制镜像的不同版本,这对于应用程序的持续集成和交付以及故障恢复非常有用

  • 每个层都可以被视为一个单独的版本,可以轻松地回滚到先前的版本或创建新的版本

5.支持容器快速启动和销毁:由于Docker容器的可写层是在镜像的顶部,容器的创建和销毁操作只涉及对这个可写层的修改,这使得容器的启动和销毁非常快速,因为只需要对可写层的变更进行操作,而不需要重新加载整个镜像

  • 在Docker中,容器的可写层是指容器运行时创建的可写文件系统层。该层位于镜像的顶部,用于存储容器运行时的变化和数据。当容器创建时,Docker会在镜像的基础上添加一个可写层,用于记录容器中的文件修改、新增和删除等操作
  • 由于可写层是容器独有的,而镜像的其余部分是只读的,因此在容器的启动和销毁过程中,只需要对可写层进行修改和操作,而无需重新加载整个镜像,这种设计使得容器的启动和销毁操作非常快速
    • 当启动容器时,Docker只需要加载基础镜像的只读部分和可写层,而不需要重新加载整个镜像。只有在镜像不存在本地时,Docker才会下载整个镜像,这种加载方式使得容器的启动速度更快,并且占用更少的存储空间
      • 在容器启动时,Docker会创建一个只读的文件系统,其中包含基础镜像的只读部分,这些只读部分通常是共享的,即多个容器可以共享相同的只读部分
    • 当销毁容器时,只需要清理掉容器的可写层,而不需要涉及整个镜像的操作
  • 这种可写层的机制使得容器可以快速启动和销毁,非常适合动态扩展和快速部署的场景。它也提供了容器间的隔离性,每个容器都有自己的可写层,互不干扰
  • 由于可写层的存在,如果频繁修改容器中的文件,可写层可能会随着时间增长而增大。这在一定程度上会对存储空间产生影响。因此,在设计容器应用时,需要注意避免不必要的文件修改,或者使用持久化卷等机制来存储需要保留的数据,以减小可写层的大小

查看镜像分层命令

docker image inspect 镜像id/镜像名字

实例理解分层

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

举一个简单的例子

1)假如基于 Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层

2)如果在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层

3)如果继续添加一个安全补丁,就会创建第三个镜像层该像当前已经包含3个镜像层

在添加额外的镜像层的同时,镜像始终保持是当前所有“镜像层”的组合!!!

image-20231219231333587


下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件

image-20231219231341287


下图中展示了一个稍微复杂的三层镜像,因为最上层中的文件7是文件5的一个更新版,那么在外部看来整个镜像只有6个文件

image-20231219231351877

这种情況下,上层镜像层中的文件覆盖了底层镜像层中的文件,这样就使得文件的更新版本作为一个新镜像层添加到镜像当中


Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统

  • 下图展示了与系统显示相同的三层镜像。所有镜像层堆并合井,对外提供统一的视图

image-20231219231359403

特点

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

image-20231219231801367

案例:做一个镜像

提交容器成为新镜像的命令

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

实战测试

# 1、启动一个默认的tomcat
[root@Mango ~]# docker run -d -p 8080:8080 tomcat
de57d0ace5716d27d0e3a7341503d07ed4695ffc266aef78e0a855b270c4064e# 2、这个默认启动的tomcat 是没有webapps应用,因为下载docker的时候使用的是阿里云的镜像,而阿里云默认是最小的镜像,所以不必要的内容都剔除掉,保证最小可运行的环境! 阿里云官方的镜像默认webapps文件夹是没有文件的
#docker exec -it 容器id /bin/bash  进入tomcat控制台
[root@Mango ~]# docker exec -it de57d0ace571 /bin/bash
root@de57d0ace571:/usr/local/tomcat#  # 3、从webapps.dist拷贝文件进去webapp
root@de57d0ace571:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@de57d0ace571:/usr/local/tomcat# cd webapps
root@de57d0ace571:/usr/local/tomcat/webapps# ls
ROOT  docs  examples  host-manager  manager# 4、将操作过的容器通过commit调整为一个镜像!我们以后就使用我们修改过的镜像即可,而不需要每次都重新拷贝webapps.dist下的文件到webapps了,这就是我们自己的一个修改的镜像。
#docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[TAG]
docker commit -a="Mango" -m="add webapps app" 原来的容器id tomcat02:1.0[root@Mango ~]# docker commit -a="csp提交的" -m="add webapps app" de57d0ace571 tomcat02.1.0
sha256:d5f28a0bb0d0b6522fdcb56f100d11298377b2b7c51b9a9e621379b01cf1487e[root@Mango ~]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
tomcat02.1.0          latest              d5f28a0bb0d0        14 seconds ago      652MB #发现比原来的版本更大
tomcat                latest              1b6b1fe7261e        5 days ago          647MB
nginx                 latest              9beeba249f3e        5 days ago          127MB
mysql                 5.7                 b84d68d0a7db        5 days ago          448MB
elasticsearch         7.6.2               f29a1ee41030        8 weeks ago         791MB
portainer/portainer   latest              2869fc110bf7        2 months ago        78.6MB
centos                latest              470671670cac        4 months ago        237MB
hello-world           latest              bf756fb1ae65        4 months ago        13.3kB

如果你想要保存当前容器的状态,就可以通过commit来提交,从而获得一个镜像,就好比我们我们使用虚拟机的快照

image-20231219230400638

相关文章:

【Docker】基础篇

文章目录 Docker为什么出现容器和虚拟机关于虚拟机关于Docker二者区别&#xff1a; Docker的基本组成相关概念-镜像&#xff0c;容器&#xff0c;仓库安装Docker卸载docker阿里云镜像加速docker run的原理**为什么容器比虚拟机快**Docker的常用命令1.帮助命令2.镜像相关命令3.容…...

Potplayer播放器远程访问群晖WebDav本地资源【内网穿透】

文章目录 本教程解决的问题是&#xff1a;按照本教程方法操作后&#xff0c;达到的效果是&#xff1a;1 使用环境要求&#xff1a;2 配置webdav3 测试局域网使用potplayer访问webdav3 内网穿透&#xff0c;映射至公网4 使用固定地址在potplayer访问webdav 国内流媒体平台的内容…...

【神经网络】imshow展示图片报错

文章目录 代码示例报错信息报错原因解决方法其他问题 代码示例 plt.imshow(np.squeeze(images[0]))报错信息 Invalid shape (3, 60, 90) for image data报错原因 格式错误&#xff0c;输入具有RGB值的图像&#xff0c;输入三维数组参数的格式应该是&#xff08;高度&#xf…...

【C++】对象特性:无参有参构造函数,拷贝构造函数,析构函数

目录 对象的初始化和清理1.1 构造函数和析构函数1.2 构造函数的分类及调用1.3 拷贝构造函数调用时机1.4 构造函数调用规则1.5 深拷贝与浅拷贝 对象的初始化和清理 生活中我们买的电子产品都基本会有出厂设置&#xff0c;在某一天我们不用时候也会删除一些自己信息数据保证安全。…...

【算法与数据结构】1005、LeetCode K 次取反后最大化的数组和

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题允许某个下标的数字多次翻转&#xff0c;因此思路比较简单。首先&#xff0c;我们要求最大和&…...

作业--day34

使用select完成TCP并发服务器和客户端 server.c #include <myhead.h>#define PORT 8888 #define IP "192.168.125.137"int main(int argc, const char *argv[]) {int sfd socket(AF_INET, SOCK_STREAM, 0);if(sfd -1){perror("socket error");re…...

车辆违规开启远光灯检测系统:融合YOLO-MS改进YOLOv8

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 随着社会的不断发展和交通工具的普及&#xff0c;车辆违规行为成为了一个严重的问题。其中&#xff0c;车辆违规开启远光灯是一种常见的违规行为&#xff0c;给其…...

爬虫工作量由小到大的思维转变---<第十三章 Scrapy之pipelines分离的思考>

前言: 收到留言: "我的爬取的数据处理有点大,scrapy抓网页挺快,处理数据慢了!" -----针对这位粉丝留言,我只想说:你那培训班老师可能给你漏了课程! 大概你们上课讲的案例属于demo,他教了你一些基本操作,但他没有对相关业务对你讲透! 你研究一下pipelines,或者看我现…...

【Unity】运行时创建曲线(贝塞尔的运用)

[Unity]运行时创建线&#xff08;贝塞尔的运用&#xff09; 1. 实现的目标 在运行状态下创建一条可以使用贝塞尔方法实时编辑的网格曲线。 2. 原理介绍 2.1 曲线的创建 unity建立网格曲线可以参考Unity程序化网格体的实现方法。主要分为顶点&#xff0c;三角面&#xff0c…...

基于DSP的IIR数字滤波器(论文+源码)

1.系统设计 在本次基于DSP的IIR数字低通滤波计中&#xff0c;拟以TMS320F28335来作为系统的主控制器&#xff0c;通过ADC0832模数转换芯片来对输入信号进行采集&#xff1b;通过TLC5615来将低通滤波后的信号进行输出&#xff1b;同时结合MATLAB仿真软件&#xff0c;对设计的II…...

Django(一)

1.web框架底层 1.1 网络通信 注意&#xff1a;局域网 个人一般写程序&#xff0c;想要让别人访问&#xff1a;阿里云、腾讯云。 去云平台租服务器&#xff08;含公网IP&#xff09;程序放在云服务器 先以局域网为例 我的电脑【服务端】 import socket# 1.监听本机的IP和…...

微信小程序如何利用createIntersectionObserver实现图片懒加载

微信小程序如何利用createIntersectionObserver实现图片懒加载 节点布局相交状态 API 可用于监听两个或多个组件节点在布局位置上的相交状态。这一组API常常可以用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见。 节点布局相交状态 API中有一个 wx.createInter…...

七:爬虫-数据解析之正则表达式

七&#xff1a;正则表达式概述 正则表达式&#xff0c;又称规则表达式,&#xff08;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xff09;&#xff0c;是一种文本模式&#xff0c;包括普通字符&#xff08;例如&#xff0c;a 到 z 之间的字母&#xf…...

云原生之深入解析亿级流量架构之服务限流思路与方法

一、限流思路 ① 熔断 系统在设计之初就把熔断措施考虑进去&#xff0c;当系统出现问题时&#xff0c;如果短时间内无法修复&#xff0c;系统要自动做出判断&#xff0c;开启熔断开关&#xff0c;拒绝流量访问&#xff0c;避免大流量对后端的过载请求。系统也应该能够动态监测…...

【Python炫酷系列】祝考研的友友们金榜题名吖(完整代码)

文章目录 环境需求完整代码详细分析系列文章环境需求 python3.11.4及以上版本PyCharm Community Edition 2023.2.5pyinstaller6.2.0(可选,这个库用于打包,使程序没有python环境也可以运行,如果想发给好朋友的话需要这个库哦~)【注】 python环境搭建请见:https://want595.…...

KL散度、CrossEntropy详解

文章目录 0. 概述1. 信息量1.1 定义1.2 性质1.3 例子2. 熵 Entropy2.1 定义2.2 公式2.3 例子3. 交叉熵 Cross Entropy3.1 定义3.2 公式3.3 例子4. KL 散度(相对熵)4.1 公式...

【算法】红黑树

一、红黑树介绍 红黑树是一种自平衡二叉查找树&#xff0c;是在计算机科学中用到的一种数据结构&#xff0c;典型的用途是实现关联数组。 红黑树是在1972年由Rudolf Bayer发明的&#xff0c;当时被称为平衡二叉B树&#xff08;symmetric binary B-trees&#xff09;。后来&am…...

2023楚慧杯 WEB方向 部分:(

1、eaaeval 查看源码能看见账号&#xff1a;username169&#xff0c;密码&#xff1a;password196提交这个用户密码可以跳转到页面/dhwiaoubfeuobgeobg.php 通过dirsearch目录爆破可以得到www.zip <?php class Flag{public $a;public $b;public function __construct(){…...

STM32 CAN多节点组网项目实操 挖坑与填坑记录2

系列文章&#xff0c;持续探索CAN多节点通讯&#xff0c; 上一篇文章链接&#xff1a; STM32 CAN多节点组网项目实操 挖坑与填坑记录-CSDN博客文章浏览阅读120次。CAN线性组网项目开发过程中遇到的数据丢包问题&#xff0c;并尝试解决的记录和推测分析。开发了一个多节点线性…...

Flink 数据类型 TypeInformation信息

Flink流应用程序处理的是以数据对象表示的事件流。所以在Flink内部&#xff0c;我么需要能够处理这些对象。它们需要被序列化和反序列化&#xff0c;以便通过网络传送它们&#xff1b;或者从状态后端、检查点和保存点读取它们。为了有效地做到这一点&#xff0c;Flink需要明确知…...

基于python的leetcode算法介绍之递归

文章目录 零 算法介绍一 简单示例 辗转相除法Leetcode例题与思路[509. 斐波那契数](https://leetcode.cn/problems/fibonacci-number/)解题思路&#xff1a;题解&#xff1a; [206. 反转链表](https://leetcode.cn/problems/reverse-linked-list/)解题思路&#xff1a;题解&…...

2023年度佳作:AIGC、AGI、GhatGPT、人工智能大语言模型的崛起与挑战

目录 前言 01 《ChatGPT 驱动软件开发》 内容简介 02 《ChatGPT原理与实战》 内容简介 03 《神经网络与深度学习》 04 《AIGC重塑教育》 内容简介 05 《通用人工智能》 目  录 前言 2023年是人工智能大语言模型大爆发的一年&#xff0c;一些概念和英文缩写也在这一…...

Axure的交互以及情形的介绍

一. 交互 1.1 交互概述 通俗来讲就是&#xff0c;谁用了什么方法做了什么事情&#xff0c;主体"谁"对应的就是axure中的元件&#xff0c;"什么方法"对应的就是交互事件&#xff0c;比如单击事件、双击事件&#xff0c;"什么事情"对应的就是交互…...

【MATLAB第84期】基于MATLAB的波形叠加极限学习机SW-ELM代理模型的sobol全局敏感性分析法应用

【MATLAB第84期】基于MATLAB的波形叠加极限学习机SW-ELM代理模型的sobol全局敏感性分析法应用 前言 跟往期sobol区别&#xff1a; 1.sobol计算依赖于验证集样本&#xff0c;无需定义变量上下限。 2.SW-ELM自带激活函数&#xff0c;计算具有phi&#xff08;x&#xff09;e^x激…...

米游社区表情包整合网站源码

源码介绍 米游社表情包整合网站源码&#xff0c;来自Github大佬的项目&#xff0c;包含米游兔123枚&#xff0c;米游社 玩家12枚&#xff0c;崩坏 星穹铁道112枚&#xff0c;绝区零218枚&#xff0c;NAP32枚&#xff0c;崩坏RPG62枚&#xff0c;崩坏3-1282枚&#xff0c;原神 …...

easyexcel调用公共导出方法导出数据

easyexcel备忘 Slf4j public class ConditionDownloadUtil {//扫描在xboot 包下所有IService 接口的子类, 每次启动服务后, 重新扫描public final static Class[] classesExtendsIService ClassUtil.scanPackageBySuper("cn.exrick.xboot", IService.class).toArra…...

C语言插入排序算法及代码

一、原理 在待排序的数组里&#xff0c;从数组的第二个数字开始&#xff0c;通过构建有序序列&#xff0c;对于未排序数据&#xff0c;在已排序序列中从后向前扫描&#xff0c;找到相应位置并插入。 二、代码部分 #include<stdio.h> #include<stdlib.h> int ma…...

2023年中国法拍房用户画像和数据分析

法拍房主要平台 法拍房主要平台有3家&#xff0c;分别是阿里、京东和北交互联平台。目前官方认定纳入网络司法拍卖的平台共有7家&#xff0c;其中阿里资产司法拍卖平台的挂拍量最大。 阿里法拍房 阿里法拍房数据显示2017年&#xff0c;全国法拍房9000套&#xff1b;2018年&a…...

Android 清除临时文件,清空缓存

python 代码&#xff1a; import os import shutil import tracebackdef delete_folder(path):if os.path.exists(path):print(f"删除文件夹: {path}")shutil.rmtree(path)print("删除完成")def delete_file(path):if os.path.exists(path):print(f"删…...

Guava限流神器:RateLimiter使用指南

1. 引言 可能有些小伙伴听到“限流”这个词就觉得头大&#xff0c;感觉像是一个既复杂又枯燥的话题。别急&#xff0c;小黑今天就要用轻松易懂的方式&#xff0c;带咱们一探RateLimiter的究竟。 想象一下&#xff0c;当你去超市排队结账时&#xff0c;如果收银台开得越多&…...

网络供应商网站网址/搜狗站长平台打不开

前言 我相信&#xff0c;来到这里的你一定曾经被maven的jar包冲突困扰过。现在&#xff0c;阿福带着你使用IDEA彻底结局后顾之忧&#xff01; 工具 众所周知&#xff0c;IDEA为我们提供了maven视图&#xff0c;让我们首先切换到这个视图&#xff01; 看到如下的样子你已经成功…...

设计网站登录框ps怎么做/李飞seo

问题导读&#xff1a;1.Flume的存在些什么问题&#xff1f;2.基于开源的Flume美团增加了哪些功能&#xff1f;3.Flume系统如何调优&#xff1f;在《基于Flume的美团日志收集系统(一)架构和设计》中&#xff0c;我们详述了基于Flume的美团日志收集系统的架构设计&#xff0c;以及…...

网站建设只有20%的利润/百度一下搜索引擎

18年开始&#xff0c;新的一年新的开始。开年伊始&#xff0c;开始去年年底规划大数据通用平台的建设。 先介绍一下大数据通用能力平台&#xff0c;整个大数据通用能力平台的思路和2年前我在上海一家大型互联网公司规划的数据公厂基本类似&#xff0c;是一个大数据全生态体系平…...

seo排名分析/湖南正规关键词优化

#01: Tell me about yourself. 告诉HR你为什么能胜任&#xff0c;告诉HR&#xff1a;我有一些项目可以谈&#xff0c;但是我想最充分利用好时间&#xff0c;因此你能告诉我“could you tell me more about the most important priorities of this position?” 然后必须follow…...

wordpress base64/北京seo课程培训

linux 系统版本信息命令查询大全查看命令1.uname -a # 查看内核/操作系统/CPU信息2.cat /proc/cpuinfo # 查看CPU信息3.hostname # 查看计算机名4.du -sh <目录名> # 查看指定目录的大小5.查看逻辑CPU的个数&#xff1a;cat /proc/cpuinfo | grep "**processor**&qu…...

衡水专业做网站/武汉网站推广优化

push()/pop() -- shift()/unshift() 不建议使用delete concat() sort()排序 reverse()反转 数组迭代 Array.map()创建一个和原数组一一对应的新数组 Array.Filter()过滤掉不符合条件的元素 Array.every() / Array.some()返回bool类型值 Array.find()返回值 返回索引...