0


Docker学习笔记

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

Docker本身是一个容器运行载体或称之为管理引擎。我们把引用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就是image镜像文件。只有通过这个镜像文件才能生成Docker容器实例(类似Java中new出来的一个对象).

image文件可以看作是容器的模板,Docker根据image文件生成容器的实例,同一个image文件,可以生成多个同时运行的容器实例。

比较Docker和传统虚拟化方式的不同之处:

1.传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需要应用进程;

2.容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便;

3.每个容器之间互相隔离,每个容器有自己的文件系统,容器之间进程不会相互影响,能区分计算资源

Docker三要素:镜像,容器,仓库

镜像文件:image文件生成的容器实例,本身也是一个文件,称为镜像文件

容器实例:一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例,也就是我们的容器。

仓库:就是防一堆镜像的地方,我们可以把镜像发布到仓库中,需要的时候再从仓库中拉下来就可以了

一、

Docker安装

Install Docker Engine on CentOS | Docker Documentation

 yum install -y yum-utils

2.设置stable镜像仓库

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

3.更新yum软件包索引

yum makecache fast

4.安装docker引擎

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

5.启动docker

systemctl start docker

6.helloworld

docker run hello-world

安装成功:

(1)卸载docker

yum remove docker-ce docker-ce-cli containerd.io docker-compose-plugin

rm -rf /var/lib/docker
rm -rf/var/lib/containerd

(2)停止docker服务

systemctl stop docker

二、阿里云镜像加速器

注册阿里云开放云原生应用-云原生(Cloud Native)-云原生介绍 - 阿里云

控制台->弹性 计算

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://n3twaq8i.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

三.Docker常用命令

1.帮助启动类命令:

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

2.镜像命令

  1. 列出本地主机上的镜像:docker images (-a:列出本地所有镜像;-q:只显示镜像ID)

      (1)REPOSITORY:表示镜像的仓库源
    
    (2)TAG:镜像的标签版本号
    
      (3)IMAGE ID :镜像ID
    
      (4):CREATED:镜像创建时间
    
     (5)SIZE:镜像大小
    
  2. 查询远程仓库镜像:docker search 镜像名字 (-limit :只列出N个镜像。默认25个)

3.下载镜像:docker pull 镜像名字 [:tag] (版本号,默认最新版本)

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

5.删除镜像:docker rmi 镜像名字

    删除单个:docekr rmi -f 镜像ID

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

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

谈谈docker虚悬镜像是什么?

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

3.容器命令

    OPTIONS:

            (1)   --name="容器新名字" :为容器指定一个名称

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

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

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

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

          (5)-P : 随机端口映射,大写P;

            (6)  -p : 指定端口映射,小写p;

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

解决:

[root@localhost root123]# docker run -it ubuntu /bin/bash
WARNING: IPv4 forwarding is disabled. Networking will not work.

2.列出当前正在运行的容器:docker ps [OPTIONS]

OPTIONS:

    (1) -a : 列出当前所有正在运行的容器 + 历史上运行过的

    (2) -l : 显示最近创建的容器

    (3) -n : 显示最近n个创建的容器

    (4) -q : 静默模式,只显示容器编号

3.退出容器:

(1)exit : run进去容器,exit退出,容器停止;

(2)ctrl+p+q :run进去容器,ctrl+p+q退出,容器不停止;

** 4.启动已经停止运行的容器:docker start 容器ID或容器名**

** 5.重启容器:docker restart 容器ID或容器名**

** 6.停止容器:docker stop 容器Id或容器名**

** 7.强制停止容器:docker kill 容器ID或容器名**

** 8.删除已经停止的容器:docker rm 容器ID ;docker rmi 镜像 **

** -f: 强制删除 **

** 一次性删除多个容器实例:慎用!!!**

** (1):docker rm -f $(docker ps -a -q)**

** (2):docker ps -a -q | xargs docker rm**

-d的讲解:

** #使用镜像centos:latest 以后台模式启动一个容器 docker run -d centos**

问题:然后docker ps -a 进行查看,会发现容器已经退出

** **很重要的要说明一点:docker容器后台运行,就必须有一个前台进程

容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出。

