Docker

  • 基础知识
    • 三要素
    • 下载安装
    • 开始使用
      • Docker Run 运行流程
    • Docker和Vm虚拟机对比
      • Dockers为什么会比虚拟机更快
  • Docker命令
    • 帮助启动类
    • 镜像命令
      • docker images
      • docker search
      • docker pull
      • docker system df
      • docker rmi
    • 容器命令
  • Docker镜像
    • 镜像
    • UnionFS(联合文件系统)
    • 重点
    • 为镜像增加功能
    • 容器数据卷
  • Docker 常规安装软件
    • 总体步骤
    • MySQL
    • Redis
  • 分布式存储
    • 哈希取余分区
    • 一致性哈希算法分区
    • 哈希槽分区
  • Docker 复杂安装
    • MySQL 主从安装
    • Redis集群部署(三主三从)
      • 基础部署
      • 数据读写存储
      • 容错切换迁移
      • 主从扩容
        • 第一次检查集群情况, 6387未分配槽位,没有从节点
        • 重新分配槽位
        • 第二次检查集群状态
        • 添加从节点
        • 第三次检查集群状态
      • 主从缩容
        • 下线6388
        • 重新分配槽位
        • 删除6387节点并检查集群状态
  • Docker File 解析
    • docker执行DockerFile的大致流程
      • 总结
    • 保留字命令
    • 虚悬镜像
  • Docker Network
    • 网络情况
    • 常用基本命令
    • Docker网络可以做什么
    • 网络模式
      • 总体介绍
      • 容器实例内默认网络IP生产规则
      • bridge
      • Host
      • Container
      • 自定义网咯
  • Docker Compose
    • 核心概念
    • 执行流程
    • 常用命令

基础知识

三要素

镜像(Image), 容器(Container), 仓库(Repository)

# 容器可以将容器看做是一个简易版的Linux环境和运行在其中的应用程序环境包括: root用户权限, 进程空间, 用户空间和网络空间,

下载安装

# 1 安装gcc  gcc-c++
yum install -y gcc
yum install -y gcc-C++
# 2 安装需要的软件包
yum install -y yum-utils
# 3 设置stable仓库位置
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 4 建立 yum 索引
yum makecache fast
# 5 安装 Docker 引擎
yum install docker-ce docker-ce-cli containerd.io
# 6 配置阿里云镜像加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{"registry-mirrors": ["https://am7dl19u.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

开始使用

# 开启 docker 服务
systemctl start docker
# 启动测试
docker run hello-world

Docker Run 运行流程

# 开始
Docker 在本机中寻找该镜像, 如果存在则以该镜像为模板生产容器实例运行
# 如果没有找到该镜像
去Docker hub 上查找该实例, 如果存在, 则镜像到本地, 然后以该镜像为模板生产容器实例运行
# 如果 Hub 上也没有该镜像
返回失败错误, 查找不到该镜像

Docker和Vm虚拟机对比

Dockers为什么会比虚拟机更快

# 1 Docker 有着比虚拟机更少的抽象层
# 2 Docker 利用的是宿主机的内核, 而不需要加载操作系统的OS内核避免了引寻, 加载操作系统内核返回等比较费时费资源的过程, 当新建一个虚拟机时, 虚拟机软件需要加载OS, 返回新建过程时分钟级别的, 而Docker 由于直接利用宿主机的操作系统, 则省略了返回过程, 新建一个Docker 容器只需要几秒钟

Docker命令

帮助启动类

# 1 启动 Docker
systemctl start docker
# 2 关闭 Docker
systemctl stop docker
# 3 重启 Docker
systemctl restart docker
# 4 检查 Docker 状态
systemctl status docker
# 5 开机启动 Docker
systemctl enable docker
# 6 查看 Docker 概要信息
docker info
# 7 查看 Docker 总体帮助文档
docker --help
# 8 查看 Docker 命令帮助文档
docker 具体命令 --help

镜像命令

docker images

# 列出本地主机上的镜像
# 表头说明REPOSITORY: 镜像的仓库源TAG : 镜像的标签版本号IMAGE ID: 镜像IDCREATED: 镜像的创建时间SIZE: 镜像大小
# 参数-a : 列出本地所有镜像(含历史镜像)-q : 只显示镜像ID

docker search

# docker search [OPTIONS] 镜像名称
查看远程仓库是否存在 目标镜像
# 案例
docker search redis
# 参数--limit: 只列出N个镜像, 默认25个docker search --limit 5 redis

docker pull

# docker pull 镜像名称[:TAG]
下载镜像
# 如果没有TAG 则下载最新版 等价于 docker pull 镜像名称:lastest

docker system df

# 查看镜像/容器/数据卷所占的空间

docker rmi

# docker rmi 镜像名称/Image ID
# 删除 单个镜像docker rmi -f 镜像ID
# 删除多个镜像docker rmi -f 镜像名1:TAG 镜像名2:TAG
# 删除全部docker rmi -f $(docker images -qa)
# 参数-f : 强制删除

