[汇总] Docker容器详解 Macvlan 创建不同容器独立跑仿真(持续更新中)

一、概念介绍

1.1 什么是macvlan

        macvlan是一种网卡虚拟化技术,能够将一张网卡(Network Interface Card, NIC)虚拟出多张网卡,这意味着每个虚拟网卡都能拥有独立的MAC地址和IP地址,从而在系统层面表现为完全独立的网络接口。这些虚拟网卡可以直接连接到物理网络,就像是网络中单独的物理设备一样,而不像传统的网络桥接或VLAN那样需要一个共同的桥接接口来转发流量。可以简单理解为macvlan是docker容器中的一种网络模式,可以让容器直接连接到宿主机的物理网络。

1.2 什么是docker容器

        Docker容器是一种轻量级、可移植的软件封装技术,它允许开发者将应用程序及其所有的依赖包打包到一个独立的、可运行的包中。这个包可以在任何安装了Docker引擎的系统上运行,无论该系统是在开发、测试还是生产环境中,保证了应用运行环境的一致性。Docker容器利用操作系统的Namespace和Control Groups等技术,实现了资源的隔离和限制,使得每个容器都像是运行在一个独立的系统中,但实际共享着宿主机的内核。

1.3docker容器与虚拟机对比

  • 资源消耗:虚拟机运行在宿主机上的虚拟化层(如Hypervisor)上,每个虚拟机都需要自己的操作系统,这导致较高的资源开销。相比之下,容器直接运行在宿主机的操作系统上,共享宿主机的内核,因此资源消耗小得多。
  • 启动速度:容器由于不需要启动完整的操作系统,其启动速度远远快于虚拟机。
  • 隔离程度:虚拟机提供了更强的隔离性,每个虚拟机都有自己的硬件虚拟化层,包括CPU、内存、硬盘等,而容器共享宿主机的硬件资源,隔离性相对较弱,但通过命名空间和控制组仍能有效隔离。
  • 灵活性与便携性:容器镜像体积小,便于在网络上分发和快速部署,更适合动态扩缩容和快速迭代的开发模式。
  • 适用场景:虚拟机更适合需要高度隔离或需要运行完全不同操作系统环境的场景,而容器则更适合微服务架构、快速部署、轻量级隔离的场景。

1.4 docker的五种网络模式

Bridge (桥接模式)  ---默认模式

解释:Bridge模式是Docker的默认网络配置。每个使用此模式的容器都会得到一个独立的Network Namespace,Docker会为容器分配一个内部IP地址,并将其连接到一个名为docker0的虚拟网桥上。这意味着容器间可以相互通信,同时也能够通过宿主机的网络栈访问外部网络。

适用情况:当你需要容器之间能够直接通信,且容器需要访问互联网或者被外部网络访问时,使用Bridge模式最为常见。

Host (主机模式)

解释:在Host模式下,容器不会获得自己的Network Namespace,而是直接使用宿主机的网络堆栈。这意味着容器将共享宿主机的网络接口和端口,容器内的网络服务可以直接使用宿主机的IP地址和端口号对外提供服务。

适用情况:如果你的应用需要直接绑定到宿主机的网络接口,或者需要极低的网络延迟,可以考虑使用Host模式。但需要注意,这样做可能会导致安全风险和端口冲突问题。

None (无网络模式)

解释:None模式下,Docker不会为容器配置任何网络设施,容器将只有一个lo(loopback)接口,无法访问外部网络,也无法和其他容器通信,除非你手动配置网络。

适用情况:如果你的容器不需要网络连接,或者你计划完全自定义网络配置(例如,使用自定义网络接口或复杂的网络拓扑),可以选择None模式。

Container (容器模式)

解释:这种模式允许一个容器共享另一个容器的Network Namespace,而不是创建新的或使用宿主机的。这意味着两个容器将共享相同的网络配置,包括IP地址和端口空间。

适用情况:当多个容器需要共享相同的网络环境时,比如在Kubernetes中的Pods,所有容器需要共享同一套网络资源和配置时,这种模式非常有用。

