玩命加载中🤣🤣🤣

DockerⅡ-深入


Docker深入

Docker复杂安装

mysql主从复制

  1. 启动主库容器
docker run \
-p 3307:3306 \
--name mysql-master \
--privileged=true \
-v /ddocker/mysql-master/data:/var/lib/mysql \
-v /ddocker/mysql-master/conf:/etc/mysql/conf.d \
-v /ddocker/mysql-master/mysql-files:/var/lib/mysql-files \
-e MYSQL_ROOT_PASSWORD=123456 \
-d mysql
  1. 编辑配置 conf/my.cnf (!!!!!!)

    注意!!!!

    此处文档权限要改成 444/474(让orangepi:7来编辑,root:4来执行)

    不能有空格!!!

[mysqld]
server-id=101
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
binlog-ignore-db=performance_schema
## 开启二进制日志功能
log-bin=mall-mysql-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=ROW
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
  1. 重启
docker restart mysql-master
  1. 进入主机容器
# 4.1进入mysql-master容器
docker exec -it mysql-master mysql -uroot -p123456
# 4.2创建数据同步用户
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
flush privileges;
  1. 启动从机容器
docker run \
-p 3308:3306 \
--name mysql-slave \
--privileged=true \
-v /ddocker/mysql-slave/data:/var/lib/mysql \
-v /ddocker/mysql-slave/conf:/etc/mysql/conf.d \
-v /ddocker/mysql-master/mysql-files:/var/lib/mysql-files \
-e MYSQL_ROOT_PASSWORD=123456 \
-d mysql
  1. 编辑配置 conf/my.cnf

    注意!!!!

    此处文档权限要改成 444/474(让orangepi:7来编辑,root:4来执行)

    不能有空格!!!

[mysqld]
server-id=102
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql,information_schema,performance_schema
## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
log-bin=mall-mysql-slave1-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=ROW
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
## relay_log配置中继日志
relay_log=mall-mysql-relay-bin  
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1  
## slave设置为只读(具有super权限的用户除外)
read_only=1
  1. 在主数据库中查看主从同步状态
show master status;

######
reset master; #清空日志,此处用于主库本身与从库不一致, 执行到了从库无法同步的sql, 就会报错, 这时候重置一下binlog
######
  1. 进入mysql-slave容器
docker exec -it mysql-slave mysql -uroot -p123456
  1. 在从库中配置主从复制
change master to master_host='192.168.1.111', master_user='slave', master_password='123456', master_port=3307, master_log_file='mall-mysql-bin.000001', master_log_pos=158, master_connect_retry=30;

配置说明

参数 说明
master_host 主数据库的IP地址
master_port 主数据库的运行端口
master_user 在主数据库创建的用于同步数据的用户账号
master_password 在主数据库创建的用于同步数据的用户密码
master_log_file 指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取File参数
master_log_pos 指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position参数
master_connect_retry 连接失败重试的时间间隔,单位为秒
  1. 在从库中打开及查看主从同步状态
start slave;
show slave status \G;
  1. 数据测试
CREATE DATABASE `testslave2`;
use testslave2;
craete table aaa(id int, name varchar(20));
insert into aaa values(1, 't1');

Redis集群模式

cluster(集群)模式-docker版哈希槽区分进行亿级数据存储

面试题

1~2 亿条数据需要缓存,请问如何设计这个存储案例

单机单台 100% 不可能,肯定是分布式存储,用 redis 如何落地?

一般业界有 3 种解决方案

  1. 哈希取余分区

2 亿条记录就是 2 亿个k,v,我们单机不行必须要分布式多机,假设有3台机器构成一个集群,用户每次读写操作都是根据公式:

hash(key) % N 个机器台数,计算出哈希值,用来决定数据映射到哪一个节点上。

优点:

​ 简单粗暴,直接有效,只需要预估好数据规划好节点,例如 3 台、8 台、10 台,就能保证一段时间的数据支撑。使用 Hash 算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到负载均衡 + 分而治之的作用。

