Docker

一、安装

1.1本地环境

1.2三要素

1.2.1镜像

Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。它也相当于是一个root文件系统。比如官方镜像 centos:7 就包含了完整的一套 centos:7 最小系统的 root 文件系统。相当于容器的“源代码”,docker镜像文件类似于Java的类模板,而docker容器实例类似于java中new出来的实例对象

1.2.2容器

  1. 从面向对象角度

Docker 利用容器(Container)独立运行的一个或一组应用,应用程序或服务运行在容器里面,容器就类似于一个虚拟化的运行环境,容器是用镜像创建的运行实例。就像是Java中的类和实例对象一样,镜像是静态的定义,容器是镜像运行时的实体。容器为镜像提供了一个标准的和隔离的运行环境,它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台

  1. 从镜像容器角度

可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

1.2.3仓库

仓库(Repository)是集中存放镜像文件的场所。

类似于

Maven仓库,存放各种jar包的地方;

github仓库,存放各种git项目的地方;

Docker公司提供的官方registry被称为Docker Hub,存放各种镜像模板的地方。

仓库分为公开仓库(Public)和私有仓库(Private)两种形式。

最大的公开仓库是 Docker Hub(https://hub.docker.com/)

存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云 、网易云等

1.3安装

1.3.1卸载旧版本

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

1.3.2安装gcc

yum -y install gcc

yum -y install gcc-c++

1.3.3安装需要的软件包

sudo yum install -y yum-utils

1.3.4设置stable镜像仓库

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

1.3.5更新yum软件包索引

yum makecache fast

1.3.6安装DOCKER CE

sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

1.3.7启动容器

sudo systemctl start docker

docker version

1.3.8运行一个hello world镜像

sudo docker run hello-world

1.3.8卸载

systemctl stop docker 
sudo yum remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
rm -rf /var/lib/docker
rm -rf /var/lib/containerd

1.4阿里云镜像加速

直接把下面命令粘贴运行即可

1.5docker run hello-world干了啥

1.6底层原理

  1. docker有着比虚拟机更少的抽象层

由于docker不需要Hypervisor(虚拟机)实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。

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

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

二、Docker的常用命令

2.1帮助启动类命令

启动docker:

 systemctl start docker

停止docker:

systemctl stop docker

重启docker:

systemctl restart docker

查看docker状态:

systemctl status docker

开机启动:

systemctl enable docker

查看docker概要信息:

docker info

查看docker总体帮助文档:

docker --help

查看docker命令帮助文档:

docker 具体命令 --help

2.2镜像命令


docker images

各个选项说明:

REPOSITORY:表示镜像的仓库源

TAG:镜像的标签版本号

IMAGE ID:镜像ID

CREATED:镜像创建时间

SIZE:镜像大小

同一仓库源可以有多个 TAG版本,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。

如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像

-a:列出本地所有镜像(含历史映像层)

-q:只显示镜像ID


docker search 某个XXX镜像名字

查看远程库是否有镜像

--limit : 只列出N个镜像,默认25个

docker search --limit 5 redis

docker pull 某个XXX镜像名字

拉取镜像

docker pull 镜像名字[:TAG]

没有TAG就是最新版


docker system df 查看镜像/容器/数据卷所占的空间

docker rmi 某个XXX镜像名字ID

删除镜像

可以根据名字删除也可以是id

#删除单个
docker rmi  -f 镜像ID
#删除多个
docker rmi -f 镜像名1:TAG 镜像名2:TAG 

删除全部docker rmi -f $(docker images -qa)


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

2.3容器命令

有镜像才能创建容器,先拉取一个ubuntu镜像


新建+启动容器

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
[OPTIONS]

--name="容器新名字" 为容器指定一个名称;

-d: 后台运行容器并返回容器ID,也即启动守护式容器(后台运行);

-i:以交互模式运行容器,通常与 -t 同时使用;

-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;

也即启动交互式容器(前台有伪终端,等待交互);

-P: 随机端口映射,大写P

-p: 指定端口映射,小写p

启动交互式容器(前台命令行)

docker run -it ubuntu /bin/bash

参数说明:

-i: 交互式操作。

-t: 终端。

ubuntu : ubuntu 镜像。

/bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。

要退出终端,直接输入 exit:容器停止,run进去容器,ctrl+p+q退出,容器不停止


列出当前所有正在运行的容器

docker ps [OPTIONS]
OPTIONS说明(常用):
-a :列出当前所有正在运行的容器+历史上运行过的
-l :显示最近创建的容器。
-n:显示最近n个创建的容器。
-q :静默模式,只显示容器编号。

启动已停止运行的容器

docker start 容器ID或者容器名

重启容器

docker restart 容器ID或者容器名

停止容器

docker stop 容器ID或者容器名

强制停止容器

docker kill 容器ID或容器名

删除已停止的容器

docker rm 容器ID

重要

在大部分的场景下,我们希望 docker 的服务是在后台运行的,我们可以过 -d 指定容器的后台运行模式。

docker run -d 容器名

使用镜像centos:latest以后台模式启动一个容器
docker run -d centos
问题:然后docker ps -a 进行查看, 会发现容器已经退出
很重要的要说明的一点: Docker容器后台运行,就必须有一个前台进程.
容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。
这个是docker的机制问题,比如你的web容器,我们以nginx为例,正常情况下,
我们配置启动服务只需要启动响应的service即可。例如service nginx start
但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用,
这样的容器后台启动后,会立即自杀因为他觉得他没事可做了.
所以,最佳的解决方案是,将你要运行的程序以前台进程的形式运行,常见就是命令行模式,表示我还有交互操作,别中断

查看容器日志

docker logs 容器ID

查看容器内运行的进程

docker top 容器ID

查看容器内部细节

docker inspect 容器ID

进入正在运行的容器并以命令行交互

docker exec -it 容器ID bashShell
docker exec -it f0ee24f4d027 /bin/bash

重新进入docker attach 容器ID

区别

  • attach 直接进入容器启动命令的终端,不会启动新的进程用exit退出,会导致容器的停止。

  • exec 是在容器中打开新的终端,并且可以启动新的进程用exit退出,不会导致容器的停止。


从容器内拷贝文件到主机上

docker cp  容器ID:容器内路径 目的主机路径

导入和导出容器

export 导出容器的内容留作为一个tar归档文件[对应import命令]

docker export f0ee24f4d027 > abcd.tar

import 从tar包中的内容创建一个新的文件系统再导入为镜像[对应export]

cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号
cat abcd.tar | docker import - msjava/ubuntu:3.7

三、Docker镜像

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

只有通过这个镜像文件才能生成Docker容器实例(类似Java中new出来一个对象)。

3.1分层的镜像

以我们的pull为例,在下载的过程中我们可以看到docker的镜像好像是在一层一层的在下载

3.2UnionFS(联合文件系统)

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

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

3.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等等。

平时我们安装进虚拟机的CentOS都是好几个G,为什么docker这里才200M

对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

镜像分层最大的一个好处就是共享资源,方便复制迁移,就是为了复用。
比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;
同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
Docker镜像层都是只读的,容器层是可写的
当容器启动时,一个新的可写层被加载到镜像的顶部。
这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”
所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的

3.4Docker镜像commit操作案例

docker commit提交容器副本使之成为一个新的镜像

docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]

