数据卷(虚拟目录)操作命令
在容器内部修改文件
docker exec -it nginx bash
: 进入Nginx容器内部
docker exec
: 进入容器内部,容器内部会模拟一份阉割版的Linux文件系统,只包含镜像运行时所需的环境和配置以及文件
-it
: 给当前进入的容器创建一个标准输入/输出
终端方便我们与容器交互nginx
: 指定要进入的容器名称bash
: 指定进入容器后自动执行的命令,bash表示使用Linux终端
交互命令如cd命令
,执行exit
命令从当前容器中退出
[root@localhost ~] docker exec --help
Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Run a command in a running container
Options:
-d, --detach Detached mode: run command in the background
--detach-keys string Override the key sequence for detaching a container
-e, --env list Set environment variables
--env-file list Read in a file of environment variables
-i, --interactive Keep STDIN open even if not attached
--privileged Give extended privileges to the command
-t, --tty Allocate a pseudo-TTY
-u, --user string Username or UID (format: <name|uid>[:<group|gid>])
-w, --workdir string Working directory inside the container
需求: 进入Nginx容器内部,在DockerHub中的Nginx镜像
页面中查找镜像的根目录,并在/usr/share/nginx/html/index.html
文件中添加内容
Nginx容器内只具备镜像所必须的系统函数库没有vi
命令,此时需要使用sed
命令替换index.html
文件的内容
# 进入nginx程序的根目录
root@310016c9b413:/ cd /usr/share/nginx/html
# 查看nginx根目录下的文件
root@310016c9b413:/usr/share/nginx/html# ls
50x.html index.html
# 替换index.html文件内容,'s#原始内容#替换内容#g'
sed -i 's#Welcome to nginx#Welcome To My Blog#g' index.html
# 设置index.html文件的编码格式
sed -i 's#<head>#<head><meta charset="utf-8">#g' index.html
数据卷的作用及其命令
容器内部包含应用程序
和其相关的文件、配置、运行时产生的数据
,由于容器是隔离环境我们要读写容器内的文件非常不方便
不便于修改
: 当MySQL、Nginx容器运行后,如果我们要修改其中的某些配置文件还需要进入容器内部修改非常的不方便数据不可复用
: 由于容器内的修改对外是不可见的,故对某个容器的所有修改对之后新创建的容器是不可复用的升级维护困难
: 数据在容器内目录里,如果要升级容器必须先删除旧容器,此时容器中的数据也跟着被删除了
数据卷(volume)是一个虚拟目录
: 它是容器内目录与宿主机目录之间映射的桥梁,最终指向的是宿主机中的一个真实目录
修改文件
: 容器内目录一旦通过数据卷关联到宿主机目录双方就形成了双向数据绑定,无论哪一方的目录内容发生改变另一方都发生相应变化如新增修改文件
数据复用
: 新创建的容器可以直接挂载到数据卷达到数据共享功能维护
: 使用数据卷后容器与容器内数据会解耦合, 删除容器并不会影响数据卷,将来新建容器时可以继续挂载到旧的数据卷上,数据迁移也方便
Nginx中有两个关键的目录, html
目录用来放置需要nginx代理访问的静态资源,conf
目录用来放置nginx的配置文件
- 每一个不同的镜像,将来创建容器后内部有哪些目录可以挂载到数据卷,可以参考DockerHub对应的页面查看目录在容器内的位置
docker volume [COMMAND]
: docker volume是数据卷操作命令前缀,command
是数据卷具体的操作命令
- 创建完数据卷后docker会在宿主机的创建对应的真实目录,默认容器数据卷的存放目录为
/var/lib/docker/volumes/数据卷名/_data
命令 | 功能 |
---|---|
docker volume create 数据卷名称 | 创建数据卷 |
docker volume ls | 查看所有数据卷 |
docker volume inspect 数据卷名称 | 查看数据卷的详细信息,如对应的宿主机真实目录位置 |
docker volume rm 数据卷名称 | 删除一个或多个指定的数据卷 |
drocker volume prune | 删除所有未使用的数据卷 |
docker inspect | 查询容器内的详情信息,也可以查看容器的数据卷挂载信息 |
在宿主机目录中修改文件
需求: 创建一个Nginx容器使用-v参数
把容器内的/usr/share/nginx/html
目录挂载到html
这个数据卷上
- 一旦完成数据卷挂载,我们操作宿主机的
/var/lib/docker/volumes/html/_data
目录内容,就等同于操作nginx容器内的/usr/share/nginx/html
目录内容
# 创建数据卷html
docker volume create html
# 查看所有数据卷
[root@localhost ~] docker volume ls
DRIVER VOLUME NAME
local html
# 查看数据卷html的详细信息
[root@localhost ~] docker volume inspect html
[
{
"CreatedAt": "2022-12-19T12:51:54+08:00",
"Driver": "local",
"Labels": {},
# 数据卷关联的宿主机目录
"Mountpoint": "/var/lib/docker/volumes/html/_data",
"Name": "html",
"Options": {},
"Scope": "local"
}
]
# 创建容器并完成数据挂载,如果html数据卷不存在会自动创建
docker run --name myNginx -v html:/usr/share/nginx/html -p 80:80 -d nginx
# 进入数据卷关联的宿主机目录,其与nginx的html目录内容一样
cd /var/lib/docker/volumes/html/_data
-rw-r--r--. 1 root root 497 12月 28 2021 50x.html
-rw-r--r--. 1 root root 615 12月 28 2021 index.html
# 在宿主机目录中修改文件对应容器内目录中的文件也会变化
vi index.html
# 打开页面,查看效果
# 进入容器内部,查看/usr/share/nginx/html目录内的文件是否变化
docker exec -it nginx bash
MySQL的匿名数据卷
MySQL容器在创建时会自动创建一个匿名数据卷
,可以将容器内的/var/lib/mysql
目录通过该数据卷关联到/var/lib/docker/volumes/295../_data
这个目录
- 每一个不同的镜像,将来创建容器后内部有哪些目录可以挂载到数据卷,可以参考DockerHub对应的页面查看目录在容器内的位置
# 查看创建的MySQL容器的详细信息
docker inspect mysql
# 关注其中.Config.Volumes部分和.Mounts部分
{
"Config": {
// ... 略
"Volumes": {
"/var/lib/mysql": {}
}
// ... 略
}
"Mounts": [
{
"Type": "volume",
# 匿名数据卷的名称,自动生成的hash值
"Name": "29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f",
# 数据卷对应的宿主机目录
"Source": "/var/lib/docker/volumes/29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f/_data",
# 容器内目录,mysql的数据存储目录data,包含容器运行时产生的数据,挂载到宿主机可以防止rong'qi
"Destination": "/var/lib/mysql",
"Driver": "local",
}
]
}
数据挂载命令
在docker run
命令中通过-v
参数将容器内目录/文件
和宿主机的目录/文件
形成双向绑定的关系即无论哪一方内容变化另一方同样变化
-v [volume名称]:[容器内目录]
: 当创建容器时将容器内的目录挂载到某个数据卷上(创建好的容器不能将容器内目录挂载到数据卷),如果要挂载的数据卷不存在docker容器会自动创建一个数据卷- 优点:
容器内目录和宿主机目录耦合度较低
,如果宿主机目录发生改变,只要改变数据卷与宿主机目录之间的映射关系即可 - 缺点: 当创建完数据卷后会由Docker创建对应要挂载的宿主机真实目录,该目录较深不好找
- 优点:
-v [宿主机目录/文件]:[容器内目录/文件]
:将容器内的目录或文件
直接挂载到宿主机的某个目录或文件
,如果要挂载的本地目录或文件不存在docker会自动创建- 优点: 我们手动创建指定的挂载目录容易查找,目录必须以
"/(根目录)"或"./(当前目录)"
开始,如果直接以名称开头会被识别为数据卷而非本地目录 - 缺点: 容器内目录与宿主机目录耦合度较高 ,如果切换了环境宿主机目录就可能发生改变,而容器一旦创建后目录挂载就无法修改导致容器无法正常工作
- 优点: 我们手动创建指定的挂载目录容易查找,目录必须以
容器目录挂载到数据卷
需求: 创建一个Nginx容器使用-v参数
把容器内的/usr/share/nginx/html
目录挂载到html
这个数据卷上,方便操作容器目录中的内容
- 一旦完成数据卷挂载,我们操作数据卷对应的宿主机的
/var/lib/docker/volumes/html/_data
目录文件,就等同于操作nginx容器内的/usr/share/nginx/html
目录文件
# 创建容器并完成数据挂载,如果html数据卷不存在会自动创建
docker run --name myNginx -v html:/usr/share/nginx/html -p 80:80 -d nginx
# 查看数据卷关联的宿主机目录
docker volume inspect html
[
{
"CreatedAt": "2022-12-19T12:51:54+08:00",
"Driver": "local",
"Labels": {},
# 数据卷关联的宿主机目录
"Mountpoint": "/var/lib/docker/volumes/html/_data",
"Name": "html",
"Options": {},
"Scope": "local"
}
]
# 进入数据卷关联的宿主机目录,其与nginx的html目录中的内容一样
cd /var/lib/docker/volumes/html/_data
-rw-r--r--. 1 root root 497 12月 28 2021 50x.html
-rw-r--r--. 1 root root 615 12月 28 2021 index.html
# 在宿主机目录中修改文件对应容器内目录中的文件也会变化
vi index.html
# 打开页面,查看效果
# 进入容器内部,查看/usr/share/nginx/html目录内的文件是否变化
docker exec -it nginx bash
容器目录挂载宿主机目录
docker创建完数据卷后会创建其对应的宿主机目录(结构较深不便访问),所以我们可以直接将容器内的目录
与我们在宿主机上指定创建的目录
进行挂载
- 本地目录或文件必须以
/
或./
开头,如果直接以名字开头会被识别为数据卷名而非本地目录名
-v mysql:/var/lib/mysql # 会被识别为一个数据卷叫mysql,运行时如果不存在会自动创建这个数据卷
-v ./mysql:/var/lib/mysql # 会被识别为当前目录下的mysql目录,运行时如果不存在会自动创建目录
在DockerHub中的MySQL镜像文档中找到MySQL容器内可以挂载的conf.d目录
和mysql目录
以及init目录
的位置
-
数据存储目录
: 将容器内的/var/lib/mysql
目录挂载到宿主机的/root/mysql/data
目录 -
配置文件目录
: 将容器内的/etc/mysql/conf.d
目录挂载到宿主机的/root/mysql/conf
配置文件目录 -
初始化SQL脚本目录
: 将/docker-entrypoint-initdb.d
目录挂载到宿主机的/root/mysql/init
目录
第一步: 在宿主机目录中创建/root/mysql/conf/hm.cnf
和/root/mysql/init/hm.sql
文件,当容器目录挂载到这两个宿主机目录时对应容器目录内就会有同样的文件
- 将容器内目录挂载到宿主机目录时,如果宿主机目录不存在docker会自动创建,挂载完后
容器内对应目录的内容
也会随宿主机目录的内容
发生变化
# 创建conf目录
mkdir -p /root/mysql/conf
# 编写配置文件配置MySQL的默认编码格式为utf8mb4
vi /root/mysql/conf/hm.cnf
# 配置文件内容
[client]
default_character_set=utf8mb4
[mysql]
default_character_set=utf8mb4
[mysqld]
character_set_server=utf8mb4
collation_server=utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
# 创建init目录
mkdir -p /root/mysql/init
# 编写MySQL容器初始化的SQL脚本
vi /root/mysql/init/hm.sql
# SQL脚本内容
# 导出hmall的数据库结构
DROP DATABASE IF EXISTS `hmall`;
CREATE DATABASE IF NOT EXISTS `hmall` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
USE `hmall`;
# 导出表hmall.address结构
DROP TABLE IF EXISTS `address`;
CREATE TABLE IF NOT EXISTS `address` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint DEFAULT NULL COMMENT '用户ID',
`province` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '省',
`city` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '市',
`town` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '县/区',
`mobile` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '手机',
`street` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '详细地址',
`contact` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '联系人',
`is_default` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '是否是默认 1默认 0否',
`notes` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE,
KEY `user_id` (`user_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=64 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=COMPACT;
# 正在导出表hmall.address的数据
DELETE FROM `address`;
INSERT INTO `address` (`id`, `user_id`, `province`, `city`, `town`, `mobile`, `street`, `contact`, `is_default`, `notes`) VALUES
(59, 1, '北京', '北京', '朝阳区', '13900112222', '金燕龙办公楼', '李嘉诚', '0', NULL),
(60, 1, '北京', '北京', '朝阳区', '13700221122', '修正大厦', '李佳红', '0', NULL),
(61, 1, '上海', '上海', '浦东新区', '13301212233', '航头镇航头路', '李佳星', '1', NULL),
(63, 1, '广东', '佛山', '永春', '13301212233', '永春武馆', '李小龙', '0', NULL);
第二步: 启动MySQL容器并使用-e MYSQL_ROOT_PASSWORD
参数设置MySQL密码,然后尝试使用Navicat连接数据库
# 1.删除原来的MySQL容器
docker rm -f mysql
# 2.进入root目录
cd ~
# 在宿主机中创建数据存储目录,其实在进行目录挂载时如果本地目录不存在,docker也会自动创建
mkdir -p /root/mysql/data
# 3.创建并运行新mysql容器,将容器内目录挂载到本地目录,如果本地目录不存在会自动创建,挂载完后容器内对应目录的内容也会发生变化
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
-v ./mysql/data:/var/lib/mysql \
-v ./mysql/conf:/etc/mysql/conf.d \
-v ./mysql/init:/docker-entrypoint-initdb.d \
mysql
# 4.查看宿主机的/root/mysql/data目录发现里面有大量数据库数据,说明其对应的容器内目录/var/lib/mysql产生了数据,即MySQL容器初始化时执行了初始化脚本
ls -l /root/mysql/data
# 5.查看MySQL容器内数据
# 5.1.进入MySQL
docker exec -it mysql mysql -uroot -p123
# 5.2.查看编码表
show variables like "%char%";
# 5.3.结果,发现编码是utf8mb4没有问题
+--------------------------+--------------------------------+
| Variable_name | Value |
+--------------------------+--------------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/share/mysql-8.0/charsets/ |
+--------------------------+--------------------------------+
# 6.查看数据
# 6.1.查看初始化的数据库
show databases;
+--------------------+
| Database |
+--------------------+
| hmall |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
# 6.2.切换到hmall数据库并查看该数据库中的表
use hmall;
show tables;
+-----------------+
| Tables_in_hmall |
+-----------------+
| address |
+-----------------+
# 6.4.查看address表中的数据
select * from address
+----+---------+----------+--------+----------+-------------+---------------+-----------+------------+-------+
| id | user_id | province | city | town | mobile | street | contact | is_default | notes |
+----+---------+----------+--------+----------+-------------+---------------+-----------+------------+-------+
| 59 | 1 | 北京 | 北京 | 朝阳区 | 13900112222 | 金燕龙办公楼 | 李佳诚 | 0 | NULL |
| 60 | 1 | 北京 | 北京 | 朝阳区 | 13700221122 | 修正大厦 | 李佳红 | 0 | NULL |
| 61 | 1 | 上海 | 上海 | 浦东新区 | 13301212233 | 航头镇航头路 | 李佳星 | 1 | NULL |
| 63 | 1 | 广东 | 佛山 | 永春 | 13301212233 | 永春武馆 | 李晓龙 | 0 | NULL |
+----+---------+----------+--------+----------+-------------+---------------+-----------+------------+-------+
4 rows in set (0.00 sec)