缺点:

​ 原来规划好的节点,进行扩容或者缩容就比较麻烦了额,不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化:Hash(key)/3 会变成 Hash(key) /?。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。

某个 redis 机器宕机了,由于台数数量变化,会导致 hash 取余全部数据重新洗牌。

  1. 一致性哈希算法

    Ⅰ 背景

    一致性哈希算法在1997年由麻省理工学院中提出的,设计目标是为了解决分布式缓存数据变动和映射问题,某个机器宕机了,分母数量改变了,自然取余数不 OK 了。

    Ⅱ 能干吗

    提出一致性 Hash 解决方案。 目的是当服务器个数发生变动时, 尽量减少影响客户端到服务器的映射关系

    Ⅲ 三大步骤

    1. 算法构建一致性哈希环

      一致性哈希环

      ​ 一致性哈希算法必然有个 hash 函数并按照算法产生 hash 值,这个算法的所有可能哈希值会构成一个全量集,这个集合可以成为一个 hash 空间[0,2^32-1],这个是一个线性空间,但是在算法中,我们通过适当的逻辑控制将它首尾相连(0 = 2^32),这样让它逻辑上形成了一个环形空间。

      ​ 它也是按照使用取模的方法,前面笔记介绍的节点取模法是对节点(服务器)的数量进行取模。而一致性 Hash 算法是对 2^32 取模,简单来说,一致性 Hash 算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数 H 的值空间为 0-2^32-1(即哈希值是一个 32 位无符号整形),整个哈希环如下图:整个空间按顺时针方向组织,圆环的正上方的点代表 0,0 点右侧的第一个点代表1,以此类推,2、3、4、……直到 2^32-1,也就是说0点左侧的第一个点代表 2^32-1, 0 和 2^32-1 在零点中方向重合,我们把这个由2^32个点组成的圆环称为 Hash 环。

    2. 服务器 IP 节点映射

      节点映射

      将集群中各个 IP 节点映射到环上的某一个位置。

      将各个服务器使用Hash进行一个哈希,具体可以选择服务器的 IP 或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。假如 4 个节点 NodeA、B、C、D,经过 IP 地址的哈希函数计算(hash(ip)),使用 IP 地址哈希后在环空间的位置如下:

    3. key 落到服务器的落键规则

      当我们需要存储一个 kv 键值对时,首先计算 key 的 hash 值,hash(key),将这个 key 使用相同的函数 Hash 计算出哈希值并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器,并将该键值对存储在该节点上。

      如我们有 Object A、Object B、Object C、Object D 四个数据对象,经过哈希计算后,在环空间上的位置如下:根据一致性 Hash 算法,数据 A 会被定为到 Node A 上,B 被定为到 Node B 上,C 被定为到 Node C 上,D 被定为到 Node D 上。

    Ⅳ 优点

    • 一致性哈希算法的容错性

      假设 Node C 宕机,可以看到此时对象 A、B、D 不会受到影响,只有 C 对象被重定位到 Node D。一般的,在一致性 Hash 算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。简单说,就是 C 挂了,受到影响的只是 B、C 之间的数据,并且这些数据会转移到 D 进行存储。

    • 一致性哈希算法的扩展性

      数据量增加了,需要增加一台节点 NodeX,X 的位置在 A 和 B 之间,那收到影响的也就是 A 到 X 之间的数据,重新把 A 到 X 的数据录入到 X 上即可,

      不会导致 hash 取余全部数据重新洗牌。

    Ⅴ 缺点

    一致性哈希算法的数据倾斜问题

    一致性 Hash 算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题,

    例如系统中只有两台服务器:

    Ⅵ 总结

    为了在节点数目发生改变时尽可能少的迁移数据

    将所有的存储节点排列在收尾相接的 Hash 环上,每个 key 在计算 Hash 后会顺时针找到临近的存储节点存放。

    而当有节点加入或退出时仅影响该节点在 Hash 环上顺时针相邻的后续节点。

    优点

    加入和删除节点只影响哈希环中顺时针方向的相邻的节点,对其他节点无影响。

    缺点

    数据的分布和节点的位置有关,因为这些节点不是均匀的分布在哈希环上的,所以数据在进行存储时达不到均匀分布的效果。

  2. 哈希槽分区

    Ⅰ 背景

    解决均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系,现在就相当于节点上放的是槽,槽里放的是数据。

    槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。

    哈希解决的是映射问题,使用 key 的哈希值来计算所在的槽,便于数据分配。

    Ⅱ 多少个hash槽

    一个集群只能有 16384 个槽,编号 0-16383(0-2^14-1)。这些槽会分配给集群中的所有主节点,分配策略没有要求。可以指定哪些编号的槽分配给哪个主节点。集群会记录节点和槽的对应关系。解决了节点和槽的关系后,接下来就需要对 key 求哈希值,然后对 16384 取余,余数是几 key 就落入对应的槽里。slot = CRC16(key) % 16384。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。

    Ⅲ 哈希槽计算

    Redis 集群中内置了 16384 个哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,也就是映射到某个节点上。如下代码,key之A 、B 在 Node2, key 之 C 落在 Node3 上