例:案例演示ubuntu安装vim

原始的默认Ubuntu镜像是不带着vim命令的

3.4.1进入ubuntu容器安装vim

# 更新包管理工具
apt-get update
# 安装vim
apt-get -y install vim

3.4.2安装完成后,commit我们自己的新镜像

docker commit -m="add vim to ubuntu" -a="majava" 7f24413021d9 msjava/ubuntu:2.0

镜像变大了

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

4.1登录阿里云

进入阿里云容器与镜像服务控制台

选择个人实例

新建命名空间

在创建的命名空间下新建镜像仓库,选择本地仓库

床架安完成,点击管理,获取操作脚本

4.2推送至仓库

从获得的操作脚本中可以看到

根据命令复制粘贴即可

代表推送成功

4.3拉取镜像

五、本地镜像发布到私有库

5.1下载镜像Docker Registry

docker pull registry

相当于本地也有一个docker hub

5.2根据镜像运行容器

docker run -d -p 5000:5000  -v /msjava/myregistry/:/tmp/registry --privileged=true registry

默认情况,仓库被创建在容器的/var/lib/registry目录下,建议自行用容器卷映射,方便于宿主机联调

-d:后台运行
-p 5000:5000:容器端口5000映射到主机端口5000(前主机后容器)

5.3案例演示创建一个新镜像,ubuntu安装ifconfig命令