Macvlan (MAC VLAN 模式) 

Macvlan 是一种网络虚拟化技术,允许在单个物理网络接口上创建多个虚拟以太网接口(每个都有独立的MAC地址),这些虚拟接口可以直接连接到物理网络,仿佛是直接连接到交换机上的独立物理设备。在 Docker 中使用 macvlan 模式,可以为每个容器提供一个直接与物理网络相连的网络接口,绕过 Docker 默认的网络桥接,从而获得更低的网络延迟和更接近物理机的网络行为。这种模式非常适合需要直接与外部网络交互,且要求低延迟或特定网络配置的场景。

二、 Docker的安装与使用

2.1  Docker的安装

安装教程:https://docker-practice.github.io/zh-cn/install/ubuntu.html

安装完后一定要添加镜像源:

比如我在广州或东莞:

{

      "registry-mirrors": ["https://cn-guangzhou.mirror.aliyuncs.com"]

 基础操作:

nano daemon.json  #进入文件,文件不存在时自动创建

ctrl + o  保存文件           ctrl + x 退出文件            rm -i 文件名   #删除文件

mkdir  目录名  #创建目录                   rmdir  目录名  #删除目录

更改文件前建议备份文件:

  • cp example.txt example.txt.backup       #假设要编辑的文件名为example.txt,cp命令创建一个副本
  • mv example.txt.backup example.txt    #如果修改后的文件已经保存,你可以直接用mv将备份文件覆盖回去
  • diff example.txt.example.txt.backup   #如果你不确定是否需要完全恢复,或者想查看具体哪些地方发生了变化,可以使用diff命令比较两个文件的差异,然后手动决定如何修改。

安装完上面后再拉取镜像 

docker pull ubuntu  #获取Ubuntu的最新长期支持版本(LTS)

docker pull ubuntu:20.04 #如果你需要特定版本,比如10.04

2.1.1 相关知识了解

   daemon.json是Docker守护进程(dockerd)的配置文件,它允许系统管理员自定义Docker守护程序的行为和参数。这个文件通常位于/etc/docker/目录下,并且在Docker Engine 1.12及更高版本中可以被使用。docker服务使用 systemctl start docker 命令启动失败时,考虑daemon.json的配置是否正确。

作用:

  1. 网络配置:通过daemon.json,你可以配置Docker的网络设置,比如桥接网络的子网、网关等。

  2. 日志记录:配置Docker日志的驱动、日志级别以及日志输出目标,比如将日志发送到syslog或文件系统。

  3. 存储驱动:选择或修改Docker使用的存储驱动(如overlay2、aufs等),这对于容器的存储性能和管理非常重要。

  4. 镜像加速:对于中国用户而言,可以在该文件中配置镜像加速器地址,以加快从Docker Hub拉取镜像的速度。

  5. 注册表镜像认证:配置私有注册表的认证信息,使得Docker守护进程能够无需交互式输入凭据就能拉取私有镜像。

  6. TLS配置:设定Docker守护进程的TLS加密和证书路径,增强Docker API的安全性。

  7. 资源限制:例如内存、CPU使用限制,可以在这里全局设置Docker容器可使用的最大资源量。

  8. live-restore:设置容器在Docker守护进程重启时不退出,保持容器持续运行。

  9. 其他高级选项:包括IPv6支持、容器默认的隔离技术、容器标签策略等。

2.2 Docker的基础使用命令

查看信息   --------------------------------------------------------------------------docker ps   # 查看正在运行的容器
docker ps -a   # 查看所有容器#查看容器相关信息(推荐使用这个)
#打印网络名称、容器名称、主机名及对应的IP地址
docker inspect --format '{{range $key, $value := .NetworkSettings.Networks}}{{$key}}: {{$.Name}} - {{$.Config.Hostname}} - {{$value.IPAddress}}{{println}}{{end}}' 容器名/ID#查看存在的网络
docker network ls#查看某个网络下连接的容器
docker network inspect 网络名或ID#查看容器连接的网络
docker inspect  容器名/IDip addr show #列出系统中所有网络接口,包括IP地址、子网掩码、广播地址、网络接口的状态ip route #展示系统的路由表。路由表是决定数据包在网络中如何转发删除    ------------------------------------------------------------------------------#将容器从指定网络断开
docker network disconnect my_network my_container#删除网络(无容器连接时才可删除)
docker network rm my_network -f  (-f表示强制删除)#删除容器
docker rm  容器名/ID      #(正在运行容器不能删除,除非加-f选项)进入和退出容器   ------------------------------------------------------------------------#进入容器前要先启动
docker start 容器名/ID       #启动容器  无法启动时检查/etc/docker/daemon.json文件
docker restart 容器名/ID       #重启容器
docker stop 容器名/ID         #停止正在运行的容器# 进入容器,推荐exec        进入容器前要先启动容器
docker attach  容器名/ID  #使用attach进入后退出,容器停止运行
docker exec -it 容器名/ID /bin/bash  #使用exec进入后退出,容器不会停止
docker exec -it 容器名/ID bash# 退出容器
exit    #直接退出
crlt + P 再按 ctrl + Q     #退出容器但是不终止运行docker相关服务   ------------------------------------------------------------------------
systemctl start docker   #启动服务
systemctl status docker   #查看状态  active(runing)表示已启动
systemctl stop docker   #停止服务ubuntu防火墙  ---------------------------------------------------------------------------
sudo ufw status  #查看防火墙状态,inactive是关闭,active是开启
sudo ufw enable  #开启防火墙
udo ufw disable  #关闭防火墙

三、创建macvlan网络连接的容器

3.1 创建macvlan网络

        创建容器时必须选择连接一个网络,如果不选择就是默认桥接模式brideg,可以使用docker network ls查看目前存在的网络。

sudo docker network create \--driver macvlan \--subnet=<你的宿主机子网,如192.168.0.0/24> \--gateway=<你的宿主机网关> \-o parent=物理接口名称,如ens33 \net-1

 参数介绍:

  •  --driver macvlan:指定网络类型为macvlan。
  • --subnet:192.168.1.0/24表示容器将会从这个子网范围内分配IP地址
  • --gateway: 通过宿主机网关容器知道如何路由到外部网络
  • -o parent: 指定macvlan网络将绑定到宿主机的哪个物理网络接口
  • net-1: 这个是你创建的网络名称

 3.2 查询创建网络时需要的相关信息

docker network ls   #显示所有网络,如net-1

 ip addr  #查看所有网络接口的详细信息       ifconfig也可以

 查询信息如下列所示:

  我的物理网络接口为ens33,所以接口的IP地址配置显示为192.168.1.100/24。这里的/24就是子网掩码的CIDR表示形式,意味着网络部分有24个二进制的1,即子网掩码为255.255.255.0。因此,从这个输出中可以看出,该接口配置在一个子网为192.168.1.0/24的网络中,一般来说默认网关就是你的ip地址,比如这里的192.168.1.100。如果不确定则按下面步骤查询。

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000inet 192.168.1.100/24 brd 192.168.1.255 scope global dynamic ens33valid_lft 3444sec preferred_lft 3444sec

ip route  #查看路由表,网关,其中包括了目标网络、网关、接口、标志以及路由的优先级等信息。路由表来决定数据包应当通过哪个接口(网络接口卡,如 Ethernet 卡)以及下一跳的IP地址(通常是网关)来转发数据。

default via [网关IP] dev [网络接口名称] proto [协议] metric [数值]
  • [网关IP]:这部分显示的就是你的默认网关地址。
  • [网络接口名称]:表示数据包将通过哪个网络接口发送到默认网关。
  • [协议]:可能是dhcp, static, kernel, boot等,表示路由设置的来源。
  • [数值]:metric值,用于衡量路径的优先级,数值越小优先级越高。 

3.3 创建一个docker容器

sudo docker run -itd \--name container-1 \--network=net-1 \--ip=192.168.0.61  \-v /home/norten/Public/tools:/mnt \ubuntu

  参数介绍:

  • -i: 表示以交互模式运行容器,即使没有连接到终端也会保持STDIN(标准输入)打开
  • -t: 为容器分配一个伪TTY(虚拟终端),这使得它看起来更像是一个交互式会话
  • -d: 表示以后台模式运行容器(守护进程模式),你不会直接看到容器的输出,但容器会在后台持续运行
  • --name container-1: 为新创建的容器指定一个名称
  • --network=net-1: 指定容器要加入的网络名为net-1
  • --ip=192.168.0.61: 为容器指定了一个固定的IP地址
  • -v /home/norten/Public/tools:/mnt: 使用卷挂载功能,将宿主机的/home/norten/Public/tools目录挂载到容器内的/mnt目录,mnt全称为mount挂载
  • ubuntu: 这是告诉Docker使用ubuntu镜像作为基础来创建容器

需要注意的是:

  1. 容器要先使用docker start [容器名称] 命令启动后才能够进入容器内部
  2. 可以使用dokcer ps查看所有正在运行的容器,docker ps -a显示所有存在的容器
  3. 使用docker exec -it [容器名称] bash 进入容器后,使用exit退出时容器仍正常运行
  4. 使用docker attach [容器名称] 进入容器后,使用exit退出容器则容器停止运行
  5. 可以使用docker inspect [网络名称] 查看该网络所有相关的信息
  6. 可以使用docker inspect [容器名称] 查看该容器所有相关的信息,如以下图片所示
docker inspect container-1

Mounts:  (对应mnt)

Networks: 

同样的,我们可以使用 docker inspect net-1 来查看这个网络上所连接的容器

(这里展示的是部分容器连接)

        上面我们是使用了ssh终端(MobaXterm)来实现与ubuntu宿主机的交互,在宿主机上使用卷挂载来实现宿主机与容器之间的交互。还有一种方式可以实现windows电脑与ubuntu宿主机之间共享文件,具体看:

  • ubuntu访问windows共享文件夹-CSDN博客
  • 在ubuntu中创建容器并挂载windows共享的文件(SMB挂载到本地后,本地的文件再挂载到容器中)-CSDN博客

        除此以外,容器在创建的时候还可以指定DNS,先查询宿主机的DNS,再指定容器的DNS,则能够让容器与宿主机DNS一致,是否需要看个人用途,这个不作过多介绍 

sudo docker run -itd \--name container-5 \--network=my-macvlan-1 \--ip=192.168.0.65  \-v /home/norten/Desktop/SmbShare:/home/public/tools/MediumBoxBase \--dns 宿主机DNS \--dns 8.8.8.8 \--dns 114.114.114.114 \--dns-opt="ndots:0" \--dns-opt="edns0" \ubuntu

3.4 docker容器的使用

进入容器后直接使用脚本:./mnt/container_run_medium.sh

 container_run_medium.sh内的脚本内容:

rm -f *.log
rm -f nohup.out
rm -f cssd.dat
nohup /mnt/simutools/pwbox_simu /mnt/simutools/pw_box.conf &
/mnt/mediumSimu/MediumBoxBase /mnt/mediumSimu/hynn_flash_config_simu.conf 
  • 查看当前容器ID
    cat /etc/hostname
  • 查看当前所在容器名称:
    docker inspect --format '{{.Name}}' 容器ID

脚本docker_operations.sh: 

#!/bin/bash# all definition
NETWORK_NAME="net-1"
VOLUME_MOUNT="-v /home/norten/Public/tools:/mnt"
IMAGE_NAME="ubuntu"# View help command
function help_container() {echo "/mnt/simutools# ./pwbox_simu pw_box.conf "echo "/mnt/mediumSimu# ./MediumBoxBase hynn_flash_config_simu.conf  "echo " "echo " "echo "create: ./docker_operations.sh create [num]"   #创建一个容器echo "./docker_operations.sh create 20 *means* create container-20 ,ip=192.168.0.80"echo " "echo " "echo "start: ./docker_operations.sh start [start_num] [end_num]"  #启动容器echo "./docker_operations.sh start 20 25 *means* start 20-25 containers"echo "./docker_operations.sh start 20 *means* start one container"echo " "echo " "echo "exec: ./docker_operations.sh exec [num] "   #进入容器echo "./docker_operations.sh exec 20  *means* execute container-20"echo "After you execute container ,you should use <exit> to exit your container"echo " "echo " "echo "stop: ./docker_operations.sh stop [start_num] [end_num]"   #停止容器echo "./docker_operations.sh stop 20 25 *means* stop 20-25 containers"echo "./docker_operations.sh stop 20 *means* stop one container"echo " "echo " "echo "remove: ./docker_operations.sh remove [num] "   #删除容器echo "./docker_operations.sh remove 20  *means* remove container-20"echo " "echo " "echo "info: ./docker_operations.sh info [container_ID] "echo " ./docker_operations.sh info a536fbad17b4 *means* view the container name"    #进入容器后输入命令左边那一串就是容器的IDecho " "echo " "echo "<docker ps>"   #查看所有的容器echo "Used to see which containers are running"echo " "echo " "echo "<docker ps -a>"  #查看正在运行的容器echo "Used to see all containers exist"echo " "echo " "echo "<docker inspect container-[num]>"echo "Used to check all information about a container"echo " "echo " "}# Dynamic container creation
function create_container() {echo "create zero paremeter is: $0"  echo "create first paremeter is: $1"echo "create second paremeter is: $2"  local num="$1"local CONTAINER_IP="192.168.0.$((num+60))"echo "IP IS $CONTAINER_IP"local CONTAINER_NAME="container-$num"# Check whether the IP address is already in uselocal existing_ips=($(docker inspect --format='{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq) 2>/dev/null))for ip in "${existing_ips[@]}"; doif [[ "$ip" == "$CONTAINER_IP" ]]; thenecho "Error: IP Address $CONTAINER_IP is already in use by another container."exit 1fidone  # Trying to create a containerdocker run -itd \--name "$CONTAINER_NAME" \--network="$NETWORK_NAME" \--ip="$CONTAINER_IP" \$VOLUME_MOUNT \$IMAGE_NAME \&& echo "Container $CONTAINER_NAME created with IP $CONTAINER_IP." \|| { echo "Failed to create container $CONTAINER_NAME."; exit 1; }}# Start specified or a range of containers
function start_container() {echo "start zero paremeter is: $0"  echo "start first paremeter is: $1"echo "start second paremeter is: $2"local start_num="$1"local end_num="${2:-$start_num}"  # If the second argument is not provided, it defaults to the value of the first argumentfor (( i=start_num; i<=end_num; i++ )); dolocal CONTAINER_NAME="container-$i"if docker ps -a --format '{{.Names}}' | grep -q "^$CONTAINER_NAME\$"; thenecho "Starting container $CONTAINER_NAME..."docker start "$CONTAINER_NAME"echo "Container $CONTAINER_NAME started."elseecho "Error: Container $CONTAINER_NAME does not exist."exit 1fidone
}# Stop specified or a range of containers
function stop_container() {local start_num="$1"local end_num="${2:-$start_num}"  # If the second argument is not provided, it defaults to the value of the first argumentfor (( i=start_num; i<=end_num; i++ )); dolocal CONTAINER_NAME="container-$i"if docker ps -a --format '{{.Names}}' | grep -q "^$CONTAINER_NAME\$"; thenecho "Stopping container $CONTAINER_NAME..."docker stop "$CONTAINER_NAME"echo "Container $CONTAINER_NAME stopped."elseecho "Warning: Container $CONTAINER_NAME does not exist."fidone
}# Enter the shell of a specified container
function exec_container() {local container_num="$1"local CONTAINER_NAME="container-$container_num"if docker ps -a --format '{{.Names}}' | grep -q "^$CONTAINER_NAME\$"; thenecho "Entering container $CONTAINER_NAME..."docker exec -it "$CONTAINER_NAME" bash  elseecho "Error: Container $CONTAINER_NAME does not exist or is not running."exit 1fi
}# Remove a specified container
function remove_container() {local container_num="$1"local CONTAINER_NAME="container-$container_num"if docker ps -a --format '{{.Names}}' | grep -q "^$CONTAINER_NAME\$"; thenecho "Removing container $CONTAINER_NAME..."docker rm -f "$CONTAINER_NAME"echo "Container $CONTAINER_NAME removed."elseecho "Error: Container $CONTAINER_NAME does not exist."exit 1fi
}# 添加一个新的函数来查询容器信息
function info_container() {local search_term="$1"local containers_info=$(docker ps -a --format '{{.ID}} {{.Names}}' | grep "$search_term")if [ -z "$containers_info" ]; thenecho "No container found matching '$search_term'."return 1fiecho "Matching containers:"echo "$containers_info" | while read -r container_id container_name; doecho "ID: $container_id, Name: $container_name"done
}case "$1" inhelp)help_container;;create)if [ "$#" -ne 2 ]; thenecho "Error: You should provide a parameter after 'create'."exit 1fiif ! [[ "$2" =~ ^[1-9][0-9]{0,2}|[1-9][0-9]{3}$ ]]; thenecho "Error: The number must be an integer between 1 and 1000."exit 1ficreate_container "$2";;start)# Check the number of parameters to determine whether to start a single container or a container rangeif [ "$#" -lt 2 ]; thenecho "Error: You should provide at least one number after 'start'."exit 1elif [ "$#" -eq 2 ]; then# If there are only two parameters, try starting a containerstart_container "$2"elif [ "$#" -eq 3 ]; then# If you have three parameters, try starting a series of containersif ! [[ "$2" =~ ^[1-9][0-9]{0,2}|[1-9][0-9]{3}$ ]] || ! [[ "$3" =~ ^[1-9][0-9]{0,2}|[1-9][0-9]{3}$ ]]; thenecho "Error: Both numbers must be integers between 1 and 1000."exit 1fiif [ "$2" -gt "$3" ]; thenecho "Error: The first number must be less than or equal to the second."exit 1fistart_container "$2" "$3"elseecho "Error: Too many arguments for 'start'."exit 1fi;;stop)if [ "$#" -lt 2 ]; thenecho "Error: You should provide at least one number after 'stop'."exit 1fiif ! [[ "$2" =~ ^[1-9][0-9]{0,2}|[1-9][0-9]{3}$ ]]; thenecho "Error: The number(s) must be integers between 1 and 1000."exit 1fiif [ "$#" -eq 2 ]; thenstop_container "$2"elif [ "$#" -eq 3 ]; thenif ! [[ "$3" =~ ^[1-9][0-9]{0,2}|[1-9][0-9]{3}$ ]]; thenecho "Error: Both numbers must be integers between 1 and 1000."exit 1fiif [ "$2" -gt "$3" ]; thenecho "Error: The second number must be greater than or equal to the first."exit 1fistop_container "$2" "$3"elseecho "Error: Too many arguments for 'stop'."exit 1fi;;exec)if [ "$#" -ne 2 ]; thenecho "Error: You should provide exactly one number after 'exec'."exit 1fiif ! [[ "$2" =~ ^[1-9][0-9]{0,2}|[1-9][0-9]{3}$ ]]; thenecho "Error: The number must be an integer between 1 and 1000."exit 1fiexec_container "$2";;remove)if [ "$#" -ne 2 ]; thenecho "Error: You should provide exactly one number after 'remove'."exit 1fiif ! [[ "$2" =~ ^[1-9][0-9]{0,2}|[1-9][0-9]{3}$ ]]; thenecho "Error: The number must be an integer between 1 and 1000."exit 1firemove_container "$2";;info)if [ "$#" -ne 2 ]; thenecho "Usage: $0 info <container_search_term>"exit 1fiinfo_container "$2";;logs|status)echo "Function '$1' has not been updated to handle numbered containers."exit 1;;*)echo "Invalid command. Use './docker_operations.sh help' to get instructions."exit 1;;
esacexit 0

 

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

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

