Docker

Docker

一、Docker简介

1、简介

Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖到一个可抑的容器中,然后发布到任何流行的Linux平台上,也可以实现虚拟化。容器完全使用沙盒机制,相互之间不会存在任何接口,几乎没有性能消耗,可以很容易的在机器和数据中心运行。最重要的是它不需要依赖任何的语言、框架或者包装系统。

简单的说:Docker解决了运行环境和配置问题的软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术。

2、Docker的三要素

  • 镜像(image)

    Docker镜像就是一个只读的模板。镜像可以用来创建docker容器,一个镜像可以创建很多个容器。

    它也相当于一个root文件系统。比如官方镜像centOS7,就包含了一整套最小的root文件系统。

    相当于容器的源代码,docker镜像文件类似于Java的类模板,而docker容器实例类似于Java通过new出来实例的对象。

  • 容器(container)

    • 从面向对象的角度,Docker利用容器独立运行一个或者一组应用,应用程序或服务运行在容器里面,容器就类似于一个虚拟化的运行环境,容器是用镜像创建的实例,就像Java里的类和实例对象一样,镜像是静态的定义,容器是镜像运行的实体。容器为镜像提供了一个标准的和隔离的运行环境,它可以被启动、运行、暂停、删除。每个容器都是相互隔离的,保证安全的平台。
    • 从镜像的角度,可以把容器看作一个简易的Linux环境和运行在其中的程序。
  • 仓库(repository)

    是集中存放镜像的场所。类似于maven存放各种jar包,GitHub存放各种Git项目,docker hub是存放各种镜像模板的地方。

二、Docker安装

1、如果之前安装过老版本需要卸载
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
2、安装gcc相关
yum -y install gcc
yum -y install gcc-c++
3、安装yum工具包
yum -y install yum-utils
4、配置仓库资源
# 1. 默认使用国外源,非常非常非常慢!
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

# 2. 推荐用国内源,丝滑!
yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
5、更新yum软件包索引(可做可不做)
yum makecache fast
6、安装Docker
yum install docker-ce docker-ce-cli containerd.io
7、启动Docker
systemctl start docker
8、查看是否安装成功
// 查看docker版本
docker version

// 查看是否安装成功,要先从远程仓库拉取镜像
docker pull hello-world
docker run hello-world
9、配置阿里云镜像加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://8oizdfoz.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
10、卸载Docker
systemctl stop docker
yum remove docker-ce docker-ce-cli containerd.io
rm -rf /var/lib/docker
rm -rf /var/lib/containerd

三、Docker的常用指令

1、帮助启动类命令
  • 启动docker: systemctl start docker

  • 关闭docker: systemctl stop docker

  • 重启docker: systemct restart docker

  • 查看docker状态: systemctl status docker

  • 开机自启动docker: systemctl enable docker

  • 查看docker概要信息: docker info

  • 查看docker总体帮助文档: docker help

  • 查看docker指定命令文档: docker [指令] help

2、镜像指令
  • docker images:列出本主机上的所有镜像
    • -a 列出本地所有镜像(包括历史映像层)
    • -q 只显示镜像Id
  • docker search [镜像名]:从镜像仓库查找镜像
    • docker search --limit 5 redis 从镜像仓库里查找排名前五的名为Redis的镜像
  • docker pull [镜像名]:下载镜像
    • docker pull [镜像名] [TAG]:下载指定版本的镜像,没有写就是最新的
  • docker system df:查看镜像、容器、数据卷所占用的空间
  • docker rmi [镜像名/镜像Id]:删除镜像
    • docker rmi -f [镜像名/镜像Id]:强制删除
    • docker rmi -f [镜像名]:[TAG] [镜像名]:[TAG]:删除多个镜像
    • docker rmi -f $(docker image -qa):删除所有镜像,其中指令 “docker image -qa” 查询所有镜像Id
3、容器命令
  • docker run [OPTIONS] IMAGE [COMMAND] [ARG]:新增或启动容器
    • [OPTIONS]说明:有时“-”,有时“–”,常用
      • –name:为容器指定一个名称
      • -d:后台运行容器并返回容器Id
      • -i:以交互模式运行容器,常与 -t 一起使用
      • -t:为容器重新分配一个伪命令终端,常与 -i 一起使用
      • -it:启动交互式容器,前台有伪终端,等待交互
      • -P:随机端口映射
      • -p:指定端口映射
    • [COMMAND]说明:指令,如 /bin/bash
  • docker ps [OPTIONS]:列举容器中正在运行的镜像
    • [OPTIONS]说明:
      • -a:列出当前正在运行的容器 + 历史运行过的容器
      • -l:显示最近创建的容器
      • -n:显示最近创建的n个容器
      • -q:静默模式,只显示容器编号
  • 在容器中退出容器:
    • exit:退出并停止当前容器
    • Ctrl + p + q:退出,但当前容器并不终止
  • docker start [容器Id/容器名]:启动已经停止的容器/容器名
  • docker restart [容器Id/容器名]:重启容器/容器名
  • docker stop [容器Id/容器名]:停止容器/容器名
  • docker kill [容器Id/容器名]:强制停止容器/容器名
  • docker rm [容器Id/容器名]:删除容器/容器名,注意区分 docker rmi [镜像Id],删除
  • 启动守护式容器:docker run -d [容器ID/容器名]
  • 查看容器日志:docker logs [容器ID]
  • 查看容器内部运行的进程:docker ps,docker top [容器ID]
  • 查看容器内部细节:docker inspect [容器ID]
  • 进入正在运行的容器并以命令行交互:
    • docker exec -it [容器ID] bashShell,在容器中打开新的终端,启动新的进程,exit退出时,不会导致容器停止
    • docker attach [容器ID],直接进入容器启动命令终端,不会启动新的进程,exit退出时,会导致容器的停止
    • 例:docker exec -it [容器ID] /bin/bash, redis-cli -p 6379
  • 从容器中拷贝文件到当前主机上:docker ps [容器ID]:容器内路径 目的主机路径
  • 导出和导出容器:
    • 导出容器:docker export [容器ID] > 文件名.tar
    • 导入容器:cat 文件名.tar | docker import - 镜像用户/镜像名: 镜像保本号