5.3.1安装命令

apt-get update
apt-get install net-tools

5.3.2commit

docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]

命令:在容器外执行,记得

docker commit -m="ifconfig cmd add" -a="majava" e62cfb09b2fc myubuntu:2.0

5.3.3curl验证私服库上有什么镜像

curl -XGET http://192.168.232.130:5000/v2/_catalog

5.3.4将新镜像修改符合私服规范的Tag

docker tag  镜像:Tag Host:Port/Repository:Tag
docker tag myubuntu:2.0 192.168.232.130:5000/myubuntu:2.0

5.3.5修改配置文件使之支持http

vim /etc/docker/daemon.json

{
  "registry-mirrors": ["https://zw7p1qdg.mirror.aliyuncs.com"],
  "insecure-registries": ["192.168.232.130:5000"]
}

上述理由:docker默认不允许http方式推送镜像,通过配置选项来取消这个限制。====> 修改完后如果不生效,建议重启docker

5.3.6push推送到私服库

docker push 192.168.232.130:5000/myubuntu:2.0

5.3.7curl验证私服库上有什么镜像

curl -XGET http://192.168.232.130:5000/v2/_catalog

5.3.8pull到本地并运行

docker pull 192.168.232.130:5000/myubuntu:2.0

5.3.9验证

六、Docker容器数据卷

5.2中,根据私有库镜像运行容器
docker run -d -p 5000:5000 -v /msjava/myregistry/:/tmp/registry --privileged=true registry
-v 添加自定义的容器卷
:左边是宿主机的路径
:右边是容器内路径
要记得在后面加--privileged=true
默认情况,仓库被创建在容器的/var/lib/registry目录下,建议自行用容器卷映射,方便于宿主机联调

Docker挂载主机目录访问 如果出现cannot open directory .: Permission denied
解决办法:在挂载目录后多加一个--privileged=true参数即可
如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,
在SELinux里面挂载目录被禁止掉了额,如果要开启,我们一般使用--privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即
使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。

6.1是什么

运行一个带有容器卷存储功能的容器实例

 docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录  镜像名

6.2能干嘛

将运用与运行的环境打包镜像,run后形成容器实例运行 ,但是我们对数据的要求希望是持久化的

Docker容器产生的数据,如果不备份,那么当容器实例删除后,容器内的数据自然也就没有了。

为了能保存数据在docker中我们使用卷。

特点:

1:数据卷可在容器之间共享或重用数据

2:卷中的更改可以直接实时生效,爽

3:数据卷中的更改不会包含在镜像的更新中

4:数据卷的生命周期一直持续到没有容器使用它为止

6.3案例

docker run -it --privileged=true -v /tmp/host_data:/tmp/docker_data --name="u1" bc99ed49b67c

在容器目录下新建文件,会同步到主机目录下

反过来也一样,同样修改文件内容也会同步

6.3.1查看数据卷是否挂载成功

docker inspect 容器ID
-v可以有多个

6.3.2读写规则映射添加说明

默认是可读可写

 docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:rw 镜像名

容器内只读

 docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro  镜像名

6.3.3卷的继承和共享

容器1完成和宿主机的映射

docker run -it  --privileged=true -v /mydocker/u:/tmp --name u1 ubuntu