容器命令

# 新建并启动容器docker run [OPTIONS] IMAGE [COMMAND] [ARG...]# 参数--name  : 为容器指定一个名称-d      : 后台运行容器并返回容器ID, 即启动守护式容器(后台运行) # 在大部分的场景中, 我们希望docker的服务是在后台运行的-i      : 前台交互模式运行容器, 通常与 -t 同时使用-t     : 为容器重新分配一个伪输入终端, 通常与 -i 同时使用-P     : 随机端口映射, 大写P-p     : 指定端口映射, 小写p
# 列出容器列表docker ps [OPTIONS]# 默认列出所有正在进行的容器# 参数-a        : 列出当前所有正在运行 + 历史上运行过的容器-l     : 显示最近创建的容器-n       : 显示最近的n个创建的容器-q        : 静默模式, 只显示容器编号
# 退出容器# 两种退出方式# exitrun 进去容器, exit退出, 容器停止# ctrl + p + qrun 进去容器, ctrl + p + q, 容器不停止
# 启动已停止运行的容器docker restart 容器名称/ID
# 停止容器docker stop 容器名称/ID
# 强制停止容器docker kill 容器名称/ID
# 删除已停止的容器docker rm 容器名称/ID# 一次性删除多个容器docker rm -f $(docker ps -a -q)docker rm -a -q | xargs docker rm
# 查看容器日志docker logs 容器ID
# 查看容器内运行的进程docker top 容器ID
# 查看容器内部细节docker inspect 容器ID
# 进入正在运行的容器, 并以命令行进行交互docker exec -t 容器ID bashShell # (推荐使用)在容器中打开新的终端, 并且可以启动新的进程, 用exit退出, 不会导致容器的停止docker attach 容器ID直接进入容器启动命令的终端, 不会启动新的进程, 用exit退出, 会导致容器的停止
# 复制容器内文件到主机docker cp 容器ID:容器内路径 目的主机路径# 导入和导出容器docker export 容器ID > 文件名.tar导出容器内容流作为一个tar归档文件cat 文件名.tar | docker import -镜像用户/镜像名:镜像版本号从tar包中的内容创建一个新的文件系统在导入为镜像# 实例docker export ccc5370f6fae > redis.jarcat redis.jar | docker import ccc5370f6fae

Docker镜像

镜像

 一种轻量级, 可执行的独立软件包, 包含运行某个软件所需要的所有内容, 将应用程序和配置依赖打包好行程一个可交付的运行环境(包括代码, 运行时所需要的库, 环境变量和配置文件)这个打包好的运行环境就是 Image 镜像文件只有通过这个镜像文件才能生成Docker容器实例, (类似于Java中 New出来一个对象)

UnionFS(联合文件系统)

# Union文件系统一种分层, 轻量级并且高性能的文件系统支持对文件系统的修改作为一次提交来一层层的叠加, 同时可以将不同目录挂载到同一个虚拟文件系统下Union文件系统是Docker镜像的基础, 镜像可以通过分层来进行继承, 基于基础进行(没有父镜像), 可以制作各种具体的应用镜像
# 镜像分层结构优点           共享资源, 方便复制迁移, 镜像复用

重点

Docker镜像层都是只读的, 容器层是可写的

当容器启动时, 一个新的可写层被加载到镜像的顶部
这一层通常被称作容器层, 容器层 之下的 都叫镜像层

为镜像增加功能

# 提交容器副本使之成为一个新的镜像docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]# 实例 为原始Ubuntu系统添加 vim 命令# 1 进入原始Ubuntu系统docker run -it ubuntu /bin/bash # 2 更新包管理工具apt-get update # 3 下载 vim 命令apt-get install vim# 4 下载 ifconfig 命令apt-get install net-tools# 6 下载 ip addr 命令apt-get install iproute iproute-doc# 5 提交容器为镜像docker commit -m="add cmd: vim" -a="muu" e6578101222a muu/ubuntu:1.0

容器数据卷

# docker容器产生的数据 如果不备份, 那么当容器删除后,容器内的数据自然会被删除, 为了能保存数据在 Docker中使用卷
# 类似于Redis里面的RDB和ROF
将docker容器内的数据保存进宿主机的磁盘中一容器数据卷的方式完成数据的持久化重要资料backup映射: 容器内的数据备份 + 持久化到本地主机目录# 特点:1 数据卷可以在容器之间共享或者重用数据2 卷中的更改可以实时生效3 数据卷中的更高不会包含在镜像的更新中4 数据卷的生命周期一直持续到没有容器使用它为止
# 运行一个带有容器卷存储功能的容器实例docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名称# 查看数据卷是否挂载成功docker inspect 容器ID
# 容器和宿主机之间可以实现双向的数据共享

