Docker(认识且会基础操作)

前言

当然,Docker运维 的工作中也是不可或缺的!

之前其实已经写了一篇Docker了,但是已经全忘了。害!

该篇的目的是为了了解Docker基本操作,并且会用Docker

参考文献

开发者必备的 Docker 实践指南

【狂神说Java】Docker最新超详细版教程通俗易懂

Docker架构

  • Docker daemon理解成Docker服务

Docker是一个Client - Server的结构系统,Docker的守护进程(Docker daemon)运行在主机上,通过Socket从客户端访问。

  • -H fd://Docker 默认通过 Unix 套接字(/var/run/docker.sock)通信。
  • --containerd=/run/containerd/containerd.sock:使用 containerd 作为容器运行时。

不知道大家是否学过MySQL,连接到MySQL怎么做?
服务器 进程和客户端 进程都运行在同一台操作系统为类Unix的机器上的话,可以使用Unix域套接字文件来进行进程间通信

不同进程间 通过套接字文件通信。

  • Docker Client 客户端,怎么理解呢?小黑框输入命令等待服务端响应。
  • Docker_HOST 服务端,接收命令,做出反应。
  • 镜像images理解成容器Containers就是对象

安装Docker

CentOS8 CentOS9都能用。

官网地址

为什么是Docker Engine,在Docker Engine包含着docker daemondocker CLI

bash 复制代码
dnf -y install dnf-plugins-core
dnf config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
dnf makecache
  • docker-ce docker引擎(ce 社区版,ee 企业版)
  • docker-ce-cli docker引擎命令行程序
  • container.io docker的运行环境
  • docker-buildx-plugin 构建镜像的插件工具
  • docker-compose做批量工具一次性都安装
bash 复制代码
#启动docker
systemctl start docker
#判断是否安装成功,查看是否有版本。
docker version
docker run hello-world

启动不起来?

bash 复制代码
#关闭防火墙
#一句话总结一下,如果关闭防火墙,就相当于对外暴露所有端口
systemctl stop firewalld.service
systemctl disable firewalld.service

#配置镜像源
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<EOF
{	#修改镜像源
    "registry-mirrors": [
        "https://docker.1ms.run",
        "https://hub.rat.dev",
        "https://docker.1panel.live"
    ]
}
EOF
#重启后台进程
sudo systemctl daemon-reload
#重启docker
sudo systemctl restart docker

查看安装的镜像

bash 复制代码
[root@CentOS8 /]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
hello-world   latest    74cc54e27dc4   5 weeks ago   10.1kB

卸载Docker

bash 复制代码
#卸载依赖
sudo dnf remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
#删除资源,资源一般都在lib目录下
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

Namespace

命名空间Linux核心在 2.4 版本后逐渐引入的一项用于运行隔离的模块。

Linux 内核的命名空间 ,就是能够将计算机资源 进行切割划分,形成各自独立的空间

LinuxPID Namespace 是资源隔离的核心机制之一。通过它,系统可以创建一个独立的进程运行环境,其中的进程编号(PID)会从1开始重新计数,就像在一个全新的操作系统中运行一样。


容器内的进程 无法感知宿主机其他容器 的进程(例如容器内的 PID 44 进程,在宿主机中可能显示为 PID 1543)。

Control Groups


资源控制组 的作用就是控制计算机资源 的。通过 CGroups,可以指定任意一个隔离环境对任意资源的占用值或占用率,这对于很多分布式使用场景来说是非常有用的功能。

Run的流程和Docker原理

镜像

bash 复制代码
#显示docker的版本
docker version 
#显示docker的系统信息
docker info
#万能命令
docker 命令 --help