容器2继承容器1的卷规则

docker run -it --privileged=true --volumes-from 父类 --name u2 ubuntu
docker run -it --privileged=true --volumes-from u1 --name u2 bc99ed49b67c

如果u2继承的u1挂了,挂载不会丢失,单纯的继承规则

七、Docker常规软件安装

总体步骤:
搜索镜像、拉取镜像、查看镜像、启动镜像(服务端口映射)、服务端口映射、停止容器、移除容器

7.1安装tomcat

7.1.1docker hub上面查找tomcat镜像

7.1.2从docker hub上拉取tomcat镜像到本地

docker pull tomcat

7.1.3docker images查看是否有拉取到的tomcat

7.1.4使用tomcat镜像创建容器实例(也叫运行镜像)

docker run -it -p 8080:8080 tomcat

7.1.5测试

http://192.168.232.130:8080/

出现404

可能1:没有映射端口,没有关闭防火墙
可能2:把webapps.dist目录换成webapps

说明

docker pull billygoo/tomcat8-jdk8
docker run -d -p 8080:8080 --name mytomcat8 billygoo/tomcat8-jdk8

7.2安装mysql

7.2.1拉取镜像

docker pull mysql:5.7

7.2.2创建容器

命令

docker run -p 3388:3306 --name="some-mysql" -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

同时可以用navicat连接

存在问题:插入中文报错
容器停止或删除,数据丢失

7.2.3实战版

7.2.3.1新建实例
docker run -d -p 3399:3306 --privileged=true -v /msdocker/mysql/log:/var/log/mysql -v /msdocker/mysql/data:/var/lib/mysql -v /msdocker/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456  --name mysql mysql:5.7
7.2.3.2新建my.cnf

通过容器卷同步给mysql容器实例

[client]
default_character_set=utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8
7.2.3.3重新启动mysql容器实例再重新进入并查看字符编码
即使删除容器,由于数据卷挂载,数据不会丢失

7.3安装redis

7.3.1拉取镜像

docker pull redis:6.0.8

7.3.2创建容器

7.3.3测试

7.3.4实战

7.3.4.1宿主机中新建一个redis.conf

从其他地方拷贝过来

拷贝过来的配置文件对应redis的版本最好和你拉取的一致,否则容器可能创建不起来
7.3.4.2创建容器
docker run  -p 6399:6379 --name myredis --privileged=true -v /msdocker/redis/redis.conf:/etc/redis/redis.conf -v /msdocker/redis/data:/data -d redis:6.2.1 redis-server /etc/redis/redis.conf

八、安装mysql主从复制

8.1新建主服务器容器实例

docker run -d -p 3399:3306 --privileged=true -v /msdocker/mysql/mysql-master/log:/var/log/mysql -v /msdocker/mysql/mysql-master/data:/var/lib/mysql -v /msdocker/mysql/mysql-master/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456  --name mysql-master mysql:5.7

8.2进入主机的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

8.3重启master实例并进入,创建同步用户

docker restart mysql-master

docker exec -it mysql-master /bin/bash

创建同步用户

mysql -uroot -p

CREATE USER 'slave'@'%' IDENTIFIED BY '123456';

GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';

8.4新建从服务器实例

docker run -d -p 3377:3306 --privileged=true -v /msdocker/mysql/mysql-slave/log:/var/log/mysql -v /msdocker/mysql/mysql-slave/data:/var/lib/mysql -v /msdocker/mysql/mysql-slave/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456  --name mysql-slave mysql:5.7

8.5进入主机的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.6重启slave实例

docker restart mysql-slave

8.7进入主机实例的MySQL,查看同步状态

show master status;

8.8进入从实例配置主从复制

docker exec -it mysql-slave /bin/bash