# 读写规则映射添加说明     # 读写(默认)docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录路径:rw 镜像名称# 只读 容器内部只能读 不能写docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录路径:ro 镜像名称# 如果为只读模式 如果向文件夹写入文件Read-only file system  # 报错
# 卷的继承和共享容器1 完成和 宿主机的映射# docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录路径:rw 镜像名称 --name="u1"容器2 继承容器1 的卷规则       # docker run -it --privileged=true -v --volumes-from u1 镜像名称

Docker 常规安装软件

总体步骤

1 搜索镜像
docker search 镜像名称
2 拉取镜像  # docker pull 镜像名称:版本号
3 查看镜像  # docker inspect 镜像名称:版本号
4 启动镜像容器 -- 服务端口映射 # docker run .. 镜像名称:版本号
5 停止容器  # docker stop 容器名称/id
6 移除容器  # docker rm 容器名称/id

MySQL

# 1 新建MySQL容器实例 卷映射 防止删除容器后数据丢失
docker run -d -p 3307:3306 --privileged=true -v /muu/mysql/log:/var/log/mysql -v /muu/mysql/data:/var/lib/mysql -v /muu/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql80 mysql:8.0.26
# 2 新建my.cnf -- 通过容器卷同步给 MySQL 容器实例
[client]
default_character_set=utf8mb4
[mysqld]
character_set_server=utf8mb4
collation_server=utf8_general_ci
# 3 重新启动 MySQL 容器实例再重新进入并查看字符编码 -- 解决中文乱码问题
show variables like 'character%';

Redis

docker run -p 6379:6379 --name redis --privileged=true -v /muu/redis/redis.conf:/etc/redis/redis.conf -v /muu/redis/data:/data -d redis redis-server /etc/redis/redis.conf

redis.conf

# Minimal redis.confport 6379
daemonize no
dir .
save ""
appendonly yes
cluster-config-file nodes.conf
cluster-node-timeout 30000
maxclients 1001

分布式存储

哈希取余分区

# 理论假设有 N 台机器构成一个集群, 用户每次读写操作都是根据公式: hash(key) % N 计算出哈希值, 用来决定数据映射到哪一个节点上
# 优点简单粗暴, 直接有效, 只需要预估好数据, 规划好节点, 就能保证一段时间的数据支撑, 使用 hash 算法让固定的一部分请求落到同一台服务器上, 这样每台服务器固定处理一部分请求(并维护这些请求), 起到了 负载均衡 + 分而治之的作用
# 缺点扩容和缩容比较麻烦, 如果出现弹性扩容或者故障宕机时 N更改了 此时地址经过取余的结果发生很大变化 映射关系需要重新计算, 全部数据重新洗牌 会导致根据公式获取的服务器变得不可控

一致性哈希算法分区

# 目的当服务器个数(N)发生变动时, 尽量减少影响客户端到服务器的映射关系
# 构建步骤# 1 构建一致性哈希环一致性哈希算法将整个哈希值空间组织成一个虚拟的圆环, 假设哈希值空间为0-2^31-1 整个哈希空间 按顺时针方向组织# 2 服务器IP节点映射选择服务器的IP或者主机名作为关键字进行哈希, 得到的哈希结果 对应到哈希环空间的 对应位置# 3 落键规则当存储一个kv键值对, 首先计算key的hash值, hash(key), 将这个key 使用相同的函数 hash计算出哈希值并确定此数据在环上的位置, 从此位置沿环顺时针姓周,第一台遇到的服务器就是其应该定位到的服务器, 并将该键值对存储在该节点上
# 优点# 提高了容错性如果一台服务器不可用, 则受影响的仅仅是此服务器到其环空间中前一台服务器,(即沿着其逆时针行走遇到的第一台服务器)之间数据, 其他则不会受到影响# 提高了扩展性数据量增加, 添加一台新的服务器X, 如果 X 在 A和B 之间, 那么受到影响的就是 A-X之间的数据, 重新将A-X的数据录入到X上即可, 不会导致全部数据洗牌
# 缺点# 数据倾斜问题在服务节点太少的时候, 容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)的问题数据的分布和节点的位置有关, 因为这些节点不是均匀的分布在哈希环上的, 所以数据在存储的时候达不到均匀分布的效果

哈希槽分区