3主3从Redis集群扩缩容配置

3主3从redis集群配置

  1. run 6个容器
docker run \
--name redis-node-n \
--net host \
--privileged=true \
-v /ddocker/redis-share/redis-node-n:/data \
-d redis:6.0.8 \
--cluster-enabled yes \
--appendonly yes \
--port 638n

docker run --name redis-node-1 --net host --privileged=true -v /ddocker/redis-share/redis-node-1:/data -d redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381
docker run --name redis-node-2 --net host --privileged=true -v /ddocker/redis-share/redis-node-2:/data -d redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382
docker run --name redis-node-3 --net host --privileged=true -v /ddocker/redis-share/redis-node-3:/data -d redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383
docker run --name redis-node-4 --net host --privileged=true -v /ddocker/redis-share/redis-node-4:/data -d redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384
docker run --name redis-node-5 --net host --privileged=true -v /ddocker/redis-share/redis-node-5:/data -d redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385
docker run --name redis-node-6 --net host --privileged=true -v /ddocker/redis-share/redis-node-6:/data -d redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386

##注意:
## cluster-enabled | appendonly yes | port 638n 这几个是跟在redis:6.0.8后的
## net host模式不能用-p参数,会报错

参数详解

参数 详解
–net host 使用宿主机的IP和端口,默认
–cluster-enabled yes 开启 redis 集群
–appendonly yes 开启持久化
–port 6386 redis 端口号
  1. 进入1号机,建立主从关系
docker exec -it redis-node-1 /bin/bash

redis-cli --cluster create 192.168.1.111:6381 192.168.1.111:6382 192.168.1.111:6383 192.168.1.111:6384 192.168.1.111:6385 192.168.1.111:6386 --cluster-replicas 1
## --cluster-replicas 1 表示为每个master创建一个slave节点

  1. 以 6281 作为切入点,查看集群状态
redis-cli -p 6381

cluster info

cluster nodes
#从下图可看到 1号机下面挂的4号, 2号机下面挂的5号, 3号机下面挂的6号

cluster info 命令

cluster nodes 命令

主从容错切换迁移案例

数据独写存储

  1. 启动6机构成的集群并通过 exec 进入

    docker exec -it redis-node-1 /bin/bash

    redis-cli -p 6381

  2. 对 6381 新增两个key

    keys *

    set k1 v1

  3. 防止路由失效加参数 -c 并新增两个key

    redis-cli -p 6381 -c

  4. 查看集群信息

    redis-cli --cluster check 192.168.1.111:6381

容错切换迁移

  1. 主 6381和从机切换, 先停止主机 6381
docker stop redis-node-1

docker exec -it redis-node-4 /bin/bash

redis-cli -p 6382 -c

cluster nodes

84498 宕机了,e9b2d上位成为新的master

  1. 还原之前的 84498