四、镜像

1、何为镜像?

是一种轻量级的、可执行的独立软件包,它包含某些软件所需的所有内容,我们把应用程序和配置依赖打包好成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。

Docker镜像层是只读的,容器层是可写的。当容器启动时,一个新的可写层被加载到镜像的底部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。

2、UnionFS(联合文件系统)

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

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

3、Docker镜像加载原理

Docker镜像实际上是由一层一层的文件系统组成,这种文件系统叫做UnionFS。

bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像最底层是引导文件系统bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs(root file system),在bootfs之上。包含的就是典型的Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu、centOS等等。

4、镜像分层
  • docker commit:提交一个容器副本使之成为一个新的镜像
    • docker commit -m="提交的描述信息" -a="作者" 容器Id 要创建的目标镜像名:[标签名]
案例:Ubuntu安装vim文本编辑器
  • 从Docker Hub上下载Ubuntu镜像到本地运行(原始的Ubuntu镜像是不带vim命令的)
  • 外网联通的情况下,安装vim
  • 安装完成后,commit提交Ubuntu容器副本使之成为一个新的Ubuntu镜像
  • 启动我们的新镜像,和原来的做对比
总结

Docker中的镜像分层,支持通过现有的镜像,创建新的镜像。类似于Java中的继承,基于一个Base类,按需扩展成想要的类。新镜像是从base镜像一层层叠加生成的,每安装一个软件,就是在现有的镜像基础上加一层。

五、本地镜像发布到阿里云

六、本地镜像推送到私有库

1、下载镜像Docker Registry
dokcer pull registry
2、运行私有库Docker Registry

相当于本地有个docker hub,默认情况下,仓库被创建在/var/lib/registry目录下,建议自行用容器卷映射,方便与宿主机联调

docker run -d -p 5000:5000 -v /zly/myRegistry/:/tmp/registry --privileged=true registry
* -d 后台运行
* -p 端口映射
* -v 
* -- privileged
3、创建一个新镜像

案例演示,Ubuntu安装ifconfig指令,生成新的镜像

ifconfig指令1、docker pull ubuntu:下载Ubuntu镜像
2、docker run -it ubuntu:以交互式启动Ubuntu镜像
3、apt-get update:Ubuntu容器内部包的更新
4、apt-get install net-tools:Ubuntu容器内部安装ifconfig指令
5、Ctrl + p + q:退出当前容器,但不会使容器停止
6、docker commit -m="first commit" -a="zly" 容器Id 要创建的目标镜像名:[标签名]:提交并生成新的镜像
4、查看私有库里有什么镜像
curl -XGET http://124.222.32.135:5000/v2/_catalog
结果:{"repositories":[""]}
5、将新镜像名称修改成符合私服规范的tag
docker tag myubuntuifconfig:1.0 124.222.32.135:5000/myubuntuifconfig:1.0
6、修改docker配置文件使之支持http

修改完成后如果不生效,则重启docker

vim /etc/docker/daemon.json    修改配置文件

添加 "insecure-registries": ["124.222.32.135:5000"]
修改后:
{
  "registry-mirrors": ["https://8oizdfoz.mirror.aliyuncs.com"],
  "insecure-registries": ["124.222.32.135:5000"]
}
7、推送镜像
docker pull 124.222.32.135:5000/myubuntuifconfig:1.0
8、查看私有库里是否有推送的镜像
curl -XGET http://124.222.32.135:5000/v2/_catalog
结果:{"repositories":["myubuntuifconfig"]}
9、pull到本地并运行
docker pull 124.222.32.135:5000/myubuntuifconfig:1.0
docker run -it 124.222.32.135:5000/myubuntuifconfig:1.0

七、Docker容器数据卷

1、–privileged=true详解

Centos7的安全模块比之前的系统版本进行了加强,不安全的会先安全禁止,所以目录挂载会被认为是不安全的操作。在SELinux里挂载目录被禁止掉了,如果要开启,我们一般添加 --privileged=true指令,扩大容器权限,解决目录挂载没有权限的问题。也即使用该参数,container容器内的root拥有了真正的root权限,否则,container内部的root权限只是外部的普通用户权限。

当Docker挂载主机目录访问如果出现cannot open dictionary .: Permission denied,可使用 --privileged=true指令解决

2、Docker容器数据卷是什么

有点类似于Redis中的RDB和AOF文件,将Docker容器内的数据保存到宿主机的磁盘中

卷是目录或者文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System 提供一些用于持续存储或共享数据的特性。卷设计的目的就是为了数据的持久化,完全独立于容器的生命周期,因此Docker不会在删除容器时山区其挂载的数据卷。

容器卷的特点:
  • 数据卷可以在容器之间共享或重用数据
  • 卷中数据的更改可以直接实时生效
  • 数据卷的修改不会包含在镜像的更新中
  • 数据卷的生命周期会一直持续到没有容器使用它为止
docker run -v /宿主机路径:/docker容器内路径 --privileged=true 容器名
docker run -v /宿主机路径:/docker容器内路径:ro --privileged=true 容器名  限制容器内只能读取,不能写,read-only
docker run --privileged=true --volumes-from u1 --name u2 容器名 容器u2继承u1的数据卷,u1和u2是相互独立的,一主二从

八、Docker上安装软件

1、安装MySQL(单机版)
1、拉取MySQL镜像
	docker pull mysql:5.7
2、运行MySQL镜像
	docker run -d -p 3306:3306 --privileged=true \
         -v /zly/mysql/log:/var/log/mysql \
         -v /zly/mysql/data:/var/lib/mysql \
         -v /zly/mysql/conf:/etc/mysql/conf.d \
         -e MYSQL_ROOT_PASSWORD=123456 \
         --name mysql mysql:5.7
 3、在文件夹/zly/mysql/conf下新建my.cnf的MySQL配置文件,并写入一下内容
 	[client]
    default_character_set=utf8
    [mysqld]
    collation_server=utf8_general_ci
    character_set_server=utf8
 4、设置docker启动时启动mysql
 	docker update mysql --restart=always
 5、重启MySQL
 	docker restart 容器ID
 6、进入mysql容器内部
 	docker exec -it mysql /bin/bash
 7、登录mysql
 	mysql -uroot -p    回车后输入密码