# 目的用于解决一致性哈希算法的数据倾斜问题
# 实质一个数组, 数组[0, 2^14-1] 形成 hash slot 空间
# 做什么的解决均匀分配的问题, 在数据和节点之间又加了一层, 将这层成为哈希槽(slot), 用于管理数据和节点之间的关系, 现在就相当于节点上放的是槽, 槽中放的是数据# 槽解决了问题粒度问题, 将粒度变大, 利于数据移动# 哈希解决了什么问题映射问题, 使用key的哈希值来计算所在的槽, 便于数据分配
# 哈希槽计算Redis集群中内置了16384个哈希槽, redis会根据节点数量大致均等的将哈希槽映射到不同的节点, 当需要在 Redis集群中放置一个K-V时, Redis先对Key使用crc16算法算出来一个结果, 然后将结果对16384求余数, 这样每个key都会对应一个编号在0-16383之间的哈希槽, 也就是映射到某个节点上
# 哈希槽的数量 为什么是16384个1 如果槽位是 65536 发送到心跳信息的信息头达8k, 发送的心跳包过于庞大2 redis 集群的主节点数量基本不肯能超过1000个(集群节点越多, 心跳包的消息体内携带的数据越多, 如果节点超过1000个, 也会导致网络拥堵)3 槽位越小, 节点少的情况下, 压缩比高, 容易传输

Docker 复杂安装

MySQL 主从安装

# 1 新建主服务器容器实例 3308
docker run -d -p 3308:3306 --privileged=true -v /muu/mysqlCluster/mysql-master/log:/var/log/mysql -v /muu/mysqlCluster/mysql-master/data:/var/lib/mysql -v /muu/mysqlCluster/mysql-master/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root --name mysqlMaster mysql:8.0.26
# 2 进入 /mydata/mysql-master/conf 目录下新建 my.cnf
[mysqld]
##设置server_id,同一局域网中需要唯一
server_id=101
##指定不需要同步的数据库名称
binlog-ignore-db=mysql
##开启二进制日志功能
log-bin=mall-mysql-bin
##设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
##二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
##跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断
##如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
# 3 修改配置完成, 重启 Master
docker restart mysqlMaster
# 4 进入 mysql-master 容器
docker exec -it mysqlMaster /bin/bash
# 5 master 容器实例内创建数据同步用户
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
# 6 新建从服务器容器3309
docker run -d -p 3309:3306 --privileged=true -v /muu/mysqlCluster/mysql-slave/log:/var/log/mysql -v /muu/mysqlCluster/mysql-slave/data:/var/lib/mysql -v /muu/mysqlCluster/mysql-slave/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root --name mysqlSlave mysql:8.0.26
# 7 进入 /mydata/mysql-slave/conf 目录下新建 my.cnf
[mysqld]
##设置server_id,同一局域网中需要唯一
server_id=102
##指定不需要同步的数据库名称
binlog-ignore-db=mysql
##开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
log-bin=mall-mysql-slave1-bin
##设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
##设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
##二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
##跳过主从复制中遇到的所有错误或指定类型的错误,避免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
# 8 修改完配置后重启 slave
docker restart mysqlSlave
# 9 在主数据库中查看主从同步状态
## 在主服务器的 mysql 命令行输入
show master status;
+-----------------------+----------+--------------+------------------+-------------------+
| File                  | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------------+----------+--------------+------------------+-------------------+
| mall-mysql-bin.000001 |      712 |              | mysql            |                   |
+-----------------------+----------+--------------+------------------+-------------------+
# 10 进入 mysql-Slave 容器
docker exec -it mysqlSlave /bin/bash
mysql -u root -p
# 11 在从数据库中配置主从复制
change master to master_host='宿主机Ip',master_user='slave',master_password='123456',master_port=3308,master_log_file='mall-mysql-bin.000001',master_log_pos=712,master_connect_retry=30;
## 样例
change master to master_host='192.168.239.129',master_user='slave',master_password='123456',master_port=3308,master_log_file='mall-mysql-bin.000003',master_log_pos=156,master_connect_retry=30;
## 参数说明master_host      : 主数据库的IP地址master_port      : 主数据的运行端口master_user       : 在主数据库创建的用于同步数据的用户账号master_password    : 在主数据库创建的用于同步数据的用户密码master_log_file    : 指定从数据库要复制数据的日志文件, 通过查看主数据的状态获取 File 参数        (第 #9 步)master_log_pos  : 指定从数据库的哪个位置开始复制数据, 通过查看主数据的状态获取 Position 参数   (第 #9 步)master_connect_retry: 连接重试的时间间隔 单位: 秒
# 12 在从数据库中查看主从同步状态
show slave status \G;
## \G 以键值对的方式展示输出 当输出只有一行 且 列数过多的时候可以使用
# 13 在从数据库中开启主从同步
start slave;
# 14 查看从数据库状态
show slave status \G;
# 15 主从复制测试

Redis集群部署(三主三从)

基础部署