docker start redis-node-1

docker exec -it redis-node-1 /bin/bash

redis-cli -p 6381 -c

cluster nodes

由图可看出 84998 依然是 slave, 并且挂在e9b2d下面

主从扩容案例

  1. 新增6387、6388两个节点 + 新建后启动+查看是否8个节点
docker run --name redis-node-7 --net host --privileged=true -v /ddocker/redis-share/redis-node-7:/data -d redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6387

docker run --name redis-node-8 --net host --privileged=true -v /ddocker/redis-share/redis-node-8:/data -d redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388

docker ps
  1. 进入 6387 容器实例内部,将新增的6387节点(空槽号)作为 master 节点加入原集群
docker exec -it redis-node-7 /bin/bash

redis-cli --cluster add-node 自己实际IP地址:当前端口 自己实际IP地址:集群端口
redis-cli --cluster add-node 192.168.1.111:6387 192.168.1.111:6381

  1. 检查节点
redis-cli --cluster check 192.168.1.111:6387
#可以看出虽然6387加入集群但是没有被分配槽位

redis-cli --cluster check xxx

  1. 重新分配槽号
redis-cli --cluster reshard IP地址:端口号
redis-cli --cluster reshard 192.168.1.111:6381

redis-cli --cluster check192.168.1.111:6387
#不是掀桌子重新分配,而是各自匀一部分

重新分配槽号

分配后再次查看

  1. 为新主机分配新的从节点
redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-masterid 新主机节点ID

#举例
redis-cli --cluster add-node 192.168.1.111:6388 192.168.1.111:6387 --cluster-slave --cluster-master-id eed7b613be6846910ef1dd5944ee445ec59f8b7b

  1. 再次检查集群情况
redis-cli --cluster check 192.168.1.111:6383

主从缩容案例

  1. 首先6388先下线
#检查集群获得6388的节点ID
redis-cli --cluster check 192.168.1.111:6384

redis-cli --cluster del-node ip:从机端口 从机节点ID
#举例
redis-cli --cluster del-node 192.168.1.111:6388 af386efed6f9060c21f9d1e51227d300e161a97b

  1. 将6387的槽号情况,重新分配,本例将清出来的槽号都给6384
redis-cli --cluster reshard 192.168.1.111:6381
#注意, 此处6381只是集群的一个落脚点, 并不特指某个节点

再次检查集群情况

  1. 将6387从集群中删除
redis-cli --cluster del-node 192.168.1.111:机器端口 节点id

#示例
redis-cli --cluster del-node 192.168.1.111:6387 eed7b613be6846910ef1dd5944ee445ec59f8b7b

DockerFile解析

Dockerfile 是用来构建 Docker 镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。

官网

常用保留字

关键字 解释
FROM 基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是 FROM
MAINTAINER 镜像维护者的姓名和邮箱地址
RUN 容器构建时需要运行的命令,RUN 是在 docker build 时运行
EXPOSE 当前容器对外暴露出的端口
WORKDIR 指定在创建容器后,终端默认登录的进来工作目录,一个落脚点
USER 指定该镜像以什么养的用户去执行,如果都不指定,默认是 root
ENV 用来在构建镜像过程中设置环境变量 >>> 如:ENV MY_PATH /user/mytest,可以通过 WORKDIR $MY_PATH使用
ADD 将宿主机目录下的文件拷贝进镜像且会自动运行处理 URL 和解压 tar 压缩包
COPY 类似 ADD, 拷贝文件和目录到镜像中
VOLUME 容器数据卷,用于数据保存和持久化工作
CMD 指定容器启动后的要干的事情。注意:Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换。CMD 是在 docker run 时运行;RUN 是在 docker build 时运行。
ENTRYPOINT 也是用来指定一个容器启动时要运行的命令。类似于 CMD 指令,但是 ENTRYPOINT 不会被 docker run 后面的命令覆盖,而且这些命令行参数会被当做参数送给 ENTRYPOINT 指令指定的程序

自定义镜像 mycentosjava8