[root@CentOS8 ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
hello-world   latest    74cc54e27dc4   5 weeks ago   10.1kB
  • REPOSITORY:镜像的仓库源。
  • TAG:镜像的标签(说白了就是版本)。
  • IMAGE ID:镜像的ID
  • CREATED:镜像的创建时间
  • SIZE:镜像的大小
bash 复制代码
-a, --all    #列出所有镜像
-q, --quiet #只显示镜像的ID

#列出所有的docker镜像ID
[root@CentOS8 ~]# docker images -aq
74cc54e27dc4

拉取镜像,也就是下载镜像。

bash 复制代码
[root@CentOS8 ~]# docker pull mysql
Using default tag: latest #latest 代表着最新版
latest: Pulling from library/mysql
43759093d4f6: Pull complete # 分层下载,docker images的核心 联合文件系统
d255dceb9ed5: Pull complete
23d22e42ea50: Pull complete
431b106548a3: Pull complete
2be0d473cadf: Pull complete
f56a22f949f9: Pull complete
277ab5f6ddde: Pull complete
df1ba1ac457a: Pull complete
cc9646b08259: Pull complete
893b018337e2: Pull complete
Digest: sha256:146682692a3aa409eae7b7dc6a30f637c6cb49b6ca901c2cd160becc81127d3b #签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真实地址

docker pull mysql == docker pull docker.io/library/mysql:latest

#指定版本下载
[root@CentOS8 ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
20e4dcae4c69: Pull complete
1c56c3d4ce74: Pull complete
e9f03a1c24ce: Pull complete
68c3898c2015: Pull complete
6b95a940e7b6: Pull complete
90986bb8de6e: Pull complete
ae71319cb779: Pull complete
ffc89e9dfd88: Pull complete
43d05e938198: Pull complete
064b2d298fba: Pull complete
df9a4d85569b: Pull complete
Digest: sha256:4bc6bc963e6d8443453676cae56536f4b8156d78bae03c0145cbe47c2aad73bb
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

删除镜像

bash 复制代码
#删除单个镜像
docker rmi mysql:5.7
#删除多个镜像
docker rmi 镜像名 镜像名 镜像名
#删除所有docker镜像
docker rmi -f $(docker images -aq)

容器

bash 复制代码
docker pull centos

新建容器并启动

bash 复制代码
docker run [可选参数] image

#参数说明
--name="Name" 容器名字 tomcat01 tomcat02,用来区分容器。
-d            后台方式运行
-it           使用交互方式运行,进入容器查看内容
-p            指定容器的端口 --p 8080:8080
-P            随机指定端口

启动并进入容器

bash 复制代码
docker run -it centos /bin/bash

#容器内和容器外是不是很相似
#容器内就是centos环境,基础版本,很多命令都是不完善的。
[root@886344be63b1 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

列出所有运行的容器

bash 复制代码
docker ps 
docker ps -aq

退出容器

bash 复制代码
exit 	     #直接容器停止并退出
ctrl + P + Q #容器不停止退出

删除容器

bash 复制代码
docker rm 容器ID               # 删除指定容器,不能删除正在运行的容器,如果要强制删除rm -f
docker rm -f $(docker ps -aq) # 删除所有容器

后台启动容器

bash 复制代码
#命令 docker run -d 镜像名
docker run -d centos


docker ps,发现centos停止了。
docker容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止。

bash 复制代码
#前台运行状态
ping baidu.com
#后台运行
nohup ping baidu.com &


此时停止前台运行容器,发现容器就停止了!

docker容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止。

再看这句话,此时我没有任何一个窗口被前台进程所占用是否是理解错问题呢?


Nginx在容器中通常以"daemon off"方式运行,强制它保持在前台,这样主进程 不会退出,容器持续运行。

bash 复制代码
#主进程:
root        1288       1  0 22:28 ?        00:00:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

进入当前正在运行的容器

bash 复制代码
docker exec -it 容器id /bin/bash

那么centos容器我们退出了它就关闭了,如果再次进入呢?

bash 复制代码
[root@CentOS8 ~]# docker ps -a
CONTAINER ID   IMAGE                 COMMAND                  CREATED          STATUS                        PORTS                                                                                  NAMES
1df6775e71d5   centos                "/bin/bash"              14 minutes ago   Exited (127) 2 seconds ago                                                                                           hardcore_nash
[root@CentOS8 ~]# docker start 1df6775e71d5
1df6775e71d5
#两种方式:
docker attach 1df6775e71d5
docker exec -it 1df6775e71d5 /bin/bash

从容器拷贝文件到主机上

bash 复制代码
docker cp 容器id:容器内路径 目的主机路径

docker run -it centos /bin/bash
[root@e2f90d4ed867 /]# cd /home/
[root@e2f90d4ed867 home]# touch test.txt
[root@e2f90d4ed867 home]# exit
[root@CentOS8 ~]# docker ps -a
CONTAINER ID   IMAGE          COMMAND       CREATED              STATUS                      PORTS     NAMES
e2f90d4ed867   centos         "/bin/bash"   About a minute ago   Exited (0) 20 seconds ago             bold_cerf

docker cp e2f90d4ed867:/home/test.txt /home
cd /home 
ls
test.txt

日志,元数据,进程

查看日志 (重点)

bash 复制代码
docker logs -f 容器名

查看容器中进程信息ps

bash 复制代码
# 命令 dockers top 容器id
docker top 容器id

元数据 (重点)

bash 复制代码
docker inspect 容器名

部署Nginx

bash 复制代码
docker pull nginx
docker run -d --name nginx01 -p 3344:80 nginx
  • -p 通过主机上的端口3344可以访问容器内80


端口暴露

部署Tomcat

bash 复制代码
docker run -it --rm tomcat:9.0
退出,会发现容器没了。
ctrl + C
bash 复制代码
#会发现没有tomcat容器了
docker ps -a
bash 复制代码
docker images

docker run -d -p 3355:8080 --name tomcat01 tomcat
bash 复制代码
# 发现问题:
# Linux命令少了
# 没有webapps,阿里云镜像的原因,默认最小的镜像,所有不必要的都剔除掉。
# 保证最小可运行的环境
docker exec -it tomcat01 /bin/bash
ls
webapps
cd webapps
ls

pwd
/usr/local/tomcat

cp -rf webapps.dist/* webapps
再查看网站信息

部署ES + Kibana

eselasticsearch6搜索引擎,kibana是它的可视化操作界面

bash 复制代码
#es 暴露端口多,耗内存。
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:8.0.0

#查看CPU的状态
docker stats 容器名
bash 复制代码
可以连接上

[root@CentOS8 home]# curl -v localhost:9300
* Rebuilt URL to: localhost:9300/
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9300 (#0)
> GET / HTTP/1.1
> Host: localhost:9300
> User-Agent: curl/7.61.1
> Accept: */*
>
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server
bash 复制代码
#这个是JVM的知识
-ES_JAVA_OPT="-Xms64m -Xmx512m"
# 运行容器(包含数据持久化和安全配置)
docker run -d \
  --name elasticsearch \
  -p 9200:9200 \
  -p 9300:9300 \
  -e "discovery.type=single-node" \
  -e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
  elasticsearch:8.0.0
bash 复制代码
[root@CentOS8 ~]# curl -v localhost:9300
* Rebuilt URL to: localhost:9300/
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9300 (#0)
> GET / HTTP/1.1
> Host: localhost:9300
> User-Agent: curl/7.61.1
> Accept: */*
>
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server

联合文件系统

镜像到底是什么?

镜像是一种轻量级,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

所有的应用,直接打包docker镜像,就可以直接跑起来。

如何得到镜像:

  • 从远程仓库下载
  • 朋友拷贝给你
  • 自己制作一个镜像 DockerFile

先介绍一下Git 控制版本

  • 第一步(层):安装了centos
  • 第二步(层):安装了docker
  • 第三步(层):安装了jdk

UnionFS联合文件系统 ),它支持文件系统 的修改作为一次提交来一层层的叠加。

我们对一个项目的修改,只需要管增加的部分,增加的部分则是一层。

dockers的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS
bootfs:系统启动需要引导加载,主要包含bootloaderkernel bootloader主要是引导加载kernelLinux刚启动会加载bootfs

  • 点火装置bootloader和kernel bootloader):负责检查设备 是否正常,然后点燃引擎
  • 火箭主体kernel内核):相当于火箭的核心部分,启动后就能带电脑飞起来。

黑屏 -> 加载 -> 开机进入系统

无论是什么镜像,bootfs是公用的!
Docker容器直接复用宿主机的内核 ,所以不用内核相关 的,启动快占用少。
roofsbootfs之上,包含典型的Linux系统中的/dev /proc /bin /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如UbuntuCentos等等。

Docker镜像都是只读 ,当容器启动时,一个新的可写层被加载到镜像的顶部。

这一层就是通常说的容器层 ,容器之下的都叫镜像层

写时复制

容器 修改的/etc/passwd 是修改的是容器层 ,镜像层只读 的这就是写时复制特性

也就是镜像层 里面的东西是不会变的变得只是你添加的东西所以你需要-v利用卷组保留数据。

写时复制CoW) 是一种资源管理策略 ,其核心逻辑是:在数据未被修改 时,允许多个引用共享同一份原始数据 ;当任一引用尝试修改数据时,系统才会为该引用创建独立的数据副本 。此机制通过延迟复制 操作,显著优化了资源利用率性能

容器数据卷

如果数据在容器中,那么删除容器,数据会丢失!需求!数据可以持久化
MySQL,容器删除了,删库跑路!需求:MySQL数据可以存储在本地!

容器之间有一个数据共享的技术,Docker容器中产生的数据,同步到本地!

这就是卷技术 !目录的挂载,将容器内的目录,挂载到Linux上面!

总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的!

bash 复制代码
docker run -it -v 主机目录:容器内目录
# 测试
docker run -it -v /home/test:/home centos /bin/bash
bash 复制代码
docker ps -a
docker inspect 1df6775e71d5

其实这怎么形容呢?是否看过JOJO的"恋人"那一集。

也就是我操作/home 目录下的东西,/home/test 目录也会跟着改变。

比如在/home目录下增加一个文件,/home/test也会增加一个同样的文件。

具名和匿名挂载

bash 复制代码
# 匿名挂载
-v 容器内路径 不指定主机目录
docker run -d -P --name nginx01 -v /etc/nginx nginx

[root@CentOS8 ~]# docker volume ls
DRIVER    VOLUME NAME
local     0338f9c041b34701c5ea638938801bdf2fd3261f9d6e11924528f5dcdd4ddfb2 #没有取名字为匿名卷

#具名挂载
#通过 -v 卷名:容器内路径
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
[root@CentOS8 ~]# docker volume ls
DRIVER    VOLUME NAME
local     juming-nginx #这里就有名字了


[root@CentOS8 ~]# docker volume inspect juming-nginx
[
    {
        "CreatedAt": "2025-03-04T16:51:22+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/volumes/xxx/

bash 复制代码
# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载。
-v 容器内路径             # 匿名挂载
-v 卷名:容器内路径        # 具名挂载
-v /宿主机路径:容器内路径  # 指定路径挂载

扩展:

bash 复制代码
# 通过 -v 容器内路径:ro rw 改变读写权限
ro readonly  #只读
rw readwrite #可读可写
# 一旦这个设置了容器权限,容器对挂载出来的内容就有限定了。相对于容器来说
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx

#这个目录只能从外部改变了,不能从内部改变了。
# ro 只要看到 ro 就说明这个路径只能通过宿主机操作,容器内部无法操作。
ro /etc/nginx

测试一下

bash 复制代码
docker run -it -v /home/test:/home:ro centos /bin/bash

[root@fcd193845507 home]# touch a.txt
touch: cannot touch 'a.txt': Read-only file system

MySQL部署

这位大佬写的非常详细
Docker部署MySQL 8.3.0(保姆级图文教程)

bash 复制代码
docker pull mysql:8.3.0

[root@CentOS8 ~]# docker images mysql:8.3.0
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
mysql        8.3.0     6f343283ab56   11 months ago   632MB

mkdir -p  /home/mysql/{conf,data,log}
bash 复制代码
cd /home/mysql/conf
vi my.cnf

[client]
#设置客户端默认字符集utf8mb4
default-character-set=utf8mb4
[mysql]
#设置服务器默认字符集为utf8mb4
default-character-set=utf8mb4
[mysqld]
default_authentication_plugin=mysql_native_password
#配置服务器的服务号,具备日后需要集群做准备
server-id = 1
#开启MySQL数据库的二进制日志,用于记录用户对数据库的操作SQL语句,具备日后需要集群做准备
log-bin=mysql-bin
#设置清理超过30天的日志,以免日志堆积造过多成服务器内存爆满。2592000秒等于30天的秒数
binlog_expire_logs_seconds = 2592000
#解决MySQL8.0版本GROUP BY问题
sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
#允许最大的连接数
max_connections=1000
# 禁用符号链接以防止各种安全风险
symbolic-links=0
# 设置东八区时区
default-time_zone = '+8:00'

启动容器

bash 复制代码
#\代表换行 
#--privileged=true表示赋予容器权限修改宿主文件权利
#--restart=always表示容器退出时总是重启
#-e 是配置环境,MYSQL_ROOT_PASSWORD=a12bCd3_W45pUq6表示设置mysql的root用户密码
#-d表示后台运行
#可以多个-v 挂载日志、数据、配置文件。
docker run \
-p 3306:3306 \
--restart=always \
--name mysql \
--privileged=true \
-v /home/mysql/log:/var/log/mysql \
-v /home/mysql/data:/var/lib/mysql \
-v /home/mysql/conf/my.cnf:/etc/mysql/my.cnf \
-e MYSQL_ROOT_PASSWORD=password\
-d mysql:8.3.0  

再开一个窗口

[root@CentOS8 conf]# docker ps
CONTAINER ID   IMAGE         COMMAND                  CREATED         STATUS         PORTS                                                  NAMES
d837a375948f   mysql:8.3.0   "docker-entrypoint.s..."   4 seconds ago   Up 3 seconds   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql
[root@CentOS8 conf]# docker exec -it d837a375948f /bin/bash

mysql -uroot -ppassword
use mysql;
mysql> select user,host from user;
+------------------+-----------+
| user             | host      |
+------------------+-----------+
| root             | %         |
| mysql.infoschema | localhost |
| mysql.session    | localhost |
| mysql.sys        | localhost |
| root             | localhost |
+------------------+-----------+
5 rows in set (0.00 sec)


ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
flush privileges;

Docker网络

bash 复制代码
#-d    后台运行
#-P    端口随机
#-name 指定名字
#运行tomcat镜像,生成容器。
docker run -d -P --name tomcat01 tomcat

进入镜像

bash 复制代码
#进入容器内部
docker exec -it tomcat01 /bin/bash

cd /etc

#可见操作系统版本是Ubuntu
root@d9b71213acb7:/etc# cat os-release
PRETTY_NAME="Ubuntu 24.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.1 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo

#让系统去官网检查所有软件的最新版本信息。
apt update
#安装一个叫 iproute2 的软件包,这个包里全是管理网络的神器。
apt install iproute2
bash 复制代码
#不进入容器也能查看到容器信息
#发现容器启动的时候都会得到一个eth0@if5 ip地址,Docker分配的。
docker exec -it tomcat01 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

Linux是否能ping容器内部
,因为一个容器 就是一个进程

bash 复制代码
ping 172.17.0.2


Linux可以pingdocker容器内部。

docker0ip172.17.0.1,容器内eho@if5ip172.17.0.2

同一个网段 ,是可以相互ping通的,docker0就是虚拟交换机
桥接模式,使用的技术是veth-pair技术。

启动了一个容器过后又多了一个网卡。

再运行一个容器

bash 复制代码
[root@CentOS7 ~]# docker run -d -P --name tomcat02 tomcat
d5f3197160516df059bcd2e2cb3bf079daded118b31c5c073968db05eafb5760
bash 复制代码
docker exec -it tomcat02 /bin/bash
cd /etc
root@d9b71213acb7:/etc# cat os-release
PRETTY_NAME="Ubuntu 24.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.1 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo

apt update
apt install iproute2
bash 复制代码
[root@CentOS7 ~]# docker exec -it tomcat02 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever


容器 带来的网卡 ,都是一对对
veth-pair就是一对的虚拟设备接口 ,成对出现的,一端连着协议 ,一端彼此相连。
veth-pair充当一个桥梁,让Linux可以和容器通信,连接各种虚拟网络设备。

veth-pair 就像是给容器宿主机 之间"牵了一根网线"。这根"网线 "有两个头,一个插在容器 的"网络插座 "(协议栈 )上,另一个插在宿主机 的"网络插座 "上。只要数据容器 这头塞进去,宿主机 那头就能直接收到;反过来宿主机 发数据,容器也能收到。

那么tomcat01tomcat02是否能ping通呢?

bash 复制代码
docker exec -it tomcat02 /bin/bash
apt update
apt install iputils-ping

容器和容器之间是可以互相ping通的。

Docker网络模型图

所有的容器不指定网络的情况下,都是docker0 路由的,docker会给容器分配一个默认可用IP

Docker 中的所有的网络接口都是虚拟的,虚拟的转发效率高!

删除容器以后,网络就没了!

小结一下

veth-pair技术:

每个Docker容器启动时,会创建一对虚拟网卡(veth-pair),其中一端在容器内命名为eth0,另一端连接到宿主机的docker0网桥(名称类似veth*)。这对设备通过Linux内核协议栈直接联通,实现容器与宿主机之间的数据传输

docker0网桥的作用:
docker0Docker默认创建的虚拟网桥,工作在二层(类似物理交换机),负责为容器分配IP(如172.17.0.0/16子网)并管理容器间的通信。

容器间通信时,数据通过docker0直接转发,无需经过宿主机物理网卡。

容器到宿主机的路径

容器内部流量通过eth0veth-pairdocker0网桥,再由宿主机内核的路由和NAT规则处理:

NAT转换:

当容器访问外网时,宿主机通过iptablesMASQUERADE规则将容器IP(如172.17.0.2)转换为宿主机的物理网卡IP(如192.168.1.100)。
物理网卡转发

转换后的流量通过宿主机的物理网卡(如eth0ens33)发送至外部网络
外网到容器的路径

若需从外网访问容器(如通过端口映射),Docker会通过iptablesDNAT规则将宿主机物理网卡上的指定端口流量转发到容器IP和端口

自定义网络

bash 复制代码
docker network --help

#查看所有的docker网络
docker network ls

网络模式
bridge:桥接(默认)
none:不配置网络
host:主机模式(和宿主机共享网络)
container:容器内网络连通!

测试

/16 子网:

网络前缀占 16 位,主机部分占 16 位,可容纳 65,534 台设备,适合大型网络(如企业内网)。
/24 子网:

网络前缀占 24 位,主机部分占 8 位,仅支持 254 台设备,适合小型网络(如家庭、小型办公室)。

bash 复制代码
#清空容器
docker rm -f $(docker ps -aq)
#默认--net bridge 这就是docker01
docker run -d -P --name tomcat01 --net bridge tomcat

#docker0特点,默认,域名不能访问。

#创建自定义网络
#subnet 是子网 gateway 网关
docker network create --driver bridge --subnet 10.1.0.0/16 --gateway 10.1.0.1 mynet
bash 复制代码
docker network inspect mynet
bash 复制代码
docker run -d -P --name tomcat-net-01 --net mynet tomcat
docker run -d -P --name tomcat-net-02 --net mynet tomcat
docker network inspect mynet

自定义网络的好处:

bash 复制代码
docker exec -it tomcat-net-01 /bin/bash
apt update
apt install iputils-ping
docker exec -it tomcat-net-02 /bin/bash
apt update
apt install iputils-ping

docker exec -it tomcat-net-01 ping 10.1.0.3
docker exec -it tomcat-net-01 ping tomcat-net-02

自定义网络docker都已经维护好了对应的关系。

单独启动的两个容器不在同一个网络命名空间,DNS无法解析名称,启动时将他们加到同一个网络通过DNS解析容器名就可以直接通信。

网络连通

bash 复制代码
docker run -d -P --name tomcat-01 tomcat
docker run -d -P --name tomcat-02 tomcat


红色的是不可能直接能通信的

那么我们的目的就是为了将容器连接到网络上

bash 复制代码
docker exec -it tomcat-01 /bin/bash
apt update
apt install iputils-ping

#容器连接网络
docker network connect mynet tomcat-01
docker network inspect mynet

一个容器两个IP地址,直接解决这个问题,比如阿里云服务器一个公网一个内网,都可以连接到服务器。

假设跨网络操作,就需要docker network connect连通!

Redis集群部署

创建网络

bash 复制代码
docker network create redis --subnet 172.38.0.0/16
docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
a96bd4671a05   redis     bridge    local

docker network inspect redis


#循环创建六个节点
for port in $(seq 1 6); \
do \
mkdir -p ./mydata/redis/node-${port}/conf
touch ./mydata/redis/node-${port}/conf/redis.conf
#配置Redis配置文件
cat << EOF >./mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done


[root@CentOS8 ~]# cd ./mydata/redis/
[root@CentOS8 redis]# ll
total 0
drwxr-xr-x. 3 root root 18 Mar  4 16:15 node-1
drwxr-xr-x. 3 root root 18 Mar  4 16:15 node-2
drwxr-xr-x. 3 root root 18 Mar  4 16:15 node-3
drwxr-xr-x. 3 root root 18 Mar  4 16:15 node-4
drwxr-xr-x. 3 root root 18 Mar  4 16:15 node-5
drwxr-xr-x. 3 root root 18 Mar  4 16:15 node-6

启动Redis容器

bash 复制代码
# redis:5.0.9-alpine3.11 镜像名称
# redis-server /etc/redis/redis.conf 启动 Redis 服务并加载自定义配置的核心指令。
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /root/mydata/redis/node-1/data:/data \
-v /root/mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /root/mydata/redis/node-2/data:/data \
-v /root/mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /root/mydata/redis/node-3/data:/data \
-v /root/mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /root/mydata/redis/node-4/data:/data \
-v /root/mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /root/mydata/redis/node-5/data:/data \
-v /root/mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /root/mydata/redis/node-6/data:/data \
-v /root/mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

进入容器

bash 复制代码
docker exec -it redis-1 /bin/sh

创建集群

bash 复制代码
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
bash 复制代码
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
成功!

总结

所有结论都需要反复测试!如果有错误欢迎指正!一起努力!

如果喜欢的话,请点个赞吧就算鼓励我一下。

相关推荐
蓁蓁啊2 小时前
GIT使用SSH 多账户配置
运维·git·ssh
程序猿小三5 小时前
Linux下基于关键词文件搜索
linux·运维·服务器
虚拟指尖5 小时前
Ubuntu编译安装COLMAP【实测编译成功】
linux·运维·ubuntu
椎4956 小时前
苍穹外卖前端nginx错误之一解决
运维·前端·nginx
刘某的Cloud6 小时前
parted磁盘管理
linux·运维·系统·parted
极验6 小时前
iPhone17实体卡槽消失?eSIM 普及下的安全挑战与应对
大数据·运维·安全
爱倒腾的老唐6 小时前
24、Linux 路由管理
linux·运维·网络
yannan201903137 小时前
Docker容器
运维·docker·容器
_清浅7 小时前
计算机网络【第六章-应用层】
运维·服务器·计算机网络
正在努力的小河7 小时前
Linux 自带的 LED 灯驱动实验
linux·运维·服务器