2、安装Redis
1、拉取Redis镜像
	docker pull redis
2、redis.conf
        # 绑定IP地址
        #解除本地限制 注释bind 127.0.0.1  
        #bind 127.0.0.1  

        # 服务器端口号  
        port 6379 

        #配置密码,不要可以删掉
        #requirepass syf133618

        #这个配置不要会和docker -d 命令 冲突
        # 服务器运行模式,Redis以守护进程方式运行,默认为no,改为yes意为以守护进程方式启动,可后台运行,除非kill进程,改为yes会使配置文件方式启动redis失败,如果后面redis启动失败,就将这个注释掉
        daemonize no

        #当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定(自定义)
        #pidfile /data/dockerData/redis/run/redis6379.pid  

        #默认为no,redis持久化,可以改为yes
        appendonly yes

        #当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
        timeout 60
        # 服务器系统默认配置参数影响 Redis 的应用
        maxclients 10000
        tcp-keepalive 300

        #指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合(分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改)
        save 900 1
        save 300 10
        save 60 10000

        # 按需求调整 Redis 线程数
        tcp-backlog 511

        # 设置数据库数量,这里设置为16个数据库  
        databases 16

        # 启用 AOF, AOF常规配置
        appendonly yes
        appendfsync everysec
        no-appendfsync-on-rewrite no
        auto-aof-rewrite-percentage 100
        auto-aof-rewrite-min-size 64mb

        # 慢查询阈值
        slowlog-log-slower-than 10000
        slowlog-max-len 128

        # 是否记录系统日志,默认为yes  
        syslog-enabled yes  

        #指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
        loglevel notice

        # 日志输出文件,默认为stdout,也可以指定文件路径  
        logfile stdout

        # 日志文件
        #logfile /var/log/redis/redis-server.log

        # 系统内存调优参数   
        # 按需求设置
        hash-max-ziplist-entries 512
        hash-max-ziplist-value 64
        list-max-ziplist-entries 512
        list-max-ziplist-value 64
        set-max-intset-entries 512
        zset-max-ziplist-entries 128
        zset-max-ziplist-value 64
3、运行Redis镜像
docker run -p 6379:6379 --name redis --privileged=true \
     -v /zly/redis/redis.conf:/etc/redis/redis.conf \
     -v /zly/redis/data:/data \
     -d redis redis-server /etc/redis/redis.conf
4、进入Redis容器
	docker exec -it redis /bin/bash
5、进入客户端
	redis-cli
3、安装MySQL(集群版)
安装主服务器容器实例

(1)、启动容器实例:3307

docker run -d -p 3307:3306 --privileged --name mysql-master \
	-v /zly/mysql-cluster/mysql-master/log:/var/log/mysql \
	-v /zly/mysql-cluster/mysql-master/data:/var/lib/mysql \
	-v /zly/mysql-cluster/mysql-master/conf:/etc/mysql \
	-e MYSQL_ROOT_PASSWORD=root \
	mysql:5.7

(2)、进入/zly/mysql-cluster/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)、重启容器实例

docker restart mysql-master

(4)、进入mysql-master容器实例内部

docker exec -it mysql-master /bin/bash
mysql -uroot -proot

(5)、在mysql-master主数据库中创建数据同步用户

// 创建用户
create user 'slave'@'%' identified by '123456';
// 授权
grant replication slave, replication client on *.* to 'slave'@'%';
安装从服务器容器实例

(1)、启动容器实例:3308

docker run -d -p 3308:3306 --privileged --name mysql-slave \
	-v /zly/mysql-cluster/mysql-slave/log:/var/log/mysql \
	-v /zly/mysql-cluster/mysql-slave/data:/var/lib/mysql \
	-v /zly/mysql-cluster/mysql-slave/conf:/etc/mysql \
	-e MYSQL_ROOT_PASSWORD=root \
	mysql:5.7

(2)、进入/zly/mysql-cluster/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

(3)、重启容器实例

docker restart mysql-slave
在主数据库中查看主从同步状态
docker exec -it mysql-master /bin/bash
mysql -uroot -p
show master status

主要查看返回结果的文件名File、当前位置Position

在从数据库中配置主从复制

(1)、进入从服务器

docker exec -it mysql-master /bin/bash
mysql -uroot -p

(2)、配置主从复制

change master to master_host='124.222.32.135', master_user='slave', master_password='123456', master_port=3307, master_log_file='mall-mysql-bin.000001', master_log_pos=617, master_connect_retry=30;
解释:
change master to master_host='宿主机ip',
master_user='主数据库配置的主从复制用户名',
master_password='主数据库配置的主从复制用户密码',
master_port=宿主机主数据库端口,
master_log_file='主数据库主从同步状态的文件名File',
master_log_pos=主数据库主从同步状态的Position,
master_connect_retry=连接失败重试时间间隔(秒);

(3)、查看主从同步状态

# \G 可以将横向的结果集表格转换成纵向展示。
# slave status的字段比较多,纵向展示比友好
show slave status \G;

除了展示刚刚配置的主数据库信息外,主要关注 Slave_IO_RunningSlave_SQL_Running。目前两个值应该都为 No,表示还没有开始。

(4)、开启主从同步

start slave;

(5)、查看主从同步状态

主从复制测试:

(1)、 在主数据库上新建库、使用库、新建表、插入数据

create database db01;
use db01;
create table t1 (id int, name varchar(20));
insert into t1 values (1, 'abc');

(2)、 在从数据库上使用库、查看记录

show databases;
use db01;
select * from t1;
4、3主3从Redis集群

(1)、启动6台Redis节点