相关文章

mybatisplus字段注入MetaObjectHandler扫描不到我的指定填充字段

使用mybatisplus自带的字段填充策略注入值的时候&#xff0c;发现并没有扫描到我的指定字段。 1. 初始代码 Component Slf4j public class MyMetaObjectHandler implements MetaObjectHandler {private static final String createByFiled "createBy";private stati…

Python数据可视化---pygal模块(基础篇)

pygal模块 安装pygal模块 pygal模块的安装非常简单&#xff0c;只需输入一行pip命令即可 pip install pygal安装完成&#xff1a; pygal模块介绍 pygal官网地址 pygal是Python的第三方库&#xff0c;他的主要功能就是数据可视化&#xff0c;即将数字转化成图表的形式来呈…

情绪管理篇:让七情自然流露,不过分压抑也不掺杂极端的想法即可来去自如

情绪管理篇&#xff1a; 人有七情&#xff0c;本属常理&#xff0c;该哭的时候哭、该笑的时候笑、该怒的时候怒、该忧的时候忧 学习圣贤之学&#xff0c;并非让我们像木头人一样&#xff0c;枯木死灰&#xff0c;而要让自己不要被七情所缠缚、被七情所乱心&#xff0c;我们的喜…

ONLYOFFICE 文档 8.1 现已发布:功能全面的 PDF 编辑器、幻灯片版式等等

