学习自b站狂神说Docker: https://www.bilibili.com/video/BV1og4y1q7M4/?spm_id_from=333.337.search-card.all.click
容器数据卷
docker的理念是将应用和环境打包成一个镜像,但数据若在容器中,容器删除,数据就会丢失(例如mysql的数据可以存储在本地,完成数据的持久化),故容器之间需要有数据共享技术,使docker容器中的数据同步到本地
这是卷技术,目录的挂载,将容器内目录挂载到Linux上,完成容器的持久化和同步操作,容器间可以数据共享
使用数据卷
方式一:直接使用命令挂载 -v (类似-p)
docker run -it -v 主机目录:容器内目录
#1.测试,启动centos进行挂载
[root@localhost home]# docker run -it -v /home/ceshi:/home centos /bin/bash
[root@9302ce5fe51a /]#
#此刻可以再开一个线程看看本机的home中是否有ceshi 存在说明启动了
#2.查看卷是否挂载成功 docker inspect ,Mounts没信息说明挂载失败
[root@localhost /]# docker inspect 9302ce5fe51a
[
//......
"Mounts": [ 挂载 -v卷
{
"Type": "bind",
"Source": "/home/ceshi", 目的地,主机内的地址
"Destination": "/home", docker容器内的地址
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
//......
]
#3.在容器外ceshi存放数据会自动同步到容器内的home中(容器关闭也会同步),容器中的home存放数据容器外也会自动同步
[root@9302ce5fe51a home]# touch xinxin.java
[root@localhost ceshi]# ls
xinxin.java
#4.在容器关闭时,编辑挂载卷的文件,进入容器查看是否自动同步(已同步)
[root@localhost ceshi]# vi xinxin.java #编辑文件
[root@localhost /]# docker start 9302ce5fe51a #启动容器
[root@localhost /]# docker attach 9302ce5fe51a #进入运行中的容器
[root@9302ce5fe51a home]# vi xinxin.java #容器内的文件已实现自动同步
实战:安装Mysql
#1.安装mysql
[root@localhost /]# docker pull mysql:5.7
#2.运行容器时,做数据卷挂载,后台运行,暴露端口3310:3306,数据卷挂载主机下的配置文件,对应数据库的conf文件(配置文件)/home/mysql/conf:/etc/mysql/conf.d 同时将mysql中的数据文件也映射出来(可以映射多个)
#注意,安装mysql,需要配置密码 -e表示配置环境(在这里配置初始密码为root)
[root@localhost /]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name mysql01 mysql:5.7
a0e6d186b021e7f4c72df919fc7ea48b47daada5821cb26420a24a36e4377943
#常用可选项
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
--name 容器名字
#3.启动成功后,可以在本地使用Navicat测试数据库是否能够连接,服务器3310-容器3306
#4.查询本地home目录下的mysql,查看是否挂载成功
[root@localhost mysql]# ls
conf data
#5.在Navicat中建数据库(容器中),本地映射的data目录中也会增加文件
[root@localhost mysql]# cd data
[root@localhost data]# ls #创建数据库查看映射路径是否ok
auto.cnf client-cert.pem ibdata1 ibtmp1 private_key.pem server-key.pem
ca-key.pem client-key.pem ib_logfile0 mysql public_key.pem sys
ca.pem ib_buffer_pool ib_logfile1 performance_schema server-cert.pem test
#6.持久化绑定到本地,容器删了也在,实现了容器数据持久化功能
[root@localhost /]# docker rm -f mysql01
[root@localhost data]# ls
auto.cnf client-cert.pem ibdata1 ibtmp1 private_key.pem server-key.pem
ca-key.pem client-key.pem ib_logfile0 mysql public_key.pem sys
ca.pem ib_buffer_pool ib_logfile1 performance_schema server-cert.pem test
具名和匿名挂载
# 匿名挂载 不指定主机名(路径),自动生成对应路径 -v 容器内路径 -P(大写)随机映射端口
[root@localhost /]# docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看卷状态 docker volume 可选项
create 创建卷
ls 查看所有卷
rm 移除
inspect 查看卷怎么做的
prune 移除没有使用的
# 查看所有卷的情况,此刻这两条就是匿名挂载
[root@localhost /]# docker volume ls
DRIVER VOLUME NAME
local cc6e3e8ebdbd022d6a77e6cf1ea1497611bbcfc4a4a0c37b29811cf1c4e8fa36
local ef566e18297260f726bddc62ca90e3f95280d66f6df43a129079db189eff9e4d
# 具名挂载 通过-v 卷名:容器内路径
[root@localhost /]# docker run -d -P --name nginx21 -v juming-nginx:/etc/nginx nginx
8b1d73e525d94936ea699a16371328dd41cfcca05fd5a24abac9c685fdc83e80
[root@localhost /]# docker volume ls
DRIVER VOLUME NAME
local juming-nginx
# 查看卷的位置,所有docker容器内的卷,没指定目录都在/var/lib/docker/volumes/xxx/_data目录下
[root@localhost /]# docker volume inspect juming-nginx
[
{
"CreatedAt": "2023-10-17T10:43:05+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data", 挂载目录地址
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
# docker的工作目录 /var/lib/docker
[root@localhost docker]# ls
buildkit containers engine-id image network overlay2 plugins runtimes swarm tmp volumes
# 卷目录 /var/lib/docker/volumes
[root@localhost volumes]# ls
backingFsBlockDev juming-nginx
cc6e3e8ebdbd022d6a77e6cf1ea1497611bbcfc4a4a0c37b29811cf1c4e8fa36 metadata.db
ef566e18297260f726bddc62ca90e3f95280d66f6df43a129079db189eff9e4d
# 可在目录下将nginx.conf配置文件拿出来做同步
[root@localhost volumes]# cd juming-nginx
[root@localhost juming-nginx]# ls
_data
[root@localhost juming-nginx]# cd _data
[root@localhost _data]# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
# 查看配置文件 -n可以添加行号,cat命令,它可以创建,查看,连接和重定向文件
[root@localhost _data]# cat -n nginx.conf
1
2 user nginx;
3 worker_processes auto;
4
5 error_log /var/log/nginx/error.log notice;
6 pid /var/run/nginx.pid;
7
8
9 events {
10 worker_connections 1024;
11 }
12
13
14 http {
15 include /etc/nginx/mime.types;
16 default_type application/octet-stream;
17
18 log_format main '$remote_addr - $remote_user [$time_local] "$request" '
19 '$status $body_bytes_sent "$http_referer" '
20 '"$http_user_agent" "$http_x_forwarded_for"';
21
22 access_log /var/log/nginx/access.log main;
23
24 sendfile on;
25 #tcp_nopush on;
26
27 keepalive_timeout 65;
28
29 #gzip on;
30
31 include /etc/nginx/conf.d/*.conf;
32 }
# 具名挂载很容易找到卷(常用),不建议使用匿名挂载
#如何区分是具名还是匿名挂载,还是指定路径挂载
-v 容器内路径 #匿名挂载 在volumes下随机生成一个路径完成映射
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载
拓展:
# 可通过 -v 容器内路径:ro rw 改变读写权限
ro #readonly 只读 说明这个路径只能通过宿主机来操作,容器内部是无法操作的
rw #readwrite 可读可写
#一旦这个设置了容器权限,容器对我们挂载出来的内容就有限定了(相对于容器),容器挂载出来后容器内就不能操作了
docker run -d -P --name nginx21 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx21 -v juming-nginx:/etc/nginx:rw nginx
初识Dockerfile
方式二:用来构建docker镜像的构建文件,命令脚本
# 测试,创建一个目录,之后的文件挂载到这里
[root@localhost home]# mkdir docker-test-volume
# 进入目录,创建脚本文件,通过脚本可生成镜像,镜像是一层一层的,脚本是一个个的命令,每个命令都是一层
[root@localhost docker-test-volume]# vim dockerfile1
# 生成镜像用centos当做基础,通过VOLUME["volume01","volume02"]挂载卷(生成时就挂载,可以挂载多个目录),输出CMD的命令行(构建完成后输出),进入后默认走/bin/bash控制台
# 指令(大写) 参数 这里每个命令就是镜像的一层
[root@localhost docker-test-volume]# cat dockerfile1
FROM centos
VOLUME ["volume01","volume02"] #匿名挂载
CMD echo "---end---"
CMD /bin/bash
# docker build通过文件构建镜像 -f 是文件的地址 -t 名字+版本 最后记得记上 .(加个点)
[root@localhost docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile1 -t hailong/centos:1.0 .
[+] Building 0.0s (5/5) FINISHED docker:default
=> [internal] load build definition from dockerfile1 0.0s
=> => transferring dockerfile: 118B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/centos:latest 0.0s
=> [1/1] FROM docker.io/library/centos 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:139235ade34847ff60bb087950d6bfc135d69865c42012862ca936647598ae1e 0.0s
=> => naming to docker.io/hailong/centos:1.0 0.0s
# 通过docker images查询创建的镜像
[root@localhost docker-test-volume]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hailong/centos 1.0 139235ade348 2 years ago 231MB
# 进入创建的镜像,volume01,volume02这两个目录就是生成镜像时自动挂载的数据卷目录
[root@localhost docker-test-volume]# docker run -it 139235ade348 /bin/bash
[root@fa5086458ad4 /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume02
dev home lib64 media opt root sbin sys usr volume01
#这个卷和外部一定有一个同步的目录,卷不存在目录是挂不上的
# 进入volume01,在容器内创建文件
[root@fa5086458ad4 /]# cd volume01
[root@fa5086458ad4 volume01]# touch container.txt
# 新启一个线程查看容器的具体信息(卷的挂载路径) inspect 获得对应的容器外目录(Source)
[root@localhost /]# docker inspect fa5086458ad4
"Mounts": [
{
"Type": "volume",
"Name": "ada7159c7e5aa1987082aaf884aac1317cca7b34524ef0b19c4912887c9f9693",
"Source": "/var/lib/docker/volumes/ada7159c7e5aa1987082aaf884aac1317cca7b34524ef0b19c4912887c9f9693/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "79b361c729b1a73c49eaf90a8fec26e2c04384a8fb851ff3119856dc434bc5f1",
"Source": "/var/lib/docker/volumes/79b361c729b1a73c49eaf90a8fec26e2c04384a8fb851ff3119856dc434bc5f1/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
# 测试一下刚才的文件是否同步出去(容器外)
[root@localhost _data]# ls
container.txt
数据卷容器-容器间数据同步
# 启动3个容器,通过刚才写的镜像
# 创建父容器docker01,必须写版本号不然会去找最新的(或者用镜像id启动),容器中有创建的挂载卷
[root@localhost /]# docker run -it --name docker01 hailong/centos:1.0
# 保持运行状态退出 ctrl+p+q
# 创建容器docker02进行挂载 --volumes-from 绑定(类似继承,数据同步) 该容器内也有两个卷
[root@localhost /]# docker run -it --name docker02 --volumes-from docker01 hailong/centos:1.0
# 进入docker01容器(数据卷容器)添加文件,查看docker02容器是否同步(仅挂载卷)
[root@localhost ~]# docker attach 7b23d2a7b9b9
[root@7b23d2a7b9b9 volume01]# touch docker01
# docker02容器已经同步(02容器内创建的01容器内也会自动同步)
[root@2596dde2bc79 volume01]# ls
docker01
#该技术可以实现多个mysql,redis之间数据共享(匿名挂载,路径相同可以不写)
[root@localhost /]# docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name mysql01 mysql:5.7
[root@localhost /]# docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=root --name mysql02 --volumes-from mysql01 mysql:5.7
结论
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止,但是一旦持久化到了本地,此时本地的数据是不会删除的。