mysql -uroot -p
change master to master_host='宿主机ip', master_user='slave', master_password='123456', master_port=3307, master_log_file='mall-mysql-bin.000001', master_log_pos=617, master_connect_retry=30;
master_host:主数据库的IP地址;
master_port:主数据库的运行端口;
master_user:在主数据库创建的用于同步数据的用户账号;
master_password:在主数据库创建的用于同步数据的用户密码;
master_log_file:指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取File参数;
master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position参数;
master_connect_retry:连接失败重试的时间间隔,单位为秒。

8.9从数据库中查看主从同步状态

show slave status \G

8.10从数据库中开启主从同步

start slave;
我这里第一个Slave_IO_Running:no
1、关闭防火墙
2、配置文件那个server-id不要和你主机上的重复
然后:stop slave; reset slave; start slave;

8.11测试

8.11.1主机创建库表,插入数据

8.11.2从机读取数据

九、分布式存储中的一些算法

9.1哈希取余算法

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

优点:

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

缺点:

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

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

9.2一致性哈希算法

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

9.2.1三大步骤

9.2.1.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环。

9.2.1.2服务器IP节点映射

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

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

9.2.1.3key落到服务器的落键规则

当我们需要存储一个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上。

9.2.3优缺点

容错性

假设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算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题,

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

9.3哈希槽分区

1 为什么出现

有效解决一致性哈希算法的数据倾斜问题

哈希槽实质就是一个数组,数组[0,2^14 -1]形成hash slot空间。

2 能干什么

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

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

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

3 多少个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上

十、使用docker搭建Redis3主3从

关闭防火墙

10.1新建6个docker容器redis实例

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

效果

10.2进入容器并为6台机器构建集群关系

# 随便就进入哪个
docker exec -it redis-node-1 /bin/bash
# 注意,进入docker容器后才能执行一下命令,且注意自己的真实IP地址
redis-cli --cluster create 192.168.232.130:6381 192.168.232.130:6382 192.168.232.130:6383 192.168.232.130:6384 192.168.232.130:6385 192.168.232.130:6386 --cluster-replicas 1

--cluster-replicas 1 表示为每个master创建一个slave节点

10.3链接进入6381作为切入点,查看集群状态

10.4主从容错切换迁移案例

10.4.1数据读写存储

进入redis-node-1容器[6381]

redis-cli -p 6381操作Redis存在的问题

插入数据可能失败,可能成功,因为对于key计算出的slot可能查出6381所对应的slot范围

所以使用redis-cli -p 6381 -c

查看集群状态

redis-cli --cluster check 192.168.232.130:6381

10.4.2容错切换迁移

停掉作为主机的6381,看其从机6386是否上位成为master

进入一个活着的容器,查看redis集群状态

如果6381从新启动,那么它将作为6386的从机

若要还原为以前的状态,启动6381之后,过会停掉6386,过会再启动6386

10.5主从扩容案例

10.5.1新建6387、6388两个节点

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

10.5.2将新增的6387节点(空槽号)作为master节点加入原集群

redis-cli --cluster add-node 192.168.232.130:6387 192.168.232.130:6381
6387 就是将要作为master新增节点
6381 就是原来集群节点里面的领路人,相当于6387拜拜6381的码头从而找到组织加入集群

第一次检查集群状态

redis-cli --cluster check 192.168.232.130:6381

10.5.3重新分派槽号

redis-cli --cluster reshard 192.168.232.130:6381

第二次检查集群状态

redis-cli --cluster check 192.168.232.130:6381

为什么6387是3个新的区间,以前的还是连续?

重新分配成本太高,所以前3家各自匀出来一部分,从6381/6382/6383三个旧节点分别匀出1364个坑位给新节点6387

10.5.4为主节点6387分配从节点6388

命令:redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID
redis-cli --cluster add-node 192.168.232.130:6388 192.168.232.130:6387 --cluster-slave --cluster-master-id 0b7886b2866bf8320bd074e8a147554d40391c9a
-------这个是6387的编号,按照自己实际情况
redis-cli --cluster add-node 192.168.232.130:6388 192.168.232.130:6387 --cluster-slave --cluster-master-id 0b7886b2866bf8320bd074e8a147554d40391c9a

第三次检查集群状态