# 1 关闭防火墙 + 启动docker后台服务
# 2 新建 6 个docker容器实例 Master 6381 6382 6383 Slave 6384 6385 6386
docker run -d --name redis-node-1 --net host --privileged=true -v /muu/redis/cluster/redis-node-1:/data redis --cluster-enabled yes --appendonly yes --port 6381
docker run -d --name redis-node-2 --net host --privileged=true -v /muu/redis/cluster/redis-node-2:/data redis --cluster-enabled yes --appendonly yes --port 6382
docker run -d --name redis-node-3 --net host --privileged=true -v /muu/redis/cluster/redis-node-3:/data redis --cluster-enabled yes --appendonly yes --port 6383
docker run -d --name redis-node-4 --net host --privileged=true -v /muu/redis/cluster/redis-node-4:/data redis --cluster-enabled yes --appendonly yes --port 6384
docker run -d --name redis-node-5 --net host --privileged=true -v /muu/redis/cluster/redis-node-5:/data redis --cluster-enabled yes --appendonly yes --port 6385
docker run -d --name redis-node-6 --net host --privileged=true -v /muu/redis/cluster/redis-node-6:/data redis --cluster-enabled yes --appendonly yes --port 6386# 参数解释--net host           : 使用宿主机的IP和端口, 默认--privileged=true : 获取宿主机root用户权限--cluster-enabled yes : 开启redis集群--appendonly yes    : 开启持久化--prot 6386          : redis端口号
# 3 进入容器 redis-node-1 并为6太机器构建集群关系(进入任意redis服务器均可)
redis-cli --cluster create 192.168.239.129:6381 192.168.239.129:6382 192.168.239.129:6383 192.168.239.129:6384 192.168.239.129:6385 192.168.239.129:6386 --cluster-replicas 1# 参数解释--cluster-replicas 1     : 为每一个 master 创建一个 slave 节点# 4 链接进入6381为切入点 查看集群状态
redis-cli -p 6381
CLUSTER INFO    # 查看集群状态
CLUSTER NODES   # 查看集群节点状态

数据读写存储

# 1 启动 6 台机器构成的集群 并且 exec 进入
docker start redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5 redis-node-6
# 2 对 6381 添加数据
set k1 v1
set k2 v2
set k3 v3
# 3 防止路由失效加参数 -C 并添加数据
redis-cli -p 6381 -c
# 4 查看集群信息
redis-cli --cluster check 192.168.239.129:6381

启动redis集群

当不添加参数-c时

当以集群模式启动

查看集群状态

容错切换迁移

# 主6381和从机切换, 先停止6381
docker stop redis-node-1
# 再次查看集群信息
docker exec -it redis-node-2
redis-cli --cluster check 192.168.239.129:6381
redic-cli -p 6382 -c
cluster nodes
# 先还原之前的3主3从
docker start redis-node-1
# 查看集群状态
同上
# 重新将6381 变为主机
docker stop redis-node-6  #
docker start redis-node-6

停止6381之后集群信息

6381 重新连接之后查看集群信息, 发现6386 仍然是主机

D:\Programming\notes\knowledge\Java面经\docker.md

关闭6386 之后再次启动, 6381 再次变为主机

主从扩容

# 需求分析从 3 主 3 从 扩容到 4 主 4 从# 新增两台redis节点, 新建后 docker ps 查看是否为八个节点
docker run -d --name redis-node-7 --net host --privileged=true -v /muu/redis/cluster/redis-node-7:/data redis --cluster-enabled yes --appendonly yes --port 6387
docker run -d --name redis-node-8 --net host --privileged=true -v /muu/redis/cluster/redis-node-8:/data redis --cluster-enabled yes --appendonly yes --port 6388
# 进入6387实例内部
docker exec -it redis-node-7 /bin/bash
# 将新增的6387节点(空槽号)作为master节点加入到原有集群
redis-cli --cluster add-node 要加入集群的ip:port 原有集群的ip:port
redis-cli --cluster add-node 192.168.239.129:6387 192.168.239.129:6381
# 检查集群情况(第一次)
redis-cli --cluster check 192.168.239.129:6381
# 重新分配槽号
redis-cli --cluster reshard IP:PORT
redis-cli --cluster reshard 192.168.239.129:6381# 注新加入的master的槽位是3个新的区间, 以前的仍然为连续区间原因: 重新分配成本过高, 所以前面三家各自匀出来一部分, 分别从6381,6382,6383三个旧节点分别匀出1364个槽位给新的节点6387
# 检查集群情况(第二次)
redis-cli --cluster check 192.168.239.129:6381
# 为主节点6387分配从节点6388
redis-cli --cluster add-node 要添加的从机IP:PORT 目的主机IP:PORT --cluster-slave --cluster-master-id 目的主机ID
redis-cli --cluster add-node 192.168.239.129:6388 192.168.239.129:6387 --cluster-slave --cluster-master-id 40e3254d180b593431b723be739a1d931da3d5bc
# 检查集群情况(第三次)
redis-cli --cluster check 192.168.239.129:6381
第一次检查集群情况, 6387未分配槽位,没有从节点

重新分配槽位

第二次检查集群状态

添加从节点

第三次检查集群状态

主从缩容