# 启动第1台节点
# --net host 使用宿主机的IP和端口,默认
# --cluster-enabled yes 开启redis集群
# --appendonly yes 开启redis持久化
# --port 6381 配置redis端口号
docker run -d --name redis-node-1 --net host --privileged=true -v /zly/redis-cluster/share/redis-node-1:/data redis --cluster-enabled yes --appendonly yes --port 6381

# 启动第2台节点
docker run -d --name redis-node-2 --net host --privileged=true -v /zly/redis-cluster/share/redis-node-2:/data redis --cluster-enabled yes --appendonly yes --port 6382

# 启动第3台节点
docker run -d --name redis-node-3 --net host --privileged=true -v /zly/redis-cluster/share/redis-node-3:/data redis --cluster-enabled yes --appendonly yes --port 6383

# 启动第4台节点
docker run -d --name redis-node-4 --net host --privileged=true -v /zly/redis-cluster/share/redis-node-4:/data redis --cluster-enabled yes --appendonly yes --port 6384

# 启动第5台节点
docker run -d --name redis-node-5 --net host --privileged=true -v /zly/redis-cluster/share/redis-node-5:/data redis --cluster-enabled yes --appendonly yes --port 6385

# 启动第6台节点
docker run -d --name redis-node-6 --net host --privileged=true -v /zly/redis-cluster/share/redis-node-6:/data redis --cluster-enabled yes --appendonly yes --port 6386

(2)、构建主从关系

1. 进入节点1(或其中任意一个节点): 
	docker exec -it redis-node-1 /bin/bash
2. 构建主从关系:
	redis-cli --cluster create 124.222.32.135:6381 124.222.32.135:6382 124.222.32.135:6383 124.222.32.135:6384 \
    124.222.32.135:6385 124.222.32.135:6386 --cluster-replicas 1
3. redis尝试自动进行主从节点分配 
4. 因为我们的docker容器IP相同,所以会出现警告,可以直接忽略该警告,
	[WARNING] Some slaves are in the same host as their master
5. redis自动分配结果完成后,需要输入 Yes 确认配置信息
6. 输入Yes确认后,redis会向其他节点发送信息加入集群,并分配哈希槽: 

(3)、查看集群状态:

1. 进入容器节点1(或集群中其他节点): 
	docker exec -it redis-node-1 /bin/bash
2. 使用redis-cli连接到6381节点: 
	redis-cli -p 6381
3. 使用redis的相关命令查看集群状态: 
	cluster info
	其中,分配的哈希槽数量 cluster_slots_assigned为16384,集群节点数量cluster_known_nodes为6 
4. 查看集群节点信息 
	cluster nodes

(4)、Redis集群读写出错

当使用 redis-cli连接redis集群时,需要添加 -c参数,否则可能会出现读写出错。

示例:
1. 进入容器节点1 
	docker exec -it redis-node-1 /bin/bash
2. 使用redis-cli连接,不加-c参数时 
	redis-cli -p 6381
3. 此时向redis中添加键值对,可能会成功,也可能会失败 
	set k1 v1
    报错:k1经过计算得到的哈希槽为12706,但是当前连接的redis-server为6381(即节点1),它的哈希槽为:[0,5460](在创建构建主从关系时redis有提示,也可以通过 cluster nodes查看),所以会因为存不进去而报错。 
    执行 set k2 v2可以成功,因为k2计算出的哈希槽在[0-5460]区间中。 
4.  使用-c参数的redis-cli命令连接即可 
	redis-cli -p 6381 -c
5.  此时可以正常的插入所有数据 
	set k1 v1
	会有提示信息,哈希槽为12706,重定向到6383(即节点3,哈希槽[10923, 16383]):  

(5)、集群信息检查

# 输入任意一台主节点地址都可以进行集群检查
redis-cli --cluster check 124.222.32.135:6381

(6)、主从扩容

假如因为业务量激增,需要向当前3主3从的集群中再加入1主1从两个节点。

1、启动2台新的容器节点 
	docker run -d --name redis-node-7 --net host --privileged=true -v /zly/redis-cluster/share/redis-node-7:/data redis --cluster-enabled yes --appendonly yes --port 6387
	docker run -d --name redis-node-8 --net host --privileged=true -v /zly/redis-cluster/share/redis-node-8:/data redis --cluster-enabled yes --appendonly yes --port 6388
	
2、进入6387(节点7)容器内部 
 	docker exec -it redis-node-7 /bin/bash
 	
3、将6387作为master加入集群 
	# redis-cli --cluster add-node 本节点地址 要加入的集群中的其中一个节点地址
	redis-cli --cluster add-node 124.222.32.135:6387 124.222.32.135:6381

4、检查当前集群状态 
	redis-cli --cluster check 124.222.32.135:6381
	可以发现,6371节点已经作为master加入了集群,但是该节点没有被分配槽位。 
5、重新分配集群的槽位 
	redis-cli --cluster reshard 124.222.32.135:6381
    redis经过槽位检查后,会提示需要分配的槽位数量: 
    例如,我们现在是4台master,我们想要给node7分配4096个槽位,这样每个节点都是4096个槽位。
    输入4096后,会让输入要接收这些哈希槽的节点ID,填入node7的节点ID即可。(就是节点信息中很长的一串十六进制串)。
    然后会提示,询问要从哪些节点中拨出一部分槽位凑足4096个分给Node7。一般选择 all,即将之前的3个主节点的槽位都均一些给Node7,这样可以使得每个节点的槽位数相等均衡。
    输入all之后,redis会列出一个计划,内容是自动从前面的3台master中拨出一部分槽位分给Node7的槽位,需要确认一下分配的计划。
    输入yes确认后,redis便会自动重新洗牌,给Node7分配槽位。 
    重新分配完成后,可以进行集群信息检查,查看分配结果:
		redis-cli --cluster check 124.222.32.135:6381

	可以发现重新洗牌后的槽位分配为:
        节点1:[1365-5460](供4096个槽位),,,分配前为[0-5460](共5461个槽位)
        节点2:[6827-10922](共4096个槽位),,,分配前为[5461-10922](共5461个槽位)
        节点3:[12288-16383](共4096个槽位),,,分配前为[10923-16383](共5462个槽位)

        节点7:[0-1364],[5461-6826],[10923-12287](共4096个槽位),从每个节点中匀出来了一部分给了节点7

	因为可能有些槽位中已经存储了key,完全的重新洗牌重新分配的成本过高,所以redis选择从前3个节点中匀出来一部分给节点7
