Docker 中级——网络和卷

814 阅读5分钟

详细了解docker的网络和数据卷之前,可以先去看看docker的进阶和使用。docker 进阶

Docker网络模式

容器是docker管理的最小单元,就好像一个房子里面的不同房间,他们彼此隔离,互不影响。一个容器故障,也不会影响其他容器的正常运行。docker提供了四种网络模式,来解决容器之间的通信。接下来介绍四种常用的docker网络模式。

bridge

默认的网络驱动程序。如果没有指定驱动程序,这就是容器默认使用的网络类型。
fb487dfaf5d6fcb7d86dc9a64b74a05f.jpeg docker0是docker默认创建的网桥,也充当默认的网关。通过主机上的ifconfig命令我们能看到docker0虚拟接口的信息。使用docker命令创建容器时,如果不指定网络(--net)将默认使用docker0分配的ip,并通过veth pair虚拟网络设备与网桥相连,容器之间可以通过容器的ip进行直接通信。

host

共享宿主机的Network namespace。去掉容器与Docker主机的网络隔离,直接使用主机的网络和端口,但是文件系统还是隔离的。 未命名文件 (1).png

none

对于这个容器,禁用所有网络。通常与自定义网络驱动程序结合使用。none不适用于群服务

未命名文件 (2).png

container

共享容器的network namespace。使用已经存在的容器的ip+端口。

未命名文件 (3).png

自定义网络及容器通信

docker网络常用命令

# 查看docker网络
docker network ls
# 创建网络,默认网络类型为bridge,docker自身已经提供了host以及none类型网络
# 自定义网络参数可以通过docker network create --help查看,可以自己设置网段和网关。
docker network create test-net [--subnet 100.10.0.0/24 --gateway 100.10.0.1]
# 查看网络详情
docker inspect test-net
# 移除网络
docker network rm test-net

测试bridge网络

  • 创建一个docker网络
docker network create redis-net
  • 创建redis容器,并使用redis-net网络(添加[]中的参数,其他容器可以通过容器名访问)
docker run -d --name redis-test --net redis-net [--network-alias redis] redis
  • 查看redis容器的ip
docker inspect redis-net
# 从输出的JSON串中的Containers中可以看到redis-test的ip地址为:172.21.0.2
  • 创建busybox容器,并ping redis-test的ip
docker run --rm -it --net redis-net busybox ping 172.21.0.2

微信截图_20210902173525.png

可以看到,是可以ping通的,容器之间完成了通信,测试成功。通过docker inspect命令,我们能查看到网络的详情,以及正在运行的容器信息。另外,在创建redis容器的时候如果加个参数 --network-alias redis,busybox容器可以通过容器名直接ping通。

测试container网络

  • 运行mysql-test容器,指不指定网络都可
docker run -d --name redis-test2 redis
  • 运行busybox,加入到redis-test2网络中
docker run --rm -it --net container:redis-test2 busybox
  • 查看本地6379端口情况
netstat -anp|grep 6379

微信截图_20210902175737.png

此时6379为监听状态,即busybox和redis在同一个ip中,与预想的一致,测试完毕。 docker0是docker默认的网桥,容器也能直接通过docker0进行相互通信,具体的操作与bridge网络的操作一致,使用时不需指定--net,默认就行。docker还提供了一个参数--link,可以将xx容器的ip和容器名映射写进运行容器的hosts文件,实现容器名通信。

Docker数据卷

由于容器的特性,当容器不再存在时,数据也会随之丢失,数据保存在容器而非宿主机。并且当另外的进程需要使用数据时,很难获取到容器里的数据。基于以上问题,docker设计了两种方式,能很方便的对数据进行持久化存储,以及容器之间实现数据共享。

Volumes

volumes是docker设计的一种容器数据持久化方案,可以理解为一个目录。创建卷时,它存储在宿主机的目录/var/lib/docker/volumes。当你将卷挂载到容器中时,容器挂载的目录中所有文件都将放在卷中。如果卷不存在,它会在容器创建的时候自动创建。当容器挂载的目录中在挂载前就存在文件时,挂在后也会存在于卷中。

# volume相关命令
# 查看volumes
docker volume ls
# 查看volume详情
docker inspect 卷名
# 创建一个volume
docker volume create test-volume
# 删除volumes
docker volume rm test-volume [其他卷名]
# 删除没有被使用的卷
docker volume prune

在mysql中使用volume持久化保存数据

docker run -d --name mysql-test -e MYSQL_ROOT_PASSWORD=123456 -v mysql-data:/var/lib/mysql mysql

查看卷目录 /var/lib/docker/volumes/mysql-data/_data volume.png

这里主要演示了命名卷,匿名卷的用法一样,在-v挂载的时候,无需写卷名,docker会自动随机创建一个唯一的卷名。我们可以通过 docker inspect 容器名查看详细的卷挂载点情况。

Bind mounts

bind mounts是docker设计的另一个持久化方案。与volumes不同的是,这种方式需要指定确定的路径让容器挂载。除此之外,容器挂载的路径中如果在挂载前存在文件,挂载后将会被清空。宿主机挂载的目录中如果存在文件,挂载后会继续存在。

在mysql中使用Bind mounts方式持久化数据

docker run -d --name mysql-test -e MYSQL_ROOT_PASSWORD=123456 -v /data/mysql:/var/lib/mysql mysql

查看挂载目录 /data/mysql

test.png

可以看到通过bind mounts方式挂载的文件也持久化的保存在了宿主机中。 当多个容器使用同一个卷时,就可以达到数据共享的目的。 小结:本篇讲述了docker中网络和卷的核心概念和用法,也是实际开发中使用最多的。通过docker inspect [卷|网络|容器]可以看到对应的详情,及时排错。接下来,我将会陆续更新Dockerfile、docker-compose等更实用的内容,敬请期待~
接下来:docker终极