0、前言 在技术的快速发展和工作方式的持续演进下&#xff0c;现代办公软件正变得越来越强大和多样化。ONLYOFFICE&#xff0c;作为市场上备受瞩目的一体化办公解决方案&#xff0c;以其全面的文档编辑、表格处理和演示制作功能&#xff0c;满足了用户在不同办公场景下的需求。…

Hi3861 OpenHarmony嵌入式应用入门--LiteOS Mutex

CMSIS 2.0接口中的Mutex&#xff08;互斥锁&#xff09;是用于在多线程环境中保护共享资源的访问机制。Mutex&#xff08;互斥锁&#xff09;是一种特殊的信号量&#xff0c;用于确保同一时间只有一个线程可以访问特定的共享资源。 在嵌入式系统或多线程应用中&#xff0c;当多…

Mysql索引底层数据结构——Java全栈知识(28)

Mysql索引底层数据结构 1、什么是索引 索引在项目中还是比较常见的&#xff0c;它是帮助MySQL高效获取数据的数据结构&#xff0c;主要是用来提高数据检索的效率&#xff0c;降低数据库的IO成本&#xff0c;同时通过索引列对数据进行排序&#xff0c;降低数据排序的成本&…

arduino按钮

Arduino - Button Arduino - 按钮 参考&#xff1a; ezButton-按钮库从按钮开关看上拉pull-up电阻、下拉电阻按键的防抖动处理 The button is also called pushbutton, tactile button or momentary switch. It is a basic component and widely used in many Arduino projec…

