【docker】12. Docker Volume(存储卷)
什么是存储卷?
存储卷就是将宿主机的本地文件系统中存在的某个目录直接与容器内部的文件系统上的某一目录建立绑定关系。这就意味着,当我们在容器中的这个目录下写入数据时,容器会将其内容直接写入到宿主机上与此容器建立了绑定关系的目录。
在宿主机上的这个与容器形成绑定关系的目录被称作存储卷。卷的本质是文件或者目录,它可以绕过默认的联合文件系统,直接以文件或目录的形式存在于宿主机上。
宿主机的/data/web 目录与容器中的/container/data/web 目录绑定关系,然后容器中的进程向这个目录中写数据时,是直接写在宿主机的目录上的,绕过容器文件系统与宿主机的文件系统建立关联关系,使得可以在宿主机和容器内共享数据库内容,让容器直接访问宿主机中的内容,也可以宿主机向容器写入内容,容器和宿主机的数据读写是同步的。
生活案例
存储卷就相当于租了个地下室,建立对应的映射就相当于有了这个地下室的钥匙,能够使用房子以外的空间。
如果有一天龙卷风来了,房子被吹毁了,但是地下室依然安然无恙,就相当于容器销毁了我们的这个地下室依然没有影响。
为什么需要存储卷?
- 数据丢失问题
容器按照业务类型,总体可以分为两类:
• 无状态的(数据不需要被持久化)
• 有状态的(数据需要被持久化)
显然,容器更擅长无状态应用。因为未持久化数据的容器根目录的生命周期与容器的生命周期一样,容器文件系统的本质是在镜像层上面创建的读写层,运行中的容器对任何文件的修改都存在于该读写层,当容器被删除时,容器中的读写层也会随之消失。
虽然容器希望所有的业务都尽量保持无状态,这样容器就可以开箱即用,并且可以任意调度,但实际业务总是有各种需要数据持久化的场景,比如 MySQL、Kafka 等有状态的业务。因此为了解决有状态业务的需求,Docker 提出了卷(Volume)的概念。 - 性能问题
UnionFS 对于修改删除等,一般效率非常低,如果对一于 I/O 要求比较高的应用,如redis 在实现持化存储时,是在底层存储时的性能要求比较高。 - 宿主机和容器互访不方便
宿主机访问容器,或者容器访问要通过 docker cp 来完成,应用很难操作 - 容器和容器共享不方便
存储卷分类
目前 Docker 提供了三种方式将数据从宿主机挂载到容器中
• volume docker 管理卷,默认映射到宿主机的/var/lib/docker/volumes 目录下,只需要在容器内指定容器的挂载点是什么,而被绑定宿主机下的那个目录,是由容器引擎 daemon 自行创建一个空的目录,或者使用一个已经存在的目录,与存储卷建立存储关系,这种方式极大解脱用户在使用卷时的耦合关系,缺陷是用户无法指定那些使用目录,临时存储比较适合;
• bind mount 绑定数据卷,映射到宿主机指定路径下,在宿主机上的路径要人工的指定一个特定的路径,在容器中也需要指定一个特定的路径,两个已知的路径建立关联关系
• tmpfs mount 临时数据卷,映射到于宿主机内存中,一旦容器停止运行,tmpfs mounts 会被移除,数据就会丢失,用于高性能的临时数据存储。
管理卷 Volume
创建卷
存储卷可以通过命令方式创建,也可以在创建容器的时候通过 -v and --mount 指定。
方式一:Volume 命令操作
命令清单如下
命令 | 别名 | 功能 | 备注 |
---|---|---|---|
docker volume create | 创建存储卷 | ||
docker volume inspect | 显示存储卷详细信息 | ||
docker volume ls | docker volume list | 列出存储卷 | |
docker volume prune | 清理所有无用数据卷 | ||
docker volume rm | 删除卷,使用中的无法删除 |
docker volume create
• 功能
○ 创建存储卷
• 语法
docker volume create [OPTIONS] [VOLUME]
• 关键参数
○ -d, --driver:指定驱动,默认是 local
○ --label:指定元数据
• 样例
docker volume create my-vol
docker volume inspect
• 功能
○ 查看卷详细信息
• 语法
docker volume inspect [OPTIONS] VOLUME [VOLUME...]
• 关键参数
○ -f:指定相应个格式,如 json
• 样例
docker volume inspect my-vol
docker volume ls
• 功能
○ 列出卷
• 语法
docker volume ls [OPTIONS]
• 关键参数
○ --format:指定相应个格式,如 json,table
○ --filter,-f: 过滤
○ -q: 仅显示名称
• 样例
docker volume ls
docker volume rm
• 功能
○ 删除卷,需要容器不使用。
• 语法
docker volume rm [OPTIONS] VOLUME [VOLUME...]
• 关键参数
○ -f,–force:强制删除
• 样例
docker volume rm hello
docker volume prune
• 功能
○ 删除不使用的本地卷
• 语法
docker volume prune [OPTIONS]
• 关键参数
○ --filter:过滤
○ -f, --force :不提示是否删除
• 样例
docker volume prune
方式二:-v 或者–mount 指定
-v 和-mount 都可以完成管理卷的创建
-v 参数
• 功能:
完成目录映射
• 语法
docker run -v name:directory[:options] .........
• 参数
○ 第一个参数:卷名称
○ 第二个参数:卷映射到容器的目录
○ 第三个参数:选项,如 ro 表示 readonly
• 样例
docker run -d --name devtest -v myvol2:/app nginx:latest
通过 docker inspect 可以看到
root@LAPTOP-H2EI4I6A:~# docker inspect devtest
–mount 参数
• 功能:
完成目录映射
• 语法
--mount '<key>=<value>,<key>=<value>'
• 关键参数
○ type : 类型表示 bind, volume, or tmpfs
○ source ,src :对于命名卷,这是卷的名称。对于匿名卷,省略此字段。
○ destination,dst,target:文件或目录挂载在容器中的路径
○ ro,readonly: 只读方式挂载
完成目录映射
• 样例
采用 mount 创建 volume
docker run -d --name devtest --mount source=myvol2,target=/app nginx:latest
通过 docker inspect 可以看到
方式三:Dockerfile 匿名卷
通过 Dockerfile 的 VOLUME 可以创建 docker 管理卷。
我们也可以通过 dockerfile 的 VOLUME 指令在镜像中创建 Data Volume,这样只要通过该镜像创建的容器都会存在挂载点,但值得注意的是通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,而是由 docker 随机生成的。
操作案例
Docker 命令创建管理卷
- 命令创建管理卷
root@139-159-150-152:/data/myworkdir/fs# docker volume create test_volume
test_volumeroot@139-159-150-152:/data/myworkdir/fs# docker container run --name nginx1 -d -p 80:80 -v test_volume:/usr/share/nginx/html nginx:1.22.1
cf56ecd6a4876a7be7ba09170c01698dc51ceb887d4faf423cf6cc4800b8ef65
- 查看我们的 docker 管理卷
root@139-159-150-152:/data/myworkdir/fs# docker volume ls
DRIVER VOLUME NAME
local test_volume
- 我们查看其中一个管理卷,可以看到对应的宿主机目录如下
root@139-159-150-152:/data/var/lib/docker/volumes# docker volume
- 我们进入宿主机目录,可以放到容器里面的内容已经放到该目录了
root@139-159-150-152:/data/var/lib/docker/volumes# cd /data/var/lib/docker/volumes/test_volume/_data
root@139-159-150-152:/data/var/lib/docker/volumes/test_volume/_data# ll
total 16
drwxr-xr-x 2 root root 4096 Mar 16 12:32 ./
drwx-----x 3 root root 4096 Mar 16 12:16 ../
-rw-r--r-- 1 root root 497 Oct 19 16:02 50x.html
-rw-r--r-- 1 root root 615 Oct 19 16:02 index.html
root@139-159-150-152:/data/var/lib/docker/volumes/test_volume/_data#
- 查看容器内容,可以看到我们的具体的 mount 信息
root@139-159-150-152:~# docker inspect nginx1
- 我们修改 index.html
cd /data/var/lib/docker/volumes/test_volume/_data
echo "hello docker" > index.html
- 通过浏览器查看
可以看到宿主机和容器是同步的 - 停止容器释放空间
docker stop nginx1
docker rm nginx1
结论:宿主机和容器之间数据是同步的
Docker -v 创建管理卷
- -v 创建管理卷,并且启动容器**(ro 就是指定了容器内挂载点对应的文件系统路径为只读模式)**
docker container run --name nginx2 -d -p 80:80 -v test_volume2:/usr/share/nginx/html:ro nginx:1.22.1
- 进入卷目录
hacha@LAPTOP-H2EI4I6A:~$ docker inspect test_volume2
root@LAPTOP-H2EI4I6A:/home/hacha# cd /var/lib/docker/volumes/test_volume2/_data
root@LAPTOP-H2EI4I6A:/var/lib/docker/volumes/test_volume2/_data# ls
50x.html index.html
- 修改 index.html
root@LAPTOP-H2EI4I6A:/var/lib/docker/volumes/test_volume2/_data# echo "Hello docker" > index.html
root@LAPTOP-H2EI4I6A:/var/lib/docker/volumes/test_volume2/_data# cat index.html
Hello docker
- 浏览器查看
- 容器中修改提示无法修改
root@139-159-150-152:/data# docker exec -it nginx2 bash
root@ad570265c31e:/# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh
etc home lib lib64 media mnt opt proc root run
sbin srv sys tmp usr var
root@ad570265c31e:/# cd /usr/share/nginx/html/
root@ad570265c31e:/usr/share/nginx/html# rm index.html
rm: cannot remove 'index.html': Read-only file system
root@ad570265c31e:/usr/share/nginx/html#
- 清理释放空间
docker stop nginx2
docker rm nginx2
结论:指定 ro 的话宿主机可以修改,但是容器里面无法修改 因为启动的时候给容器内部的路径带了ro参数(read only)
Docker mount 创建管理卷
- mount 创建管理卷,并且启动容器
docker container run --name nginx3 -d -p 8081:80 --mount type=volume,source=test_volume3,target=/usr/share/nginx/html nginx:1.22.1
- 查看卷创建成功
hacha@LAPTOP-H2EI4I6A:~$ docker volume ls
DRIVER VOLUME NAME
local test_volume
local test_volume2
local test_volume3
- 查看卷挂载点。
- 浏览器查看
- 宿主机上修改文件内容
root@LAPTOP-H2EI4I6A:/home/hacha# cd /var/lib/docker/volumes/test_volume3/_data
root@LAPTOP-H2EI4I6A:/var/lib/docker/volumes/test_volume3/_data# ls
50x.html index.html
root@LAPTOP-H2EI4I6A:/var/lib/docker/volumes/test_volume3/_data# echo "Hello docker , I am hx">index.html
root@LAPTOP-H2EI4I6A:/var/lib/docker/volumes/test_volume3/_data# cat index.html
Hello docker , I am hx
- 查看页面
- 清理释放空间
docker stop nginx3
docker rm nginx3
结论:mount 创建的卷数据也会完成同步。
Docker 卷生命周期
- -v 创建管理卷,并且启动容器
Shell
docker container run --name nginx2 -d -p 80:80 -
vtest_volume2:/usr/share/nginx/html nginx:1.22.1 - 进入卷目录,注意此时可以看到容器里面的内容自动的放到了宿主机里面,也就是说宿主机上没有容器会拷贝过去。
- 修改 index.html
root@LAPTOP-H2EI4I6A:/var/lib/docker/volumes/test_volume2/_data# echo "today is monday">index.html
root@LAPTOP-H2EI4I6A:/var/lib/docker/volumes/test_volume2/_data# cat index.html
today is monday
- 浏览器查看
- 清理释放空间
docker stop nginx2
docker rm nginx2
- 进入卷目录查看可以看到文件并没有被删除
root@139-159-150-152:/data/var/lib/docker/volumes/test_volume2/_data# cd /data/var/lib/docker/volumes/test_volume2/_data
root@139-159-150-152:/data/var/lib/docker/volumes/test_volume2/_data# cat index.html
today is monday
- 删除卷,可以看到我们的卷被删除掉了。
root@139-159-150-152:/data/var/lib/docker/volumes/test_volume2/_data# docker volume rm test_volume2
test_volume2
root@139-159-150-152:/data/var/lib/docker/volumes/test_volume2/_data/./..# ls /data/var/lib/docker/volumes/test_volume2/_data
ls: cannot access '/data/var/lib/docker/volumes/test_volume2/_data': No such file or directory
Docker 卷共享
- -v 创建管理卷,并且启动 2 容器,指定同一个卷
docker container run --name nginx2 -d -p 80:80 -vtest_volume2:/usr/share/nginx/html nginx:1.22.1
docker container run --name nginx3 -d -p 8080:80 -vtest_volume2:/usr/share/nginx/html nginx:1.22.1
- 进入卷目录
root@139-159-150-152:/data/var/lib/docker/volumes/test_volume/_data# docker inspect test_volume2
- 修改 index.html
root@LAPTOP-H2EI4I6A:/var/lib/docker/volumes/test_volume2/_data# echo "today is monday">index.html
root@LAPTOP-H2EI4I6A:/var/lib/docker/volumes/test_volume2/_data# cat index.html
today is monday
- 浏览器查看,可以看到两个都是一样的首页
- 清理释放空间
docker stop nginx2 nginx3
docker rm nginx2 nginx3
绑定卷 bind mount
-v 和-mount 都可以完成绑定卷的创建
创建卷
-v 参数创建卷
• 功能:
完成卷映射
• 语法
docker run -v name:directory[:options] .........
• 参数
○ 第一个参数:宿主机目录,这个和管理卷是不一样的
○ 第二个参数:卷映射到容器的目录
○ 第三个参数:选项,如 ro 表示 readonly
• 样例
docker run -d -it --name devtest -v "$(pwd)"/target:/app nginx:latest
–mount 参数创建绑定卷
• 功能:
完成目录映射
• 语法
--mount '<key>=<value>,<key>=<value>'
• 关键参数
○ type : 类型表示 bind, volume, or tmpfs
○ source ,src :宿主机目录,这个和管理卷是不一样的。
○ destination,dst,target:文件或目录挂载在容器中的路径
○ ro,readonly: 只读方式挂载
• 样例
docker run -d -it --name devtest --mount type=bind,source="$(pwd)"/target,target=/app nginx:latest
操作案例
mount 创建绑定卷
- 使用-mount 方式创建容器: 创建 nginx 容器,并将宿主机/webapp1 目录挂载至容器/usr/share/nginx/html 目录,注意如果 webapp1 目录不存在会启动报错
#创建目录
root@139-159-150-152:/data/myworkdir/fs# mkdir -p /data/myworkdir/fs/webapp1
root@139-159-150-152:/data/myworkdir/fs# docker run -d -p 80:80 --name bind1 --mount type=bind,source=/data/myworkdir/fs/webapp1,target=/usr/share/nginx/html nginx:1.22.1
8acce86ee0ae8e397e6824521113f1084de7890364efa2f1806d600c926a7a65
root@139-159-150-152:/data/var/lib/docker/volumes/test_volume2/_data# docker run -d -p 80:80 --name bind1 --mount type=bind,source=/data/myworkdir/fs/webapp1_new,target=/usr/share/nginx/html nginx:1.22.1
docker: Error response from daemon: invalid mount config for type
"bind": bind source path does not exist:/data/myworkdir/fs/webapp1_new.
See 'docker run --help'.
- 查看挂载信息
root@139-159-150-152:/data/myworkdir/fs# docker inspect bind1"Mounts": [{"Type": "bind","Source": "/data/myworkdir/fs/webapp1","Target": "/usr/share/nginx/html"}],
....
"Mounts": [{"Type": "bind",
"Source": "/data/myworkdir/fs/webapp1","Destination": "/usr/share/nginx/html","Mode": "","RW": true,"Propagation": "rprivate"}],
- 进入容器的终端,查看挂载点目录,和在宿主机上查看里面都是没有文件
root@139-159-150-152:/data/myworkdir/fs# docker exec -it bind1 ls /usr/share/nginx/html
root@139-159-150-152:/data/myworkdir/fs# ll webapp1
total 8
drwxr-xr-x 2 root root 4096 Mar 16 13:39 ./
drwxr-xr-x 9 root root 4096 Mar 16 13:39 ../
可以发现容器该目录本身存在的文件消失不见, 这是 bind mount 模式和 volume 模式最大的不同点
- 我们在宿主机上添加 index.html
root@139-159-150-152:/data/myworkdir/fs# cd
/data/myworkdir/fs/webapp1
root@139-159-150-152:/data/myworkdir/fs/webapp1# echo "Hello bit bind mount" >> index.html
# 这里是追加哦看仔细!
- 通过浏览器访问,可以看到,容器已经读取到宿主机的共享内容了。
- 删除容器,然后查看宿主机上的文件
还是存在,说明容器删除并不影响 bind 映射。
root@139-159-150-152:/data/myworkdir/fs/webapp1# docker stop bind1
bind1
root@139-159-150-152:/data/myworkdir/fs/webapp1# docker rm bind1
bind1
root@139-159-150-152:/data/myworkdir/fs/webapp1# ll
total 12
drwxr-xr-x 2 root root 4096 Mar 16 13:48 ./
drwxr-xr-x 9 root root 4096 Mar 16 13:39 ../
-rw-r--r-- 1 root root 21 Mar 16 13:48 index.html
- 释放空间
root@139-159-150-152:/data/myworkdir/fs/webapp1# docker stop bind2
bind2
root@139-159-150-152:/data/myworkdir/fs/webapp1# docker rm bind2
bind2
-v 创建绑定卷
- 使用-v 方式创建容器: 创建 nginx 容器,并将宿主机/webapp2 目录挂载至容器/usr/share/nginx/html 目录,
注意如果 webapp2 目录不存在,启动不会报错,这是-v 和–mount 方式的区别
docker run -d -p 8080:80 --name bind2 -v /data/myworkdir/fs/webapp2:/usr/share/nginx/html nginx:1.22.1
- 查看挂载信息
root@139-159-150-152:/data/myworkdir/fs# docker inspect bind2
"Mounts": [{"Type": "bind","Source": "/data/myworkdir/fs/webapp2","Destination": "/usr/share/nginx/html","Mode": "","RW": true,"Propagation": "rprivate"}],
- 进入容器的终端,查看挂载点目录,和在宿主机上查看里面都是没有文件
root@139-159-150-152:/data/myworkdir/fs# docker exec -it bind2 ls
/usr/share/nginx/html
root@139-159-150-152:/data/myworkdir/fs# ll webapp1
total 8
drwxr-xr-x 2 root root 4096 Mar 16 13:39 ./
drwxr-xr-x 9 root root 4096 Mar 16 13:39 ../
可以发现容器该目录本身存在的文件消失不见, 这是 bind mount 模式和 volume 模式最大的不同点
4. 我们在宿主机上添加 index.html
root@139-159-150-152:/data/myworkdir/fs# cd /data/myworkdir/fs/webapp2
root@139-159-150-152:/data/myworkdir/fs/webapp2# echo "Hello bit bind2 mount" > index.html
- 通过浏览器访问,可以看到,容器已经读取到宿主机的共享内容了。
- 删除容器,然后查看宿主机上的文件,还是存在,说明容器删除并不影响 bind 映射。
root@139-159-150-152:/data/myworkdir/fs/webapp2# docker stop bind2
bind1
root@139-159-150-152:/data/myworkdir/fs/webapp2# docker rm bind2
bind1
root@139-159-150-152:/data/myworkdir/fs/webapp2# ll
total 12
drwxr-xr-x 2 root root 4096 Mar 16 13:48 ./
drwxr-xr-x 9 root root 4096 Mar 16 13:39 ../
-rw-r--r-- 1 root root 21 Mar 16 13:48 index.html
绑定卷共享
- 我们启动两个绑定卷,都绑定到宿主机的同一个目录
root@139-159-150-152:/data/myworkdir/fs/webapp1# docker run -d -p 80:80 --name bind3 -v /data/myworkdir/fs/webapp1:/usr/share/nginx/html nginx:1.22.1
31e0ddec8d99b65a22f70c63ab6bd08effe345ad298cbadd886b8e432f8d3711
root@139-159-150-152:/data/myworkdir/fs/webapp1# docker run -d -p 81:80 --name bind4 -v /data/myworkdir/fs/webapp1:/usr/share/nginx/html nginx:1.22.1
6b9676266200f77aa2a763449a0f27e394d2426c17458063c50e0ecdfdbcdd86
- 我们访问者 2 个页面可以看到相应内容一样
root@139-159-150-152:/data/myworkdir/fs/webapp1# curl 127.0.0.1:80
Hello bit bind mount
root@139-159-150-152:/data/myworkdir/fs/webapp1# curl 127.0.0.1:81
Hello bit bind mount
- 我们修改 index.html
root@139-159-150-152:/data/myworkdir/fs/webapp1# echo "bind mount
after edit" > index.html
- 再次访问两个页面,可以看到我们实现了容器间的数据共享。
root@139-159-150-152:/data/myworkdir/fs/webapp1# curl 127.0.0.1:80
bind mount after edit
root@139-159-150-152:/data/myworkdir/fs/webapp1# curl 127.0.0.1:81
bind mount after edit
- 清理空间
docker stop bind3
docker rm bind3
docker stop bind4
docker rm bind4
临时卷 tmpfs
临时卷数据位于内存中,在容器和宿主机之外。
tmpfs 局限性
• 不同于卷和绑定挂载,不能在容器之间共享 tmpfs 挂载。
• 这个功能只有在 Linux 上运行 Docker 时才可用。
创建卷
方式一:指定–tmpfs 创建
• 功能:
完成临时卷映射
• 语法
Shell
–tmpfs /app
• 样例
docker run -d -it --name tmptest --tmpfs /app nginx:1.22.1
方式二:–mount 指定参数创建
• 功能:
完成目录映射
• 语法
--mount '<key>=<value>,<key>=<value>'
• 关键参数
○ type : 类型表示 bind, volume, or tmpfs
○ destination,dst,target:挂载在容器中的路径
○ tmpfs-size:tmpfs 挂载的大小(以字节为单位)。默认无限制。
○ tmpfs-mode:tmpfs 的八进制文件模式。例如,700 或 0770。默认为 1777
或全局可写。
• 样例
docker run -d -it --name tmptest --mount type=tmpfs,destination=/app nginx:latest
操作案例
tmpfs 参数创建临时卷
- 创建临时卷并启动容器
docker container run --name tmpfs1 -d -p 80:80 --tmpfs /usr/share/nginx/html nginx:1.22.1
- 进入容器可以看到 nginx 里面的文件被覆盖了,也就是说 tmpfs 也会覆盖容器里面的文件
root@139-159-150-152:/data/myworkdir/fs/webapp2# docker exec -it tmpfs1 bash
root@1ed9f248b659:/# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh
etc home lib lib64 media mnt opt proc root run
sbin srv sys tmp usr var
root@1ed9f248b659:/# cd /usr/share/nginx/html/
root@1ed9f248b659:/usr/share/nginx/html# ls -l
total 0
root@1ed9f248b659:
- 添加一个首页
root@1ed9f248b659:/usr/share/nginx/html# echo "Hello bit from tmpfs" > index.html
root@1ed9f248b659:/usr/share/nginx/html# cat index.html
Hello bit from tmpfs
- 浏览器查看
- 停止容器
docker stop tmpfs1
- 启动容器 **再次进入,可以看到 tmpfs 的内容完全消失了,也就是说内容是存在内存里面的。**具有一定的隐蔽性,当某些临时文件不想被查看到可以采用临时卷的方式
root@139-159-150-152:/data/myworkdir/fs/webapp2# docker start tmpfs1
tmpfs1
root@139-159-150-152:/data/myworkdir/fs/webapp2# docker exec -it tmpfs1 bash
root@1ed9f248b659:/# ls /usr/share/nginx/html/
root@1ed9f248b659:/#
- 清理空间
docker stop tmpfs1
docker rm tmpfs1
mount 创建临时卷
- 创建临时卷并启动容器
docker container run --name tmpfs1 -d -p 80:80 --mount type=tmpfs,destination=/usr/share/nginx/html,tmpfs-size=1m nginx:1.22.1
- 进入容器可以看到 nginx 里面的文件被覆盖了,也就是说 tmpfs 也会覆盖容器里面的文件
root@139-159-150-152:/data/myworkdir/fs/webapp2# docker exec -it
tmpfs1 bash
root@1ed9f248b659:/# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh
etc home lib lib64 media mnt opt proc root run
sbin srv sys tmp usr var
root@1ed9f248b659:/# cd /usr/share/nginx/html/
root@1ed9f248b659:/usr/share/nginx/html# ls -l
total 0
root@1ed9f248b659:
- 添加一个首页
root@1ed9f248b659:/usr/share/nginx/html# echo "Hello bit from
tmpfs" > index.html
root@1ed9f248b659:/usr/share/nginx/html# cat index.html
Hello bit from tmpfs
- 浏览器查看
- 拷贝一个大文件到容器里面,dockerdemo-1.0-SNAPSHOT.jar 约 17M
docker cp dockerdemo-1.0-SNAPSHOT.jar tmpfs1:/
- 拷贝文件到我们的卷目录,超过了限制,空间限制为了 1m,会提示没有空间。
root@139-159-150-152:/data/maxhou/myapp# docker exec -it tmpfs1 bash
root@1ed9f248b659:/# ls
bin dev docker-entrypoint.sh
etc lib media opt root sbin sys tmp var
boot docker-entrypoint.d dockerdemo-1.0-SNAPSHOT.jar home
lib64 mnt proc run srv test usr
root@1ed9f248b659:/# cd /usr/share/nginx/html
root@1ed9f248b659:/usr/share/nginx/html# cp /dockerdemo-1.0-
SNAPSHOT.jar .
cp: error writing './dockerdemo-1.0-SNAPSHOT.jar': No space left on device
- 停止容器
docker stop tmpfs1
- 启动容器 再次进入,可以看到 tmpfs 的内容完全消失了,也就是说内容是存在内存里面的。
root@139-159-150-152:/data/myworkdir/fs/webapp2# docker start tmpfs1
tmpfs1
root@139-159-150-152:/data/myworkdir/fs/webapp2# docker exec -it tmpfs1 bash
root@1ed9f248b659:/# ls /usr/share/nginx/html/
root@1ed9f248b659:/#
tmpfs 失踪了
实战目的
掌握临时卷的创建方式,了解临时卷的特殊存储方式
实战步骤
- 创建一个普通的容器
root@139-159-150-152:/data/myworkdir/fs/webapp1# docker run -d -it --name tmptest nginx:1.22.1
d3a0da7d9881d9bf8f409e9241c96c9ece826379eda94c3f5cc46ba633356ec3
- 在容器里面写入一个文件 mylabel.txt
root@139-159-150-152:/data/myworkdir/fs/webapp1# docker exec -it tmptest bash
root@d3a0da7d9881:/# mkdir -p /app
root@d3a0da7d9881:/# echo 1 > /app/mylabel.txt
root@d3a0da7d9881:/# exit
exit
- 我们在宿主机上查找文件,文件被找到了,是因为他在容器的可写层
root@139-159-150-152:/data/myworkdir/fs/webapp1# find / -name mylabel.txt
/data/var/lib/docker/overlay2/09ff8b4eb1604296a6e67c80918639eb8f67e7098bd1456551cb2cf858b647a8/merged/app/mylabel.txt
/data/var/lib/docker/overlay2/09ff8b4eb1604296a6e67c80918639eb8f67e7098bd1456551cb2cf858b647a8/diff/app/mylabel.txt
- 我们创建个临时卷
docker run -d --name tmptest2 --tmpfs /app nginx:1.22.1
- 进入容器在/app 目录下创建 mynewlabel.txt
root@139-159-150-152:/data/myworkdir/fs/webapp1# docker exec -it
tmptest2 bash
root@409c2f09b485:/# ls app
root@409c2f09b485:/# echo 222 > /app/mynewlabel.txt
root@409c2f09b485:/# ls /app
mynewlabel.txt
root@409c2f09b485:/# exit
exit
- 在宿主机上查找 mynewlabel.txt,可以发现,文件找不到
root@139-159-150-152:/data/myworkdir/fs/webapp1# find / -name
mynewlabel.txt
root@139-159-150-152:/data/myworkdir/fs/webapp1#
所以 tmpfs 的内容不是存储在我们的容器的可写层里面的。
7. 释放资源
root@139-159-150-152:/data/myworkdir/fs/webapp1# docker stop tmptest
tmptest
root@139-159-150-152:/data/myworkdir/fs/webapp1# docker rm tmptest
tmptest
root@139-159-150-152:/data/myworkdir/fs/webapp1# docker stop tmptest2
tmptest2
root@139-159-150-152:/data/myworkdir/fs/webapp1# docker rm tmptest2
tmptest2
综合实战-MySQL 灾难恢复
实战目的
掌握挂载卷的使用,将 mysql 的业务数据存储到外部
实战步骤
使用 MySQL 5.7 的镜像创建容器并创建一个普通数据卷 mysql-data 用来保存容器中产生的数据。需要在容器中连接 MySQL 服务, 并创建数据库 test, 并在在该数据库中创建一个简单的表并插入一些数据进来。
- 准备镜像
root@139-159-150-152:~# docker pull mysql:5.7
5.7: Pulling from library/mysql
7b659169cb92: Pull complete
e47c3f06a3f5: Pull complete
e0656a27f56e: Pull complete
b9f33f34ef42: Pull complete
9fc5cbaf8704: Pull complete
5fb8407bef93: Pull complete
f8be4a2d031b: Pull complete
b6cb2bff25e3: Pull complete
056cc4a5c89a: Pull complete
842896973144: Pull complete
e55b6e95b292: Pull complete
Digest:
sha256:9202fc6bc8fa63615e6bfc0049fc660f712d164220c5c54d86519870c30
5ea48
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
- 创建容器
root@139-159-150-152:~# docker container run --name mysql-demo -e
MYSQL_ROOT_PASSWORD=bite -itd -v /data/myworkdir/mysql-data:/var/lib/mysql mysql:5.7
c0d8fb5266b554661270cec0145389550a2455e4848023d531ad90bb4d670a04
-e 选项通过参数 MYSQL_ROOT_PASSWORD 来传递 MySQL 密码
3. 查看容器挂载信息
root@139-159-150-152:~# docker container inspect mysql-demo | grep "Mounts" -A 10"Mounts": [{"Type": "bind","Source": "/data/myworkdir/mysql-data","Destination": "/var/lib/mysql","Mode": "","RW": true,"Propagation": "rprivate"}],"Config": {
- 连接 MySQL 的 shell, 创建数据库, 密码是 bite
root@139-159-150-152:~# docker container exec -it mysql-demo
/bin/bash
bash-4.2# mysql -u root -p
Enter password:
ERROR 1045 (28000): Access denied for user 'root'@'localhost'
(using password: YES)
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.41 MySQL Community Server (GPL)
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current
input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql> create database user;
Query OK, 1 row affected (0.00 sec)
mysql> use user
Database changed
mysql> create table student(sno char(3), sname varchar(10));
Query OK, 0 rows affected (0.01 sec)
mysql> insert into student values('1', 'zs'),('2', 'ls');
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from student;
+------+-------+
| sno | sname |
+------+-------+
| 1 | zs |
| 2 | ls |
+------+-------+
2 rows in set (0.00 sec)
mysql> exit
Bye
创建了一个 user 数据库,并在该数据库中创建一个 student 表,在表中插入了两条数据。
5. 在宿主机中查看 volume
root@139-159-150-152:~# ll /data/myworkdir/mysql-data/
total 188488
drwxr-xr-x 6 systemd-coredump root 4096 Mar 16 15:16 ./
drwxr-xr-x 6 root root 4096 Mar 16 15:14 ../
-rw-r----- 1 systemd-coredump systemd-coredump 56 Mar 16 15:14 auto.cnf
-rw------- 1 systemd-coredump systemd-coredump 1680 Mar 16 15:14 ca-key.pem
-rw-r--r-- 1 systemd-coredump systemd-coredump 1112 Mar 16 15:14 ca.pem
-rw-r--r-- 1 systemd-coredump systemd-coredump 1112 Mar 16 15:14 client-cert.pem
-rw------- 1 systemd-coredump systemd-coredump 1676 Mar 16 15:14 client-key.pem
-rw-r----- 1 systemd-coredump systemd-coredump 1318 Mar 16 15:14 ib_buffer_pool
-rw-r----- 1 systemd-coredump systemd-coredump 79691776 Mar 16 15:17 ibdata1
-rw-r----- 1 systemd-coredump systemd-coredump 50331648 Mar 16 15:17 ib_logfile0
-rw-r----- 1 systemd-coredump systemd-coredump 50331648 Mar 16 15:14 ib_logfile1
-rw-r----- 1 systemd-coredump systemd-coredump 12582912 Mar 16 15:14 ibtmp1
drwxr-x--- 2 systemd-coredump systemd-coredump 4096 Mar 16 15:14 mysql/
lrwxrwxrwx 1 systemd-coredump systemd-coredump 27 Mar 16 15:14 mysql.sock -> /var/run/mysqld/mysqld.sock=
drwxr-x--- 2 systemd-coredump systemd-coredump 4096 Mar 16 15:14 performance_schema/
-rw------- 1 systemd-coredump systemd-coredump 1680 Mar 16 15:14 private_key.pem
-rw-r--r-- 1 systemd-coredump systemd-coredump 452 Mar 16 15:14 public_key.pem
-rw-r--r-- 1 systemd-coredump systemd-coredump 1112 Mar 16 15:14 server-cert.pem
-rw------- 1 systemd-coredump systemd-coredump 1680 Mar 16 15:14 server-key.pem
drwxr-x--- 2 systemd-coredump systemd-coredump 12288 Mar 16 15:14 sys/
drwxr-x--- 2 systemd-coredump systemd-coredump 4096 Mar 16 15:17 user/
root@139-159-150-152:~# cd /data/myworkdir/mysql-data/user
root@139-159-150-152:/data/myworkdir/mysql-data/user# ll
total 120
drwxr-x--- 2 systemd-coredump systemd-coredump 4096 Mar 16 15:17 ./
drwxr-xr-x 6 systemd-coredump root 4096 Mar 16 15:16 ../
-rw-r----- 1 systemd-coredump systemd-coredump 65 Mar 16 15:16 db.opt
-rw-r----- 1 systemd-coredump systemd-coredump 8590 Mar 16 15:17 student.frm
-rw-r----- 1 systemd-coredump systemd-coredump 98304 Mar 16 15:17 student.ibd
可以看到容器中 MySQL 创建的数据库和表数据以及持久化到宿主机挂载的目录下了。
6. 有一天莫名其妙停电了, 然后服务器重启了,这个时候 Mysql 没有起来,然后有个哥们看磁盘空间不多了,把所有停止的容器都删除了。结果我们的 Mysql 也没有了。
docker stop mysql-demo
docker rm mysql-demo
- 幸好我们的数据还在,这个时候怎么恢复呢,我们再次启动我们的运行命令,确保目录映射一致就能找回我们的数据了。
root@139-159-150-152:/data/myworkdir/mysql-data/user# docker container run --name mysql-demo-new -e MYSQL_ROOT_PASSWORD=bite -itd -v /data/myworkdir/mysql-data:/var/lib/mysql mysql:5.7
59f87837af7815bd679f06efc95d1ad7420c260442a7318c994c103dee8e5d01
- 我们通过 mysql 的客户端进去,再次查看我们的数据
root@139-159-150-152:/data/myworkdir/mysql-data/user# docker exec -it mysql-demo-new bash
bash-4.2# msyql
bash: msyql: command not found
bash-4.2# msyql -p
bash: msyql: command not found
bash-4.2# msyql -uroot -p
bash: msyql: command not found
bash-4.2# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.41 MySQL Community Server (GPL)
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current
input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| user |
+--------------------+
5 rows in set (0.01 sec)
mysql> use user;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+----------------+
| Tables_in_user |
+----------------+
| student |
+----------------+
1 row in set (0.00 sec)
mysql> select * from student;
+------+-------+
| sno | sname |
+------+-------+
| 1 | zs |
| 2 | ls |
+------+-------+
2 rows in set (0.00 sec)
mysql> exit
Bye
我们的数据还在!!!!
9. 释放空间
docker stop mysql-demo-new
docker rm mysql-demo-new
常见问题
- 什么时候用 Volume,什么时候用 bind、tmpfs?
volume:volume 是 docker 的宿主机文件系统一部分,用于不需要规划具体目录的场景
bind:bind mount 完全是依赖于主机的目录结构和操作系统,用于目录需要提前规划,比如 mysql 的目录需要个空间大的,其他服务有不占用的时候,用 volume 就不太合适了
tmpfs:用于敏感文件存储,文件不想存储的宿主机和容器的可写层之中
扩展思考:存储卷在实际研发中带来了哪些问题
- 跨主机使用
docker 存储卷是使用其所在的宿主机上的本地文件系统目录,也就是宿主机有一块磁盘,这块磁盘并没有共享给其他的 docker 主机,容器在这宿主机上停止或删除,是可以重新再创建的,但是不能调度到其他的主机上,这也是 docker 本身没有解决的问题,所以 docker 存储卷默认就是 docker 所在主机的本地,但是自己搭建一个共享的 NFS来存储 docker 存储的数据,也可以实现,但是这个过程强依赖于运维人员的能力。
所以未来应用的存储和数据往往分离,越来越多的分布式存储方案出现,如 s3 系列,nfs 等。 - 启动参数未知
容器有一个问题,一般与进程的启动不太一样,就是容器启动时选项比较多,如果下次再启动时,很容器会忘记它启动时的选项,所以最好有一个文件来保存容器的启动,这就是容器编排工具的作用。
一般情况下,是使用命令来启动操作 docker,但是可以通过文件来读,也就读文件来启动,读所需要的存储卷等,但是它也只是操作一个容器,如果要几十上百个容器操作,就需要专业的容器编排工具
这种一般像开源的 k8s,各个云厂商也有自己的企业版编排软件。 - 复杂场景仍然需要运维
对于有状态要持久的集群化组件,如 mysql 的主从。部署维护一个 Mysql 主从需要运维知识、经验整合进去才能实现所谓的部署,扩展或缩容,出现问题后修复,必须要了解集群的规模有多大,有多少个主节点,有多少个从节点,主节点上有多少个库,这些都要一清二楚,才能修复故障,这些就强依赖于运维经验这种复杂的场景往往还是需要人力,很难有完美的工具出现。
相关文章:
【docker】12. Docker Volume(存储卷)
什么是存储卷? 存储卷就是将宿主机的本地文件系统中存在的某个目录直接与容器内部的文件系统上的某一目录建立绑定关系。这就意味着,当我们在容器中的这个目录下写入数据时,容器会将其内容直接写入到宿主机上与此容器建立了绑定关系的目录。 在宿主机上…...
1. 机器学习基本知识(4)——机器学习测试和验证
1.6 测试和验证 了解模型对新实例的泛化能力的唯一方法是在新实例上进行实际尝试。 一种方法是将模型部署到生产环境并监控其性能。 这种方法很有效,但如果模型非常糟糕,你的用户就会抱怨,所以这显然不是最好的方法。 更好的选择是将数…...
生成式AI概览与详解
1. 生成式AI概览:什么是大模型,大模型应用场景(文生文,多模态) 生成式AI(Generative AI)是指通过机器学习模型生成新的数据或内容的人工智能技术。生成式AI可以生成文本、图像、音频、视频等多种…...
软件项目标书参考,合同拟制,开发合同制定,开发协议,标书整体技术方案,实施方案,通用套用方案,业务流程,技术架构,数据库架构全资料下载(原件)
1、终止合同协议书 2、项目合作协议 3、合同交底纪要 4、合同管理台账 软件资料清单列表部分文档清单:工作安排任务书,可行性分析报告,立项申请审批表,产品需求规格说明书,需求调研计划,用户需求调查单&…...
C++ extern “C“ 用法
extern “C” 由于c中需要支持函数重载,所以c和c中对同一个函数经过编译后生成的函数名是不相同的 extern “C” 的主要作用就是为了实现c代码能够调用其他 c 语言代码。 1(不常用) //告诉编译器 show() 函数按c语言的方式进行编译和链接 extern "C" voi…...
Node.js(v16.13.2版本)安装及环境配置教程
一、进入官网地址下载安装包 https://nodejs.org/zh-cn/download/ 选择对应你系统的Node.js版本,这里我选择的是Windows系统、64位(v16.13.2版本) 下载后的zip文件 二、解压文件到nodejs,并打开文件夹nodejs,复制解压…...
父组件调用子组件的方法
父组件 在父组件中调用子组件的sayHello()函数 <template><div><button click"getChild(wendu)">触发子组件方法wendu</button><button click"getChild(shidu)">触发子组件方法shidu</button><el-dialog v-model…...
运维排错系列:Excel上传失败,在剪切板有大量信息。是否保存其内容...
问题点 在导入 Excel 数据到 SAP 的时候,某些时刻系统会出现如下的弹窗。 上载 excel 文件时,您会收到错误:“剪贴板上有大量信息。XXX” Microsoft Office Excel 的弹出窗口显示以下信息: 剪贴板上存在大量信息。是否保留其内容…...
【自学】Vues基础
学习目录 Vues基础本地应用网络应用综合应用 工具的准备 我个人比较喜欢使用HTMLDROWNER,学习资料推荐使用VC,仅供选择吧 前置知识 HTMLCSSJSAJAX:这个是学习资料博主推荐的 个人感觉认真学好HTMLCSSJS理解vues基础很容易上手 官方网址…...
ubuntu 7z解压rar文件报错:unsupported method message
问题说明 最近项目需要支持线上上传rar格式,7z来解压缩入库。开发测试过程中发现使用以下命令解压报错, 7z x FileImportTest01.rar -p"123456" -o/home/download -y文件目录内容已列出,但无法解压文件!!! 仔细检查命令没有问题…...
C语言基础六:循环结构及面试上机题
Day06:循环结构 定义 代码的重复执行,就叫做循环 循环的分类 无限循环:其实就是死循环,程序设计中尽量避免无限循环。程序中的无限循环必须可控。有限循环:循环限定循环次数或者循环的条件。 循环的构成 循环条件循环体 当型循环的实现…...
【蓝桥杯每日一题】技能升级
技能升级 2024-12-10 蓝桥杯每日一题 技能升级 二分 题目大意 一个角色有 N 种可以增加攻击力的技能,对于第 i 个技能首次升级可以提升 A i A_i Ai 点攻击力,随后的每次升级增加的攻击力都会减少 B i B_i Bi 。升级 ⌈ A i B i ⌉ \lceil \frac{A…...
C++作业4
1、思维导图 2、Person和Stu的拷贝构造和拷贝赋值函数 #include <iostream> using namespace std; class Person {string name;int *age; public:Person():age(new int(23)){cout << "Person的无参构造" << endl;}//初始化列表 :成员属性1(值),成…...
密码学——密码学基础、散列函数与数字签名
1.密码学概述 是信息安全的基础和核心,是防范各种安全威胁的重要手段,信息安全的许多相关知识都与密码学相关。 密码学发展 密码学是一门古老而又年轻的学科 ,几千年以前就存在,至今仍在发展演进。地位非常重要甚至起决定性作用…...
鹦鹉的饮食偏好:探索多彩的食物世界
鹦鹉,作为聪明且迷人的鸟类,其饮食习性一直是鸟类爱好者关注的焦点。了解鹦鹉喜欢吃什么食物,对于确保它们的健康与幸福至关重要。 鹦鹉的食物种类丰富多样,首先是各类种子与谷物。例如,葵花籽富含脂肪和蛋白质&#…...
AtCoder Beginner Contest 383
C - Humidifier 3 Description 一个 h w h \times w hw 的网格,每个格子可能是墙、空地或者城堡。 一个格子是好的,当且仅当从至少一个城堡出发,走不超过 d d d 步能到达。(只能上下左右走,不能穿墙)&…...
HALCON算子函数 Filter(过滤)(1)
Arithmetic图像算数处理 abs_diff_image:计算两个图像的绝对差别;abs_image:计算一个图像的绝对值(模数);add_image:使两个图像相加;div_image:使两个图像相除ÿ…...
哈希知识详解
目录 一、哈希 二、哈希函数 1、直接定值法 2、除留余数法 三、哈希冲突 四、哈希冲突解决 1、闭散列(开放定值法) 闭散列代码 2、哈希桶 哈希桶的结构 查找方法 插入方法 删除方法 析构 迭代器 完整哈希桶代码 五、通过哈希桶封装 unordered_map 和 unordered_set 一、…...
分库分表基本概念讲解
一、基本概念 产生背景 在数据爆炸的年代,单表数据达到千万级别,甚至过亿的量,都是很常见的情景。这时候再对数据库进行操作就是非常吃力的事情了,select个半天都出不来数据,这时候业务已经难以维系。不得已…...
【DRAM存储器四十二】LPDDR5介绍--LPDDR5的bank架构还能配,为什么8B模式只支持BL32?
👉个人主页:highman110 👉作者简介:一名硬件工程师,持续学习,不断记录,保持思考,输出干货内容 参考资料:《某LPDDR5数据手册》 、《JESD209-5C》 目录 BG mode 16B mode 8B mode...
ubuntu 新建脚本shell并增加图标 双击应用实现python运行
1.使用nano创建shell脚本文件 需要在终端窗口中输入“nano”以打开文本编辑器。 nano 在创建脚本文件前,我们要了解脚本文件是如何运行的: 直接运行:直接在终端直接输入需要运行的脚本文件名称,系统或用缺省版本的shell运行脚…...
【0x0006】HCI_Disconnect命令详解
目录 一、命令概述 二、命令格式和参数说明 2.1. HCI_Disconnect 命令格式 2.2. Connection_Handle 2.3. Reason 三、返回事件说明 3.1. HCI_Command_Status 事件 3.2. HCI_Disconnection_Complete事件 3.3. HCI_LE_CIS_Established事件(针对CIS) 四、事件执行流程…...
【C语言练习(5)—回文数判断】
C语言练习(5) 文章目录 C语言练习(5)前言问题问题解析结果总结 前言 通过回文数练习,巩固数字取余和取商如何写代码 问题 输入一个五位数判断是否为回文数? 问题解析 回文数是指正读反读都一样的整数。…...
【全连接神经网络】核心步骤及其缺陷
前向传播 计算公式(其中一种) x1/x2:输入值,一般是神经网络上一层的输出或者输入数据本身,上图中表示两个节点w11 w13:权重,在神经网络中,权重是学习的参数,表示每个输入…...
【Vulkan入门】11-CreateCommandBuffer
[TOC]目录 先叨叨 先叠个甲,我个人都觉得本篇有点灌水的嫌疑。 到上篇为止,已经创建好了Pipeline。接下来就是要给Pipeline发指令进行渲染了。 从一开始就不断强调,发给Vulkan的指令要通过Queue发送给Device。命令不是一条一条推到Queue中的…...
Redis原理—4.核心原理摘要
大纲(9870字) 1.Redis服务器的Socket网络连接建立 2.Redis多路复用监听与文件事件模型 3.基于队列串行化的文件事件处理机制 4.完整的Redis Server网络通信流程 5.Redis串行化单线程模型为什么能高并发 6.Redis内核级请求处理流程与原理 7.Redis通信协议与内核级请求数据…...
面向对象系统的分析和设计
来源:《设计模式精解-GOF23种设计模式解析》 作者:k_eckel k_eckels mindview - 博客园 (cnblogs.com) --------- 面向对象系统的分析和设计实际上追求的就是两点: (1)高内聚 (2)低耦合 …...
单片机:实现交通信号灯(附带源码)
使用单片机实现交通信号灯控制系统是一个经典的嵌入式系统应用。这个项目可以帮助你理解如何通过单片机控制不同颜色的LED灯、处理时间控制、以及输入输出的基本操作。通过这个项目,你将掌握如何设计交通信号灯的时序控制、如何实现定时控制交通灯的切换、以及如何与…...
小白如何学习看懂CAD图纸?
首先,你需要了解CAD图纸的基本构成,包括图例、尺寸标注、比例等等。接着,你可以通过一些专业的书籍、在线课程或视频教程来逐步学习如何识别和理解这些元素。但建议不要学的太复杂了。 掌握基本概念: 坐标系:了解CAD…...
HarmonyOS-高级(一)
文章目录 一次开发、多端部署自由流转 🏡作者主页:点击! 🤖HarmonyOS专栏:点击! ⏰️创作时间:2024年12月09日12点19分 一次开发、多端部署 布局能力 自适应布局 拉伸能力均分能力占比能力缩放…...
Datawhale AI 冬令营(第一期)定制你的第一个专属模型-学习笔记
最近我报名参加了Datawhale组织的主题为“动手学系列,人人都能应用的AI”的Datawhale AI冬令营(第一期)。 本次学习一共12天,从12月10日-12月21日,学习会包含【跑通速通手册】,【学习大模型微调&数据集…...
群控系统服务端开发模式-应用开发-登录退出发送邮件
一、登录成功发送邮件 在根目录下app文件夹下controller文件夹下common文件夹下,修改Login.php,代码如下 <?php /*** 登录退出操作* User: 龙哥三年风水* Date: 2024/10/29* Time: 15:53*/ namespace app\controller\common; use app\controller\Em…...
app-2 App 应用抓包之 Postern+Charles
一、前言 本篇是基于 Postern Charles 方式对安卓应用数据包进行抓取。可以抓取到市面上大多数的app数据包。 二、环境准备 postern:postern下载地址 charles:Charles 4.5.6 中文版(便携免安装).rar 提取码:6d8f 三、配置及抓包测试 3.…...
cnocr配置及训练测试
cnocr配置及训练测试 1,相关链接2,已有模型调用测试(1)下载相关模型(2)Cnstd文本检测模型(3)模型调用解析脚本 3,自定义数据集训练测试(1)标签转换…...
【优选算法 前缀和】前缀和算法模板详解:一维前缀 & 与二维前缀和
一维前缀和 题目解析 算法原理 解法一:暴力解法 简单模拟,读完题意有 q 次询问,给哪两个数,就求哪段区间的和并且返回,这样的做法,时间复杂度为O(N*q),这个时间复杂度会超时…...
【记录】用JUnit 4的@Test注解时报错java.lang.NullPointerException的原因与解决方法
项目场景: 在练习黑马点评的逻辑过期解决缓存击穿时,编写了一个预热缓存数据的单元测试 SpringBootTest public class HmDianPingApplicationTests {Resourceprivate ShopServiceImpl shopService;Testpublic void testSaveShop() throws InterruptedE…...
Transformer入门(6)Transformer编码器的前馈网络、加法和归一化模块
文章目录 7.前馈网络8.加法和归一化组件9.组合所有编码器组件构成完整编码器 7.前馈网络 编码器块中的前馈网络子层如下图所示: 图1.32 – 编码器块 前馈网络由两个带有ReLU激活函数的全连接层组成。全连接层(Fully Connected Layer)有时也…...
(七)腾讯cloudstudio+Stable-Diffusion-webui AI绘画教程-安装Stable-Diffusion-WebUI
一、说明 本文选择安装stable-diffusion-webui最新版本 cloud studio 免费版最大的问题是空间不足,我晚上上传时超过了硬盘大小,直接不能启动,没办法,删除,又建了一个工作空间 二、安装 1、打开终端 2、配置Git代理…...
算法基础Day7(动态规划)
文章目录 1.题目2.题目解答1.第N个泰波那契数题目及题目解析动态规划算法学习1.状态表示2.状态转移方程3.初始化4.填表顺序5.空间优化 代码提交空间优化 2.三步问题题目及题目解析算法学习代码提交 1.题目 1137. 第 N 个泰波那契数 - 力扣(LeetCode)面试…...
代理IP地址和端口是什么?怎么进行设置?
保护个人隐私、突破地域限制、提升网络安全性是我们不断追求的目标。IP地址与端口一种实现这些目标的重要工具。但是,你可能对它是什么,以及如何设置感到困惑。别担心,本文将为你揭开这些神秘的面纱,让你轻松掌握这项技能。 1.IP…...
一文详解TCP协议 [图文并茂, 明了易懂]
欢迎来到啊妮莫的学习小屋! 目录 什么是TCP协议 TCP协议特点✨ TCP报文格式 三次握手和四次挥手✨ 可靠性 效率性 基于字节流✨ 基于TCP的应用层协议 什么是TCP协议 TCP(传输控制协议, Transmission Control Protocol) 是一种面向连接的, 可靠的, 基于字节流的传输层通…...
js后端开发之Next.js、Nuxt.js 与 Express.js
后端js之Next.js、Nuxt.js 与 Express.js 在现代 Web 开发中,JavaScript 已经成为前后端通用的编程语言,而选择合适的后端框架则是构建高效、可扩展应用程序的关键。本文将带你深入了解三个流行的 JavaScript 后端框架:Next.js、Nuxt.js 和 …...
人工智能概要
目录 前言1.什么是人工智能(Artificial Intelligence, AI)2.人工智能发展的三次浪潮2.1 人工智能发展的第一次浪潮2.2 人工智能发展的第二次浪潮2.3 人工智能发展的第三次浪潮 3.人工智能发展的必备三要素3.1 数据3.2 算法(algorithm…...
spring boot 3集成swagger
Spring Boot 3 集成 Swagger 的过程与之前版本相比有一些变化,主要是因为 springfox 库已经停止更新,并且不再支持新的 Spring Boot 版本。因此,对于 Spring Boot 3 来说,推荐使用 springdoc-openapi 作为集成 Swagger 的解决方案…...
【PlantUML系列】状态图(六)
一、状态图的组成部分 状态:对象在其生命周期内可能处于的条件或情形,使用 state "State Name" as Statename 表示。初始状态:表示对象生命周期的开始,使用 [*] 表示。最终状态:表示对象生命周期的结束&…...
前端缓存页面处理方法
当前一个前端应用新发布时,重新编译后,原来引用的资源文件名都会有变化。如果这个应用的页面在前端浏览器中有缓存,则会导致加载资源失败。怎样去除这种缓存,同时也能尽可能的保证前端访问的性能 ChatGPT said: ChatGPT 这是一个经…...
每日一题 284. 窥视迭代器
284. 窥视迭代器 想要提前知道下一个内容,就需要缓存 class PeekingIterator : public Iterator { public:PeekingIterator(const vector<int>& nums) : Iterator(nums) {// Initialize any member here.// **DO NOT** save a copy of nums and manipula…...
Cesium-(Primitive)-(BoxGeometry)
含实现代码 GISer世界 效果: 以下是 BoxGeometry 类的构造函数属性,以表格形式展示: 属性名类型默认值描述minimumCartesian3盒子的最小 x, y, 和 z 坐标。maximumCartesian3盒子的最大 x, y, 和 z 坐标。vertexFormatVertexFormatVertexFormat.DEFAULT要计算的顶点属性。以下…...
CSS元素宽高特点、类型转化、显式和隐藏(display)
元素的宽高特点 块级元素 可以设置宽高,不可以和其他元素在一行设置宽高时,元素的宽高为设置的值没有设置宽高时,宽度和父级宽高一样,高度由元素内容决定 行级元素 不可以设置宽高,可以和其他元素在一行元素的宽高…...
上市公司投资效率Biddle模型数据(包括最终数据、原始数据及构造说明)2003-2022年
一、计算方式:参考《Journal of accounting and economics》Biddle G C,构建Biddle模型使用企业投资对成长机会的回归模型来估计企业的投资效率,这里成长机会用销售增长率来衡量。回归模型如下图所示: 二、资料范围:包括原始数据…...