# 目的将 6387 和 6388 下线
# 检查集群情况(第一次), 获取6388节点ID
redis-cli --cluster check 192.168.239.129:6381
# 从集群中将4号从节点6388下线
redis-cli --cluster del-node 节点IP:PORT 节点ID
redis-cli --cluster del-node 192.168.239.129:6388 5a5cc0454d8955188a7bb4440d52135e103beaef
# 将6387的槽号清空, 重新分配, 本例将清理出来的槽号全部分配给6381
redis-cli --cluster reshard 集群内任一主机IP:PORT
redis-cli --cluster reshard 192.168.239.129:6382
# 检查集群情况(第二次)
redis-cli --cluster check 192.168.239.129:6381
# 将6387下线
redis-cli --cluster del-node 192.168.239.129:6387 40e3254d180b593431b723be739a1d931da3d5bc
# 检查进群情况(第三次)
redis-cli --cluster check 192.168.239.129:6381
下线6388

重新分配槽位
此处将6387的所有槽位全部分配给了6381
可以重复此过程平均分配给其他节点

删除6387节点并检查集群状态

Docker File 解析

Docker FIle 是用来构建Docker镜像的文本文件, 是由一条条构建镜像所需的指令和参数构成的脚本从应用软件的角度来看, DockerFile, docker镜像与docker容器 分别代表软件的三个不同阶段DockerFile      : 软件的原材料DockerImage     : 软件的交付品DockerContainer : 可以认为是软件镜像的运行态, 也即镜像运行的容器实例
DockerFIle 面向开发, DockerImage 成为交付标准, Docker Container 则涉及部署和运维
三者缺一不可, 合理充当Docker体系的基石

docker执行DockerFile的大致流程

# 1  docker 从基础镜像运行一个容器# 2 执行一条指令并对容器进行修改# 3 执行类似docker commit 的操作提交一个新的镜像层# 4 docker 在基于刚提交的镜像运行一个新容器# 5 执行 dockerfile 中的下一条指令 知道所有指令全部执行完成

总结

# 1 DockerFile需要定义一个 DockerFile, DockerFile定义了进程需要的一切东西, DockerFile涉及的内容包括执行代码或者文件, 环境, 变量, 依赖包, 运行时环境, 动态链接库, 操作系统的发行版, 服务进程, 内核进程(当应用程序需要和系统服务和内核进程打交道, 这是需要考虑如何涉及namespace的权限控制)
# 2 Docker Image在使用 DockerFile 定义一个文件之后, docker bulid 会产生一个DOcker镜像, 当运行 Docker 镜像时会真正开始提供服务,
# 3 Docker Container直接提供服务

保留字命令

# 构建时命令
# 01 From基础镜像, 当前新镜像是基于哪个镜像的, 指定一个已经存在的镜像作为模板, 第一条必须是From
# 02 MAINTAINER 镜像维护者的姓名, 邮箱地址
# 03 RUN 容器构建时需要的命令两种格式shell 格式RUN  <命令行命令>eg: RUN yum -y install vimexec  格式RUN ["可执行文件", "参数1", "参数2"]Eg: RUN ["./test.php", "dev", "offline"]RUN 在 Docker Build 运行# 04 ADD将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包Eg: # 05 COPY类似ADD, 拷贝文件和目录到镜像中将从构建上下文目录中 <源路径>的文件/目录复制到新的一层的镜像内的 <目标路径>位置EG:{COPY src dest / COPY ["src", "dest"]<src源路径>    : 源文件或者源路径<dest目标路径>  : 容器内指定的路径, 该路径可以自动创建}  # 构建和执行时命令
# 06 WORKDIR指定在创建容器后, 终端默认登录进来的工作目录, 一个落脚点
# 07 USER (通常不指定)指定该镜像以什么样的用户去执行, 如果不指定, 则默认为root # 执行时命令
# 08 ENV用来在构建镜像的过程中设置环境变量Eg: ENV MY_PATH /user/home这个环境变量可以在后续的任何RUN命令中使用, 如同在命令面前指定了环境变量前缀一样也可以在其他指令中直接使用这些环境变量Eg: WORKDIR $MY_PATH
# 09 VOLUME容器数据卷, 用于数据保存和持久化工作
# 10 EXPOSE当前容器对外暴露的端口
# 11 CMD指定容器启动后要做的事情  Eg: /bin/bashCMD 指令的格式 与 RUN 相似:shell: CMD <命令>exec:  CMD ["可执行文件", "参数1", "参数2"]参数列表格式: CMD ["参数1", "参数2"], 在指定了 ENTRYPOINT 指令后, 用 CMD指定具体的参数注意:DockerFile中可以有多个 CMD 指令, # 但是只有最后一个生效, CMD 会被 docker run 后面的参数替代Eg:(Tomcat)docker run -it -p 8080:8080 Tomcat /bin/bash # 只启动容器, 不启动Tomcat与 RUN 指令的区别CMD 指令是在 docker run 时运行RUN 指令是在 docker build 时运行
# 12 ENTRYPOINT指定一个容器启动时要运行的命令与 CMD 的区别:1. ENTRYPOINT 不会被 docker run 后面的指令覆盖2. 这些命令行参数会被当做参数送给 ENTRYPOINT 指令指定的程序优点: 在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数注意:如果 DockerFile 中存在多个 ENTRYPOINT指令, 仅最后一个生效命令格式:ENTRYPOINT ["<executeable>", "<param1>", "<param2>"]ENTRYPOINT 可以和 CMD 一起使用, 一般是 '变参' 才会使用 CMD 这里的 CMD 等于是给 ENTRYPOINT 传参Eg: FROM nginxENTRYPOINT ["nginx", "-c"]  # 定参CMD ["/etc/ngin/nginx.conf"] # 实参