这是docker的机制问题,比如你的web容器,我们以nginx为例,正常情况下,我们配置启动服务只需要启动响应的service即可,例如service nginx start ,但是,这样做nginx为后台进程模式运行,就导致docker前台没有运行的应用,这样的容器后台启动后,就会自杀因为他觉得他没有事可做,所以,最佳的解决方案式是,将你要运行的程序以前台进程的形式运行,常见就是命令行模式,表示我还有工作,别中端

运行redis 6.0.8

  1. 前台运行redis :docker run -it redis:6.0.8
  2. 后台运行redis:docker run -d reids:6.0.8
  3. 查看日志:docker logs 容器ID
  4. 查看容器内运行的进程:docker top 容器ID
  5. 查看容器内部细节:docker inspect 容器ID
  6. 进入正在运行的容器: 1. docker exec -it 容器ID bashShell2. 重新进入: docker attach 容器ID3. 上述两个区别: 1. attach 直接进入容器启动命令的终端,不会启动新的进程。用exit退出,会导致容器的停止;2. exec是在容器中打开新的终端,并且可以启动新的进程。用exit退出,不会导致容器的停止。3. 推荐使用docker exec 命令,因为退出容器终端,不会导致容器的停止。

7.从容器内拷贝文件到主机:docker cp 容器ID:容器内路径 目的主机路径

8.导入和导出容器:

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

    (2)import 从tar 包中的内容创建一个新的文件系统在导入为镜像

    案例:

            (1)docker export 容器ID > 文件名.tar

            (2)cat 文件名.tar | docker import -镜像用户/镜像名:镜像版本号

四、Docker镜像

1.什么是镜像:

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

2.UnionFS(联合文件系统):

    Union文件系统是一种分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交 一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。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,在bootfs之上,包含的就是典型的Linux系统中的/dev,/proc/bin/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等待。

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

4.为什么Docker镜像采用这种分层结构呢

    镜像分层最大的一个好处就是共享资源,方便复制迁移,就是为了复用。

    比如说有多个镜像都从相同的base镜像构建而来,那么Docker Host只需要在磁盘上保存一份base镜像;同时内存也只需要加载一份base镜像,就可以为所有容器服务了,而且镜像的每一层都可以被共享。

Docker镜像层都只是只读的,容器层是可写的;当容器启动时,一个新的可写容器被加载到镜像的顶部,这层通常被称作 ”容器层“,容器层之下的都叫”镜像层“;所有对容器的改动-无论添加删除,还是修改文件都只发生在容器层,只有容器层是可写的,容器层下面的所有镜像层都是只读的。

** 5.docker 的commit 案例 提交生成一个新的镜像**

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

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

案例演示ubuntu安装vim

   1)apt-get update
    2)apt-get -y install vim

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

1.进入阿里云>控制台>弹性镜像容器服务>个人

2.创建镜像仓库>本地仓库>进入管理界面获得脚本

3.将镜像推送到阿里云registry

$ docker login --username=aliyun4214424794 registry.cn-hangzhou.aliyuncs.com$ docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/sutdy_docker/myubuntu1.3:[镜像版本号]$ docker push registry.cn-hangzhou.aliyuncs.com/sutdy_docker/myubuntu1.3:[镜像版本号]

4.将阿里云的镜像拉取到本地

六.本地镜像发布到私有库

1.下载镜像Docker Registry : docker pull registry

2.运行私有库有Registry ,相当于本地有个私有Docker hub :

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

3.ubuntu安装ifconfig功能

    (1) apt-get update

    (2)apt-get install net-tools
     (3)安装完成后,commit我们的新镜像:

                    docker commit -m="ifconfig cmd add" -a="zcl" 6ae9dccbc190 zclubuntu:1.2

4.curl验证私服库上有什么镜像: curl -XGET http://192.168.238.80:5000/v2/_catalog

5.将新镜像zclubuntu1.2修改符合规范的Tag: docker tag 镜像:TAG Host:Port/Repository:Tag

