目录
2、数据卷容器(DataVolumes Containers)
一、数据管理
管理 Docker 容器中数据主要有两种方式:数据卷(Data Volumes)和数据卷容器(DataVolumes Containers)
1、数据卷(Data Volumes)
- 数据卷是一个供容器使用的特殊目录,位于容器中
- 可将宿主机的目录挂载到数据卷上,对数据卷的修改操作立刻可见,并且更新数据不会影响镜像,从而实现数据在宿主机与容器之间的迁移
- 数据卷的使用类似于 Linux 下对目录进行的 mount 操作
- 数据卷通常适用于挂载服务器的配置文件目录、网页站点目录、日志目录
1.1 案例一:挂载目录
1.1.1 创建新容器test1-1和test1-2
情况说明:创建新容器并设置数据卷,然后在容器的数据卷目录写入新文件
注意事项:
- 如果宿主机本地目录的路径,必须是使用绝对路径。如果路径不存在,Docker会自动创建相应的路径,该方式为绑定挂载(Bind Mounts)
- 如果不是使用的路径而是类似名称的字符串,字符串中不能包含/等特殊字符,该方式为数据卷(Volumes),会在/var/lib/docker/volumes/目录下生成对应的该名称
#宿主机目录/var/www挂载到容器中的/data1
docker run -it -v /var/www:/data1 --name web1 centos:7 /bin/bash
#-v 选项可以在容器内创建数据卷
#查看volum卷
docker volume ls
#在容器的数据卷目录里写入新文件,并退出
ls
echo "welcome to my world" > /data1/test
cat /data1/test
exit
#列出一下/testdir,testdir,/var/lib/docker/volumes/testdir/三个文件或目录
ls /testdir testdir /var/lib/docker/volumes/testdir/
#列出一下volume,此时为空
docker volume ls
#使用镜像centos:7创建容器test1-1,将宿主机的/testdir挂载到容器里的/data1-1目录下,两者都无,会自动创建
docker run -itd -v /testdir:/data1-1 --name test1-1 centos:7 /bin/bash
#使用镜像centos:7创建容器test1-2,将名为testdir的volumes卷挂载到容器里的/data1-2目录下,两者都无,会自动创建
docker run -itd -v testdir:/data1-2 --name test1-2 centos:7 /bin/bash
#查看一下,此时自动创建了一个/testdir/空目录
ls /testdir/
#名为testdir的volumes不在当前目录下
ls testdir
#而是在/var/lib/docker/volumes/下有个testdir的目录,也是自动创建的
ls /var/lib/docker/volumes/testdir/
#testdir目录下有个_data/,也是自动创建的,用来持久化数据的
ls /var/lib/docker/volumes/testdir/_data/
#使用volume也能查看到当前的volumes
docker volume ls
#进入test1-1容器
docker exec -it test1-1 /bin/bash
#挂载到该容器的data1-1目录,该容器没有此目录也会被自动创建
ls data1-1
#写一个测试文件
echo "This is the `hostname` test file" |tee /data1-1/file-1-`hostname`.txt
#退出该容器
exit
#进入test1-2容器
docker exec -it test1-2 /bin/bash
#挂载到该容器的data1-1目录,该容器没有此目录也会被自动创建
ls data1-2
#写一个测试文件
echo "This is the `hostname` test file" |tee /data1-2/file-1-`hostname`.txt
#退出该容器
exit
#宿主机的/testdir/有了刚才创建的测试文件
ls /testdir/
#查看一下文件内容
cat /testdir/file-1*
#宿主机的/var/lib/docker/volumes/testdir/_data/也有了刚才创建的测试文件
ls /var/lib/docker/volumes/testdir/_data/
#查看一下文件内容
cat /var/lib/docker/volumes/testdir/_data/file-1*
命令示例:
ls /testdir testdir /var/lib/docker/volumes/testdir
docker volume ls
docker run -itd -v /testdir:/data1-1 --name test1-1 centos:7 /bin/bash
docker run -itd -v testdir:/data1-2 --name test1-2 centos:7 /bin/bash
ls /testdir/
ls testdir
ls /var/lib/docker/volumes/testdir/
ls /var/lib/docker/volumes/testdir/_data/
docker volume ls
docker exec -it test1-1 /bin/bash
ls data1-1
echo "This is the `hostname` test file" |tee /data1-1/file-1-`hostname`.txt
exit
docker exec -it test1-2 /bin/bash
ls data1-2
echo "This is the `hostname` test file" |tee /data1-2/file-1-`hostname`.txt
exit
ls /testdir/
cat /testdir/file-1*
ls /var/lib/docker/volumes/testdir/_data/
cat /var/lib/docker/volumes/testdir/_data/file-1*
输出结果:
[root@MineGi ~]# ls /testdir testdir /var/lib/docker/volumes/testdir
ls: 无法访问/testdir: 没有那个文件或目录
ls: 无法访问testdir: 没有那个文件或目录
ls: 无法访问/var/lib/docker/volumes/testdir: 没有那个文件或目录
[root@MineGi ~]# docker volume ls
DRIVER VOLUME NAME
[root@MineGi ~]# docker run -itd -v /testdir:/data1-1 --name test1-1 centos:7 /bin/bash
0dbcf149327708ab5d14e025c6526713fc116df96ef723b3acc5cb64cb800a23
[root@MineGi ~]# docker run -itd -v testdir:/data1-2 --name test1-2 centos:7 /bin/bash
ef789d5da7facf3e22d2be7f2a016270d4c4b49ce7b402b2aae22a79ffa2cf5e
[root@MineGi ~]# ls /testdir/
[root@MineGi ~]# ls testdir
ls: 无法访问testdir: 没有那个文件或目录
[root@MineGi ~]# ls /var/lib/docker/volumes/testdir/
_data
[root@MineGi ~]# ls /var/lib/docker/volumes/testdir/_data/
[root@MineGi ~]# docker volume ls
DRIVER VOLUME NAME
local testdir
[root@MineGi ~]# docker exec -it test1-1 /bin/bash
[root@0dbcf1493277 /]# ls data1-1
[root@0dbcf1493277 /]# echo "This is the `hostname` test file" |tee /data1-1/file-1-`hostname`.txt
This is the 0dbcf1493277 test file
[root@0dbcf1493277 /]# exit
exit
[root@MineGi ~]# docker exec -it test1-2 /bin/bash
[root@ef789d5da7fa /]# ls data1-2
[root@ef789d5da7fa /]# echo "This is the `hostname` test file" |tee /data1-2/file-1-`hostname`.txt
This is the ef789d5da7fa test file
[root@ef789d5da7fa /]# exit
exit
[root@MineGi ~]# ls /testdir/
file-1-0dbcf1493277.txt
[root@MineGi ~]# cat /testdir/file-1*
This is the 0dbcf1493277 test file
[root@MineGi ~]# ls /var/lib/docker/volumes/testdir/_data/
file-1-ef789d5da7fa.txt
[root@MineGi ~]# cat /var/lib/docker/volumes/testdir/_data/file-1*
This is the ef789d5da7fa test file
[root@MineGi ~]#
1.1.2 创建新容器test2-1和test2-2
情况说明:创建一个容器test2-1和test2-2,test2-1共用test1-1容器的数据卷挂载点目录,test2-2共用test1-2容器的数据卷挂载点目录,也就是新的容器还是使用之前的命令创建而已
命令示例:
docker run -itd -v /testdir:/data2-1 --name test2-1 centos:7 /bin/bash
docker run -itd -v testdir:/data2-2 --name test2-2 centos:7 /bin/bash
docker exec -it test2-1 ls /data2-1/
docker exec -it test2-1 cat /data2-1/file-1*
docker exec -it test2-1 cat /data2-1/file-1-0dbcf1493277.txt
docker exec -it test2-2 ls /data2-2/
docker exec -it test2-2 cat /data2-2/file-1-ef789d5da7fa.txt
输出结果:
[root@MineGi ~]# docker run -itd -v /testdir:/data2-1 --name test2-1 centos:7 /bin/bash
93be92ef94ab1018aa6af59ab61120a2aa80912994d655f474b3f44c565905ad
[root@MineGi ~]# docker run -itd -v testdir:/data2-2 --name test2-2 centos:7 /bin/bash
175e21ac01db2cd9a7186fabc689a8587a093f6845647d7cf4ee016482b6ea35
[root@MineGi ~]# docker exec -it test2-1 ls /data2-1/
file-1-0dbcf1493277.txt
[root@MineGi ~]# docker exec -it test2-1 cat /data2-1/file-1*
cat: /data2-1/file-1*: No such file or directory
[root@MineGi ~]# docker exec -it test2-1 cat /data2-1/file-1-0dbcf1493277.txt
This is the 0dbcf1493277 test file
[root@MineGi ~]# docker exec -it test2-2 ls /data2-2/
file-1-ef789d5da7fa.txt
[root@MineGi ~]# docker exec -it test2-2 cat /data2-2/file-1-ef789d5da7fa.txt
This is the ef789d5da7fa test file
[root@MineGi ~]#
1.1.3 验证所有容器是否共用目录
情况说明:验证所有容器是否共用宿主机的对应的目录,首先在宿主机的目录下创建新的文件,然后查看容器内的目录下是否会出现新创建的文件。
命令示例:
echo "/testdir/file-2-`hostname`.txt" |tee /testdir/file-2-`hostname`.txt
echo "../_data/file-2-`hostname`.txt" |tee /var/lib/docker/volumes/testdir/_data/file-2-`hostname`.txt
docker exec -it test1-1 ls /data1-1/
docker exec -it test1-1 cat /data1-1/file-2-MineGi.txt
docker exec -it test1-2 ls /data1-2/
docker exec -it test1-2 cat /data1-2/file-2-MineGi.txt
docker exec -it test2-1 ls /data2-1/
docker exec -it test2-1 cat /data2-1/file-2-MineGi.txt
docker exec -it test2-2 ls /data2-2/
docker exec -it test2-2 cat /data2-2/file-2-MineGi.txt
输出结果:
[root@MineGi ~]# echo "/testdir/file-2-`hostname`.txt" |tee /testdir/file-2-`hostname`.txt
/testdir/file-2-MineGi.txt
[root@MineGi ~]# echo "../_data/file-2-`hostname`.txt" |tee /var/lib/docker/volumes/testdir/_data/file-2-`hostname`.txt../_data/file-2-MineGi.txt
[root@MineGi ~]# docker exec -it test1-1 ls /data1-1/
file-1-0dbcf1493277.txt file-2-MineGi.txt
[root@MineGi ~]# docker exec -it test1-1 cat /data1-1/file-2-MineGi.txt
/testdir/file-2-MineGi.txt
[root@MineGi ~]# docker exec -it test1-2 ls /data1-2/
file-1-ef789d5da7fa.txt file-2-MineGi.txt
[root@MineGi ~]# docker exec -it test1-2 cat /data1-2/file-2-MineGi.txt
../_data/file-2-MineGi.txt
[root@MineGi ~]# docker exec -it test2-1 ls /data2-1/
file-1-0dbcf1493277.txt file-2-MineGi.txt
[root@MineGi ~]# docker exec -it test2-1 cat /data2-1/file-2-MineGi.txt
/testdir/file-2-MineGi.txt
[root@MineGi ~]# docker exec -it test2-2 ls /data2-2/
file-1-ef789d5da7fa.txt file-2-MineGi.txt
[root@MineGi ~]# docker exec -it test2-2 cat /data2-2/file-2-MineGi.txt
../_data/file-2-MineGi.txt
[root@MineGi ~]#
1.1.4 清理实验环境
情况说明:该步骤非常危险,可省略,目的是删除所有的容器和所有的数据卷,该操作在实验环境中,无所谓。
docker rm -f $(docker ps -aq) #删除所有容器
docker volume ls --format {{.Name}} | xargs docker volume rm #删除所有的卷
命令示例:
docker rm -f $(docker ps -aq) &>/dev/null
docker volume ls --format {{.Name}} | xargs docker volume rm &>/dev/null
docker ps
docker volume ls
输出结果:
[root@MineGi ~]# docker rm -f $(docker ps -aq) &>/dev/null
[root@MineGi ~]# docker volume ls --format {{.Name}} | xargs docker volume rm &>/dev/null
[root@MineGi ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@MineGi ~]# docker volume ls
DRIVER VOLUME NAME
[root@MineGi ~]#
1.2 案例二:挂载文件1
情况说明:将宿主机中的nginx配置文件复制到nginx容器中,并且能访问到nginx容器提供的页面
1.2.1 准备nginx.conf配置文件
情况说明:可以使用yum安装nginx或者简单编写,获取nginx.conf配置文件,用于测试。
命令示例:
yum install -y epel-release.noarch
yum install -y nginx
ls /opt/nginx.conf
cp /etc/nginx/nginx.conf /opt/
ls /opt/nginx.conf
输出结果:
[root@MineGi ~]# yum install -y -q epel-release.noarch
软件包 epel-release-7-14.noarch 已安装并且是最新版本
[root@MineGi ~]# yum install -y -q nginx
软件包 1:nginx-1.20.1-10.el7.x86_64 已安装并且是最新版本
[root@MineGi ~]# ls /opt/nginx.conf
ls: 无法访问/opt/nginx.conf: 没有那个文件或目录
[root@MineGi ~]# cp /etc/nginx/nginx.conf /opt/
[root@MineGi ~]# ls /opt/nginx.conf
/opt/nginx.conf
[root@MineGi ~]#
1.2.2 修改nginx.conf配置文件
情况说明:修改nginx.conf配置文件,指定的网页站点根目录
命令示例:
sed -i -e 's#/usr/share/nginx/html#/mnt/html/#g' -e 's/80/1180/g' /opt/nginx.conf
grep "/mnt/html/" /opt/nginx.conf
grep -Ev "^$|^#" /opt/nginx.conf
输出结果:
[root@MineGi ~]# sed -i -e 's#/usr/share/nginx/html#/mnt/html/#g' -e 's/80/1180/g' /opt/nginx.conf
[root@MineGi ~]# grep "/mnt/html/" /opt/nginx.conf
root /mnt/html/;
# root /mnt/html/;
[root@MineGi ~]# grep -Ev "^$|^#" /opt/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 1180;
listen [::]:1180;
server_name _;
root /mnt/html/;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
[root@MineGi ~]#
1.2.3 创建新容器nginx-01
情况说明:创建nginx-01容器,将本地的nginx配置文件挂载到容器的nginx配置文件
#创建nginx-01容器,并将本地的nginx配置文件挂载到容器的nginx配置文件
docker run -itd --name nginx-01 -p 80:1180 -v /opt/nginx.conf:/etc/nginx/nginx.conf nginx /bin/bash
命令示例:
docker run -itd --name nginx-01 -p 80:1180 -v /opt/nginx.conf:/etc/nginx/nginx.conf nginx /bin/bash
docker ps
输出结果:
[root@MineGi ~]# docker run -itd --name nginx-01 -p 80:1180 -v /opt/nginx.conf:/etc/nginx/nginx.conf nginx /bin/bash
841ba5a9e2ff385938bd90db93d5935bed772ea061ca52ec48714e33837266b4
[root@MineGi ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
841ba5a9e2ff nginx "/docker-entrypoint.…" 3 seconds ago Up 2 seconds 80/tcp, 0.0.0.0:80->1180/tcp, :::80->1180/tcp nginx-01
[root@MineGi ~]#
1.2.4 进入到nginx-01容器
情况说明:进入到nginx-01容器中,然后创建站点目录和网页测试文件,最后启动或重载nginx服务
#进入到nginx-01容器中
docker exec -it nginx-01 /bin/bash
#创建站点目录和网页文件
mkdir /mnt/html
echo " hello world" > /mnt/html/index.html
#启动nginx服务
/usr/sbin/nginx
命令示例:
docker exec -it nginx-01 /bin/bash
mkdir /mnt/html
echo "hello world" |tee /mnt/html/index.html
ls /etc/nginx/conf.d/default.conf
mv /etc/nginx/conf.d/default.conf .
nginx
输出结果:
[root@MineGi ~]# docker exec -it nginx-01 /bin/bash
root@841ba5a9e2ff:/# mkdir /mnt/html
root@841ba5a9e2ff:/# echo "hello world" |tee /mnt/html/index.html
hello world
root@841ba5a9e2ff:/# ls /etc/nginx/conf.d/default.conf
/etc/nginx/conf.d/default.conf
root@841ba5a9e2ff:/# mv /etc/nginx/conf.d/default.conf .
root@841ba5a9e2ff:/# nginx
root@841ba5a9e2ff:/#
1.2.5 进行浏览器访问测试
情况说明:浏览器访问宿主机IP地址,测试能否查看到网页资源
命令示例:
ip r g 1
netstat -lntup |grep 80
curl 10.4.7.11
输出结果:
[root@MineGi ~]# ip r g 1
1.0.0.0 via 10.4.7.254 dev eth0 src 10.4.7.11
cache
[root@MineGi ~]# netstat -lntup |grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 12484/docker-proxy
tcp6 0 0 :::80 :::* LISTEN 12493/docker-proxy
[root@MineGi ~]# curl 10.4.7.11
hello world
[root@MineGi ~]#
1.2.6 清理实验环境
情况说明:该步骤非常危险,可省略,目的是删除所有的容器和所有的数据卷,该操作在实验环境中,无所谓。
docker rm -f $(docker ps -aq) #删除所有容器
docker volume ls --format {{.Name}} | xargs docker volume rm #删除所有的卷
命令示例:
docker rm -f $(docker ps -aq) &>/dev/null
docker volume ls --format {{.Name}} | xargs docker volume rm &>/dev/null
docker ps
docker volume ls
输出结果:
[root@MineGi ~]# docker rm -f $(docker ps -aq) &>/dev/null
[root@MineGi ~]# docker volume ls --format {{.Name}} | xargs docker volume rm &>/dev/null
[root@MineGi ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@MineGi ~]# docker volume ls
DRIVER VOLUME NAME
[root@MineGi ~]#
1.3 案例三:挂载文件2
情况说明:将容器的内的某个文件或目录持久化到宿主机中。
1.3.1 创建新容器nginx-02和nginx-03
情况说明:容器nginx-02不指定名称,默认会是一串hash字符串,容器nginx-03指定名称为nginx-03,会自动创建一个nginx-03的数据卷,内容的内容都是相同内容,后面拿nginx-03文件举例。
命令示例:
docker run -it nginx /bin/bash -c "ls /etc/nginx/conf.d/;ls /usr/share/nginx/html/"
docker volume ls
docker run -d --name nginx-02 -v /etc/nginx/conf.d/ -p 8080:80 nginx
docker run -d --name nginx-03 -v conf.d-01:/etc/nginx/conf.d/ -v html-01:/usr/share/nginx/html/ -p 80:80 nginx
docker volume ls
ls /var/lib/docker/volumes/
ls /var/lib/docker/volumes/conf.d-01/_data/
ls /var/lib/docker/volumes/html-01/_data/
ls /var/lib/docker/volumes/c206edebc05c1d34759ba1c71bbd919c3d866a88377a19df5ba8c037b3a9548c/_data/
输出结果:
[root@MineGi ~]# docker run -it nginx /bin/bash -c "ls /etc/nginx/conf.d/;ls /usr/share/nginx/html/"
default.conf
50x.html index.html
[root@MineGi ~]# docker volume ls
DRIVER VOLUME NAME
[root@MineGi ~]# docker run -d --name nginx-02 -v /etc/nginx/conf.d/ -p 8080:80 nginx
29bc3abe2bc1709aefb787a37c1d7efde97acb6a892fc1725dab3afd05fefe11
[root@MineGi ~]# docker run -d --name nginx-03 -v conf.d-01:/etc/nginx/conf.d/ -v html-01:/usr/share/nginx/html/ -p 80:80 nginx
93a18cf87df765f6f00571adaac752e082f8e75a7e92540321ffbb70b76dc6a3
[root@MineGi ~]# docker volume ls
DRIVER VOLUME NAME
local c206edebc05c1d34759ba1c71bbd919c3d866a88377a19df5ba8c037b3a9548c
local conf.d-01
local html-01
[root@MineGi ~]# ls /var/lib/docker/volumes/
backingFsBlockDev c206edebc05c1d34759ba1c71bbd919c3d866a88377a19df5ba8c037b3a9548c conf.d-01 html-01 metadata.db
[root@MineGi ~]# ls /var/lib/docker/volumes/conf.d-01/_data/
default.conf
[root@MineGi ~]# ls /var/lib/docker/volumes/html-01/_data/
50x.html index.html
[root@MineGi ~]# ls /var/lib/docker/volumes/c206edebc05c1d34759ba1c71bbd919c3d866a88377a19df5ba8c037b3a9548c/_data/
default.conf
[root@MineGi ~]#
1.3.2 修改配置文件和访问测试
情况说明:在宿主机中修改配置文件,相当于直接在容器中修改配置文件
#查看本地宿主机IP地址
ip r g 1
#看是否能够访问,返回200 OK
curl -I 10.4.7.11
#修改一下index.html文件内容
echo "This hostname is `hostname`" |tee /var/lib/docker/volumes/html-01/_data/index.html
#测试是否能够访问,返回修改后的内容
curl 10.4.7.11
#过滤80
grep 80 /var/lib/docker/volumes/conf.d-01/_data/default.conf
#修改端口80为8080
sed -i 's/80/8080/g' /var/lib/docker/volumes/conf.d-01/_data/default.conf
#过滤8080
grep 8080 /var/lib/docker/volumes/conf.d-01/_data/default.conf
#测试是否能够访问,没加载配置文件前能够方法
curl 10.4.7.11
#加载nginx服务
docker exec -it nginx-03 nginx -s reload
#测试是否能够访问,加载配置文件后无法方法
curl 10.4.7.11
#因为端口映射还是之前的端口
docker port nginx-03
#重新启动一个nginx-04的新容器,用修改过的配置文件
docker run -d --name nginx-04 -v conf.d-01:/etc/nginx/conf.d/ -v html-01:/usr/share/nginx/html/ -p 81:8080 nginx
#测试是否能够访问,能够成功访问
curl 10.4.7.11:81
命令示例:
ip r g 1
curl -I 10.4.7.11
echo "This hostname is `hostname`" |tee /var/lib/docker/volumes/html-01/_data/index.html
curl 10.4.7.11
grep 80 /var/lib/docker/volumes/conf.d-01/_data/default.conf
sed -i 's/80/8080/g' /var/lib/docker/volumes/conf.d-01/_data/default.conf
grep 8080 /var/lib/docker/volumes/conf.d-01/_data/default.conf
curl 10.4.7.11
docker exec -it nginx-03 nginx -s reload
curl 10.4.7.11
docker port nginx-03
docker run -d --name nginx-04 -v conf.d-01:/etc/nginx/conf.d/ -v html-01:/usr/share/nginx/html/ -p 81:8080 nginx
curl 10.4.7.11:81
输出结果:
[root@MineGi ~]# ip r g 1
1.0.0.0 via 10.4.7.254 dev eth0 src 10.4.7.11
cache
[root@MineGi ~]# curl -I 10.4.7.11
HTTP/1.1 200 OK
Server: nginx/1.27.3
Date: Mon, 16 Dec 2024 08:35:45 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 26 Nov 2024 15:55:00 GMT
Connection: keep-alive
ETag: "6745ef54-267"
Accept-Ranges: bytes
[root@MineGi ~]# echo "This hostname is `hostname`" |tee /var/lib/docker/volumes/html-01/_data/index.html
This hostname is MineGi
[root@MineGi ~]# curl 10.4.7.11
This hostname is MineGi
[root@MineGi ~]# grep 80 /var/lib/docker/volumes/conf.d-01/_data/default.conf
listen 80;
listen [::]:80;
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
[root@MineGi ~]# sed -i 's/80/8080/g' /var/lib/docker/volumes/conf.d-01/_data/default.conf
[root@MineGi ~]# grep 8080 /var/lib/docker/volumes/conf.d-01/_data/default.conf
listen 8080;
listen [::]:8080;
# proxy the PHP scripts to Apache listening on 127.0.0.1:8080
[root@MineGi ~]# curl 10.4.7.11
This hostname is MineGi
[root@MineGi ~]# docker exec -it nginx-03 nginx -s reload
2024/12/16 08:36:18 [notice] 33#33: signal process started
[root@MineGi ~]# curl 10.4.7.11
curl: (7) Failed connect to 10.4.7.11:80; 拒绝连接
[root@MineGi ~]# docker port nginx-03
80/tcp -> 0.0.0.0:80
80/tcp -> [::]:80
[root@MineGi ~]# docker run -d --name nginx-04 -v conf.d-01:/etc/nginx/conf.d/ -v html-01:/usr/share/nginx/html/ -p 81:8080 nginx
25d59ce54e029cf0d13a281fce5db131e8e3cf084480147b1e5f76dc785bbe1b
[root@MineGi ~]# curl 10.4.7.11:81
This hostname is MineGi
[root@MineGi ~]#
1.3.3 清理实验环境
情况说明:该步骤非常危险,可省略,目的是删除所有的容器和所有的数据卷,该操作在实验环境中,无所谓。
docker rm -f $(docker ps -aq) #删除所有容器
docker volume ls --format {{.Name}} | xargs docker volume rm #删除所有的卷
命令示例:
docker rm -f $(docker ps -aq) &>/dev/null
docker volume ls --format {{.Name}} | xargs docker volume rm &>/dev/null
docker ps
docker volume ls
输出结果:
[root@MineGi ~]# docker rm -f $(docker ps -aq) &>/dev/null
[root@MineGi ~]# docker volume ls --format {{.Name}} | xargs docker volume rm &>/dev/null
[root@MineGi ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@MineGi ~]# docker volume ls
DRIVER VOLUME NAME
[root@MineGi ~]#
2、数据卷容器(DataVolumes Containers)
如果需要在容器之间共享一些数据,最简单的方法就是使用数据卷容器
数据卷容器是一个独立的容器,专门用来提供数据卷供其他容器挂载。当你创建一个数据卷容器时,它会在容器的指定目录中创建一个数据卷,其他容器可以通过挂载这个数据卷来访问其中的数据
2.1 创建新容器centos-01
#创建一个容器作为数据卷容器
docker run -it --name web01 -v /mnt -v /opt centos:7 /bin/bash
#在数据卷容器中的数据卷目录中写入新文件
echo "this is mnt" > /mnt/file1.txt
echo "this is opt" > /opt/file1.txt
情况说明:创建一个容器centos-01作为数据卷容器,提供数据目录为/testdir-01和/testdir-01
命令示例:
docker volume ls
docker run -it --name centos-01 -v /testdir-01 -v /testdir-02 centos:7 /bin/bash
ls
echo "this is testdir-01" |tee /testdir-01/file.txt
echo "this is testdir-02" |tee /testdir-02/file.txt
exit
docker volume ls
输出结果:
[root@MineGi ~]# docker volume ls
DRIVER VOLUME NAME
[root@MineGi ~]# docker run -it --name centos-01 -v /testdir-01 -v /testdir-02 centos:7 /bin/bash
[root@ae66620cc19e /]# ls
anaconda-post.log dev home lib64 mnt proc run srv testdir-01 tmp var
bin etc lib media opt root sbin sys testdir-02 usr
[root@ae66620cc19e /]# echo "this is testdir-01" |tee /testdir-01/file.txt
this is testdir-01
[root@ae66620cc19e /]# echo "this is testdir-02" |tee /testdir-02/file.txt
this is testdir-02
[root@ae66620cc19e /]# exit
exit
[root@MineGi ~]# docker volume ls
DRIVER VOLUME NAME
local f8f033a00dd772533141163033b8751a9c6032de9d22af80f47d3d73a94c6131
local f3015dca0eec627687f3613468f64a49fe1ec2cf827837b8342e52f5155f9542
[root@MineGi ~]#
2.2 创建新容器centos-02
#使用 --volumes-from 来挂载 web2 容器中的数据卷到新的容器
docker run -it --volumes-from web2 --name web3 centos:7 /bin/bash
cat /mnt/file1.txt
cat /opt/file1.txt
情况说明:使用 --volumes-from 来挂载 centos-01 容器中的数据卷到新的容器centos-02中
命令示例:
docker run -it --volumes-from centos-01 --name centos-02 centos:7 /bin/bash
ls
cat /testdir-01/file.txt
cat /testdir-02/file.txt
exit
输出结果:
[root@MineGi ~]# docker run -it --volumes-from centos-01 --name centos-02 centos:7 /bin/bash
[root@ae6ef2f317d8 /]# ls
anaconda-post.log dev home lib64 mnt proc run srv testdir-01 tmp var
bin etc lib media opt root sbin sys testdir-02 usr
[root@ae6ef2f317d8 /]# cat /testdir-01/file.txt
this is testdir-01
[root@ae6ef2f317d8 /]# cat /testdir-02/file.txt
this is testdir-02
[root@ae6ef2f317d8 /]# exit
exit
[root@MineGi ~]#
2.3 清理实验环境
情况说明:该步骤非常危险,可省略,目的是删除所有的容器和所有的数据卷,该操作在实验环境中,无所谓。
docker rm -f $(docker ps -aq) #删除所有容器
docker volume ls --format {{.Name}} | xargs docker volume rm #删除所有的卷
命令示例:
docker rm -f $(docker ps -aq) &>/dev/null
docker volume ls --format {{.Name}} | xargs docker volume rm &>/dev/null
docker ps
docker volume ls
输出结果:
[root@MineGi ~]# docker rm -f $(docker ps -aq) &>/dev/null
[root@MineGi ~]# docker volume ls --format {{.Name}} | xargs docker volume rm &>/dev/null
[root@MineGi ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@MineGi ~]# docker volume ls
DRIVER VOLUME NAME
[root@MineGi ~]#
二、容器互联
情况说明:容器互联是通过容器的名称在容器间建立一条专门的网络通信隧道。简单点说,就是会在源容器和接收容器之间建立一条隧道,接收容器可以看到源容器指定的信息
1、基于默认桥接网络(bridge)的互联
原理:Docker 默认使用桥接网络(bridge)模式。在这种模式下,Docker 会创建一个名为docker0的虚拟网桥,每个容器都会连接到这个网桥,并被分配一个私有 IP 地址。这些 IP 地址通常在172.17.0.0/16等子网范围内。容器之间可以通过这些 IP 地址进行通信。
示例操作:
首先,启动两个容器。例如,启动一个alpine容器作为测试:
docker run -d --name container1 alpine sleep 3600
再启动另一个alpine容器:
docker run -d --name container2 alpine sleep 3600
可以通过docker inspect命令查看容器的 IP 地址。例如,查看container1的 IP 地址:
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container1
假设得到container1的 IP 地址是172.17.0.2,container2的 IP 地址是172.17.0.3。
在container1中可以通过ping命令测试与container2的连通性(需要在容器中安装ping工具,如果是alpine容器,可通过apk add iputils命令安装):
进入container1:docker exec -it container1 sh
执行ping 172.17.0.3来测试与container2的连通性。
命令示例:
docker run -itd --name centos01-1 centos:7
docker run -itd --name centos01-2 centos:7
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' centos01-1
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' centos01-2
docker exec -it centos01-1 ping -c2 172.17.0.3
docker exec -it centos01-2 ping -c2 172.17.0.2
ifconfig docker0
输出结果:
[root@MineGi ~]# docker run -itd --name centos01-1 centos:7
34b719e2f86b5b4f2ca6c835056c22c9efc398370641c7eb6cf65ef5d46956e1
[root@MineGi ~]# docker run -itd --name centos01-2 centos:7
ff1ea36543684b7f50d5ba4d0d7ebb6f72e62db3dbe9363052976a78b1311436
[root@MineGi ~]# docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' centos01-1
172.17.0.2
[root@MineGi ~]# docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' centos01-2
172.17.0.3
[root@MineGi ~]# docker exec -it centos01-1 ping -c2 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.204 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.081 ms
--- 172.17.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.081/0.142/0.204/0.062 ms
[root@MineGi ~]# docker exec -it centos01-2 ping -c2 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.348 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.211 ms
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.211/0.279/0.348/0.070 ms
[root@MineGi ~]# ifconfig docker0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:a0ff:fe17:6d55 prefixlen 64 scopeid 0x20<link>
ether 02:42:a0:17:6d:55 txqueuelen 0 (Ethernet)
RX packets 197 bytes 15863 (15.4 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 181 bytes 15580 (15.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@MineGi ~]#
2、使用自定义网络实现容器互联
创建自定义网络
使用docker network create命令创建一个自定义网络。例如,创建一个名为my-network的网络:
docker network create my-network
将容器添加到自定义网络
启动容器并将其添加到自定义网络中。例如:
启动一个nginx容器:docker run -d --name nginx-container --network my-network nginx
启动一个mysql容器:docker run -d --name mysql-container --network my-network mysql
容器间通信:在这种情况下,容器可以通过容器名称进行通信。例如,在nginx-container中,如果需要连接到mysql-container,可以使用mysql-container作为主机名。假设mysq-container服务监听在3306端口,在nginx-container中配置连接mysql的相关参数时,主机名可以写为mysql-container,端口为3306。
#运行容器container01,使用默认网络
docker run -itd --name container01 centos:7
#运行容器container02,使用默认网络
docker run -itd --name container02 centos:7
#自定义网络,名为demo_net,网段172.25.0.0/16,类型为bridge
docker network create -d bridge --subnet 172.25.0.0/16 demo_net
#查看一下
docker network ls |grep demo_net
#查看具体信息
docker network inspect demo_net |grep Subnet
#将container02添加自定义网络demo_net
docker network connect demo_net container02
#运行容器container03,使用自定义网络demo_net,并指定IP地址为172.25.3.3
docker run -itd --name container03 --network=demo_net --ip=172.25.3.3 centos:7
#查看容器container01的IP地址
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container01
#查看容器container02的IP地址
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container02
#查看容器container03的IP地址
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container03
#容器container02 ping container01的IP地址
docker exec -it container02 ping -c2 172.17.0.4
#容器container02 ping container03的IP地址
docker exec -it container02 ping -c2 172.25.3.3
#容器container01 ping container03的IP地址
docker exec -it container01 ping -c2 172.25.3.3
命令示例:
docker run -itd --name container01 centos:7
docker run -itd --name container02 centos:7
docker network create -d bridge --subnet 172.25.0.0/16 demo_net
docker network ls |grep demo_net
docker network inspect demo_net |grep Subnet
docker network connect demo_net container02
docker run -itd --name container03 --network=demo_net --ip=172.25.3.3 centos:7
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container01
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container02
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container03
docker exec -it container02 ping -c2 172.17.0.4
docker exec -it container02 ping -c2 172.25.3.3
docker exec -it container01 ping -c2 172.25.3.3
输出结果:
[root@MineGi ~]# docker run -itd --name container01 centos:7
751fab7fe71086b2b9d11f9f185e05c7b139237b4f66600b087e0611ee8ba42f
[root@MineGi ~]# docker run -itd --name container02 centos:7
5860257a29240c70f92c3267fe30af84666ad80794977cf8b7befa5bda7490e0
[root@MineGi ~]# docker network create -d bridge --subnet 172.25.0.0/16 demo_net
78d9b906d4fd7d4b96195ed0ad9ec02244ffdfb75de1e5d725f6f450c34aff67
[root@MineGi ~]# docker network ls |grep demo_net
78d9b906d4fd demo_net bridge local
[root@MineGi ~]# docker network inspect demo_net |grep Subnet
"Subnet": "172.25.0.0/16"
[root@MineGi ~]# docker network connect demo_net container02
[root@MineGi ~]# docker run -itd --name container03 --network=demo_net --ip=172.25.3.3 centos:7
ee7fe24d901769a34898923caeae2895cc60f981f2e0284630a4b9d3ad86c226
[root@MineGi ~]# docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container01
172.17.0.4
[root@MineGi ~]# docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container02
172.17.0.5172.25.0.2
[root@MineGi ~]# docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container03
172.25.3.3
[root@MineGi ~]# docker exec -it container02 ping -c2 172.17.0.4
PING 172.17.0.4 (172.17.0.4) 56(84) bytes of data.
64 bytes from 172.17.0.4: icmp_seq=1 ttl=64 time=0.104 ms
64 bytes from 172.17.0.4: icmp_seq=2 ttl=64 time=0.090 ms
--- 172.17.0.4 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.090/0.097/0.104/0.007 ms
[root@MineGi ~]# docker exec -it container02 ping -c2 172.25.3.3
PING 172.25.3.3 (172.25.3.3) 56(84) bytes of data.
64 bytes from 172.25.3.3: icmp_seq=1 ttl=64 time=0.114 ms
64 bytes from 172.25.3.3: icmp_seq=2 ttl=64 time=0.142 ms
--- 172.25.3.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.114/0.128/0.142/0.014 ms
[root@MineGi ~]# docker exec -it container01 ping -c2 172.25.3.3
PING 172.25.3.3 (172.25.3.3) 56(84) bytes of data.
--- 172.25.3.3 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 999ms
[root@MineGi ~]#
3、使用--link选项(旧方法,不推荐用于新的开发)
原理:--link选项允许一个容器链接到另一个容器。当使用--link时,Docker 会在源容器的/etc/hosts文件中添加目标容器的信息,包括 IP 地址和容器名称等。
示例操作:在web-container中,可以通过db-alias(这里是db)这个名称来访问db-container。不过,这种方式有一些局限性,例如不支持容器的动态添加和删除,并且在较复杂的网络环境中可能会出现问题,现在更推荐使用自定义网络来实现容器互联。
启动一个web容器和一个db容器,将web容器链接到db容器:
启动db容器:docker run -d --name db-container postgres
启动web容器并链接到db容器:docker run -d --name web-container --link db-container:db -alias nginx
命令示例:
docker run -itd --name centos02-1 centos:7
docker exec -it centos02-1 cat /etc/hosts
docker run -itd --name centos02-2 --link centos02-1:dbserver centos:7
docker exec -it centos02-2 tail -2 /etc/hosts
docker exec -it centos02-1 tail -2 /etc/hosts
docker exec -it centos02-2 ping -c2 dbserver
docker exec -it centos02-2 ping -c2 centos01-1
docker exec -it centos02-2 ping -c2 centos02-1
docker ps |grep centos01-1
输出结果:
[root@MineGi ~]# docker run -itd --name centos02-1 centos:7
a49bcedd8ed5eaae0e8a15a1e170cfc02a78e19d00629187c2e52e635159a65e
[root@MineGi ~]# docker exec -it centos02-1 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.6 a49bcedd8ed5
[root@MineGi ~]# docker run -itd --name centos02-2 --link centos02-1:dbserver centos:7
b0fd9c8196005a2ae56c1a30c0c096c4cd7a6d017e3b4950bd8c5633fccff90a
[root@MineGi ~]# docker exec -it centos02-2 tail -2 /etc/hosts
172.17.0.6 dbserver a49bcedd8ed5 centos02-1
172.17.0.7 b0fd9c819600
[root@MineGi ~]# docker exec -it centos02-1 tail -2 /etc/hosts
ff02::2 ip6-allrouters
172.17.0.6 a49bcedd8ed5
[root@MineGi ~]# docker exec -it centos02-2 ping -c2 dbserver
PING dbserver (172.17.0.6) 56(84) bytes of data.
64 bytes from dbserver (172.17.0.6): icmp_seq=1 ttl=64 time=0.110 ms
64 bytes from dbserver (172.17.0.6): icmp_seq=2 ttl=64 time=0.096 ms
--- dbserver ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.096/0.103/0.110/0.007 ms
[root@MineGi ~]# docker exec -it centos02-2 ping -c2 centos01-1
ping: centos01-1: Name or service not known
[root@MineGi ~]# docker exec -it centos02-2 ping -c2 centos02-1
PING dbserver (172.17.0.6) 56(84) bytes of data.
64 bytes from dbserver (172.17.0.6): icmp_seq=1 ttl=64 time=0.096 ms
64 bytes from dbserver (172.17.0.6): icmp_seq=2 ttl=64 time=0.092 ms
--- dbserver ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.092/0.094/0.096/0.002 ms
[root@MineGi ~]# docker ps |grep centos01-1
43a125c2f1b7 centos:7 "/bin/bash" 2 minutes ago Up 2 minutes centos01-1
[root@MineGi ~]#
4、清理实验环境
情况说明:该步骤非常危险,可省略,目的是删除所有的容器和所有的数据卷,该操作在实验环境中,无所谓。
docker rm -f $(docker ps -aq) #删除所有容器
docker volume ls --format {{.Name}} | xargs docker volume rm #删除所有的卷
命令示例:
docker rm -f $(docker ps -aq) &>/dev/null
docker volume ls --format {{.Name}} | xargs docker volume rm &>/dev/null
docker network rm demo_net
docker ps
docker volume ls
输出结果:
[root@MineGi ~]# docker rm -f $(docker ps -aq) &>/dev/null
[root@MineGi ~]# docker volume ls --format {{.Name}} | xargs docker volume rm &>/dev/null
[root@MineGi ~]# docker network rm demo_net
demo_net
[root@MineGi ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@MineGi ~]# docker volume ls
DRIVER VOLUME NAME
[root@MineGi ~]#
三、简单总结
1、数据卷创建
docker run -v 宿主机绝对路径目录(不存在直接创建):容器数据集目录 --name 容器名 -it 镜像:标签 /bin/bash
2、数据卷容器创建
1.首先创建数据卷:
docker run --name 容器a -v /容器挂载点1 -v /容器挂载点2 -it 镜像:标签 /bin/bash
2.挂载容器a中的数据卷:
docerk run -it --volume-from 容器a --name 容器b 镜像:标签 /bin/bash
3、容器互联,文件共享,传输
容器a:
docker run -itd -P --name 容器a 镜像:标签 /bin/bash
容器b:
docker run -itd -P --name 容器b --link 容器a:容器a的别名 镜像:标签 /bin/bash
进入容器b:
docker exec -it 容器b的id/容器b(名字) /bin/bash