Docker入门笔记(2)

容器网络管理

容器网络类型

Docker安装以后,会在我们的主机上创建三个网络

1
docker network ls

image-20240312130610389

可以看到有bridge、host和none三种网络类型

我们先把ubuntu的网络环境配置一下

1
2
3
docker run -it ubuntu
apt update
apt install net-tools iputils-ping curl

这样环境就配置好了,接下来就退出容器,打包成为新的镜像

1
docker commit <容器name> <新镜像名>

现在我们来研究一下刚才上面的显示的三种网络类型

  • none网络:既然是none网络了,基本就是“没网络”,它只有一个本地的环回网络

    我们在创建容器时可以指定none网络来看看

    1
    docker run -it --network=none ubuntu-net

    进入容器后可以ifconfig来查看一下网络

    image-20240312131219509

    他是无法连接到外界的互联网的,是一个真单机运行,没有人能从外部访问它

  • bridge网络:容器默认会使用bridge网络,即桥接网络,它被广泛应用

    image-20240312131459070

    我们进入桥接模式再ifconfig,发现相比none网络,它多了一个新的网络接口;其实这是Docker创建的虚拟网络,docker在此时就充当了一个桥接的角色,一边链接宿主网络,一头连接自己的虚拟子网

    image-20240312131634536

    通过这样的网桥,我们可以对容器的网络进行管控,可以使用network inspect来查看docker0网桥的配置信息

    1
    docker network inspect bridge

    image-20240312131840073

  • host网络:当容器使用host网络时,会共享宿主网络,他们的配置完全一致

    1
    docker run -it --network=host ubuntu-net

    在host网络的情况下,只要宿主主机能连上互联网,那么容器内部也没问题;这样一来就可以直接使用宿主的网络了,也不需要去开放端口了, 比桥接网络要方便的多,但相应的,安全性会有所下降。

    在使用时要根据实际情况来选择这三种网络的使用。

用户自定义网络

Docker为我们默认提供了三种网络驱动:bridge、overlay、macvlan。

我们可以用bridge来试着实现一下自定义的桥接网络

1
docker network create --driver bridge test

这里就创建好了一个名为test的桥接网络

image-20240312140247955

我们新建一个使用test网络的容器

1
docker run -it --network=test ubuntu-net

使用ifconfig来看一下网络情况

image-20240312135734646

我们现在退出这个容器,但不是关闭它,而是将其挂到后台

这里按ctrl + qctrl + p就能挂起

我们再次创建一个容器,这次不指定网络,看他的网络如下

image-20240312135750061

很明显他们不在一个网段,应该是相互隔离的,这是ping是ping不通的

接下来我把他的网络也接入test网络

1
docker network connect test <容器ID/名称>

image-20240312135823757

使用docker attach <容器id>来重新进入容器,再看看ifconfig里的配置

发现多了一个网络设备,现在两个容器就成功接入同一个网络环境下了

img

现在再试试ping原来的容器,就可以顺利ping通了

img

容器间网络

上面我们完成了通过自定义的网桥来实现容器间的通信,下面还可以直接配置容器间的网络来管理他们的通信

我们海狮先创建两个ubuntu-net容器

1
docker run -it ubuntu-net

我们直接在另外一个容器中ping它,由于他们都默认使用beidge网络处在同一个子网下,所以是可以顺利ping通的。

我们可以通过指定容器的ip来实现容器间通信,但是这样写的比较死。我们在配置容器的时候常常是自动分配的ip,这该怎么办呢

我们可以通过Docker为我们提供的DNS服务器来完成对域名的解析,只需要在启动容器时为容器所爱的网络命名,然后就可以实现互相的通信

1
2
docker run -it --name=test01 --network=test ubuntu-net
docker run -it --name=test02 --network=test ubuntu-net

image-20240313142337144

我们还可以直接让两个容器共享一个网络(设备),就相当于让他们处于同一网络环境下

1
docker run -it --name=test03 --network=container:test02 ubuntu-net

现在test02和test03的ip就完全一致了;

我们可以试着在test02中安装nginx

1
2
apt install -y systemctl nginx
systemctl start nginx

然后在tesst03中访问nginx

1
curl localhost