6.修改配置文件使之支持http

    (1) vim /etc/docker/daemon.json

    (2)配置文件中新增:别忘记”  , “![](https://img-blog.csdnimg.cn/dcb631a8e4034433a7f80dedc32844f5.png)

  (3)重启docker : systemctl restart docker

    (4)开启本地私服库:

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

7.push推送到私服库:docker push 192.168.238.80:5000/zclubuntu:1.2

8.curl验证私服库上有什么镜像: curl -XGET http://192.168.238.80:5000/v2/_catalog

9.pull到本地并运行: docker pull 192.168.238.80:5000/zclubuntu:1.2

七.Docker容器卷

Docker挂载主机目录访问如果出现cannot open dircctory.:Permission denied

解决方法:挂载目录后多加一个-privileged=true 参数即可

7.1.docker容器卷是什么:有点类似我们redis里面的rdb和aof文件 ;将docker容器内的数据保存进宿主机的磁盘中。

卷就是目录或文件。存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持久化存储或共享数据的特性;

    卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷;

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

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

7.2.能干什么:将运用与运行的环境打包镜像,run后形成实例运行,但是我们对数据的要求时持久化的。

    docker容器产生的数据,如果不备份,那么当容器实例删除后,容器内地数据自然就没有了。为了能保存数据在docker中我们使用卷。

    特点:        
  1. 数据卷可在容器之间共享重用数据
  2. 卷中的更改可以直接实例时生效
  3. 数据卷中的更改不会包含在镜像的更新中
  4. 数据卷的生命周期一直持续待没有容器使用它为止

7.3.读写规则映射添加:

    (1)读写(默认):                          

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

     (2)只读:容器实例内部被限制,只能读取不能写:

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

**7.4.卷的继承和共享 **

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

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

八.Docker常规安装

1.安装Tomcat:

    (1)Docker Hub 上面查找tomcat镜像
docker search tomcat
    (2)从docker hub 上拉取tomcat镜像到本地
docker pull tomcat
  (3)查看是否有拉取到tomcat
docker images
     (4)使用tomcat镜像创建容器实例(也叫运行镜像):

    -p小写:主机端口号:docker容器端口    ; -P大写:随机分配端口

    -i:交互    ;    t:终端    ;   -d:后台
docker run -it -p 8080:8080 tomcat
    (5)访问猫主页

            问题报404!!!

    解决:1.可能没有映射端口或者关闭防火墙

               2. (1)进入tomcat容器中,删除webapps: rm -r webapps

                   (2)将webapps.dist 改名替换成webapps : mv webapps.dist webapps 

             (6)免修改版:docker pull billygoo/tomcat8-jdk8

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

安装成功



** 2.安装mysql**

** 简易版的运行:(存在中文乱码问题,以及数据备份问题)**

** **(1)Docker Hub 上面查找mysql镜像:docker search mysql

    (2)从docker hub上(阿里云加速器)拉取MySQL镜像到本地 标签为5.7 :

             docker pull mysql:6.7

    (3)使用mysql5.7镜像创建容器(也叫运行镜像):
docker run -p 3306:3306 --name some-mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:tag
    (4)进入mysql :docker exec -it  > 进入mysql  密码:123456 ![](https://img-blog.csdnimg.cn/b8267428559c4e25af7cc136e97c8055.png)         (5)使用mysql

(6)使用navicat连接mysql

1)插入中文会报错

2)修正字符集编码:SHOW VARIABLES LIKE 'character%'

** 实战版:解决简易版存在的问题**

一.乱码

** 1.**

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

    2.新建my.conf ,通过容器卷同步给mysql容器实例,解决中文乱码问题
[client]
default_character_set=utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8
    3.重新启动mysql容器实例再重新进入并查看字符编码 : docker restart mysql

     乱码解决成功!!!