前置工作

  1. 将安装包放置于同一目录下
  2. vim Dockerfile (注意文件名大小写)

编写

FROM centos
MAINTAINER dee<saddyfire@155.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

#由于 CentOS 已经停止维护的问题。2020 年 12 月 8 号,CentOS 官方宣布了停止维护 CentOS Linux 的计划,并推出了 CentOS Stream 项目,CentOS Linux 8 作为 RHEL 8 的复刻版本,生命周期缩短,于 2021 年 12 月 31 日停止更新并停止维护(EOL),更多的信息可以查看 CentOS 官方公告。如果需要更新 CentOS,需要将镜像从 mirror.centos.org 更改为 vault.centos.org
RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
RUN yum makecache

#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令查看网络IP
RUN yum -y install net-tools
#安装java8及lib库
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
#ADD是相对路径jar,把jdkxxx.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置
ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH

EXPOSE 80

CMD echo $MYPATH
CMD echo "success-----------OK"
CMD /bin/bash

构建

docker build -t 新镜像名字:TAG .
#注意,上面TAG后面有个空格,有个点

#举例
docker build -t centosjava8:1.1 . 

补充:进入 docker 容器后,export可以查看所有环境变量

运行

docker run my

虚悬镜像

仓库名、标签都是 <none> 的镜像,俗称dangling image

vim Dockerfile

####
FROM  ubuntu
CMD echo 'action is success'
####

#构建
docker build .

#查看
docker images ls -f dangling=true

#删除
docker image prune

自定义镜像myubuntu

FROM ubuntu
MAINTAINER dee<saddyfire@155.com>
ENV MYPATH /

RUN apt update
RUN apt install net-tools
RUN apt install openjdk-8-jdk -y

EXPOSE 80
CMD echo $MYPATH
CMD echo "install ifconfig cmd success----"
CMD /bin/bash

Docker微服务

  1. 打 jar 包
  2. Dockerfile
#基础镜像
FROM java:8
#作者
MAINTAINER dee<saddyfire@155.cn>
#指定临时文件目录为 /tmp,在主机 /var/lib/docker 目录下创建了一个临时文件并链接到容器的 /tmp
VOLUME /tmp
#将 jar 包添加到容器中并更名为 dee_docker.jar
ADD 
ENV MYPATH 

Docker网络

常用基本命令

查看网络

docker network ls

##############
NETWORK ID     NAME      DRIVER    SCOPE
b1dfde1fa38f   bridge    bridge    local
22fdd425c457   host      host      local
8a0d6dff90e5   none      null      local
##############

查看网络源数据

docker network inspect XXX网络名字

#举例
docker network inspect b1dfde1fa38f

##############
[
    {
        "Name": "bridge",
        "Id": "b1dfde1fa38f03e0db1e81eafefbd89db931593233e81bcabe631c6d4d66a16e",
        "Created": "2024-03-12T20:55:02.274728201+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]
#############

作用

容器间的互联和通信以及端口映射

容器IP变动时候可以通过服务名直接网络通信而不受到影响

网络模式

网络模式 简介
bridge 为每一个容器分配、设置IP等,并将容器链接到一个 docker0
虚拟网桥,默认为该模式。
host 容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口
none 容器有独立的 Network namespace,但并没有对其进行任何网络设置,如分配 veth pair 和网桥连接,IP 等
container 新创建的容器不会创建自己的网卡和配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。

bridge模式:使用–network bridge指定,默认使用docker0

host模式:使用–network host指定

none模式:使用–network none指定

container模式:使用–network container:NAME或者容器ID指定

bridge

Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),该桥接网络的名称为 docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker 默认指定了 docke0 接口的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信

查看 bridge 网络的详细信息,并通过 grep 获取名称项

docker network inspect bridge|grep name

######
"com.docker.network.bridge.name": "docker0",
######
  1. Docker 使用 Linux 桥接,在宿主机虚拟一个 Docker 容器网桥(docker0), Docker 启动一个容器时会根据 Docker 网桥的网段分配给容器一个IP地址,称为 Container-lP, 同时 Docker 网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container-lP 直接通信。
  2. docker run 的时候,没有指定 network 的话默认使用的网桥模式就是 bridge,使用的就是 docker0。在宿主机ifconfig, 就可以看到 docker0 和自己 create 的 network(后面讲)eth0, eth1, eth2…代表网卡一,网卡二,网卡三…,lo 代表 127.0.0.1,即 localhost, inet addr)用来表示网卡的 IP 地址
  3. 网桥 docker0 创建一对对等虚拟设备接口一个叫 veth, 另一个叫 eth0, 成对匹配。
    1. 整个宿主机的网桥模式都是 docker0, 类以一个交换机有一堆接口,每个接口叫 veth, 在本地主机和容器内分别创建一个虚拟接口,并让他们彼比联通(这样一对接口叫veth pair)
    2. 每个容器实例内部也有一块网卡,每个接口叫eth0
    3. docker0 上面的每个 veth 匹配某个容器实例内部的 eth0, 两两配对,一一匹配。

