本篇主要是mysql主从,redis主从搭建,Dockerfile解析及docker-compose编排、轻量化可视化工具Portainer、重量级工具CAdvisor+InfluxDB+Granfana的使用。
docker的安装、配置、卸载,自定义镜像和搭建公有和私有镜像仓库,以及常规软件安装示例见另一篇:docker基础篇-docker的安装、配置、卸载,自定义镜像和搭建公有和私有镜像仓库
docker run -d -p 3307:3306 --privileged=true -v /home/mydata/mysql-master/log:/var/log/mysql -v /home/mydata/mysql-master/data:/var/lib/mysql -v /home/mydata/mysql-master/conf:/etc/mysql --name=mysql-master -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
/home/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
docker restart mysql-master
docker exec -it mysql-master /bin/bash
mysql -u root -p
create user 'slave'@'%' identified by '123456';
grant replication slave,replication client on *.* to 'slave'@'%';
docker run -d -p 3308:3306 --privileged=true -v /home/mydata/mysql-slave/log:/var/log/mysql -v /home/mydata/mysql-slave/data:/var/lib/mysql -v /home/mydata/mysql-slave/conf:/etc/mysql --name=mysql-slave -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
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
docker restart mysql-slave
show master status;
docker exec -it mysql-slave /bin/bash
mysql -u root -p
change master to master_host='宿主机ip',master_user='slave',master_password='123456',master_port=3307,master_log_file='mall-mysql-bin.000005',master_log_pos=617,master_connect_retry=30;
参数说明:
- master_host:主数据库的ip
- master_user:在主数据库中创建的用于同步数据的用户账号
- master_password:在主数据库中创建的用于同步数据的用户密码
- master_port:主数据库的运行端口
- master_log_file:指定从数据库要复制数据的日志文件,通过查看主数据库的状态(见上方1.9),获取File参数
- master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据库状态(见上方1.9),获取Position参数
- master_connect_retry:连接失败重试的时间间隔,单位秒
# \G可不加,不加就是默认以列表的形式展示,如(上方1.9章节)查询主数据库状态。
#加上\G表示以K-V键值对的形式展示。
show slave status \G;
start slave;
show slave status \G;
答:肯定是需要进行分布式集群部署的。3种方案,从易到难
分布式缓存数据变动和映射问题
,当服务器个数发生变化时,尽量减少影响客户端到服务器的映射关系。16384
个槽,编号0~16383(2^14^-1)
。将这些槽分配给集群中的所有主节点,分配策略没有要求。可以指定哪些编号的槽分配给哪些主节点。集群会记录节点和槽的对应关系。然后计算键值对的key落在那个槽中,slot=CRC16(key)%16384
。以槽为单位移动数据,因为槽是固定的,处理起来很容易,这样数据的移动问题就解决了。redis集群中内置了16384个哈希槽,redis会根据节点数量大致均等的将哈希槽映射到不同的节点
。docker run -d --name=redis-node-1 --net host --privileged=true -v /home/redis/data/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381
docker run -d --name=redis-node-2 --net host --privileged=true -v /home/redis/data/redis-node-2:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382
docker run -d --name=redis-node-3 --net host --privileged=true -v /home/redis/data/redis-node-3:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383
docker run -d --name=redis-node-4 --net host --privileged=true -v /home/redis/data/redis-node-4:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384
docker run -d --name=redis-node-5 --net host --privileged=true -v /home/redis/data/redis-node-5:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385
docker run -d --name=redis-node-6 --net host --privileged=true -v /home/redis/data/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386
参数说明
- --net host :使用宿主机的ip和端口,默认
- --privileged=true :获取宿主机root用户权限
- --cluster-enabled yes :开启redis集群
- --appendonly yes :开启持久化
- --port 6386 :redis端口号
#可以进入任意节点,只是以redis-node-1为例
docker exec -it redis-node-1 /bin/bash
#然后执行下面的命令,注意更换ip地址
redis-cli --cluster create 192.168.64.128:6381 192.168.64.128:6382 192.168.64.128:6383 192.168.64.128:6384 192.168.64.128:6385 192.168.64.128:6386 --cluster-replicas 1
参数说明
- --cluster-replicas 1 :表示为每一个master创建一个slave节点
主从对应关系随机,由系统分配
3. 连接进入6381位切入点,查看集群状态
#进入6381端口的redis
redis-cli -p 6381
cluster info
cluster nodes
注:防止路由失效,在进入redis指令后加参数 -c
,不加-c时,只有当新增的key满足当前节点哈希槽才能成功,否则会失败,不会自动路由切换。docker exec -it redis-node-1 /bin/bash
redis-cli -p 6381 -c
redis-cli --cluster check 192.168.64.128:6381
模拟主从切换:停止6381主机,发现6386主机成为master,再次启动6381主机后,6381成为了6386的从机slave。
docker run -d --name=redis-node-7 --net host --privileged=true -v /home/redis/data/redis-node-7:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6387
docker run -d --name=redis-node-8 --net host --privileged=true -v /home/redis/data/redis-node-8:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388
docker exec -it redis-node-7 /bin/bash
# 6387就是要作为master的新增节点
# 6381就是原来集群节点中的领路人,相当于6387拜拜6381的码头找到组织加入集群
redis-cli --cluster add-node 192.168.64.128:6387 192.168.64.128:6381
redis-cli --cluster check 192.168.64.128:6381
redis-cli --cluster reshard 192.168.64.128:6382
redis-cli --cluster check 192.168.64.128:6381
redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新master节点的ID
redis-cli --cluster check 192.168.64.128:6382
redis-cli --cluster check 192.168.64.128:6382
redis-cli --cluster del-node ip:从节点端口 从节点ID
redis-cli --cluster check 192.168.64.128:6382
redis-cli --cluster reshard 192.168.64.128:6383
4. 检查集群情况:发现6387节点的槽位全部分配给了6386
redis-cli --cluster check 192.168.64.128:6382
redis-cli --cluster del-node ip:主节点端口 主节点ID
redis-cli --cluster check 192.168.64.128:6382
docker build
时运行。有两种格式:shell命令格式和exec格式。ENV MY_PATH /use/local
,可以其他地方使用 $MY_PATH
。COPY src dest
。启动后
要干的事情,但只有最后一个生效,CMD会被docker run
之后的参数替换。有两种格式:shell命令格式和exec格式。启动时
要运行的命令,不会被覆盖,而是将docker run
后面的命令行作参数,当做参数送给ENTRYPOINT指令。给centos7添加vim+ifconfig+jdk8
Dockerfile文件
FROM centos:7
MAINTAINER gongl<********@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令查看网络IP
RUN yum -y install net-tools
#安装jdk8及lib库
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
#ADD是相对路径jar,把jdk-8u371-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一个位置
ADD jdk-8u371-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_371
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 'sucess-------------------ok'
CMD /bin/bash
#注意TAG后面有个空格和点.
docker build -t 新镜像的名字:TAG .
docker run -it centos7jdk8:1.1 /bin/bash
from ubuntu
CMD echo'action is sucess'
docker image ls -f dangling=true
docker image prune
#基础镜像使用java8
FROM java:8
#作者信息
MAINTAINER gongl<********@qq.com>
# VOLUME 指定临时文件目录/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
#将jar包添加到容器中并命名为 aaaaa_test.jar
ADD test.jar aaaaa_test.jar
#运行jar
ENTRYPOINT ["java","-jar","aaaaa_test.jar"]
#暴露端口9561作为微服务的端口
EXPOSE 9561
docker build -t aaaaa_test:1.4 .
生成镜像
- connect:连接
- create:创建
- disconnect:中断
- inspect:查看
- ls:列表
- prune:删除所有无效网络
- rm:删除
--network bridge
-p
参数会无效 ,如上图给出的警告。--network host
--network none
当指定容器停止后,新建的容器也无法使用网络
。 --network container:指定的容器名
docker network create 自定义网络名
创建。将服务设置同一个自定义网络,可以通过容器的服务名
直接通信。自定义网络本身就维护好了主机名和ip的对应关系。 --network 自定义网络名
实现对docker集群的快速编排
下载地址:https://docs.docker.com/compose/install/
安装文档:https://docs.docker.com/compose/install/other/
compose版本对应文档地址:https://docs.docker.com/compose/compose-file/compose-file-v3/
#下载
curl -SL https://github.com/docker/compose/releases/download/v2.17.3/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
#添加权限
chmod +x /usr/local/bin/docker-compose
#测试安装
docker-compose --version
#卸载
rm /usr/local/lib/docker/cli-plugins/docker-compose
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 #停止服务
version: "3" #版本
services: #所有的服务
microService: #服务名,自定义,不重复即可
image: aaaaa_test:1.4 #镜像名称:TAG
container_name: ms01 #容器名称,自定义。不加该参数默认生成带前缀和后缀的容器名
ports: #端口映射
- "9561:9561"
volumes: #数据卷
- /app/microService:/data
networks: #自定义网络,为了直接使用 服务名 进行容器间通信
- test_net
depends_on: #当前服务依赖于哪些服务
- redis1
- mysql
reids1: #服务名,自定义,不重复即可
image: redis:6.0.8 #镜像名称:TAG
ports: #端口映射
- "6379:6379"
volumes: #数据卷
- /app/redis/redis.conf:/etc/redis/redis.conf
- /app/redis/data:/data
networks:
- test_net
command: redis-server /etc/redis/redis.conf
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: '123456'
MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
MYSQL_DATABASE: 'db2023'
MYSQL_USER: 'root'
MYSQL_PASSWORD: '123456'
ports:
- "3306:3306"
volumes:
- /app/mysql/db:/var/lib/mysql
- /app/mysql/conf/my.cnf:/etc/my.cnf
- /app/mysql/init:/docker-entrypoint-initdb.d
networks:
- test_net
command: --default-authentication-plugin=mysql_native_password #解决外部无法访问
networks:
test_net:
2.2 将java项目中的ip地址修改为对应的服务名(如:redis的ip修改为上面配置文件的redis1)。打包并生成镜像:具体实现查看上面 三、docker微服务实战
2.3 docker-compose config -q
检查docker-compose.yml文件
2.4 docker-compose up
或者docker-compose up -d
启动服务
2.5 进入mysql容器完成数据库初始化等操作
2.6 docker-compose stop
可停止所有的服务
Portainer是一款轻量级的应用,提供了图形化界面,用于方便的管理Docker环境,包括单机和集群环境。
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
--restart=always
表示docker启动时同时启动该容器
2. 第一次登录需要创建admin,访问地址:ip:9000
docker-compose.yml
文件version: '3.1'
volumes:
grafana_data: {} #实现了grafana数据的挂载
services: #表示我们要启动的服务,即要docker run的内容,多个实例服务
influxdb:
image: tutum/influxdb:0.9
restart: always
environment:
- PRE_CREATE_DB=cadvisor #预先创建一个数据库
ports:
- "8083:8083" #对外是8083
- "8086:8086" #内部即8086
volumes:
- ./data/influxdb:/data
cadvisor:
image: google/cadvisor
links:
- influxdb:influxsrv
command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxsrv:8086 #这就是相当于mysql选择的那个驱动
restart: always
ports:
- "18080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
grafana:
image: grafana/grafana
user: "104"
restart: always #随着docker启动,就启动
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
- INFLUXDB_NAME=cadvisor
- INFLUXDB_USER=root
- INFLUXDB_PASS=root
docker-compose -q
检查并执行 docker-compose up
运行