6、为主节点6387分配从节点6388:
	redis-cli --cluster add-node 124.222.32.135:6388 124.222.32.135:6381 --cluster-slave --cluster-master-id node7节点的十六进制编号字符串
	redis便会向6388发送消息,使其加入集群并成为6387的从节点。
7、检查集群当前状态
	redis-cli --cluster check 124.222.32.135:6381

(7)、主从缩容

假如业务高峰期过去,需要将4主4从重新缩容到3主3从。即从集群中移除node8和node7.

1、进入容器节点1 
	docker exec -it redis-node-1 /bin/bash
 
2、检查容器状态,获取6388的节点编号 
	redis-cli --cluster check 124.222.32.135:6381
 
3、将6388从集群中移除 
	redis-cli --cluster del-node 124.222.32.135:6388 6388节点编号
 
4、对node7重新分配哈希槽:
    redis-cli --cluster reshard 124.222.32.135:6381
    redis经过槽位检查后,会提示需要分配的槽位数量: 
    How many slots do you want to move (from 1 to 16384)?
    如果我们想直接把node7的4096个哈希槽全部分给某个节点,可以直接输入4096。
    输入4096后,会让输入要接收这些哈希槽的节点ID。假如我们想把这4096个槽都分给Node1,直接输入node1节点的编号即可。
    然后会提示,询问要从哪些节点中拨出一部分槽位凑足4096个分给Node1。这里我们输入node7的节点编号,回车后输入done。 
    node7上面没有了哈希槽,此时便可以将node7从集群中移除。(如果node7上面有哈希槽,直接从集群中移除会报错)
redis-cli --cluster del-node 124.222.32.135:6387 node7节点编号

九、DockerFile解析

1、概述

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

构建步骤

  • 编写DockerFile文件
  • docker build 命令构建镜像
  • docker run 运行镜像容器实例
2、DockerFile文件构建过程解析
a、DockerFile文件基础知识
  • 每条保留字指令都必须为大写字母且后面至少要跟一个参数
  • 指令按照从上到下顺序执行
  • #表示注释
  • 每条指令都会创建一个新的镜像,并对镜像进行提交
b、docker执行Dockerfile的大致流程
  • docker从基础镜像运行一个容器
  • 执行一条命令并对容器做出修改
  • 执行类似docker commit的操作提交一个新的镜像层
  • docker 再基于刚刚提交的镜像运行一个新的容器
  • 执行dockerfile中的下一条指令,直至所有指令都执行完成
总结

从应用软件的角度来看,dockerfiledocker镜像docker容器分别代表软件的三个阶段:

  • dockerFile是软件的原材料
  • docker镜像是软件的交付品
  • docker容器则是软件镜像的运行态,也即依照镜像运行的容器实例

dockerfile面向开发,docker镜像成为交付的标准,docker容器则涉及部署与运维,三者缺一不可,合力充当docker体系的基石。

3、dockerfile常用保留字
  • FROM:基础镜像,当前镜像是基于哪个镜像的,指一个已经存在的镜像模板,在dockerfile文件的第一行
  • MAINTAINER:镜像维护者的姓名和邮箱
  • RUN:容器构建时需要运行的命令,在docker build时运行,一般有两种格式
    • shell格式:RUN <命令行命令>
    • exec格式:RUN ["可执行文件", "参数1", "参数2"]
  • EXPOSE:当前容器对外暴露的端口
  • WORKDIR:指定在容器创建后,终端默认进入容器内的工作目录,一个落脚点
  • USER:指定该镜像以什么样的用户去执行,如果都不指定,则默认root
  • ENV:用于构建镜像过程中设置环境变量
  • ADD:将宿主机下的文件拷贝进镜像,且会自动处理URL和解压tar压缩包
  • COPY
  • 类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中<源路径>的文件目录复制到新的一层镜像内的<目标路径>位置。
    • COPY src dest
    • COPY ["src", "dest"]
  • VOLUME:容器数据卷,用于数据保存和持久化操作
  • CMD:指定容器启动后要做什么事情,如果有多个CMD指令,只有最后一个会生效,CMD会被docker run后面的参数替代
  • ENTRYPOINT
    • 用来指定一个容器启动时要运行的命令。
    • 类似于CMD命令,但是ENTRYPOINT不会被docker run后面的命令覆盖,这些命令参数会被当做参数送给ENTRYPOINT指令指定的程序。
    • ENTRYPOINT可以和CMD一起用,一般是可变参数才会使用CMD,这里的CMD等于是在给ENTRYPOINT传参。
    • 当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行期命令,而是将CMD的内容作为参数传递给ENTRYPOINT指令,它们两个组合会变成 <ENTRYPOINT> "<CMD>"