redis-cli --cluster check 192.168.232.130:6381

10.6主从缩容案例

10.6.1将6388删除从集群中将4号从节点6388删除

redis-cli --cluster del-node 192.168.232.130:6388 42fa651e7955f25f2b24485678e7685ed8897e2a

检查集群状态

redis-cli --cluster check 192.168.232.130:6381

10.6.2将6387的槽号清空,重新分配,本例将清出来的槽号都给6381

redis-cli --cluster reshard 192.168.232.130:6381

检查集群状态

redis-cli --cluster check 192.168.232.130:6381

10.6.3将6387删除

redis-cli --cluster del-node 192.168.232.130:6387 0b7886b2866bf8320bd074e8a147554d40391c9a

查看集群情况

redis-cli --cluster check 192.168.232.130:6381

十一、DockerFile解析

11.1简介

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

官网

11.2构建三步骤

  1. 编写Dockerfile文件

  1. docker build命令构建镜像

  1. docker run依镜像运行容器实例

11.3DockerFile构建过程解析

11.3.1Dockerfile内容基础知识

  1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数

  1. 指令按照从上到下,顺序执行

  1. #表示注释

  1. 每条指令都会创建一个新的镜像层并对镜像进行提交

11.3.2Docker执行Dockerfile的大致流程

(1)docker从基础镜像运行一个容器

(2)执行一条指令并对容器作出修改

(3)执行类似docker commit的操作提交一个新的镜像层

(4)docker再基于刚提交的镜像运行一个新容器

(5)执行dockerfile中的下一条指令直到所有指令都执行完成

11.4DockerFile保留字简介

11.4.1FROM

基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是from

11.4.2MAINTAINER

镜像维护者的姓名和邮箱地址

11.4.3RUN

容器构建时需要运行的命令

两种格式

(1)shell格式

RUN yum -y install vim

(2)exec格式

RUN是在 docker build时运行

11.4.4EXPOSE

当前容器对外暴露出的端口

11.4.5WORKDIR

指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点

11.4.6USER

指定该镜像以什么样的用户去执行,如果都不指定,默认是root

11.4.7ENV

用来在构建镜像过程中设置环境变量

ENV MY_PATH /usr/mytest
这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;
也可以在其它指令中直接使用这些环境变量,

比如:WORKDIR $MY_PATH

11.4.8ADD

将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包

11.4.9COPY

类似ADD,拷贝文件和目录到镜像中。

将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置

COPY src dest
COPY ["src", "dest"]
<src源路径>:源文件或者源目录
<dest目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

11.4.10VOLUME

容器数据卷,用于数据保存和持久化工作

11.4.11CMD

指定容器启动后的要干的事情

Dockerfile 中可以有多个 CMD 指令, 但只有最后一个生效,CMD 会被 docker run 之后的参数替换

和RUN的区别

CMD是在docker run 时运行。

RUN是在 docker build时运行。

11.4.12ENTRYPOINT

也是用来指定一个容器启动时要运行的命令

类似于 CMD 指令,但是ENTRYPOINT不会被docker run后面的命令覆盖, 而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序

命令格式和案例说明

优点:在执行docker run的时候可以指定 ENTRYPOINT 运行所需的参数。

注意
如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

11.5案例

Centos7镜像具备vim+ifconfig+jdk8

准备一个linux下的java8官网

docker拉取一个centos7的镜像

11.5.1编写Dockerfile文件

vim Dockerfile

FROM centos:7
MAINTAINER majava<1822172305@qq.com>
 
ENV MYPATH /usr/local
WORKDIR $MYPATH
 
#安装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-8u361-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置
ADD jdk-8u361-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_361
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

11.5.2构建

docker build -t 新镜像名字:TAG .

docker build -t centosjava8:1.5 .

11.5.3验证

11.6虚悬镜像

仓库名、标签都是<none>的镜像,俗称dangling image
# 查看
docker image ls -f dangling=true
# 删除
docker image prune

十二、Docker微服务实战

12.1将springboot项目打包