二.数据库被删除数据恢复

    在这已经配置了容器数据卷,当容器重新启动时,数据会从容器卷中重新读取达到数据备份的作用![](https://img-blog.csdnimg.cn/99c9f319651445e383d5cd213e260ce7.png)

数据依旧可以读取

3.安装Redis

    (1)在centos宿主机下新建目录/app/redis: mkdir -p /app/redis

    (2)将一个redis.conf文件模板拷贝到/app/redis目录下

    (3)修改redis.conf配置

            将bind注解掉,允许redis外地连接

            ![](https://img-blog.csdnimg.cn/94320927f6394dfea285c86a45c94847.png)

            daemonize 改为no 或注释起来,因为该配置和docker run 中 -d 参数冲突,会导致容器一直启动失败

            ![](https://img-blog.csdnimg.cn/5a9ed297481f418abeb92e93a860c938.png)

     (3)启动redis镜像

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

九.高级学习

1.docker复杂安装

** 1.mysql主从复制原理:**

            (1)新建主服务器容器实例3307        

          
docker run -p 3307:3306 --name mysql-master -v /mydata/mysql-master/log:/var/log/mysql -v /mydata/mysql-master/data:/var/lib/mysql -v /mydata/mysql-master/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
            (2)进入/mydata/mysql-master/conf目录下新建my.cnf
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=1
## 指定不需要同步的数据库名称
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 mysql-master
            (4)进入mysql-master容器
docker exec -it mysql-master /bin/bash
mysql -uroot -proot
            (5)master容器实例内创建数据同步用户
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'slave'@'%';
            (6)创建从服务器容器实例3308
docker run -p 3308:3306 --name mysql-slave -v /mydata/mysql-slave /log:/var/log/mysql -v /mydata/mysql-slave /data:/var/lib/mysql -v /mydata/mysql-slave /conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
            (7)进入/mydata/mysql-slave/conf目录下新建my.cnf
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=2
## 指定不需要同步的数据库名称
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 mysql-slave
            (9)在主数据库中查看主从同步状态
show master status;
            (10)进入mysql-slave容器
docker exec -it mysql-slave /bin/bash
mysql -uroot -p
            (11)在从数据库中配置主从复制

·主从复制命令参数说明
master_host:主数据库的IP地址;
master_port:主数据库的运行端口;
master_user:在主数据库创建的用于同步数据的用户账号;
master_password:在主数据库创建的用于同步数据的用户密码;
master_log_file:指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取File参数;
master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position参数;
master_connect_retry:连接失败重试的时间间隔,单位为秒。

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;
            (12)在从数据库中查看主从同步状态
show slave status \G;

             (13)在从数据库中开启主从同步
start slave;
            (14)查看从数据库状态发现已经同步
show slave status \G;

             (15)主从复制测试:主机新建库-使用库-新建表-插入数据,

                                                    从机使用库-查看记录

                   master:

            ![](https://img-blog.csdnimg.cn/06cfa26ec1b7432c93f0756d80338ba0.png)

    slave:

    ![](https://img-blog.csdnimg.cn/c5e5cd39d47f4268bc57e5d9cf3c6702.png)


** 2.安装redis集群**

面试题:1~2亿条数据需要缓存,请问如何设计这个存储案例

** 回答:单机单台100%不可能,肯定是分布式存储。有三种方式**

** 1.哈希取余分区**

** 2亿条记录就是2亿个k,v,我们单机不行必须要分布式多机,假设有三台机器构成一个集群,用户每次读写操作都是根据公式hash(key)%N个机器个数,计算出哈希值,用来决定数据映射到哪一个节点上。**

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

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

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

** 2.一致性哈希算法分区**

** 当服务器个数发生变动时,尽量减少影响客户端到服务器的映射关系。将所有的存储节点排列在收尾相接的Hash环上,每个key在计算Hash后会顺时针找到临界的存储点存放。而当有节点加入或退出时仅影响该节点在Hash环上顺时针相邻的后续节点。三个步骤: 算法构建一致性哈希环;服务器IP节点映射;key落到服务器的落键规则 .**

** 优点:加入和删除节点只影响哈希环中顺时针方向的相邻的节点,对其他节点无影响。**

** 缺点:数据的分布和节点的位置有关,因为这些节点不是均匀的分布在哈希环上的,所以数据在进行存储时达不到均匀分布的效果。**

** 3.哈希槽分区(常用)**

** 哈希槽实质就是一个数组,数组【0~2^14-1】形成的hash slot 空间。解决均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽,用于管理数据和节点之间的关系。现在就相当于节点上方的就是槽,槽里面放的是数据。**



**三主三从redis集群扩缩容配置案例 **

** **1.关闭防火墙+启动docker后台服务

    2.新建6个docker容器实例   --net hsot :使用宿主机的IP和端口,默认;--privileged=true :获取宿主机root用户权限 ;--cluster-enable yes : 开启redis集群  --appendonly yes :开启持久化
docker run -d --name redis-node-1 --net host --privileged=true -v /data/redis/share/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 /data/redis/share/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 /data/redis/share/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 /data/redis/share/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 /data/redis/share/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 /data/redis/share/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386
     3.进入容器redis-node-1并为6台机器构建集群关系

            (1)进入容器
docker exec -it redis-node-1 /bin/bash
            (2)构建主从关系  --cluster-replicas 1 :表示为每个master构建一个slave节点
redis-cli --cluster create 192.168.238.80:6381 192.168.238.80:6382 192.168.238.80:6383 192.168.238.80:6384 192.168.238.80:6385 192.168.238.80:6386 --cluster-replicas 1
    ![](https://img-blog.csdnimg.cn/204263cbf3f644198f37363b1d08e54c.png)

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



主从容错切换迁移案例

** 数据读取存储**

** · **启动6机构成的集群并通过exec进入

           **·** 对6381新增两个key :以单机的方式启动redis

           **` **防止路由失效加参数-c并新增key : 加 -c :表示以集群的方式启动redis

             ![](https://img-blog.csdnimg.cn/f2d005cc73334772a0ff9e5f7db139ad.png)

             **`**检查集群信息: redis-cli --cluster check 192.168.238.80:6381

            ![](https://img-blog.csdnimg.cn/b88c1eb4e4de4f1999674c9318b4a624.png)

** 容错切换迁移**

    **        ·**主6381和从机切换,先停止主机6381

** ·**再次查看集群信息 (哨兵模式:反客为主的自动版)

** ·**先还原之前的3主3从

                    1.先启动6381    docker start redis-node-1  (6381恢复后成为了6385的slaver )![](https://img-blog.csdnimg.cn/fe912d6f2412493c90d4a9e8df6d6b38.png)

                    2.再停6385   docker stop redis-node-5        

                    3.再重新启动6385 :  docker start redis-node-5 

** ·**查看集群状态

** 主从扩容案例**

  1. 新建6387,6388两个节点+新建后启动+查看是否有8节点docker run -d --name redis-node-7 --net host --privileged=true -v /data/redis/share/redis-node-7:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6387docker run -d --name redis-node-8 --net host --privileged=true -v /data/redis/share/redis-node-8:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388
  2. 进入6387容器实例内部 :docker exec -it redis-node-7 /bin/bash
  3. 将新增的6387节点(空槽号)作为master节点加入原集群redis-cli --cluster add-node 192.168.238.80:6387 192.168.238.80:6381
  4. 检查集群情况第1次 ;redis-cli --cluster check 192.168.238.80:6381
  5. 重新分配槽号:redis-cli --cluster reshard 192.168.238.80:6387
  6. 检查集群情况第2次:原来的三个master每个将自己从左边开始给了一点给6387,是的6387有4096个槽位,并不是重新分配
  7. 为主节点6387分配从节点6388:redis-cli --cluster add-node ip:新slaver端口 ip:新master端口 --cluster-slaver --cluster-master-id 新主机节点ID redis-cli --cluster add-node 192.168.238.80:6388 192.168.238.80:6387 --cluster-slave --cluster-master-id 6899abd525f6a3088cbc345a2efcbd333de4f02e
  8. 检查集群情况第3次

** 主从缩容案例**

  1. 检查集群情况1获得6388的节点ID : redis-cli --cluster check 192.168.238.80:6382
  2. 将6388删除,从集群中将4号从节点6388删除 : redis-cli --cluster del-node ip:从机端口号 从机6388节点ID redis-cli --cluster del-node 192.168.238.80:6388 aadd958f00fec4424a340844854a9cf95781d922
  3. 将6387的槽号清空,重新分配,本例将清出来的槽号都给6381 :redis-cli --cluster reshard 192.168.238.80:6381
  4. 检查集群情况第2次1. 将6387删除 :redis-cli --cluster del-node ip:端口号 6387节点ID
redis-cli --cluster del-node 192.168.238.80:6387 6899abd525f6a3088cbc345a2efcbd333de4f02e
  1. 检查集群情况第三次

2.DockerFile解析

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

dockerfile保留字指令:tomcat/Dockerfile at master · docker-library/tomcat · GitHub

  • FROM:基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是FROM
  • MAINTAINER:镜像维护者的姓名和邮箱地址
  • RUN:容器构建时需要运行的命令;RUN是再docker build时运行;两种格式: - shell格式- exec格式
  • EXPOSE:当前容器对外暴露出的端口
  • WORKDIR:指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点
  • USER:指定该镜像以什么样的用户去执行,如果都不指定,默认是root
  • ENV:用来在构建镜像过程中设置环境变量
  • ADD:将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包
  • COPY:类似ADD,拷贝文件和目录到镜像中,将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内<目标路径>位置: - COPY src dest- COPY ["src","dest"]- <src源路径>:源文件或者源目录- <dest目录路径>:容器内的指定路径,该路径不用事先建好
  • VOLUME:容器数据卷,用于数据保存和持久化工作
  • CMD: 指定容器启动后要干的事情 - 注意:Dockerfile中可以有多个CMD指定,但只有最后一个生效,CMD会被docker run之后的参数替代- 它和RUN命令的区别: - CMD是在docker run 时运行- RUN是在 docker build时运行
  • ENTRYPOINT: 也是用来指定一个容器启动时要运行的命令。类似于CMD指令。但是ENTRYPOINT不会被docker run 后面的命令覆盖,而且这些命令行参数会被当作参数送给ENTRYPOINT指令指定的程序

案例

    自定义镜像mycentosjava8:

    要求:centos7镜像具备vim + ifconfig + jdk8

    JDK下载:Java Downloads | Oracle
  1. 准备编写Dockerfile文件 ,在压缩包同一目录下创建Dockerfile文件:
FROM centos7.6.1810
MAINTAINER zcl

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-8u171-linux.x64.tar.gz添加到容器中,安装包必须要和Dckerfile文件在同一位置
ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH

EXPOSE 80
CMD echo $MYPATH
CMD echo "success---------------ok"
CMD /bin/bash
 2.构建:docker build -t 新镜像名字:TAG .      注意TAG后面有个空格,有个点
docker build -t centosjava8:1.5 .
    3.运行:docker run -it 心镜像名:TAG
docker run -it 87ea3c3e1155 /bin/bash

虚悬镜像

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

    删除:docker image prune

3.Docker微服务

    一.通过IDEA新建一个普通微服务模块
package com.example.docker.controller;/**
 * @Author: ZCL
 * @DATE: 2022/11/8 21:07
 */

import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

/**
 * @program: docker-boot
 * @author: ZCL
 * @create: 2022-11-08 21:07
 */
@RestController
public class OrderController {

    @Value("${server.port}")
    private String port;

    @RequestMapping("/order/docker")
    public String helloDocker(){
        return "hello docker"+"/t"+port+"/t"+ UUID.randomUUID().toString();
    }

    @RequestMapping(value = "/order/index",method = RequestMethod.GET)
    public String index(){
        return " 服务端口号"+"/t"+port+"/t"+ UUID.randomUUID().toString();
    }
}

    二.通过dockerfile发布微服务部署到docker容器

            1.编写dockerfile
#基础使用镜像java
FROM java:8
#作者
MAINTAINER zcl
#VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建一个临时文件并链接到容器的/tmp
VOLUME /tmp
#将jar包添加到容器中并更名为zcl_docker.jar
ADD docker-0.0.1-SNAPSHOT.jar zcl_docker.jar
#运行jar包
RUN bash -c 'touch /zcl_docker.jar'
ENTRYPOINT ["java","-jar","/zcl_docker.jar"]
#暴露6001端口号作为微服务
EXPOSE 6001

            2.构建
docker build -t zcl_docker:1.6 .
            3.运行容器  
 docker run -d -p 6001:6001 ab6314e8f16a
            4.访问微服务


4.Docker网络

能干什么:容器间的互联和通信以及端口映射

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

    docker启动后其网络情况:

查看docker网络模式:docker network ls

** 常用命令**

Commands:
  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

查看网络:docker network ls

查看网络源数据:docker network inspect 网络名字

删除网络:docker network rm 网络名字

网络模式:
网络模式简介bridge
为每一个容器分配,设置IP等,并将容器链接到一个docker0

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


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

案例:

    1.启动两个tomcat容器
 docker run -d -p 8081:8080 --name tomcat81 billygoo/tomcat8-jdk
docker run -d -p 8082:8080 --name tomcat82 billygoo/tomcat8-jdk8

原理:

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

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

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

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


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

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

案例:

docker run -d --network host --name tomcat83 billygoo/tomcat8-jdk8
  1. 查看tomcat83网络数据源:docker inspect tomcat83

3.进入tomcat83:docker exec -it tomcat83 bash :发现与宿主机的网络配置一样


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

在none模式下,并不为Docker容器进行任何网络配置,也就是说,这个Docker容器没有网卡,IP,路由等信息,只有一个lo,需要我们自己为Docker容器添加网卡,配置IP等。

案例:

docker run 8084:8080 --network none --name tomcat84 billygoo/tomcat -jdk8

3.进入内部查看:只有一个lo


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

案例:

错误案例

docker run -d -p 8085:8080 --name tomcat85 billygoo/tomcat8-jdk8
docker run -d -p 8086:8080 --name container:tomcat85 --name tomcat86 billygoo/tomcat8-jdk8

tomcat86与tomcat85公用一个ip同一个端口,导致端口冲突

正确案例 :Alpine操作系统是一个面向安全的轻型Linux发行版

docker run -it --name alpine1 alpine /bin/sh
docker run -it --network container:alpine1 --name alpine2 alpine /bin/sh

分别进入两个容器中,发现alpine2使用的是alpine1的网络配置,当alpine1共享源关闭后,alpine2就没有自己的配置了


自定义网络

案例:

** 1.自定义桥接网络,自定义网络默认使用的是桥接网络bridge**

** 2.新建自定义网络 : docker network create a_network**

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

docker run -d -p 8081:8080 --network a_network --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --network a_network --name tomcat82 billygoo/tomcat8-jdk8

** 4.互相ping测试**


5.Docker-compose容器编排

    Docker_compose是Docker官方的开源项目,负责实现对Docker容器集群的快速编排,可以管理多个Docker容器组成一个应用,你需要定义一个YAML格式的配置文件docker-compose.yml,写好多个容器之间的调用关系,然后只需要一个命令,就能同时启动/关闭这些容器

Overview | Docker Documentation

安装

1curl -L https://get.daocloud.io/docker/compose/releases/download/1.29.2/docker-compose-`uname -s-uname -m` > /usr/local/bin/docker-compose

2.chmod +x /usr/local/bin/docker-compose

3.docker-compose --version

Maven打包命令

** >mvn clean install -Dmaven.test.skip=true**

将jar放到mydocker目录下

编写Dockerfile

#基础使用镜像java
FROM java:8
#作者
MAINTAINER zcl
#VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建一个临时文件并链接到容器的/tmp
VOLUME /tmp
#将jar包添加到容器中并更名为zcl_docker.jar
ADD docker_boot-0.0.1-SNAPSHOT.jar zcl_docker.jar
#运行jar包
RUN bash -c 'touch /zcl_docker.jar'
ENTRYPOINT ["java","-jar","/zcl_docker.jar"]
#暴露6001端口号作为微服务
EXPOSE 6001

build

 docker build -t zcl_docker:1.7 .

Docker-compose.yml 在mydocker目录下


 version: "3"

 services:
    microService:
      image: zcl_docker:1.7
      container_name: ms01
      ports:
        - "6001:6001"
      volumes:
        - /app/microService:/data
      networks:
        - zcl_net
      depends_on:
        - redis
        - mysql

    redis:
      image: redis:6.0.8
      ports:
        - "6379:6379"
      volumes:
        - /app/redis/redis.conf:/etc/redis/redis.conf
        - /app/redis/data:/data
      networks:
        - zcl_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: 'dbdocker'
         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:
        - zcl_net
      command: --default-authentication-plugin=mysql_native_password

 networks:
    zcl_net:

修改原来项目的配置。重新打包成jar

检查docker-compose 中是否存在语法错误:docker-compose config -q

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


Pointainer的安装

Powerful container management software for Platform Teams, DevOps, Dev

命令安装:

 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

1.第一次登录需创建admin,访问地址:本机IP:9000

2.设置admin用户和密码后首次登录密码八位

3.选择local选项卡后本机docker详细信息展示


容器监控3剑客:CAdivsor监控收集+InfluxDB存储数据+Granfana 数据分析

docker-compose容器编排:


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
 
  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
 
    - INFLUXDB_NAME=cadvisor
 
    - INFLUXDB_USER=root
 
    - INFLUXDB_PASS=root

docker-compose config -q 检查错误

docker-compose up 启动

测试

acdvisor: http://192.168.238.80:8080

influxdb : http://192.168.238.80:8083/

Grafana : ​​​​​​​http://192.168.238.80:3000/

为grafana配置数据源:

    ![](https://img-blog.csdnimg.cn/e2ac5b91d4ca4f218c240fc356fd0d4d.png)

选择influxdb为数据源:

面板panel的添加:

选择图形化展示方式:

标签: docker linux 运维

本文转载自: https://blog.csdn.net/qq_61812971/article/details/127623599
版权归原作者 Maserati477 所有, 如有侵权,请联系我们删除。

“Docker学习笔记”的评论:

还没有评论