【gif制作】Win下视频生成GIF;工具GifCam单色保存,灰度保存,调速,编辑删除帧添加文本

下载地址 https://blog.bahraniapps.com/gifcam/#download https://gifcam.en.softonic.com/ 界面功能 GifCam 简洁、小巧的 gif 录制软件。GifCam就像照相机一样位于所有窗口的顶部&#xff0c;可以移动它并调整其大小录屏所需的区域。 如图&#xff1a;空闲状态下窗口内…

给XPTABLE添加右键菜单(XPTable控件使用说明十一)

用户右键点击TABLE控件&#xff0c;弹出一个菜单&#xff0c;选择菜单对应到相关的操作 1、增加一个contextMenuStrip6控件&#xff0c;在里面增加2个ITEM&#xff0c;名称用中文命名 2、给两个ITEM添加点击后的事件 3、在XPTABLE上增加点击事件&#xff1a; 4、当用户右键点击…

vantUI upload 上传组件v-model绑定问题

直接绑定一个数组会有问题,删除失效/上传不了等等 解决在v-model绑定的数组外包一个对象即可

零基础MySQL完整学习笔记

零基础MySQL完整学习笔记 1. 基础操作(必须会!)1.1 修改密码(4种方法)1.2 创建新用户1.3 导入数据库 2. SQL四种语言介绍2.1 DDL(数据库定义语言)2.2 DML(数据操纵语言)2.3 DCL(数据库控制语言)2.4 TCL(事务控制语言) 3. 数据库操作3.1 创建数据库3.2 查询数据库3.3 删除数据库…