打包结束上传到linux

12.2编写Dockerfile

# 基础镜像使用java,这是一个dockerhub中的一个java8镜像
FROM openwhisk/java8action
# 作者
MAINTAINER msjava
# VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
# 将jar包添加到容器中并更名为msjava_docker.jar
ADD service-ucenter-0.0.1-SNAPSHOT.jar msjava_docker.jar
# 运行jar包
RUN bash -c 'touch /msjava_docker.jar'
ENTRYPOINT ["java","-jar","/msjava_docker.jar"]
#暴露8160端口作为微服务
EXPOSE 8160

12.3创建镜像

docker build -t msjava_docker:1.6 .

12.4创建容器测试

docker run -d -p 8160:8160 0a5c9bfcc628

访问我的项目的swagger页面

十三、Docker网络

docker容器启动后,会产生一个docker0的虚拟网桥

默认会创建三个网络模式

13.1常用命令

13.2能干嘛

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

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

13.3网络模式

bridge模式:使用--network bridge指定,默认使用docker0
host模式:使用--network host指定
none模式:使用--network none指定
container模式:使用--network container:NAME或者容器ID指定

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

以ubuntu新建两个容器

docker run -it --name u1 ubuntu bash
docker run -it --name u2 ubuntu bash

查看容器详情

关闭u2新建u3

docker容器内部的ip是有可能会发生改变的

13.3.2bridge模式

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

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

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,成对匹配。

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

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

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

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

13.3.3host模式

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

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

问题:
docke启动时总是遇见标题中的警告
原因:
docker启动时指定--network=host或-net=host,如果还指定了-p映射端口,那这个时候就会有此警告,
并且通过-p设置的参数将不会起到任何作用,端口号会以主机端口号为主,重复时则递增。
直接取消配置端口映射即可消除警告

host模式没有自己的ip

那没有ip,且没有端口映射,如何访问呢

http://宿主机IP:8080/

在CentOS里面用默认的火狐浏览器访问容器内的tomcat83看到访问成功,因为此时容器的IP借用主机的,

所以容器共享宿主机网络IP,这样的好处是外部主机与容器可以直接通信。

13.3.4none模式

在none模式下,并不为Docker容器进行任何网络配置。

也就是说,这个Docker容器没有网卡、IP、路由等信息,只有一个lo

需要我们自己为Docker容器添加网卡、配置IP等。

禁用网络功能,只有lo标识(就是127.0.0.1表示本地回环)

13.3.5container模式

container⽹络模式

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

docker run -d -p 8085:8080 --name tomcat85 tomcat

docker run -d -p 8085:8080 --network container:tomcat85 --name tomcat86 tomcat

报错

相当于tomcat86和tomcat85公用同一个ip同一个端口,导致端口冲突

换一个镜像

13.3.6自定义网络模式

13.3.6.1没有自定义之前

新建两个带ifconfig命令的ubuntu容器

docker run -it --name ubuntu1 bc99ed49b67c bash
docker run -it --name ubuntu2 bc99ed49b67c bash

它们的ip分别是172.17.0.2、172.17.0.3

现在我用ping命令,从一个容器ping向另一个容器,通过ip是可以ping通的

但是要是根据容器的名字去ping的话就会报错

由于ip是会变化的,所有就要想办法让它通过容器名ping通

13.3.6.2自定义网络模式

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

docker run -it --name ubuntu1 --network my_network bc99ed49b67c bash
docker run -it --name ubuntu2 --network my_network bc99ed49b67c bash

这样就完事了

十四、Docker-compose容器编排

14.1是什么

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

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

14.2安装下载

官网文档

下载链接

此处安转的单机版

curl -SL https://github.com/docker/compose/releases/download/v2.17.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

测试安装成功

docker compose version

14.3Compose核心概念

14.3.1一文件

docker-compose.yml

14.3.2两要素

  1. 服务(service):一个个应用容器实例,比如订单微服务、库存微服务、mysql容器、nginx容器或者redis容器

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