通过上述,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的,此时两个容器的网络互通的。

案例

#拉镜像
docker pull billygoo/tomcat8-jdk8

#启动两个容器
docker run -d -p 8081:8080 --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --name tomcat82 billygoo/tomcat8-jdk8

通过 ip addr 查看当前网络信息

主机ip 信息

进入容器内部

docker exec -it tomcat81 /bin/bash

查看容器内部网络

ip addr

tomcat81 内部网络

可以看到 宿主机 >>> 49: veth@if48tomcat81 >>> 48: eth0@if49 一一对应

host

直接使用宿主机的 IP 地址与外界进行通信,不在需要额外进行 NAT 转换

容器将不会获得一个独立的 Network Namespace,而是和宿主机公用一个 Network Namespace. 容器将不会虚拟出自己的网卡而是使用宿主机的 IP 和端口。

案例

docker run -d -p --network host --name tomcat83 billygoo/tomcat8-jdk8

在 CentOS 里面用默认的浏览器访问容器内的 tomcat83 看到访问成功,因为此时容器的 IP 借用主机的,
所以容器共享宿主机网络 IP, 这样的好处是外部主机与容器可以直接通信。

none

在 none 模式下,并不为 Docker 容器进行任何网络配置。
也就是说,这个 Docker 容器没有网卡、IP、路由等信息,只有一个lo
需要我们自己为 Docker 容器添加网卡、配置 IP 等。

container

新建的容器和己经存在的一个容器共享一个网络配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而 是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。

案例

docker run -d -p 8085:8080 --name tomcat85 billygoo/tamcat8-jdk8
docker run -d -p 8086:8080 --network container:tomcat85 --name tomcat86 billygoo/tamcat8-jdk8

自定义网络

docker run -d -p 8081:8080 --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --name tomcat82 billygoo/tomcat8-jdk8

#启动后进入容器实例内部
docker exec -it tomcat81 /bin/bash
docker exec -it tomcat82 /bin/bash

#在81里ping 82
ping 172.17.0.3

通过自定义网络使用服务名连通网络

  1. 新建自定义网络

    docker network create dee_network

  2. 新建容器加入上一步新建的自定义网络

    docker run -d -p 8081:8080 --network dee_network --name tomcat81 billygoo/tomcat8-jdk8
    
    docker run -d -p 8082:8080 --network dee_network --name tomcat82 billygoo/tomcat8-jdk8
  3. 互相ping测试

Docker-compose容器编排

Docker-Compose 是 Docker 官方的开源项目, 负责实现对 Docker 容器集群的快速编排。

官网

下载地址

docker compose version

常用命令