聊聊 oracle varchar2 字段的gbk/utf8编码格式和字段长度问题

聊聊 oracle varchar2 字段的gbk/utf8编码格式和字段长度问题 1 问题现象 最近在排查某客户现场的数据同步作业报错问题时&#xff0c;发现了部分 ORACLE 表的 varchar2 字段&#xff0c;因为上游 ORACLE数据库采用 GBK 编码格式&#xff0c;而下游 ORACLE 数据库采用UTF8 编…

封装了一个优雅的iOS转场动画

效果图 代码 // // LBTransition.m // LBWaterFallLayout_Example // // Created by mac on 2024/6/16. // Copyright © 2024 liuboliu. All rights reserved. //#import "LBTransition.h"interface LBPushAnimation:NSObject<UIViewControllerAnimated…

【服务器02】之【阿里云平台】

百度一下阿里云官网 点击注册直接使用支付宝注册可以跳过认证 成功登录后&#xff0c;点击产品 点击免费试用 点击勾选 选一个距离最近的 点满GB 注意&#xff1a;一般试用的时用的是【阿里云】&#xff0c;真正做项目时用的是【腾讯云】 现在开始学习使用&#xff1a; 首先…

2024年综合艺术与媒体传播国际会议(ICIAMC 2024)

2024年综合艺术与媒体传播国际会议(ICIAMC 2024) 2024 International Conference on Integrated Arts and Media Communication (ICIAMC 2024) 会议地点&#xff1a;贵阳&#xff0c;中国 网址&#xff1a;www.iciamc.com 邮箱: iciamcsub-conf.com 投稿主题请注明:ICIAMC…