14.4Compose使用的三个步骤

  1. 编写Dockerfile定义各个微服务应用并构建出对应的镜像文件

  1. 使用 docker-compose.yml 定义一个完整业务单元,安排好整体应用中的各个容器服务。

  1. 最后,执行docker-compose up命令 来启动并运行整个应用程序,完成一键部署上线

14.5常用命令

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 # 停止服务

14.6微服务实战

可参考前面十二章
如果不使用服务编排存在的问题
先后顺序要求固定,先mysql+redis才能微服务访问成功
多个run命令......
容器间的启停或宕机,有可能导致IP地址对应的容器实例变化,映射出错, 要么生产IP写死(可以但是不推荐),要么通过服务调用

使用Compose

14.6.1编写docker-compose.yml文件

version: "3"
 
services:
  microService:
    image: msjava_docker:1.7
    container_name: service_ucenter
    ports:
      - "8160:8160"
    volumes:
      - /msdocker/district/microService:/data
    networks: 
      - my_net 
    depends_on: 
      - redis
      - mysql
 
  redis:
    image: redis:6.2.1
    ports:
      - "6388:6379"
    volumes:
      - /msdocker/district/redis/redis.conf:/etc/redis/redis.conf
      - /msdocker/district/redis/data:/data
    networks: 
      - my_net
    command: redis-server /etc/redis/redis.conf
 
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: '123456'
      MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
      MYSQL_USER: 'msjava'
      MYSQL_PASSWORD: '123456'
    ports:
       - "3388:3306"
    volumes:
       - /msdocker/district/mysql/db:/var/lib/mysql
       - /msdocker/district/mysql/conf/my.cnf:/etc/my.cnf
       - /msdocker/district/mysql/init:/docker-entrypoint-initdb.d
    networks:
      - my_net
    command: --default-authentication-plugin=mysql_native_password #解决外部无法访问
 
networks: 
   my_net: 
 

14.6.2修改springboot工程重新打包

14.6.3编写Dockerfile

FROM java8
# 作者
MAINTAINER msjava
# VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
# 将jar包添加到容器中并更名为msjava_docker.jar
ADD service-ucenter-0.0.1-SNAPSHOT.jar msjava_docker.jar
# 运行jar包
RUN bash -c 'touch /msjava_docker.jar'
ENTRYPOINT ["java","-jar","/msjava_docker.jar"]
#暴露8160端口作为微服务
EXPOSE 8160

14.6.4创建镜像

docker build -t msjava_docker:1.8 .

14.6.5执行 docker-compose up或者执行 docker-compose up -d

docker-compose up
docker-compose up -d

14.6.6关停

docker-compase stop

十五、Docker轻量级可视化工具Portainer

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

官网

下载

15.1安装

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

15.2使用

第一次登录需创建admin,访问地址:xxx.xxx.xxx.xxx:9000

选择local,进行连接

stacks代表compose编排的个数

15.3用其安装nginx

15.4docker启动则Portainer也启动

安装命令中关注--restart=always

十六、Docker容器监控之CAdvisor+InfluxDB+Granfana

16.1是什么

CAdvisor监控收集+InfluxDB存储数据+Granfana展示图表

16.2在compose容器编排中的应用

16.2.1新建docker-compose.yml

version: '3.1'
 
volumes:
  grafana_data: {}
 
services:
 influxdb:
  image: tutum/influxdb:0.9
  restart: always
  environment:
    - PRE_CREATE_DB=cadvisor
  ports:
    - "8083:8083"
    - "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
  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
    - INFLUXDB_NAME=cadvisor
    - INFLUXDB_USER=root
    - INFLUXDB_PASS=root

16.2.2启动

docker-compose up
docker-compose up -d

16.2.3测试

浏览cAdvisor收集服务,http://ip:8080/

浏览influxdb存储服务,http://ip:8083/

浏览grafana展现服务,http://ip:3000

admin,admin

16.2.4配置步骤

16.2.4.1配置数据源
16.2.4.2配置面板panel

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值