命令 详情
docker compose -h 查看帮助
docker compose up 启动所有docker-compose服务
docker compose up -d 启动所有docker-compose服务并后台运行
docker compose down 停止并删除容器、网络、卷、镜像
docker compose exec yml里的服务id 进入容器实例内部 docker-compose exec docker-compose.yml文件中写的服务id /bin/bash
docker compose ps 展示当前docker-compose编排过的运行的所有容器
docker compose top 展示当前docker-compose编排过的容器进程
docker compose logs yml里面的服务id 查看容器输入日志
docker compose config 检查配置
docker compose config -q 检查配置,有问题才输出
docker compose restart 重启服务
docker compose start 启动服务
docker compose stop 停止服务

编排服务

docker-compose.yml

version: "3.8"

services:
  microService:
    image: dee_docker:1.6
    container_name: dd01
    ports:
      - "6001:6001"
    volumes:
      - /app/microService:/data
    networks:
      -dee_net
    depends_on:
      - redis
      - mysql
  redis:
    restart: always
    image: redis:6.0.8
    container_name: dee_redis
    ports:
      - "16379:6379"
    volumes:
      - /ddocker/redis/conf/redis.conf:/etc/redis/redis.conf
      - /ddocker/redis/data:/data
    networks:
      - dee_net
    command: redis-server /etc/redis/redis.conf
  mysql:
    image: mysql:8.0
    container_name: dee_mysql
    restart: always
    ports:
      - "13306:3306"
    logging:
      driver: 'json-file'
      options:
        max-size: '5g'
    environment:
      MYSQL_ROOT_PASSWORD: 2323
    volumes:
      - /ddocker/mysql/data:/var/lib/mysql
      - /ddocker/mysql/conf/my.cnf:/etc/my.cnf
      - /ddocker/mysql/init:/docker-entrypoint-initdb.d
    networks:
      - dee_net
    command: --default-authentication-plugin=mysql_native_password #解决外部无法访问

networks:
  dee_net:

单独mysql编排

version: "3.8"

services:
  mysql:
    image: mysql:8.0
    container_name: dee_mysql
    restart: always
    ports:
      - "13306:3306"
    logging:
      driver: 'json-file'
      options:
        max-size: '5g'
    environment:
      MYSQL_ROOT_PASSWORD: 2323
    volumes:
      - /ddocker/mysql/data:/var/lib/mysql
      - /ddocker/mysql/conf/my.cnf:/etc/my.cnf
      - /ddocker/mysql/init:/docker-entrypoint-initdb.d
    networks:
      - dee_net
    command: --default-authentication-plugin=mysql_native_password #解决外部无法访问

networks:
  dee_net:

轻量级可视化工具Portainer

官网

官网

在 Linux 上使用 Docker 安装 Portainer CE |2.19 |Portainer 文档

步骤

docker volume create portainer_data

#官方
docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest

#如果要用http端口
docker run -d -p 8000:8000 -p 9000:9000 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest

docker ps

访问 http://192.168.10.100:9000/

docker system df

监控之CAdvisor+InfluxDB+Granfana

新建目录

cd /ddocker
mkdir cig
vim docker-compose.yml

docker-compose.yml

version: '3.8'

volumes:
  grafana_data: {}
services:
  influxdb:
    image: tutum/influxdb:0.9
    restart: always
    environment:
      - RPE_CREATE_DB=cadvisor
    ports:
      - "8083:8083"
      - "8086:8086"
    volumes:
      - ./data/influxdb:/data
      
  cadvisor:
    image: goolgle/cadvisor
    links:
      - influxdb: influxsrv
    command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxsrv:8086
    restart: always
    ports:
      - "8080:8080"
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:rw
      - /sys:/sys:ro
      - /var/lib/docker/:var/lib/docker:ro
  
  grafana:
    user: "104"
    image: grafana/grafana
    restart: always
    links:
      - influxdb:influxsrv
    ports:
      - "3000:3000"
    volumes:
      - grafana_data:/var/lib/grafana
    environment:
      - HTTP_USER=admin
      - HTTP_PASS=admin
      - INFLUXDB_HOST=influxsrv
      - INFLUXDB_PORT=8086

docker compose

docke compose up


文章作者: 👑Dee👑
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 👑Dee👑 !
  目录