image-20240313142907208

成功访问,这俩容器的网络就接上了,实现了你中有我我中有你的网络状态

容器外部网络

上面了解了容器间的通信,接下来看看容器与外网的通信

在容器的三种网络模式下, 显然none模式是连不了外网的,这下只剩下共享和桥接两种模式来连接网络了。

学过计网的话,这里的物理机可以看做一个路由,容器将网络数据发给物理机,物理机通过地址变换再进行转发;所以这里公网是无法直接访问容器的

image-20240313143609477

上面的图是我们一般意义上的网络的转发,而对于Docker容器的也是差不多的

image-20240313143716050

这里有一个问题,如果只依靠NAT的话,我们的容器只能发送数据,而不能接收数据,该怎么办呢?

我们以前通过nginx实现过端口映射,这里的逻辑也是差不多的。

1
docker run -d -p 80:80 nginx

这里的-p是port端口映射,规则是宿主端口:容器端口,这里就是把容器的80端口映射到主机的80端口上

image-20240313144404741

我们可以使用docker ps,然后在PORTS里查看端口的映射情况

以上就是Docker中单机下的网络操作~


容器存储管理

我们前面学习了容器的网络,现在接受到了数据,如果需要存储数据,就涉及到了容器的存储管理。

容器持久化存储

之前介绍过,对容器内的文件操作,实际上是在最顶层的容器层操作的,这是为了保证镜像本身的文件的安全性,但是这样特性也会造成删除容器时,容器存储的数据的全部丢失。

在某些情况下(比如说操作数据库数据),我们希望对容器内的部分数据进行持久化的存储,这是就需要用到数据卷了

先准备一个新的镜像

1
2
3
docker run -it ubuntu
apt update
apt install -y vim

安装vim完毕后打包成新的镜像

1
docker commit <容器名/id> 镜像名:<TAG>

我们在主机上创建一个文件

1
2
mkdir test
vim test/hello.txt

在文件中随便写点东西,然后将主机的目录或文件挂载到容器的某个目录中

1
docker run -it -v ~/test:/root/test/ ubuntu-vim

这里的-v就是要挂载文件,把我们刚才的test目录挂载到容器的/root/test目录中

然后我们在容器上也可以打开该文件了

image-20240313151542805

这时候我们销毁容器,文件还会存在吗?

1
2
exit
docker rm <容器名/id>

我们再次查看文件

image-20240313151808681

能看见容器内的修改,同时显然这个文件没有随着容器的删除而消失

如果我们不想让容器与主机之间以这种类似于共享文件夹的方式共享文件的话,我们可以使用cp指令来在容器和主机之间复制文件

1
docker cp ~/test/hello.txt ubuntu-vim:/root/test

容器间数据共享

上面说了容器与主机间的数据共享,如果我们想实现容器之间的数据共享,可以怎么做?

  • 通过上面学的,最直接的办法就是把两个容器挂到主机的同一个目录上,既然你俩都指向同一块区域了,那可不是实现共享了吗

我们先创建一个容器,让他挂载主机上的某个目录

1
docker run -it -v ~/test:root/test --name=data_test ubuntu-vim

然后再创建一个容器,使用--volumes-from来指定要挂载到的另一个容器

1
docker run -it --volumes-from data_test ubuntu-vim

这下挂载成功了

image-20240313154105295

显然上面的方式很麻烦,而且明明是两个容器间的共享,却要牵扯到主机,我们不想要这样。

  • 我们可以创建一个专门的容器来将容器中打包好的数据分享给其他容器(其本质上仍然是一个由Docker管理的数据卷),虽然没有完全脱离主机,但是移植性大大提升了

我们编写一个Docklefile来创建这个数据卷

1
2
3
FROM ubuntu
COPY hello.txt /usr/share/test/
VOLUME /usr/share/test

这里的VOLUME和之前的-v一样,会在容器中创建一个挂载点

然后创建镜像

1
docker build -t data .

然后运行容器,进入对应的挂载点,就能找到我们设置的数据卷了


参考视频:Docker 容器技术 已完结(2022 最新版)4K蓝光画质+杜比音效 从内卷到开摆

视频教程文档:Docker容器技术