虚悬镜像

# 构建时或者删除时出现一些错误 导致仓库名, 标签都是 <none> 的镜像, 俗称虚悬镜像 dangling image
# 虚悬镜像已经失去了存在价值且有可能会危害计算机, 看到删除即可
# 查出所有的虚悬净吸纳过docker image ls -f dangling=true
# 删除所有的虚悬镜像 docker image prune

Docker Network

网络情况

# Docker 不启动ens33Iovirbr0
# Docker 启动在docker不启动的情况下增加 docker

常用基本命令

# 查看所有的docker networkdocker network ls
# 删除所有的无用网络docker network prune
# 删除一个或多个网络docker network rm 网络名称
# 展示一个或多个网络的信息docker network inspect 网络名称

Docker网络可以做什么

容器之间的互联和通信及端口映射容器IP变动时候可以通过服务名直接网络通信而不受到影响

网络模式

总体介绍

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

容器实例内默认网络IP生产规则

docker容器内部的ip是动态变化的

bridge

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

网桥docker0创建爱你一对对等虚拟设备接口一个叫 veth 另一个叫 eth0 成对匹配1. 整个宿主机的网桥模式都是 docker0 类似一个交换机有多个接口, 每个接口都叫 veth 在本地主机和容器内部分别创建一个虚拟接口, 并让他们彼此联通(这样一堆接口叫 veth pair)2. 每个容器实例内部也有一块网卡, 每个接口叫 eth03. docker0上面的每个veth匹配某个容器实例内部eth0, 两两配对, 一一匹配通过上述, 将宿主机上的所有容器都连接到这个内部网络上, 两个容器在同一网络下, 会从这个网关下各自拿到分配的ip, 此时两个容器的网络是互通的

Host

# 介绍(不推荐使用)容器将不会获得一个独立的 Network Namespace 而是和宿主机公用一个 Network Namespace容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口# 问题docker 启动时总会遇见警告: WARNING: Published ports are discarded when using host network mode
# 原因docker 启动时指定 --network=host 或者 -net=host, 如果还指定了 -p 映射端口, 那么这个时候就会有此警告并且通过 -p 设置端口参数不会起到任何作用, '端口号会以主机端口号为主' 重复则递增
# 解决方案使用 docker 的其他网络模式 eg: --net=bridge

Container

# 介绍新建的容器和已经存在的一个容器共享一个网络ip配置而不是和宿主机共享, 新创建的容器不会创建自己的网卡, 配置自己的ip, 而是和一个指定的容器共享IP和端口范围, 同样, 两个容器除了网络方面,其他的如文件系统, 进程列表还是隔离的
# Eg 1docker run -d -p 8085:8080                              --name tomcat85 muu/tomcat8-jdk8docker run -d 0p 8086:8080 --network container:tomcat85 --name tomcat86 muu/tomcat8-jdk8 # 端口冲突
# Eg 2docker run -it                               --name alpine1 alpine /bin/shdocker run -it --network container:aloine1 --name alpine2 alpine /bin/sh  # 两者公用一个网桥# 注:当 关闭 alpine1 时, alpine2 的网络也会停止

自定义网咯

# 介绍自定义网络本身就维护好了主机名和ip的对应关系, 通过ip 和域名 都可以ping通
# 作用使得容器IP变动的时候可以通过服务名直接网络通信而不受影响
# 命令:docker network create muu_netdocker network psdocker run -d --name a1 --network muu_net alpine /bin/shdocker run -d --name a2 --network muu_net alpine /bin/sh

Docker Compose

核心概念

# 一 文件docker-compose.yml
# 二 要素服务(service)一个个应用容器实例, 例如: 订单微服务, 库存微服务, mysql 容器 , redis容器工程(project)由一组关联的引用容器组成的一个完整业务单元, 在 docker-compose.yml 文件中定义

执行流程

# 一编写 DockerFile 定义各个微服务应用并构建出对应的镜像文件
# 二使用 Docker-compose 定义一个完整业务单元, 安排好整体应用中的各个容器服务
# 三执行 docker-compose up 命令, 启动并运行整个应用程序, 完成一键部署上线

常用命令

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

