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.
成功!

总结

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

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

相关推荐
海鸥812 小时前
查看k8s集群的资源使用情况
云原生·容器·kubernetes
云上艺旅2 小时前
K8S学习之基础十八:k8s的灰度发布和金丝雀部署
学习·云原生·容器·kubernetes
jiarg4 小时前
linux 内网下载 yum 依赖问题
linux·运维·服务器
yi个名字4 小时前
Linux第一课
linux·运维·服务器
菜鸟xy..5 小时前
linux 基本命令教程,巡查脚本,kali镜像
linux·运维·服务器·kali镜像·巡查脚本·nmtui
暴躁的小胡!!!5 小时前
Linux权限维持之协议后门(七)
linux·运维·服务器·网络·安全
安 当 加 密5 小时前
中小企业Radius认证服务器的低成本高安全解决方案
运维·服务器·安全
Macle_Chen6 小时前
Mac服务器上创建Docker并安装宝塔环境
服务器·macos·docker
ChinaRainbowSea6 小时前
Linux: Centos7 Cannot find a valid baseurl for repo: base/7/x86_64 解决方案
java·linux·运维·服务器·docker·架构
Hellc0076 小时前
Docker 部署 MongoDB 并持久化数据
mongodb·docker·容器