4、构建镜像
a、新建dockerfile文件
FROM centos
MAINTAINER zly@1163977538@qq.com
ENV MYPATH /usr/local
WORKDIR $MYPATH
#CentOS8 yum源配置
RUN rm -f /etc/yum.repos.d/*.repo
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-8.repo
#安装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,把jdk-8u271-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置
ADD jdk-8u271-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_271
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
b、下载jdk
下载jdk-8u271-linux-x64.tar.gz并把其放入和Dockerfile文件在同一位置
c、构建镜像
# 注意:定义的TAG后面有个空格,空格后面有个点
# docker build -t 新镜像名字:TAG .
docker build -t centosjava8:1.0.1 .
d、启动镜像
 docker run -it 810641de7ec0 /bin/bash
e、测试
1、进入后在 /usr/local 文件夹下
2、测试vim 编辑器
3、测试 ifconfig
4、测试 java -version

十、Docker运行微服务

1、在idea中升成jar包
把项目在Maven下 docker-test  ->  Lifecycle  ->  package  ->  生成docker-test-1.0-SNAPSHOT.jar
将jar包放在和Dockerfile文件同一目录下
2、在Linux目录下编写Dockerfile文件
FROM openjdk:11-jre
MAINTAINER zly@1163977538@qq.com

# 在主机 /var/lib/docker目录下创建一个临时文件,并链接到容器的 /tmp
VOLUME /tmp

# 将jar包添加到容器中,并命名为 springboot_docker.jar
ADD docker-test-1.0-SNAPSHOT.jar /springboot_docker.jar
# 运行jar包
RUN bash -c 'touch /springboot_docker.jar'
ENTRYPOINT ["java", "-jar", "/springboot_docker.jar"]

# SpringBoot项目配置的端口号为9876,需要将9876暴露出去
EXPOSE 9876
3、构建镜像
# 注意:定义的TAG后面有个空格,空格后面有个点(可能需要先拉取镜像openjdk:11-jre)
# docker build -t 新镜像名字:TAG .
docker build -t docker-spring-boot-test:1.0 .
4、启动容器
docker run -d -p 9876:9876 docker-spring-boot-test:1.0
5、测试
http://124.222.32.135:9876/docker/index

十一、Docker network

1、概述

docker安装并成功启动后,会在宿主机添加一个虚拟网卡docker0

作用:

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

docker容器的网络隔离是通过Linux内核特性namespacecgroup实现的

2、常用指令
使用 --help 查询
docker network --help

  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks
3、网络模式
网络模式简介
bridge为每一个容器分配、设置 IP 等,并将容器连接到一个docker0,虚拟网桥,默认为该模式
host容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口
none容器有独立的NetWork NameSpace,并没有对其进行网络配置,入分配veth pair 和网桥连接,IP 等
container新建的容器不会虚拟出自己的网卡,配置自己的 IP 等,而是和一个指定的容器共享 IP 、端口范围等
docker0

Docker 服务默认会创建一个docker0网桥(其上有一个docker0内部接口),该桥接网络的名称为 docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。

Docker默认指定了docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥互相通信。

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

docker network inspect bridge | grep name

可以看到其名称为docker0

bridge模式

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一个宿主机内的容器接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

docker run的时候,没有指定--network的话,默认使用的网桥模式就是bridge,使用的就是docker0。在宿主机ifconfig就苦役看到docker0和自己createnetwork

网桥docker0创建一对对等虚拟设备接口,一个叫veth,另一个叫eth0,成对匹配:

整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口叫 veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫做 veth pair)。

每个容器实例内部也有一块网卡,容器内的网卡接口叫做eth0

docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。

在这里插入图片描述

例如:

启动tomcat容器,进入tomcat容器后,执行 ip addr,可以看到其网卡信息:

1: lo ..................

容器内的网卡为 eth0
@符号后面就是宿主机上对应的veth网卡的编号28
27: eth0@if28 ...............................

在宿主机执行 ip addr 查看宿主机网卡信息:

每个veth都有个编号:vethXXXXXX
@符号后面对应就是容器内的eth0网卡编号27

28: vethXXXXXX@if27  ................
host模式

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

容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个 Network space。

容器将不会虚拟出自己的网卡,而是直接使用宿主机的 IP 和端口。

在这里插入图片描述

如果在 docker run 命令中同时使用了 --network host-p端口映射,例如:

docker run -p 8082:8080 --network host tomcat

那么会出现一个警告:

WARNING: Published ports are discarded when using host network mode

因为此时已经使用了host模式,本身就是直接使用的宿主机的IP和端口,此时的-p端口映射就没有了意义,也不会生效,端口号还是会以主机端口号为主。

正确做法是:不再进行-p端口映射,或者改用bridge模式

none模式

禁用网络功能。

none模式下,并不为docker容器进行任何网络配置。进入容器内,使用 ip addr查看网卡信息,只能看到 lo(本地回环网络127.0.0.1网卡)。

container模式

新建的容器和已经存在的一个容器共享网络IP配置,而不是和宿主机共享。

新创建的容器不会创建自己的网卡、IP,而是和一个指定的容器共享IP、端口范围。两个容器除了网络共享,其他的如文件系统、进程列表依然是隔离的。

在这里插入图片描述

示例:

docker run -it --name alpine1 alpine /bin/sh

# 指定和 alpine1 容器共享网络
docker run -it --network container:alpine1 --name alpine2 alpine /bin/sh

此时使用 ip addr查看两台容器的网络,会发现两台容器的eth0网卡内的IP等信息完全相同。

如果关掉了alpine1容器,因为alpine2的网络使用的alpine1共享网络,所以关掉alpin1后,alpine2eth0网卡也随之消失了。

自定义网络

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

容器 IP 变动时候可以通过服务名直接网络通信而不受影响。(类似Eureka,通过服务名直接互相通信,而不是写死IP地址)。

docker中还有一个 --link 进行容器网络互联,但是已经被标记为过时的,可能会在将来的版本中移除这个功能。推荐使用自定义网络替换link。

自定义桥接网络(自定义网络默认使用的是桥接网络 bridge):

  1. 新建自定义网络
docker network create tomcat_network
  1. 查看网络列表
docker network ls
  1. 创建容器时,指定加入我们自定义的网络中
docker run -d -p 8081:8080 --network tomcat_network --name tomcat1 tomcat:8.5-jdk8-corretto

docker run -d -p 8082:8080 --network tomcat_network --name tomcat2 tomcat:8.5-jdk8-corretto
  1. 此时进入tomcat1中,使用ping命令测试连接tomcat2容器名,发现可以正常连通
# 安装ifconfig命令
yum install -y net-tools
# 安装ip addr命令
yum install -y iproute
# 安装ping命令
yum install -y iputils

# 直接ping容器名,不需要ping IP地址
ping tomcat2

十二、Docker-compose容器编排

1、概述

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

Docker-Compose可以管理多个Docker容器组成一个应用。需要定义一个yaml格式的配置文件 docker-compose.yml,配置好多个容器之间的调用关系,然后只需要一个命令就能同时启动/关闭这些容器。

2、安装Docker-Compose

Docker-Compose的版本需要和Docker引擎版本对应,可以参照官网上的对应关系

安装Compose:

# 例如从github下载 2.5.0版本的docker-compose
# 下载下来的文件放到 /usr/local/bin目录下,命名为 docker-compose
curl -L https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose

# 添加权限
chmod +x /usr/local/bin/docker-compose

# 验证
docker-compose version

卸载Compose:直接删除 usr/local/bin/docker-compose文件即可

3、核心概念
  • 服务(service):一个个应用容器实例

  • 工程(project):由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml中定义

4、使用步骤
  1. 编写 Dockerfile 定义各个应用容器,并构建出对应的镜像文件
  2. 编写 docker-compose.yml,定义一个完整的业务单元,安排好整体应用中的各个容器服务
  3. 执行 docker-compose up 命令,其创建并运行整个应用程序,完成一键部署上线
5、常用命令
docker-compose -h 查看帮助

docker-compose up 创建并启动docker-compose服务
docker-compose up -d # 后台运行

docker-compose down 停止并删除容器、网络、卷、镜像

ocker-compose exec <yml里面的服务id> /bin/bash  进入容器实例内部

docker-compose ps  展示当前docker-compose编排过的运行的所有容器
docker-compose top	展示当前docker-compose编排过的容器进程

docker-compose log <yml里面的服务id>  查看容器输出日志

docker-compose config  检查配置
docker-compose config -q   # 有问题才输出

docker-compose restart	重启服务
docker-compose start	启动服务
docker-compose stop		停止服务
6、部署微服务(mysql+redis+微服务)
1、启动MySQL,详见第八章第一节 安装MySQL(单机版)
2、启动redis,详见第八章第二节 安装Redis
3、构建镜像,运行微服务

上述方法的弊端:

  • 容器启动先后顺序固定,必须先启动mysql+redis
  • 多个run指令,操作复杂
  • 容器间的启停或宕机,有可能导致IP地址对应的容器实例发生变化,映射出错,要么生产IP写死(不推荐),要么通过服务调用
7、compose编排服务
a. 编写docker-compose.yml文件
# docker-compose文件版本号
version: "3"

# 配置各个容器服务
services:
  microService:
    image: docker-compose:1.0
    container_name: docker-compose  # 容器名称,如果不指定,会生成一个服务名加上前缀的容器名
    ports:
      - "6001:6001"
    volumes:
      - /app/microService:/data
    networks:
      - docker_compose_net
    depends_on:  # 配置该容器服务所依赖的容器服务
      - redis
      - mysql

  redis:
    image: redis
    ports:
      - "6379:6379"
    volumes:
      - /app/redis/redis.conf:/etc/redis/redis.conf
      - /app/redis/data:data
    networks:
      - docker_compose_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: 'docker_compose'
      MYSQL_USER: 'dev'
      MYSQL_PASSWORD: 'dev'
    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:
      - docker_compose_net
    command: --default-authentication-plugin=mysql_native_password # 解决外部无法访问

networks:
  # 创建 docker_compose_net 网桥网络
  docker_compose_net:
b.将项目yml文件中的IP替换为服务名
spring:
  datasource:
    username: root
    password: 123456
#    url: jdbc:mysql://124.222.32.135:3306/docker_compose?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    url: jdbc:mysql://mysql:3306/docker_compose?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver
  redis:
#    host: 124.222.32.135 
    host: redis 
    port: 6379 
    password:
    database: 0 
    timeout: 1800000 
    lettuce:
      pool:
        max-active: 20 
        max-wait: -1
        max-idle: 5
        min-idle: 0
c. 构建镜像
docker build -t docker-compose:1.0 .
d.语法检查
docker-compose config -q
e.以docker-compose.yml文件启动项目
docker-compose up -d

十三、Portainer可视化工具

1、概述

Portainer是一款轻量级的应用,它提供了图形化界面,用于方便的管理docker环境,包括单机环境和集群环境。

2、安装
# 旧版镜像地址为portainer/portainer,从2022年1月标记为过期
# 新版镜像地址为portainer/portainer-ce

# --restart=always 如果Docker引擎重启了,那么这个容器实例也会在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

启动之后,便可以在浏览器中进行访问:http://xxx.xxx.xxx.xxx:9000

首次进来时,需要创建 admin 的用户名(默认admin)、密码(必须满足校验规则,例如portainer.io123)。

选择 local管理本地docker,即可看到本地Docker的详细信息,包括其中的镜像(images)、容器(containers)、网络(networks)、容器卷(volumes)、compose编排(stacks)等等。

十四、CIG重量级监控

1、CIG

通过docker stats 命令可以很方便的查看当前宿主机上所有容器的CPU、内存、网络流量等数据,可以满足一些小型应用。

但是 docker stats 统计结果只能是当前宿主机的全部容器,数据资料是实时的,没有地方存储、没有健康指标过线预警等功能。

CAdvisor(监控收集) + InfluxDB(存储数据) + Granfana(展示图表),合称 CIG
在这里插入图片描述

2、CAdvisor

CAdvisor是一个容器资源监控工具,包括容器的内存、CPU、网络IO、磁盘IO等监控,同时提供了一个Web页面用于查看容器的实时运行状态。

CAdvisor默认存储2分钟的数据,而且只是针对单物理机。不过CAdvisor提供了很多数据集成接口,支持 InfluxDB、Redis、Kafka、Elasticsearch等集成,可以加上对应配置将监控数据发往这些数据库存储起来。

CAdvisor主要功能:

  • 展示Host和容器两个层次的监控数据

  • 展示历史变化数据

3、InfluxDB

InfluxDB是用Go语言编写的一个开源分布式时序、事件和指标数据库,无需外部依赖。

CAdvisor默认只在本机保存2分钟的数据,为了持久化存储数据和统一收集展示监控数据,需要将数据存储到InfluxDB中。InfluxDB是一个时序数据库,专门用于存储时序相关数据,很适合存储 CAdvisor 的数据。而且 CAdvisor本身已经提供了InfluxDB的集成方法,在启动容器时指定配置即可。

InfluxDB主要功能:

  • 基于时间序列,支持与时间有关的相关函数(如最大、最小、求和等)

  • 可度量性,可以实时对大量数据进行计算

  • 基于事件,支持任意的事件数据

4、Granfana

Grafana是一个开源的数据监控分析可视化平台,支持多种数据源配置(支持的数据源包括InfluxDB、MySQL、Elasticsearch、OpenTSDB、Graphite等)和丰富的插件及模板功能,支持图表权限控制和报警。

Granfana主要功能:

  • 灵活丰富的图形化选项

  • 可以混合多种风格

  • 支持白天和夜间模式

  • 多个数据源

5、安装部署
  1. 编写docker-compose.yml服务编排文件
version: '3.1'

volumes:
  grafana_data: {}

services:
  influxdb:
	# tutum/influxdb 相比influxdb多了web可视化视图。但是该镜像已被标记为已过时
    image: tutum/influxdb:0.9
    restart: always
    environment:
      - PRE_CREATE_DB=cadvisor
    ports:
      - "8083:8083"         # 数据库web可视化页面端口
      - "8086:8086"         # 数据库端口
    volumes:
      - ./data/influxdb:/data

  cadvisor:
    image: google/cadvisor:v0.32.0
    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:
    image: grafana/grafana:8.5.2
    user: '104'
    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
  1. 检查语法
docker-compose config -q
  1. 创建并启动容器
docker-compose up -d

容器启动之后:

  1. 在浏览器打开InfluxDB数据库的页面: http://xxx.xxx.xxx.xxx:8083,使用命令查看当前数据库中的数据库实例:
SHOW DATABASES

查看其中是否自动创建了我们在配置文件中配置的 cadvisor 数据库实例

  1. 在浏览器打开CAdvisor页面:http://xxx.xxx.xxx.xxx8080/,查看当前docker中的cpu、内存、网络IO等统计信息
  2. 在浏览器打开Grafana页面:http://xxx.xxx.xxx.xxx:3000/,默认用户名密码是:admin/admin
6、Grafana配置
添加数据源

Configuration(小齿轮)选项卡中,选择Data Sources,添加一个InfluxDB数据源:

  • name:自定义一个数据源名称,例如InfluxDB

  • Query Language:查询语言,默认InfluxQL即可

  • URL:根据compose中的容器服务名连接,http://influxdb:8086

  • database:我们在InfluxDB中创建的数据库实例,cadvisor

  • User:InfluxDB的默认用户,root

  • Password:root

保存并测试,可以连通即可

添加工作台
  1. Create(加号)选项卡中,选择创建 Dash Board工作台。右上角配置中可以配置创建出来的工作台的标题、文件夹等信息。

  2. 在创建出来的工作台中,选择Add panel中的Add a new panel添加一个新的面板。

    1. 在右上角Time series(时序图)位置可以切换展示的图表样式(柱状图、仪表盘、表格、饼图等等)
    2. 右侧边栏为该图表配置相关信息:标题、描述
    3. 图表下方可以配置该图表展示的数据的查询语句,例如:
      • FROM:cpu_usage_total(Grafana会自动获取InfluxDB数据库中的元数据,可以直接选择对应表名)
      • WHERE:添加一个条件,container_name=cig-cadvisor-1
      • ALIAS:配置一个别名,CPU使用情况汇总

十五、面试题

1、为什么Docker比VM虚拟机要快?
  • Docker有比虚拟机更少的抽象层

    由于Docker不需要虚拟机实现硬件资源虚拟化,运行在Docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存的应用率上Docker更有优势。

  • Docker利用的是宿主机内核,而不需要加载操作系统OS内核

    当新建一个容器时,Docker不需要和虚拟机一样重新加载一个操作系统的内核。进而避免引寻、加载操作系统内核返回等比较费时、费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载OS,返回新建过程是分钟级别的。而Docker由于直接利用宿主机操作系统省略了返回过程,因此新建一个Docker是秒级的。

Docker容器VM虚拟机
操作系统与宿主机共享OS宿主机OS上运行虚拟机OS
存储大小镜像小,便于存储和传输镜像庞大(vmdk、vdi等)
运行性能几乎无额外性能损失操作系统额外的CPU、内存消耗
移植性轻便、灵活、适用于Linux笨重,与虚拟化技术耦合度高
硬件亲和性面向软件开发者面向硬件运维者
部署速度快速,秒级较慢,分钟级
2、谈谈什么是虚悬镜像

仓库名、标签的值都是的镜像称之为虚悬镜像,一般删除,例:

在这里插入图片描述

  • Query Language:查询语言,默认InfluxQL即可

  • URL:根据compose中的容器服务名连接,http://influxdb:8086

  • database:我们在InfluxDB中创建的数据库实例,cadvisor

  • User:InfluxDB的默认用户,root

  • Password:root

保存并测试,可以连通即可

添加工作台
  1. Create(加号)选项卡中,选择创建 Dash Board工作台。右上角配置中可以配置创建出来的工作台的标题、文件夹等信息。

  2. 在创建出来的工作台中,选择Add panel中的Add a new panel添加一个新的面板。

    1. 在右上角Time series(时序图)位置可以切换展示的图表样式(柱状图、仪表盘、表格、饼图等等)
    2. 右侧边栏为该图表配置相关信息:标题、描述
    3. 图表下方可以配置该图表展示的数据的查询语句,例如:
      • FROM:cpu_usage_total(Grafana会自动获取InfluxDB数据库中的元数据,可以直接选择对应表名)
      • WHERE:添加一个条件,container_name=cig-cadvisor-1
      • ALIAS:配置一个别名,CPU使用情况汇总

本文档参考:
1、尚硅谷Docker实战教程(docker教程天花板)
2、云原生开发

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值