【Python机器学习】DBSCAN(具有噪声的基于密度的空间聚类应用)

DBSCAN&#xff08;具有噪声的基于密度的空间聚类应用&#xff09;是一种非常有用的聚类算法&#xff0c;它的主要优点是不需要用户先验地设置簇的个数&#xff0c;可以划分具有复杂形状的簇&#xff0c;还可以找出不属于任何簇的点。DBSCAN比凝聚聚类和k均值稍慢&#xff0c;但…

常见加密方式:MD5、DES/AES、RSA、Base64

16/32位的数据&#xff0c;最有可能就是使用md5加密的 使用对称加密的时候&#xff0c;双方使用相同的私钥 私钥&#xff1a;单独请求/隐藏在前端的隐藏标签当中 二、RSA非对称密钥加密 公钥加密&#xff0c;私钥解密 私钥是通过公钥计算生成的 加密解密算法都在js源文件当…

U盘数据恢复全攻略:从原理到实践

一、引言&#xff1a;为何U盘数据恢复至关重要 在信息化时代&#xff0c;U盘作为便携存储设备&#xff0c;广泛应用于各个领域。然而&#xff0c;U盘数据的丢失往往给个人和企业带来极大的困扰。数据丢失的原因多种多样&#xff0c;可能是误删除、格式化、文件系统损坏&#x…

session 共享、Nginx session 共享、Token、Json web Token 【JWT】等认证

.NET JWT JWT 》》Json Web Token header . payload . Signature 三部分组成 JWT 在线生成 》》 https://jwt.io/ 》》https://tooltt.com/jwt-encode/ 》》解码工具 https://tool.box3.cn/jwt.html JWT 特点 无状态 JWT不需要在服务端存储任何状态&#xff0c;客户端可以携…

【FFMPEG+Mediamtx】 本地RTSP测试推流记录

利用本地FFMPEGMediamtx 搭建本地RTSP测试推流电脑摄像头 起因 本来要用qt的qml的Video做摄像头测试。 &#x1f614;但是&#xff0c;不在现场&#xff0c;本地测试&#xff0c;又要测试rtsp流&#xff0c;又因为搜了一圈找不到一个比较好的在线测试rtsp推流网址&#x1f6…