一文带你走进Docker相关推荐

  1. 一文带你走进C++【内存泄漏】

    背景 ​没想到项目放到线上后,随着请求量的增多,却感觉到首屏速度越来越慢,并且是在持续性地变慢.而且在发布完后(也就是容器重建了),耗时又陡然降下来了. ​因此很合理地怀疑是内存泄漏了.故而在 STK ...

  2. 仓鼠体重年龄对照表_一文带你走进仓鼠世界:仓鼠种类之叙利亚仓鼠(上)

    (宠鼠百科第76期) 今天咱们要谈的是仓鼠中的巨无霸--叙利亚仓鼠,又名金丝熊,黄金鼠.叙利亚仓鼠,很显然祖籍叙利亚,是位来自戈壁荒漠的浪子.叙利亚仓鼠体长12~15厘米,尾长1~1.5厘米,体重10 ...

  3. 【中兴】web训练营~一文带你走进前端 百图制作

    ??作者简介:物联网领域创作者,??阿里云专家博主?? ??华为云享专家?? 个人主页:Choice~ ??格言:可正因为难,才有价值!?? ??系列专栏: 1 C/C++ 2 C和指针 3 Linu ...

  4. 一文带你走进软路由和 OpenWrt 系统

    软路由 VS 硬路由 先说说硬路由,顾名思义就是通过专用硬件电路实现的路由器.大家家里用的路由器(比如 TP-LINK.华为.水星等)基本都是硬路由,它们内部的硬件电路是专门为数据包转发和通信功能量身 ...

  5. 一文带你走进网络编程

    网络编程 什么是网络编程: 就是用来实现网络互通的不同计算机运行程序之间进行数据的交换的编程 网络模型 OSI(模型):七层协议 应用层: 如: HTTP协议 主要解决如何包装数据,用于通信的应用程序 ...

  6. 一文带你走进seo,新手必须了解的seo知识你知道吗

    互联网的极速发展催生了一系列行业的发展,在此基础上又衍生出了许多的新生职位和行业,互联网的发展少不了网站和网页,建站在近些年来的也逐渐的由纯代码建站演变到可使用建站软件快捷建站,站长们只需了解一些建站 ...

  7. python vector 初始化_一文带你走进Python中的数据类

    全文共2607字,预计学习时长14分钟 图源:unsplash 数据类适用于Python3.7或更高版本,它不仅可以用作数据容器,还可以编写样板代码,简化创建类的过程. 创建第一个数据类 创建一个数据 ...

  8. 一文带你走进CI/CD

    前言: 前几天在阿里云的大咖问答板块瞎逛 遇到一个同学的问题吸引到了我:CI/CD Not Found? 我心想:什么是 CI/CD? 虽然很丢人,但咱也不能说谎不是.赶紧学习才是正道. 目录 一.C ...

  9. 统计学新手必知必会:1文带你走进数据分析!(下)

    Mykite | 作者 人人都是产品经理 | 来源 http://www.woshipm.com/data-analysis/917862.html 4 回归分析 1.什么是回归分析? 在统计学中,回 ...

最新文章

  1. Android众说纷纭分辨率
  2. float x 与“零值”比较的if语句为?
  3. maven给默认中央仓库设置镜像为阿里云maven仓库并添加全局远程仓库
  4. 资料分享 | 数学建模竞赛备战大全
  5. C#设计模式之13-职责链模式
  6. Intel® Nehalem/Westmere架构/微架构/流水线 (4) - 执行引擎
  7. (38)FPGA面试题Verilog设计计数器
  8. java判断读到末尾_Java Web入门之java--第一节 java 简介及开发环境安装
  9. qtextedit非编辑时去边框_10分钟看懂Photoshop图像的基本编辑方法-数字化图像、图像基础理论知识(置入文件)...
  10. QT自定义控件(电池)
  11. 永恒之蓝漏洞复现(包括常见问题处理)和修复方案
  12. OpenSesame免费提供新冠病毒防疫准备和远程工作培训
  13. docker---dockerfile 编写优化
  14. windows7浏览器无法打开html,win7网页无法打开出现HTML Parsing Error的解法
  15. 学习大数据有推荐的么
  16. 二、执行v8引擎示例代码
  17. Day 10 你喜欢合租还是独居
  18. 图像对齐(图像配准)方法记录
  19. Web前端 | HTML表单form
  20. Python核心编程第二版第五章数字(课后习题)----我的答案

热门文章

  1. Mac的环境配置的详细步骤
  2. 【文学文娱】《屌丝逆袭》-出任CEO、迎娶白富美、走上人生巅峰
  3. DedeCms SEO 优化全攻略
  4. JS: 刷新iframe的方法
  5. POI操作ppt图表完整示例演示
  6. 非负矩阵分解的矩阵求解
  7. HC-SR04超声波测距块讲解(附32单片机源码)
  8. 【181125】VC++ 绘制立方体的生成与控制旋转程序源代码
  9. 如何在微软Azure上搭建个人博客网站
  10. 特征函数和概率密度函数的关系