Docker深入
Docker复杂安装
mysql主从复制
- 启动主库容器
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
-
编辑配置 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
- 重启
docker restart mysql-master
- 进入主机容器
# 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;
- 启动从机容器
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
-
编辑配置 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
- 在主数据库中查看主从同步状态
show master status;
######
reset master; #清空日志,此处用于主库本身与从库不一致, 执行到了从库无法同步的sql, 就会报错, 这时候重置一下binlog
######
- 进入mysql-slave容器
docker exec -it mysql-slave mysql -uroot -p123456
- 在从库中配置主从复制
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 | 连接失败重试的时间间隔,单位为秒 |
- 在从库中打开及查看主从同步状态
start slave;
show slave status \G;
- 数据测试
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 种解决方案
- 哈希取余分区
2 亿条记录就是 2 亿个k,v,我们单机不行必须要分布式多机,假设有3台机器构成一个集群,用户每次读写操作都是根据公式:
hash(key) % N 个机器台数,计算出哈希值,用来决定数据映射到哪一个节点上。
优点:
简单粗暴,直接有效,只需要预估好数据规划好节点,例如 3 台、8 台、10 台,就能保证一段时间的数据支撑。使用 Hash 算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到负载均衡 + 分而治之的作用。
缺点:
原来规划好的节点,进行扩容或者缩容就比较麻烦了额,不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化:Hash(key)/3 会变成 Hash(key) /?。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。
某个 redis 机器宕机了,由于台数数量变化,会导致 hash 取余全部数据重新洗牌。
-
一致性哈希算法
Ⅰ 背景
一致性哈希算法在1997年由麻省理工学院中提出的,设计目标是为了解决分布式缓存数据变动和映射问题,某个机器宕机了,分母数量改变了,自然取余数不 OK 了。
Ⅱ 能干吗
提出一致性 Hash 解决方案。 目的是当服务器个数发生变动时, 尽量减少影响客户端到服务器的映射关系
Ⅲ 三大步骤
-
算法构建一致性哈希环
一致性哈希环
一致性哈希算法必然有个 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 环。
-
服务器 IP 节点映射
节点映射
将集群中各个 IP 节点映射到环上的某一个位置。
将各个服务器使用Hash进行一个哈希,具体可以选择服务器的 IP 或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。假如 4 个节点 NodeA、B、C、D,经过 IP 地址的哈希函数计算(hash(ip)),使用 IP 地址哈希后在环空间的位置如下:
-
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 环上顺时针相邻的后续节点。
优点
加入和删除节点只影响哈希环中顺时针方向的相邻的节点,对其他节点无影响。
缺点
数据的分布和节点的位置有关,因为这些节点不是均匀的分布在哈希环上的,所以数据在进行存储时达不到均匀分布的效果。
-
-
哈希槽分区
Ⅰ 背景
解决均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽(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集群配置
- 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号机,建立主从关系
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节点
- 以 6281 作为切入点,查看集群状态
redis-cli -p 6381
cluster info
cluster nodes
#从下图可看到 1号机下面挂的4号, 2号机下面挂的5号, 3号机下面挂的6号
主从容错切换迁移案例
数据独写存储
-
启动6机构成的集群并通过 exec 进入
docker exec -it redis-node-1 /bin/bash
redis-cli -p 6381
-
对 6381 新增两个key
keys *
set k1 v1
-
防止路由失效加参数 -c 并新增两个key
redis-cli -p 6381 -c
-
查看集群信息
redis-cli --cluster check 192.168.1.111:6381
容错切换迁移
- 主 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
- 还原之前的 84498
docker start redis-node-1
docker exec -it redis-node-1 /bin/bash
redis-cli -p 6381 -c
cluster nodes
由图可看出 84998 依然是 slave, 并且挂在e9b2d下面
主从扩容案例
- 新增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
- 进入 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
- 检查节点
redis-cli --cluster check 192.168.1.111:6387
#可以看出虽然6387加入集群但是没有被分配槽位
- 重新分配槽号
redis-cli --cluster reshard IP地址:端口号
redis-cli --cluster reshard 192.168.1.111:6381
redis-cli --cluster check192.168.1.111:6387
#不是掀桌子重新分配,而是各自匀一部分
- 为新主机分配新的从节点
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
- 再次检查集群情况
redis-cli --cluster check 192.168.1.111:6383
主从缩容案例
- 首先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
- 将6387的槽号情况,重新分配,本例将清出来的槽号都给6384
redis-cli --cluster reshard 192.168.1.111:6381
#注意, 此处6381只是集群的一个落脚点, 并不特指某个节点
- 将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
前置工作
- 将安装包放置于同一目录下
- 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微服务
- 打 jar 包
- 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",
######
- Docker 使用 Linux 桥接,在宿主机虚拟一个 Docker 容器网桥(docker0), Docker 启动一个容器时会根据 Docker 网桥的网段分配给容器一个IP地址,称为 Container-lP, 同时 Docker 网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container-lP 直接通信。
- docker run 的时候,没有指定 network 的话默认使用的网桥模式就是 bridge,使用的就是 docker0。在宿主机ifconfig, 就可以看到 docker0 和自己 create 的 network(后面讲)eth0, eth1, eth2…代表网卡一,网卡二,网卡三…,lo 代表 127.0.0.1,即 localhost, inet addr)用来表示网卡的 IP 地址
- 网桥 docker0 创建一对对等虚拟设备接口一个叫 veth, 另一个叫 eth0, 成对匹配。
- 整个宿主机的网桥模式都是 docker0, 类以一个交换机有一堆接口,每个接口叫 veth, 在本地主机和容器内分别创建一个虚拟接口,并让他们彼比联通(这样一对接口叫veth pair)
- 每个容器实例内部也有一块网卡,每个接口叫eth0
- 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
查看当前网络信息
进入容器内部
docker exec -it tomcat81 /bin/bash
查看容器内部网络
ip addr
可以看到 宿主机 >>> 49: veth@if48 和 tomcat81 >>> 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
通过自定义网络使用服务名连通网络
-
新建自定义网络
docker network create dee_network
-
新建容器加入上一步新建的自定义网络
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
-
互相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/
监控之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