• Docker的那些事


    1. Docker简介

           Docker是基于Go语言实现的云开源项目
           Docker的主要目标是“Build,Ship and Run Any App,Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到“一次镜像,处处运行”。

           Linux容器技术的出现就解决了这样一个问题,而 Docker 就是在它的基础上发展过来的。将应用打成镜像,通过镜像成为运行在Docker容器上面的实例,而 Docker容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。

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

           Docker官网:http://www.docker.com

           DockerHub安装镜像的仓库官网: https://hub.docker.com

    2. Docker的基本组成

    2.1 镜像

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

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

            UnionFS(联合文件系统)(Union文件系统)(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 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。

           为什么 Docker 镜像要采用这种分层结构呢? 
           镜像分层最大的一个好处就是共享资源,方便复制迁移,就是为了复用。比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

           Docker镜像层都是只读的,容器层是可写的。当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。
           Docker中的镜像分层,支持通过扩展现有镜像,创建新的镜像。类似Java继承于一个Base基础类,自己再按需扩展。新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。

    2.2 容器

    1 从面向对象角度
           Docker 利用容器(Container)独立运行的一个或一组应用,应用程序或服务运行在容器里面,容器就类似于一个虚拟化的运行环境,容器是用镜像创建的运行实例。就像是Java中的类和实例对象一样,镜像是静态的定义,容器是镜像运行时的实体。容器为镜像提供了一个标准的和隔离的运行环境,它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台
    2 从镜像容器角度
           可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

    2.3 仓库

            仓库(Repository)是集中存放镜像文件的场所。类似于Maven仓库,存放各种jar包的地方;
            github仓库,存放各种git项目的地方;Docker公司提供的官方registry被称为Docker Hub,存放各种镜像模板的地方。 仓库分为公开仓库(Public)和私有仓库(Private)两种形式。
           最大的公开仓库是 Docker Hub(https://hub.docker.com/),存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云 、网易云等

    2.4 总结

           Docker 本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就是image镜像文件。只有通过这个镜像文件才能生成Docker容器实例(类似Java中new出来一个对象)。
    image文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例。
           镜像文件生成的容器实例,本身也是一个文件,称为镜像文件。
           容器实例 ,一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例,也就是我们的容器。
           仓库就是放一堆镜像的地方,我们可以把镜像发布到仓库中,需要的时候再从仓库中拉下来就可以了。

    3. Docker运行流程

           Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。 容器,是一个运行时环境,就是我们前面说到的集装箱。可以对比mysql演示对比讲解。

     

    4. 在Centos7上安装Docker

    Install Docker Engine on CentOS | Docker Documentation

    1. # 查看centos版本
    2. cat /etc/redhat-release
    3. #CentOS Linux release 7.7.1908 (Core)
    4. # 显示操作系统的发行版号
    5. uname -r
    6. #3.10.0-1062.el7.x86_64
    1. # 先固定好IP地址
    2. vim /etc/sysconfig/network-scripts/ifcfg-ens33
    1. #修改这些参数或添加
    2. BOOTPROTO="static"
    3. IPADDR=192.168.235.135
    4. GATEWAY=192.168.235.2
    5. NETMASK=255.255.255.0
    6. DNS1=218.4.4.4
    7. DNS2=8.8.8.8 
    1. #重启网卡
    2. systemctl restart network
    1. # 卸载旧版本
    2. sudo yum remove docker \
    3. docker-client \
    4. docker-client-latest \
    5. docker-common \
    6. docker-latest \
    7. docker-latest-logrotate \
    8. docker-logrotate \
    9. docker-engine
    1. # 安装依赖包
    2. yum -y install gcc
    3. yum -y install gcc-c++
    4. yum install -y yum-utils
    1. # 镜像加速器访问地址
    2. https://cr.console.aliyun.com/cn-beijing/instances/mirrors

    1. # 修改或新增docker配置文件
    2. vim /etc/docker/daemon.json
    1. #graph代表docker指定的安装目录
    2. #registry-mirrors 指定加速器地址
    3. {
    4. "registry-mirrors": ["https://fujwmaum.mirror.aliyuncs.com"],
    5. "graph":"/opt/docker"
    6. }
    1. # 设置为国内阿里云的镜像源
    2. yum-config-manager --add-repo \
    3. http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    4. # 更新yum软件包索引
    5. yum makecache fast
    6. # 安装Docker引擎
    7. yum -y install docker-ce docker-ce-cli containerd.io
    8. #加载镜像:
    9. systemctl daemon-reload
    1. #设置开机自启动
    2. systemctl enable docker
    1. #查看docker是否开机自启
    2. systemctl list-unit-files | grep enable | grep docker
    3. #docker.service enabled
    1. # 启动Docker服务
    2. systemctl start docker
    3. ps -ef | grep docker
    4. #root 5835 1 3 07:20 ? 00:00:00 /usr/bin/dockerd -H
    5. #root 6040 4378 0 07:20 pts/0 00:00:00 grep --color=auto docker
    1. # 查看Docker版本号
    2. docker --version
    3. #Docker version 20.10.21, build baeda1f
    4. # 查看Docker版本详情
    5. docker version
    6. #Client: Docker Engine - Community
    7. #Version: 20.10.21
    8. #API version: 1.41
    9. #Go version: go1.18.7
    10. #Git commit: baeda1f
    11. #Built: Tue Oct 25 18:04:24 2022
    12. #OS/Arch: linux/amd64
    13. #Context: default
    14. #Experimental: true
    15. # 试运行安装启动是否正常
    16. docker run hello-world
    17. #Unable to find image 'hello-world:latest' locally
    18. #latest: Pulling from library/hello-world
    19. #2db29710123e: Pulling fs layer
    20. cd /opt
    21. ll
    22. #total 2772
    23. #drwx--x--x 4 root root 28 Nov 14 07:20 containerd
    24. #drwx--x--- 13 root root 167 Nov 14 07:55 docker
    25. cd docker/
    26. ll
    27. #total 0
    28. #drwx--x--x 4 root root 120 Nov 14 07:55 buildkit
    29. #drwx--x--- 2 root root 6 Nov 14 07:55 containers
    30. #drwx------ 3 root root 22 Nov 14 07:55 image
    31. #drwxr-x--- 3 root root 19 Nov 14 07:55 network
    32. #drwx--x--- 3 root root 40 Nov 14 07:55 overlay2
    33. #drwx------ 4 root root 32 Nov 14 07:55 plugins
    34. #drwx------ 2 root root 6 Nov 14 07:55 runtimes
    35. #drwx------ 2 root root 6 Nov 14 07:55 swarm
    36. #drwx------ 2 root root 6 Nov 14 07:55 tmp
    37. #drwx------ 2 root root 6 Nov 14 07:55 trust
    38. #drwx-----x 2 root root 50 Nov 14 07:55 volumes
    1. # Docker停止并卸载
    2. systemctl stop docker
    3. yum remove docker-ce docker-ce-cli containerd.io
    4. rm -rf /opt/docker
    5. rm -rf /opt/containerd

    5. Docker操作命令

    5.1 Docker帮助命令

    1. #查看docker概要信息
    2. docker info
    3. #查看docker帮助文档
    4. docker --help
    5. docker 具体命令 --help

    5.2 Docker镜像命令

    5.2.1 docker镜像查看与搜索

    1. # 列出本地主机上的镜像
    2. docker images
    3. #仓库源 标签版本号 镜像ID 创建时间 大小
    4. #REPOSITORY TAG IMAGE ID CREATED SIZE
    5. #hello-world latest feb5d9fea6a5 14 months ago 13.3kB
    6. # 搜索某个镜像,比如redis,并显示为2行
    7. docker search --limit 2 redis
    8. #名称 描述 点赞数量 是否官方 是否自动构建
    9. #NAME DESCRIPTION STARS OFFICIAL AUTOMATED
    10. #redis Redis is an open source key-value 11601 [OK]
    11. #redislabs/redisearch Redis With the RedisSearch module 56
    12. # 查看镜像/容器/数据卷所占的空间
    13. docker system df
    14. #TYPE TOTAL ACTIVE SIZE RECLAIMABLE
    15. #Images 2 1 104.2MB 104.2MB (99%)
    16. #Containers 1 0 0B 0B
    17. #Local Volumes 0 0 0B 0B
    18. #Build Cache 0 0 0B 0B
    19. # 展示本地的所有镜像
    20. docker images -a
    21. #REPOSITORY TAG IMAGE ID CREATED SIZE
    22. #hello-world latest feb5d9fea6a5 14 months ago 13.3kB

    5.2.2 docker镜像的拉取 

    1. #拉取镜像,不指定版本号则默认取最新版本
    2. docker pull hello-world
    3. #Using default tag: latest
    4. docker pull redis:6.0.8
    5. docker images -a
    6. #REPOSITORY TAG IMAGE ID CREATED SIZE
    7. #hello-world latest feb5d9fea6a5 14 months ago 13.3kB
    8. #redis 6.0.8 16ecd2772934 2 years ago 104MB
    9. #查看镜像/容器/数据卷所占的空间
    10. docker system df
    11. #TYPE TOTAL ACTIVE SIZE RECLAIMABLE
    12. #Images 2 1 104.2MB 104.2MB (99%)
    13. #Containers 1 0 0B 0B
    14. #Local Volumes 0 0 0B 0B
    15. #Build Cache 0 0 0B 0B

     5.2.3 docker镜像的删除

    1. docker images -a
    2. #REPOSITORY TAG IMAGE ID CREATED SIZE
    3. #hello-world latest feb5d9fea6a5 14 months ago 13.3kB
    4. # 删除某个或多个镜像,比如hello-world的镜像ID=feb5d9fea6a5
    5. docker rmi feb5d9fea6a5
    6. #Error response from daemon: conflict: unable to delete feb5d9fea6a5 (must be forced) - image is being used by stopped container f617daec0750
    7. docker rmi -f feb5d9fea6a5
    8. #Untagged: hello-world:latest
    9. #Untagged: hello-world@sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f
    10. #Deleted: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412
    1. #删除全部镜像
    2. docker rmi -f $(docker images -aq)

     5.2.4 docker镜像的导入

    1. docker load -i xxx.tag.gz
    2. #如果遇到unexpected EOF,应该是镜像包有问题,需要重新打包

    5.3 Docker容器命令

    5.3.1 Docker容器的运行

    1. #使用镜像ubuntu:latest以前台交互模式启动一个容器,在容器内执行/bin/bash命令
    2. # -i: 前台交互式 -t: 终端
    3. #/bin/bash:放在镜像名后的是命令,这里我们希望有个交互式Shell。
    4. #如果退出,输入exit,则是退出后容器停止
    5. # 输入Ctrl+p+q,则是退出后,容器继续运行
    6. docker run -it ubuntu /bin/bash
    7. #如果输入Ctrl+p+q,又想重新进入,比如容器ID=5760ab297b72
    8. docker exec -it 5760ab297b72 /bin/bash
    9. #用exec后,后面再输入exit退出,也不会让容器停止。因此推荐使用!
    10. #vi a.txt 此时在ubuntu上输入vi命令发现命令不存在
    11. #bash: vi: command not found
    12. #在ubuntu上安装vim
    13. apt-get update
    14. apt-get -y install vim
    15. exit
    16. #提交容器副本使之成为一个新的镜像
    17. #docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]
    18. docker commit -m="vim cmd add" -a="zmj" 5760ab297b72 zmjubuntu:1.2
    19. docker images
    20. #REPOSITORY TAG IMAGE ID CREATED SIZE
    21. #zmjubuntu 1.2 838afddae82b 9 seconds ago 180MB
    22. #停掉旧的容器,开启新的
    23. docker stop 5760ab297b72
    24. docker exec -it 838afddae82b /bin/bash
    25. # vim abc.txt 此时就可以编辑了
    26. #复制文件
    27. #docker cp 容器ID:容器内路径 目的主机路径
    28. docker cp 5760ab297b72:/a.txt /home/zmj/
    29. #镜像导出容器
    30. #docker export 容器ID > 文件名
    31. docker export 5760ab297b72 > /home/zmj/ubuntu.tar.gz
    32. #镜像导入容器
    33. #cat 路径文件名 | docker import - 镜像用户/镜像名:镜像版本号
    34. cat /home/zmj/ubuntu.tar.gz | docker import - zmj/ubuntu
    35. #使用镜像redis:6.0.8以后台守护式启动一个容器
    36. # -d 后台守护式
    37. docker run -d redis:6.0.8
    38. #列出当前所有正在运行的容器
    39. docker ps
    40. #CONTAINER ID IMAGE COMMAND CREATED STATUS
    41. #d5124db3104d ubuntu "/bin/bash" 7 minutes ago Up 7 minutes
    42. #e3063d7fa15c redis:6.0.8 "docker-ent" a minute ago Up a minute
    43. #查看容器日志,比如这个redis的容器ID=e3063d7fa15c
    44. docker logs e3063d7fa15c
    45. #查看容器内运行的进程
    46. docker top e3063d7fa15c
    47. ##查看容器内部细节
    48. docker inspect e3063d7fa15c
    49. #使用镜像ubuntu:latest以交互模式启动一个容器,在容器内执行bash命令
    50. #--name 指定容器名称。如果不指定会自动生成一个
    51. docker run -it --name=ubuntu01 ubuntu bash

    5.3.2 Docker容器的查看

    1. #列出当前所有正在运行的容器
    2. docker ps
    3. #CONTAINER ID IMAGE COMMAND CREATED STATUS
    4. #d5124db3104d ubuntu "/bin/bash" 7 minutes ago Up 7 minutes
    5. #e3063d7fa15c redis:6.0.8 "docker-ent" a minute ago Up a minute
    6. #查看容器日志,比如这个redis的容器ID=e3063d7fa15c
    7. docker logs e3063d7fa15c
    8. #查看容器内运行的进程
    9. docker top e3063d7fa15c
    10. ##查看容器内部细节
    11. docker inspect e3063d7fa15c
    12. #列出当前所有正在运行+历史出现过的容器
    13. docker ps -a
    14. #CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
    15. #8e1fa21791b2 ubuntu "bash" 11 minutes ago Up 11 minutes ubuntu01
    16. #d5124db3104d ubuntu "/bin/bash" 43 minutes ago Exited (0) sweet_bassi
    17. #f617daec0750 feb5d9fea6a5 "/hello" 11 days ago Exited (0) vigorous_mahavira
    18. #查看名称为idms-application-settle的容器ID
    19. docker ps -aqf 'name=idms-application-settle'
    20. #2f75d6a7ae9b
    21. #查看名称为idms-application-finance的容器ID
    22. docker ps -aqf 'name=idms-application-finance'
    23. #7eca7355dbf5

    5.3.3 Docker容器的启停删

    1. #启动已经停止的容器
    2. docker start d5124db3104d
    3. #重启启动容器
    4. docker restart d5124db3104d
    5. docker restart $(docker ps -aqf 'name=rabbitmq')
    6. #停止容器
    7. docker stop d5124db3104d
    8. #强制停止容器
    9. docker kill d5124db3104d
    10. #删除已经停止的容器
    11. docker rm f617daec0750
    12. #删除所有容器
    13. docker rm -f $(docker ps -a -q)

    5.3.4 Docker容器的日志跟踪

    1. # idms-finance-gateway-service:容器名称
    2. # --tail 1000 仅列出最新1000条容器日志
    3. # gateway.log 将日志输出到gateway.log里面
    4. docker logs -f idms-finance-gateway-service --tail 1000 > gateway.log

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

    https://cr.console.aliyun.com/cn-beijing/instance/namespaces

     

     

     

    1. # 开始上传镜像到阿里云
    2. docker login --username=dream98 registry.cn-beijing.aliyuncs.com
    3. docker tag 838afddae82b \
    4. registry.cn-beijing.aliyuncs.com/zmjdream/zmjubuntu:1.2
    5. docker push registry.cn-beijing.aliyuncs.com/zmjdream/zmjubuntu:1.2
    6. docker images
    7. #REPOSITORY TAG IMAGE ID CREATED SIZE
    8. #zmjubuntu 1.2 838afddae82b 16 minutes ago 180MB
    9. #registry.cn-beijing.aliyuncs.com/zmjdream/zmjubuntu 1.2 838afddae82b
    10. #ubuntu latest ba6acccedd29 13 months ago 72.8MB
    11. # 为了看从阿里云下载镜像,先强制删除
    12. docker rmi -f 838afddae82b
    13. #从阿里云下载镜像
    14. docker pull registry.cn-beijing.aliyuncs.com/zmjdream/zmjubuntu:1.2
    15. docker images
    16. #REPOSITORY TAG IMAGE ID
    17. #registry.cn-beijing.aliyuncs.com/zmjdream/zmjubuntu 1.2 838afddae82b
    18. # 运行这个新镜像,并打开前台终端
    19. docker run -it 838afddae82b /bin/bash
    20. vim abc.txt

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

    Docker Registry是官方提供的工具,可以用于构建私有镜像仓库

    1. #1.下载镜像Docker Registry
    2. docker pull registry
    3. #2. 运行私有库Registry
    4. # /home/zmj/mydockerregistry/:/tmp/registry 宿主机绝对路径:容器内目录
    5. # --privileged=true 放开权限
    6. docker run -d -p 5000:5000 \
    7. -v /home/zmj/mydockerregistry/:/tmp/registry \
    8. --privileged=true registry
    9. docker run -it ubuntu /bin/bash
    10. apt-get update
    11. apt-get install net-tools
    12. Ctrl+q+P
    13. docker ps
    14. #CONTAINER ID IMAGE COMMAND CREATED STATUS
    15. #e5d1e3d49053 ubuntu "/bin/bash" 6 minutes ago Up 6 minutes
    16. #a325d994340a registry "/entrypoint.sh /etc…" Up 6 minutes
    17. #3. 提交容器副本使之成为一个新的镜像
    18. docker commit -m="ifconfig cmd add" -a="zmj" e5d1e3d49053 zmjubuntu:1.2
    19. docker images
    20. #REPOSITORY TAG IMAGE ID CREATED SIZE
    21. #zmjubuntu 1.2 4b2e6f89ecaf 3 minutes ago 114MB
    22. #4. curl验证私服库上有什么镜像
    23. curl -XGET http://192.168.235.130:5000/v2/_catalog
    24. #5. 将新镜像zmjubuntu:1.2修改符合私服规范的Tag
    25. docker tag zmjubuntu:1.2 192.168.235.130:5000/zmjubuntu:1.2
    26. docker images
    27. #REPOSITORY TAG IMAGE ID SIZE
    28. #192.168.235.130:5000/zmjubuntu 1.2 4b2e6f89ecaf 114MB
    29. #zmjubuntu 1.2 4b2e6f89ecaf 114MB
    30. #registry latest b8604a3fe854 26.2MB
    1. #6. 修改配置文件使之支持http
    2. vim /etc/docker/daemon.json
    3. #insecure-registries docker默认不允许http方式推送镜像,通过配置选项来取消这个限制
    4. {
    5. "registry-mirrors": ["https://fujwmaum.mirror.aliyuncs.com"],
    6. "graph":"/opt/docker",
    7. "insecure-registries": ["192.168.235.130:5000"]
    8. }
    1. #7. 重启docker让配置生效
    2. systemctl restart docker
    3. #8. 运行私有库Registry
    4. docker run -d -p 5000:5000 \
    5. -v /home/zmj/mydockerregistry/:/tmp/registry \
    6. --privileged=true registry
    7. #9. 推送到私有库
    8. docker push 192.168.235.130:5000/zmjubuntu:1.2
    9. #10. curl验证私服库上有什么镜像
    10. curl -XGET http://192.168.235.130:5000/v2/_catalog
    11. #{"repositories":["zmjubuntu"]}
    12. #11.为了看pull效果,先删除掉本地zmjubuntu镜像
    13. docker rmi -f 4b2e6f89ecaf
    14. #12. 拉取刚才上传到私有库的镜像
    15. docker pull 192.168.235.130:5000/zmjubuntu:1.2
    16. docker images
    17. #REPOSITORY TAG IMAGE ID SIZE
    18. #192.168.235.130:5000/zmjubuntu 1.2 4b2e6f89ecaf 114MB
    19. #13. 运行刚才拉取的镜像,并前台终端显示
    20. docker run -it 4b2e6f89ecaf /bin/bash

    8. Docker容器数据卷

            将运用与运行的环境打包镜像,run后形成容器实例运行 ,但是我们对数据的要求希望是持久化的。Docker容器产生的数据,如果不备份,那么当容器实例删除后,容器内的数据自然也就没有了。为了能保存数据在docker中我们使用卷。
           特点:
          1:数据卷可在容器之间共享或重用数据
          2:卷中的更改可以直接实时生效
          3:数据卷中的更改不会包含在镜像的更新中
          4:数据卷的生命周期一直持续到没有容器使用它为止

    1. # 将docker容器内的数据保存进宿主机的磁盘中
    2. # 运行一个带有容器卷存储功能的容器实例
    3. # /tmp/myhostdata:/tmp/mydockerdata 宿主机绝对路径目录:/容器内目录
    4. # --privileged=true 放开权限
    5. docker run -it --name myubuntu --privileged=true \
    6. -v /tmp/myhostdata:/tmp/mydockerdata ubuntu /bin/bash

     容器内和宿主机对应的两个路径下会共享

    1. #在容器内创建一个文件
    2. cd /tmp/mydockerdata/
    3. touch rongqinei.txt
    4. ll
    5. #-rw-r--r-- 1 root root 0 Dec 2 11:43 rongqinei.txt
    6. #在宿主机查看
    7. cd /tmp/myhostdata/
    8. ll
    9. #-rw-r--r-- 1 root root 0 Dec 2 03:43 rongqinei.txt
    10. #在宿主机此路径下创建一个文件
    11. touch suzhuji.txt
    12. #在容器内查看
    13. ll
    14. #-rw-r--r-- 1 root root 0 Dec 2 11:43 rongqinei.txt
    15. #-rw-r--r-- 1 root root 0 Dec 2 11:43 suzhuji.txt

     当容器停止,宿主机对应路径下新建文件。当容器又启动后,会看到容器内可以查看到那个文件 

    1. docker ps
    2. #CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
    3. #5a998ec5e7c8 ubuntu "/bin/bash" an hour ago Up About an hour myubuntu
    4. docker stop 5a998ec5e7c8
    5. #宿主机在/tmp/myhostdata/下新建一个文件
    6. touch suzhuji2.txt
    7. docker start 5a998ec5e7c8
    8. docker exec -it 5a998ec5e7c8 /bin/bash
    9. #容器内查看
    10. cd /tmp/mydockerdata/
    11. ll
    12. #-rw-r--r-- 1 root root 0 Dec 2 11:43 rongqinei.txt
    13. #-rw-r--r-- 1 root root 0 Dec 2 11:43 suzhuji.txt
    14. #-rw-r--r-- 1 root root 0 Dec 2 12:50 suzhuji2.txt

     默认是rw的,也就是容器可读可写。还可以改成ro的,也就是容器只读 

    1. # :ro 容器只读
    2. docker run -it --name myubuntu2 --privileged=true \
    3. -v /tmp/myhostdata2:/tmp/mydockerdata2:ro ubuntu /bin/bash

      父容器内、子容器内和宿主机对应的三个路径下都会共享 

    1. #删除所有容器
    2. docker rm -f $(docker ps -a -q)
    3. #这个作为父容器
    4. docker run -it --name myubuntu --privileged=true
    5. -v /tmp/myhostdata:/tmp/mydockerdata ubuntu /bin/bash
    6. #这个作为子容器
    7. #--volumes-from 继承父容器的卷规则
    8. docker run -it --privileged=true \
    9. --volumes-from myubuntu --name myubuntuchild ubuntu

    9. Docker安装Tomcat 

      这里安装稳定版的Tomcat8

    1. # 搜索Tomcat镜像
    2. docker search tomcat
    3. # 拉取tomcat8镜像到本地
    4. docker pull billygoo/tomcat8-jdk8
    5. # 查看是否有拉取到的tomcat
    6. docker images billygoo/tomcat8-jdk8
    7. #REPOSITORY TAG IMAGE ID CREATED SIZE
    8. #billygoo/tomcat8-jdk8 latest 30ef4019761d 4 years ago 523MB
    9. # 查看主机8080端口有没有被占用
    10. ss -antup | grep 8080
    11. # 使用tomcat镜像创建容器实例
    12. # 运行镜像
    13. # -d 后台守护模式
    14. # -p 小写,主机端口:docker容器端口
    15. docker run -d -p 8080:8080 --name mytomcat8 billygoo/tomcat8-jdk8

     10. Docker安装MySQL

    1. # 拉取MySQL5.7镜像
    2. docker pull mysql:5.7
    3. docker images mysql:5.7
    4. #REPOSITORY TAG IMAGE ID CREATED SIZE
    5. #mysql 5.7 c20987f18b13 11 months ago 448MB
    1. # 查看主机3306端口有没有被占用
    2. # 有查询到结果,说明被占用了,改成3307吧
    3. ss -antup | grep 3306
    4. #tcp LISTEN 0 80 [::]:3306
    1. # 运行MySQL镜像
    2. # /home/zmj/mysql/conf:/etc/mysql/conf.d 容器数据卷宿主机路径与容器内路径对应
    3. docker run -d -p 3307:3306 --privileged=true \
    4. -v /home/zmj/mysql/log:/var/log/mysql \
    5. -v /home/zmj/mysql/data:/var/lib/mysql \
    6. -v /home/zmj/mysql/conf:/etc/mysql/conf.d \
    7. -e MYSQL_ROOT_PASSWORD=123456 \
    8. --name mysql mysql:5.7
    1. #配置字符集编码为UTF-8,解决中文乱码
    2. vim /home/zmj/mysql/conf/my.cnf

     [client]
    default_character_set=utf8
    [mysqld]
    collation_server = utf8_general_ci
    character_set_server = utf8

    1. #重启mysql容器实例
    2. docker restart mysql
    3. docker ps
    4. #CONTAINER ID IMAGE STATUS PORTS NAMES
    5. #b874c019cf66 mysql:5.7 Up 5 seconds 33060/tcp mysql
    1. #进入MySQL容器内
    2. docker exec -it mysql /bin/bash
    3. mysql -uroot -p
    1. -- mysql> 查看字符集
    2. show variables like 'character%';

    11. Docker安装MySQL主从复制

    11.1 配置MySQL主服务器

    1. # 新建MySQL容器实例-主服务器
    2. docker run -p 3307:3306 --name mysql-master \
    3. -v /mydata/mysql-master/log:/var/log/mysql \
    4. -v /mydata/mysql-master/data:/var/lib/mysql \
    5. -v /mydata/mysql-master/conf:/etc/mysql \
    6. -e MYSQL_ROOT_PASSWORD=root \
    7. -d mysql:5.7
    8. docker ps
    9. #CONTAINER ID IMAGE STATUS PORTS NAMES
    10. #7af6cc85ae25 mysql:5.7 Up 13 minutes 33060/tcp mysql-master
    vim /mydata/mysql-master/conf/my.cnf

     [mysqld]
    ## 设置server_id,同一局域网中需要唯一
    server_id=101 
    ## 指定不需要同步的数据库名称
    binlog-ignore-db=mysql  
    ## 开启二进制日志功能
    log-bin=mall-mysql-bin  
    ## 设置二进制日志使用内存大小(事务)
    binlog_cache_size=1M  
    ## 设置使用的二进制日志格式(mixed,statement,row)
    binlog_format=mixed  
    ## 二进制日志过期清理时间。默认值为0,表示不自动清理。
    expire_logs_days=7  
    ## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
    ## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
    slave_skip_errors=1062

    1. # 修改完配置文件,需重启
    2. docker restart mysql-master
    3. docker ps
    4. # 进入mysql-master容器
    5. docker exec -it mysql-master /bin/bash
    6. mysql -uroot -proot
    1. -- mysql> master容器实例内创建数据同步用户
    2. CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
    3. GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';

    11.2 配置MySQL从服务器

    1. # 新建MySQL容器实例-从服务器
    2. docker run -p 3308:3306 --name mysql-slave \
    3. -v /mydata/mysql-slave/log:/var/log/mysql \
    4. -v /mydata/mysql-slave/data:/var/lib/mysql \
    5. -v /mydata/mysql-slave/conf:/etc/mysql \
    6. -e MYSQL_ROOT_PASSWORD=root \
    7. -d mysql:5.7
    vim /mydata/mysql-slave/conf/my.cnf

     [mysqld]
    ## 设置server_id,同一局域网中需要唯一
    server_id=102
    ## 指定不需要同步的数据库名称
    binlog-ignore-db=mysql  
    ## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
    log-bin=mall-mysql-slave1-bin  
    ## 设置二进制日志使用内存大小(事务)
    binlog_cache_size=1M  
    ## 设置使用的二进制日志格式(mixed,statement,row)
    binlog_format=mixed  
    ## 二进制日志过期清理时间。默认值为0,表示不自动清理。
    expire_logs_days=7  
    ## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
    ## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
    slave_skip_errors=1062  
    ## relay_log配置中继日志
    relay_log=mall-mysql-relay-bin  
    ## log_slave_updates表示slave将复制事件写进自己的二进制日志
    log_slave_updates=1  
    ## slave设置为只读(具有super权限的用户除外)
    read_only=1

    1. # 修改完配置文件,需重启
    2. docker restart mysql-slave
    3. docker ps

    11.3 从MySQL主服务器查看状态

    1. docker exec -it mysql-master /bin/bash
    2. mysql -uroot -proot
    1. -- mysql>
    2. show master status;
    3. --+-----------------------+----------+--------------+------------------
    4. --| File | Position | Binlog_Do_DB | Binlog_Ignore_DB
    5. --+-----------------------+----------+--------------+------------------
    6. --| mall-mysql-bin.000001 | 617 | | mysql

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

    1. docker exec -it mysql-slave /bin/bash
    2. mysql -uroot -proot
    1. -- master_host:主数据库的IP地址;192.168.235.130
    2. -- master_port:主数据库的运行端口;3307
    3. -- master_user:在主数据库创建的用于同步数据的用户账号; slave
    4. -- master_password:在主数据库创建的用于同步数据的用户密码;123456
    5. -- master_log_file:指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取File参数;
    6. -- master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position参数;
    7. -- master_connect_retry:连接失败重试的时间间隔,单位为秒
    8. --mysql>
    9. change master to master_host='192.168.235.130', master_user='slave',
    10. master_password='123456', master_port=3307, master_log_file='mall-mysql-bin.000001',
    11. master_log_pos=617, master_connect_retry=30;
    1. -- 在从数据库中查看主从同步状态
    2. -- Slave_IO_Running: No Slave_SQL_Running: No 说明还没有开始进行复制
    3. --mysql>
    4. show slave status \G;
    5. -- Slave_IO_State:
    6. -- Master_Host: 192.168.235.130
    7. -- Master_User: slave
    8. -- Master_Port: 3307
    9. -- Connect_Retry: 30
    10. -- Master_Log_File: mall-mysql-bin.000001
    11. -- Read_Master_Log_Pos: 617
    12. -- Relay_Log_File: mall-mysql-relay-bin.000001
    13. -- Relay_Log_Pos: 4
    14. -- Relay_Master_Log_File: mall-mysql-bin.000001
    15. -- Slave_IO_Running: No
    16. -- Slave_SQL_Running: No
    1. -- 在从数据库中开启主从同步
    2. --mysql>
    3. start slave;
    4. -- 再次查看主从同步状态,都是YES
    5. --mysql>
    6. show slave status \G;
    7. -- Slave_IO_Running: Yes
    8. -- Slave_SQL_Running: Yes

    11.5 主数据库中新建库-使用库-新建表-插入数据 

    1. create database dbtest;
    2. use dbtest;
    3. create table t_test(id int,name varchar(20));
    4. insert into t_test values(1,'master');
    5. select * from t_test;
    6. --id name
    7. --1 master

    11.6 从数据库中使用库-查看记录 

    1. use dbtest;
    2. select * from t_test;
    3. --id name
    4. --1 master

    12. Docker安装Redis

    1. #拉取镜像redis的6.0.8版本
    2. docker pull redis:6.0.8
    1. docker images redis:6.0.8
    2. #REPOSITORY TAG IMAGE ID CREATED SIZE
    3. #redis 6.0.8 16ecd2772934 2 years ago 104MB
    1. #新建存放Redis配置文件的目录
    2. mkdir -p /app/redis
    3. cd /app/redis/
    1. #将准备好的redis.conf文件放进/app/redis目录下
    2. #或者新建一个redis.conf,复制内容进去
    3. #####################redis.conf在原来基础上简单修改 START#############
    4. #注掉这个绑定
    5. #bind 127.0.0.1
    6. #该配置和docker run中-d参数冲突,会导致容器一直启动失败,所以设置为no
    7. daemonize no
    8. #开启redis数据持久化
    9. appendonly yes
    10. #端口号设置为6379
    11. port 6379
    12. #关闭保护模式,让其他主机的客户端可以连接到Redis
    13. protected-mode no
    1. #查看宿主机6379端口是否被占用,没有结果,表示没有被占用
    2. ss -antup | grep 6379
    1. #运行Redis镜像
    2. # 6379:6379 宿主机端口号:redis容器内端口号
    3. # --privileged=true 开放权限
    4. # /app/redis/redis.conf:/etc/redis/redis.conf 容器数据卷宿主机路径与容器内路径对应
    5. # -d 后台守护模式
    6. # redis-server /etc/redis/redis.conf 根据/etc/redis/redis.conf启动Redis服务
    7. # --requirepass 123456 设置redis验证密码为123456
    8. docker run -p 6379:6379 --name myredis --privileged=true \
    9. -v /app/redis/redis.conf:/etc/redis/redis.conf \
    10. -v /app/redis/data:/data \
    11. -d redis:6.0.8 redis-server /etc/redis/redis.conf \
    12. --requirepass 123456
    1. docker ps
    2. #CONTAINER ID IMAGE STATUS NAMES PORTS
    3. #9c38512676f5 redis:6.0.8 Up About a minute myredis 0.0.0.0:6379
    4. #进入Redis容器内
    5. docker exec -it myredis /bin/bash
    6. redis-cli
    1. auth 123456
    2. #OK
    3. set k1 v1
    4. #OK

    13. Docker中Redis集群配置

    13.1 新建6个docker容器redis实例

    1. # --name redis-node-1 容器名称
    2. # --net host 使用宿主机的IP和端口
    3. # --privileged=true 获取宿主机root用户权限
    4. # redis:6.0.8 redis镜像和版本号
    5. # --cluster-enabled yes 开启redis集群
    6. # --appendonly yes 开启持久化
    7. # --port 6381 redis端口号
    8. docker run -d --name redis-node-1 --net host --privileged=true \
    9. -v /data/redis/share/redis-node-1:/data \
    10. redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381
    11. docker run -d --name redis-node-2 --net host --privileged=true \
    12. -v /data/redis/share/redis-node-2:/data redis:6.0.8 \
    13. --cluster-enabled yes --appendonly yes --port 6382
    14. docker run -d --name redis-node-3 --net host --privileged=true \
    15. -v /data/redis/share/redis-node-3:/data redis:6.0.8 \
    16. --cluster-enabled yes --appendonly yes --port 6383
    17. docker run -d --name redis-node-4 --net host --privileged=true \
    18. -v /data/redis/share/redis-node-4:/data redis:6.0.8 \
    19. --cluster-enabled yes --appendonly yes --port 6384
    20. docker run -d --name redis-node-5 --net host --privileged=true \
    21. -v /data/redis/share/redis-node-5:/data redis:6.0.8 \
    22. --cluster-enabled yes --appendonly yes --port 6385
    23. docker run -d --name redis-node-6 --net host --privileged=true \
    24. -v /data/redis/share/redis-node-6:/data redis:6.0.8 \
    25. --cluster-enabled yes --appendonly yes --port 6386

    13.2 构建集群关系

    1. #随便进入一个实例,比如redis-node-1
    2. docker exec -it redis-node-1 /bin/bash
    3. # --cluster-replicas 1 表示为每个master创建一个slave节点
    4. redis-cli --cluster create 192.168.235.130:6381 192.168.235.130:6382 \
    5. 192.168.235.130:6383 192.168.235.130:6384 192.168.235.130:6385 \
    6. 192.168.235.130:6386 --cluster-replicas 1

    一共有从0到16383,总共16384个Hash槽,这里分成了三部分。

    节点中,前三个是master,后三个是slave 

     13.3 查看集群状态

    1. #宿主机或外部设备连接6381端口的Redis,以集群的方式
    2. # -c 集群的方式
    3. redis-cli -p 6381 -c
    4. 127.0.0.1:6381> set k1 v1
    5. #-> Redirected to slot [12706] located at 192.168.235.130:6383
    6. #OK
    7. 127.0.0.1:6381> cluster info
    8. #cluster_slots_assigned:16384
    9. #cluster_slots_ok:16384
    10. #cluster_known_nodes:6
    11. #cluster_current_epoch:6
    12. 127.0.0.1:6381> cluster nodes
    13. #30181254fa5875f82c3fc3ef21f24cf7f53b56c0 192.168.235.130:6381@16381 myself,master - 0 1670068681000 1 connected 0-5460.....
    14. redis-cli --cluster check 192.168.235.130:6381
    15. #192.168.235.130:6381 (30181254...) -> 0 keys | 5461 slots | 1 slaves.
    16. #192.168.235.130:6383 (f3bd197d...) -> 1 keys | 5461 slots | 1 slaves.
    17. #192.168.235.130:6382 (232e1ef2...) -> 0 keys | 5462 slots | 1 slaves.
    18. #[OK] 1 keys in 3 masters

    13.4 主从容错切换迁移

    1. # 停掉节点1,模拟宕机
    2. docker stop redis-node-1
    3. #等待1分钟后
    4. #这次连6382端口的Redis
    5. #6386端口的Redis由原来的slave变成了master
    6. #6381端口的Redis显示为fail
    7. redis-cli -p 6382 -c
    8. 127.0.0.1:6382> CLUSTER nodes
    9. #b205b77c378323c79 192.168.235.130:6386@16386 master - 0 1670074592353 7 connected
    10. #30181254fa5875f82 192.168.235.130:6381@16381 master,fail - 1670074369387
    11. # 启动节点1,模拟已经修复
    12. docker start redis-node-1
    13. #等待1分钟后
    14. #再次连6382端口的Redis
    15. #6386端口的Redis彻底变成了master
    16. #6381端口的Redis显示为只能变成是slave
    17. redis-cli -p 6382 -c
    18. 127.0.0.1:6382> CLUSTER nodes
    19. #b205b77c378323c79 192.168.235.130:6386@16386 master - 0 1670075158169 7 connected 0-5460
    20. #30181254fa5875f82 192.168.235.130:6381@16381 slave
    21. # 停掉节点6,模拟宕机
    22. docker stop redis-node-6
    23. #等待1分钟后
    24. #这次连6382端口的Redis
    25. #6381端口的Redis再次变成了master
    26. #6386端口的Redis显示为fail
    27. redis-cli -p 6382 -c
    28. 127.0.0.1:6382> CLUSTER nodes
    29. #b205b77c378323c79 192.168.235.130:6386@16386 master,fail - 1670075633613 1670075628493
    30. #30181254fa5875f82 192.168.235.130:6381@16381 master - 0 1670075690000 8 connected
    31. # 启动节点6,模拟已经修复
    32. docker start redis-node-6
    33. #等待1分钟后
    34. #再次连6382端口的Redis
    35. #6381端口的Redis彻底变成了master
    36. #6386端口的Redis显示为只能变成是slave
    37. redis-cli -p 6382 -c
    38. 127.0.0.1:6382> CLUSTER nodes
    39. #b205b77c378323c79 192.168.235.130:6386@16386 slave 30181254fa5875f82 8 connected
    40. #30181254fa5875f82 192.168.235.130:6381@16381 master - 0 1670075963000 8 connected

    13.5 主从扩容

    1. # 再增加两个节点
    2. docker run -d --name redis-node-7 --net host --privileged=true \
    3. -v /data/redis/share/redis-node-7:/data redis:6.0.8 \
    4. --cluster-enabled yes --appendonly yes --port 6387
    5. docker run -d --name redis-node-8 --net host --privileged=true \
    6. -v /data/redis/share/redis-node-8:/data redis:6.0.8 \
    7. --cluster-enabled yes --appendonly yes --port 6388
    8. docker ps
    9. # 进入redis-node-7
    10. docker exec -it redis-node-7 /bin/bash
    11. #将新增的6387节点作为master节点加入原集群
    12. redis-cli --cluster add-node 192.168.235.130:6387 192.168.235.130:6381
    13. # 检查集群情况,会看到6387已经是master,目前还没有slave,此时槽号也为空
    14. redis-cli --cluster check 192.168.235.130:6381
    15. #192.168.235.130:6381 (30181254...) -> 0 keys | 5461 slots | 1 slaves.
    16. #192.168.235.130:6382 (232e1ef2...) -> 0 keys | 5462 slots | 1 slaves.
    17. #192.168.235.130:6383 (f3bd197d...) -> 1 keys | 5461 slots | 1 slaves.
    18. #192.168.235.130:6387 (68d7de26...) -> 0 keys | 0 slots | 0 slaves.
    19. #[OK] 1 keys in 4 masters.
    20. #M: 68d7de26299d486f121311270d89a360142172d0 192.168.235.130:6387
    21. # slots: (0 slots) master
    22. # 重新分派槽号
    23. # 16384 / 4 = 4096
    24. # nodeID填写6387对应的ID=68d7de26299d486f121311270d89a360142172d0
    25. # 键入“all”将所有节点用作哈希槽的源节点
    26. redis-cli --cluster reshard 192.168.235.130:6381
    27. # How many slots do you want to move (from 1 to 16384)?
    28. 4096
    29. # What is the receiving node ID?
    30. 68d7de26299d486f121311270d89a360142172d0
    31. #Please enter all the source node IDs.
    32. # Type 'all' to use all the nodes as source nodes for the hash slots.
    33. # Type 'done' once you entered all the source nodes IDs.
    34. #Source node #1:
    35. all
    36. #Do you want to proceed with the proposed reshard plan (yes/no)?
    37. yes
    38. # 检查集群情况,会看到6387目前还没有slave,此时槽号有4096个,其他三个也是4096个了
    39. # 另外一个现象是6387的槽号是分了三段。原因是重新分配成本太高,其他三个是在原来各自的基础上做的减法,6387所获得是其他三个节点每个都拿出来一部分给它的
    40. redis-cli --cluster check 192.168.235.130:6381
    41. #192.168.235.130:6381 (30181254...) -> 0 keys | 4096 slots | 1 slaves.
    42. #192.168.235.130:6382 (232e1ef2...) -> 0 keys | 4096 slots | 1 slaves.
    43. #192.168.235.130:6383 (f3bd197d...) -> 1 keys | 4096 slots | 1 slaves.
    44. #192.168.235.130:6387 (68d7de26...) -> 0 keys | 4096 slots | 0 slaves.
    45. #M: 68d7de26299d486f121311270d89a360142172d0 192.168.235.130:6387
    46. # slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
    47. #为主节点6387分配从节点6388
    48. #redis-cli --cluster add-node ip:新加的slave端口 ip:master端口 \
    49. #--cluster-slave --cluster-master-id master主机节点ID
    50. redis-cli --cluster add-node 192.168.235.130:6388 192.168.235.130:6387 \
    51. --cluster-slave --cluster-master-id 68d7de26299d486f121311270d89a360142172d0
    52. #检查集群情况,会看到6387,此时槽号有4096个,且也有了一个6388端口号的slave
    53. redis-cli --cluster check 192.168.235.130:6381
    54. #192.168.235.130:6381 (30181254...) -> 0 keys | 4096 slots | 1 slaves.
    55. #192.168.235.130:6382 (232e1ef2...) -> 0 keys | 4096 slots | 1 slaves.
    56. #192.168.235.130:6383 (f3bd197d...) -> 1 keys | 4096 slots | 1 slaves.
    57. #192.168.235.130:6387 (68d7de26...) -> 0 keys | 4096 slots | 1 slaves.
    58. #S: 81c8446a8a94481efcf2de1bab000ccdb997fbce 192.168.235.130:6388
    59. # slots: (0 slots) slave
    60. # replicates 68d7de26299d486f121311270d89a360142172d0
    61. #M: 68d7de26299d486f121311270d89a360142172d0 192.168.235.130:6387
    62. # slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
    63. # 1 additional replica(s)

    13.6 主从缩容

    1. # 检查集群情况
    2. # 6387的从服务器个数此时显示为1
    3. # 并拿到从服务器6388的节点ID=81c8446a8a94481efcf2de1bab000ccdb997fbce
    4. redis-cli --cluster check 192.168.235.130:6381
    5. #192.168.235.130:6387 (68d7de26...) -> 0 keys | 4096 slots | 1 slaves.
    6. #S: 81c8446a8a94481efcf2de1bab000ccdb997fbce 192.168.235.130:6388
    7. # slots: (0 slots) slave
    8. # 将6388删除
    9. redis-cli --cluster del-node 192.168.235.130:6388 \
    10. 81c8446a8a94481efcf2de1bab000ccdb997fbce
    11. # 检查集群情况
    12. # 6387的从服务器个数此时显示为0,有4096个槽号
    13. # 6387的节点ID=68d7de26299d486f121311270d89a360142172d0
    14. # 6381的节点ID=30181254fa5875f82c3fc3ef21f24cf7f53b56c0
    15. redis-cli --cluster check 192.168.235.130:6382
    16. #192.168.235.130:6382 (232e1ef2...) -> 0 keys | 4096 slots | 1 slaves.
    17. #192.168.235.130:6387 (68d7de26...) -> 0 keys | 4096 slots | 0 slaves.
    18. #192.168.235.130:6381 (30181254...) -> 0 keys | 4096 slots | 1 slaves.
    19. #192.168.235.130:6383 (f3bd197d...) -> 1 keys | 4096 slots | 1 slaves.
    20. #M: 68d7de26299d486f121311270d89a360142172d0 192.168.235.130:6387
    21. # slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
    22. #M: 30181254fa5875f82c3fc3ef21f24cf7f53b56c0 192.168.235.130:6381
    23. # slots:[1365-5460] (4096 slots) master
    24. # 1 additional replica(s)
    25. # 将6387的槽号都给6381
    26. redis-cli --cluster reshard 192.168.235.130:6381
    27. #How many slots do you want to move (from 1 to 16384)?
    28. 4096
    29. #What is the receiving node ID?
    30. 30181254fa5875f82c3fc3ef21f24cf7f53b56c0
    31. #Please enter all the source node IDs.
    32. # Type 'all' to use all the nodes as source nodes for the hash slots.
    33. # Type 'done' once you entered all the source nodes IDs.
    34. #Source node #1:
    35. 68d7de26299d486f121311270d89a360142172d0
    36. #Source node #2:
    37. done
    38. #Do you want to proceed with the proposed reshard plan (yes/no)?
    39. yes
    40. # 检查集群情况
    41. # 6387显示此时已经是0个槽,0个slave
    42. # 6381显示此时已经是8192个槽
    43. redis-cli --cluster check 192.168.235.130:6381
    44. #192.168.235.130:6381 (30181254...) -> 0 keys | 8192 slots | 1 slaves.
    45. #192.168.235.130:6382 (232e1ef2...) -> 0 keys | 4096 slots | 1 slaves.
    46. #192.168.235.130:6383 (f3bd197d...) -> 1 keys | 4096 slots | 1 slaves.
    47. #192.168.235.130:6387 (68d7de26...) -> 0 keys | 0 slots | 0 slaves.
    48. #M: 68d7de26299d486f121311270d89a360142172d0 192.168.235.130:6387
    49. # slots: (0 slots) master
    50. #M: 30181254fa5875f82c3fc3ef21f24cf7f53b56c0 192.168.235.130:6381
    51. # slots:[0-6826],[10923-12287] (8192 slots) master
    52. # 1 additional replica(s)
    53. #将6387删除
    54. redis-cli --cluster del-node 192.168.235.130:6387 \
    55. 68d7de26299d486f121311270d89a360142172d0
    56. # 检查集群情况
    57. # 6387已经被删除
    58. redis-cli --cluster check 192.168.235.130:6381
    59. #192.168.235.130:6381 (30181254...) -> 0 keys | 8192 slots | 1 slaves.
    60. #192.168.235.130:6382 (232e1ef2...) -> 0 keys | 4096 slots | 1 slaves.
    61. #192.168.235.130:6383 (f3bd197d...) -> 1 keys | 4096 slots | 1 slaves.

    14. DockerFile解析

    14.1 DockerFile简介

            官网:Dockerfile reference | Docker Documentation

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

           从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段:Dockerfile是软件的原材料;Docker镜像是软件的交付品;Docker容器则可以认为是软件镜像的运行态,也即依照镜像运行的容器实例。
           Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

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

    14.2 DockerFile案例演示

       需求:原始的centos不包含vim/ifconfig/java等命令,让其具备

    1. docker search centos
    2. #拉取一个centos镜像
    3. docker pull centos:7
    4. #才204MB,这个里面是不包含vim/ifconfig/java等命令的
    5. docker images
    6. #REPOSITORY TAG IMAGE ID CREATED SIZE
    7. #centos 7 eeb6ee3f44bd 14 months ago 204MB
    8. mkdir /myfile
    9. cd /myfile
    10. wget https://mirrors.yangxingzhen.com/jdk/jdk-8u171-linux-x64.tar.gz
    11. # 编辑文件,必须是大写的D
    12. vim Dockerfile
    1. #FROM 当前新镜像是基于哪个镜像,指定一个已经存在的镜像作为模板,第一条必须是from
    2. FROM centos:7
    3. #MAINTAINER 镜像维护者的姓名和邮箱地址
    4. MAINTAINER zmj
    5. ENV MYPATH /usr/local
    6. #WORKDIR 指定在创建容器后,终端默认登录进来后的工作目录,一个落脚点
    7. WORKDIR $MYPATH
    8. #安装vim编辑器
    9. RUN yum -y install vim
    10. #安装ifconfig命令查看网络IP
    11. RUN yum -y install net-tools
    12. #安装java8及lib库
    13. RUN yum -y install glibc.i686
    14. RUN mkdir /usr/local/java
    15. #ADD 将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包
    16. # 是相对路径jar,把jdk-8u171-linux-x64.tar.gz添加到容器中
    17. # 安装包必须要和Dockerfile文件在同一位置
    18. ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/
    19. #配置java环境变量
    20. ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
    21. ENV JRE_HOME $JAVA_HOME/jre
    22. ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
    23. ENV PATH $JAVA_HOME/bin:$PATH
    24. #EXPOSE 当前容器对外暴露出的端口
    25. EXPOSE 80
    26. #CMD 指定容器启动后要做什么
    27. # 可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换
    28. CMD echo $MYPATH
    29. CMD echo "success--------------ok"
    30. CMD /bin/bash
    1. # 构建,名称centos7java8,标签1.5,后面加个点
    2. docker build -t centos7java8:1.5 .
    3. docker images
    4. #REPOSITORY TAG IMAGE ID CREATED SIZE
    5. #centos7java8 1.5 97cffc20b22e 44 seconds ago 1.25GB
    6. #centos 7 eeb6ee3f44bd 14 months ago 204MB
    7. #运行新建的镜像
    8. docker run -it 97cffc20b22e /bin/bash
    9. java -version
    10. #java version "1.8.0_171"

    15. 虚悬镜像

    仓库名、标签都是的镜像,俗称dangling image

    1. # 如果Dockerfile文件内容有误,或是执行异常,就会出现镜像名称和TAG都显示为none的镜像
    2. # 这里模拟一个
    3. cd /myfile
    4. cat>Dockerfile <<-EOF
    5. from ubuntu
    6. CMD echo 'action is success'
    7. EOF
    8. docker build .
    9. #已经出现一个虚悬镜像
    10. docker image ls -f dangling=true
    11. #REPOSITORY TAG IMAGE ID CREATED SIZE
    12. # c0100057060b 22 hours ago 72.8MB
    13. #虚悬镜像已经失去存在价值,可以删除
    14. #另外还存在一定的安全隐患,建议删除
    15. docker image prune

    16. 通过Dockerfile发布微服务部署到Docker容器

    16.1 先打包成jar 

       这里模拟用一个最简单的springbootdemo来实现

    新建一个目录 

      

    16.2 上传jar文件到Centos服务器上

     

     

     

    16.3 编写Dockerfile

    1. cd /mydocker
    2. vim Dockerfile
    1. # 基础镜像使用java
    2. FROM openjdk:8
    3. # 作者
    4. MAINTAINER zmj
    5. # VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
    6. VOLUME /tmp
    7. # 将jar包添加到容器中并更名为zmj_docker.jar
    8. ADD springbootdemo-0.0.1-SNAPSHOT.jar zmj_docker.jar
    9. # 运行jar包
    10. RUN bash -c 'touch /zmj_docker.jar'
    11. ENTRYPOINT ["java","-jar","/zmj_docker.jar"]
    12. #暴露6001端口作为微服务
    13. EXPOSE 6001

    16.4 构建并运行镜像

    1. # 打包成镜像文件
    2. docker build -t zmj_docker:1.6 .
    3. docker images
    4. #REPOSITORY TAG IMAGE ID CREATED SIZE
    5. #zmj_docker 1.6 ce2ae8cdbb79 48 seconds ago 565MB
    6. #后台运行镜像
    7. docker run -d -p 6001:6001 zmj_docker:1.6
    8. #测试一下,可以访问
    9. curl 127.0.0.1:6001/order/index
    10. 服务端口号: 6001 d42caf1b-2148-4dd5-8770-e6a0b3aee5d6

    17. Docker网络

    17.1 Docker网络的作用

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

     17.2 Docker网络模式

    17.3 Docker网络相关命令 

    1. # 观察网络,发现会多一个名字为docker0的虚拟网桥,并且IP是172.17.0.1
    2. ifconfig
    3. #docker0: flags=4099 mtu 1500
    4. # inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
    5. # ether 02:42:01:c4:01:8c txqueuelen 0 (Ethernet)
    6. # RX packets 0 bytes 0 (0.0 B)
    7. # RX errors 0 dropped 0 overruns 0 frame 0
    8. # TX packets 0 bytes 0 (0.0 B)
    9. # TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
    10. # 查看docker网络模式,默认会创建三大网络模式
    11. docker network ls
    12. #NETWORK ID NAME DRIVER SCOPE
    13. #5c6d08db6309 bridge bridge local
    14. #6183fe01b81c host host local
    15. #13186cff8686 none null local
    16. # 创建一个网络
    17. docker network create network_test
    18. # 删除一个网络
    19. docker network rm network_test
    20. docker run -it --name u1 ubuntu bash
    21. # 按Ctrl+Q+P退出
    22. docker run -it --name u2 ubuntu bash
    23. # 按Ctrl+Q+P退出
    24. # 查看u2的网络源数据,内部IP=172.17.0.3
    25. docker inspect u2 | tail -n 20
    26. # "Networks": {
    27. # "bridge": {
    28. # "IPAMConfig": null,
    29. # "Links": null,
    30. # "Aliases": null,
    31. # "NetworkID": #"5c6d08db6309cd42c10f484cf635765ae5ed02e2293e2e49d0d40ee051bf7803",
    32. # "EndpointID": #"9b43344db5e119c2960b25372b12240c99dd2e906b971ac064e3ee6a4da97caf",
    33. # "Gateway": "172.17.0.1",
    34. # "IPAddress": "172.17.0.3"
    35. # 查看u1的网络源数据,内部IP=172.17.0.2
    36. docker inspect u1 | tail -n 20
    37. # "Networks": {
    38. # "bridge": {
    39. # "IPAMConfig": null,
    40. # "Links": null,
    41. # "Aliases": null,
    42. # "NetworkID": #"5c6d08db6309cd42c10f484cf635765ae5ed02e2293e2e49d0d40ee051bf7803",
    43. # "EndpointID": #"e6e3d6256806317a106c91fce44fccb720272c09c9dd6ca632344fdd05e24a84",
    44. "Gateway": "172.17.0.1",
    45. "IPAddress": "172.17.0.2"
    46. ###结论:docker容器实例不同,内部IP也不同
    47. ### 另外如果实例停了再开,原来的内部IP是有可能改变的

    17.4 Docker网络模式-bridge

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

           Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
           docker run 的时候,没有指定network的话默认使用的网桥模式就是bridge,使用的就是docker0。在宿主机ifconfig,就可以看到docker0和自己create的network(后面讲)eth0,eth1,eth2……代表网卡一,网卡二,网卡三……,lo代表127.0.0.1,即localhost,inet addr用来表示网卡的IP地址

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

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

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

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

    17.5 Docker网络模式-host

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

    docker run -d  --network host --name tomcat83 billygoo/tomcat8-jdk8

    17.6 Docker网络模式-container

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

    1. docker run -it --name alpine1 alpine /bin/sh
    2. # alpine2使用alpine1的网络配置,同一IP
    3. # 如果此时alpine1停了,alpine2同时就获取不到alpine1的了
    4. docker run -it --network container:alpine1 --name alpine2 alpine /bin/sh

    17.7 自定义Docker网络

    1. # 创建网络名为zmj_network
    2. docker network create zmj_network
    3. # 两个实例都加入到刚才创建的新网络中
    4. docker run -d -p 8081:8080 --network zmj_network --name tomcat81 billygoo/tomcat8-jdk8
    5. docker run -d -p 8082:8080 --network zmj_network --name tomcat82 billygoo/tomcat8-jdk8
    6. docker exec -it tomcat81 bash
    7. ping tomcat82
    8. #PING tomcat82 (172.19.0.3) 56(84) bytes of data.
    9. #64 bytes from tomcat82.zmj_network (172.19.0.3): icmp_seq=1 ttl=64 time=0.286 ms
    10. #64 bytes from tomcat82.zmj_network (172.19.0.3): icmp_seq=2 ttl=64 time=0.350 ms
    11. docker exec -it tomcat82 bash
    12. ping tomcat81
    13. #PING tomcat81 (172.19.0.2) 56(84) bytes of data.
    14. #64 bytes from tomcat81.zmj_network (172.19.0.2): icmp_seq=1 ttl=64 time=0.056 ms
    15. #64 bytes from tomcat81.zmj_network (172.19.0.2): icmp_seq=2 ttl=64 time=0.098 ms

    18. Docker-compose容器编排

     18.1  Docker-Compose简介

           Docker-Compose是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。 
           Compose 是 Docker 公司推出的一个工具软件,可以管理多个 Docker 容器组成一个应用。你需要定义一个 YAML 格式的配置文件docker-compose.yml,写好多个容器之间的调用关系。然后,只要一个命令,就能同时启动/关闭这些容器。
           docker建议我们每一个容器中只运行一个服务,因为docker容器本身占用资源极少,所以最好是将每个服务单独的分割开来但是这样我们又面临了一个问题?
    如果我需要同时部署好多个服务,难道要每个服务单独写Dockerfile然后在构建镜像,构建容器,这样累都累死了,所以docker官方给我们提供了docker-compose多服务部署的工具
           例如要实现一个Web微服务项目,除了Web服务容器本身,往往还需要再加上后端的数据库mysql服务容器,redis服务器,注册中心eureka,甚至还包括负载均衡容器等等。
    Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。
           可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose 解决了容器与容器之间如何管理编排的问题。
    官网:Compose file version 3 reference | Docker Documentation

    官网下载:Overview | Docker Documentation 

    18.2 Docker-compose下载安装

    1. vim /etc/hosts
    2. # 140.82.112.4 github.com
    3. systemctl daemon-reload
    4. curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    5. chmod +x /usr/local/bin/docker-compose
    6. docker-compose --version
    7. #docker-compose version 1.29.2, build 5becea4c

    18.3 不使用Docker-compose容器编排

    ...\springboot-zmj\springbootdemo\src\main\resources\application.properties

    1. server.port=6001
    2. # ========================alibaba.druid相关配置=====================
    3. spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    4. spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    5. spring.datasource.url=jdbc:mysql://192.168.235.135:13306/mytest?useUnicode=true&characterEncoding=utf-8&useSSL=false
    6. spring.datasource.username=root
    7. spring.datasource.password=123456
    8. spring.datasource.druid.test-while-idle=false
    9. # ========================redis相关配置=====================
    10. spring.redis.database=0
    11. spring.redis.host=192.168.235.135
    12. spring.redis.port=16379
    13. spring.redis.password=
    14. spring.redis.lettuce.pool.max-active=8
    15. spring.redis.lettuce.pool.max-wait=-1ms
    16. spring.redis.lettuce.pool.max-idle=8
    17. spring.redis.lettuce.pool.min-idle=0
    18. # ========================mybatis相关配置===================
    19. mybatis.mapper-locations=classpath:mapper/*.xml
    20. mybatis.type-aliases-package=com.zmj.springbootdemo.entity
    21. # ========================swagger=====================
    22. spring.swagger2.enabled=true
    1. # 运行单独的mysql容器实例
    2. docker run -p 13306:3306 --name mysql5.7 --privileged=true \
    3. -v /home/zmj/mysql/conf:/etc/mysql/conf.d \
    4. -v /home/zmj/mysql/logs:/logs \
    5. -v /home/zmj/mysql/data:/var/lib/mysql \
    6. -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
    7. docker exec -it mysql5.7 /bin/bash
    8. mysql -uroot -p
    9. mysql> create database mytest;
    10. # 运行单独的redis容器实例
    11. docker run -p 16379:6379 --name redis1608 --privileged=true \
    12. -v /app/redis/redis.conf:/etc/redis/redis.conf \
    13. -v /app/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf
    14. cd /mydocker
    15. # 构建微服务的镜像,跟之前类似
    16. docker build -t zmj_docker:1.7 .
    17. docker exec -it redis1608 /bin/bash
    18. redis-cli
    19. docker images
    20. #REPOSITORY TAG IMAGE ID CREATED SIZE
    21. #zmj_docker 1.7 0d3ea131cc72 19 seconds ago 642MB
    22. docker run -d -p 6001:6001 0d3ea131cc72

    http://192.168.235.135:6001/swagger-ui.html#/

     18.4 使用Docker-compose容器编排

     ...\springboot-zmj\springbootdemo\src\main\resources\application.properties

    通过服务名访问,与IP无关。这里只展示修改部分

    1. #spring.datasource.url=jdbc:mysql://192.168.235.135:13306/mytest?useUnicode=true&characterEncoding=utf-8&useSSL=false
    2. spring.datasource.url=jdbc:mysql://mysql:13306/mytest?useUnicode=true&characterEncoding=utf-8&useSSL=false
    3. #spring.redis.host=192.168.235.135
    4. spring.redis.host=redis

    编写docker-compose.yml文件

    1. cd /mydocker
    2. vim docker-compose.yml
    1. version: "3"
    2. services:
    3. microService:
    4. image: zmj_docker:1.7
    5. container_name: ms01
    6. ports:
    7. - "6001:6001"
    8. volumes:
    9. - /app/microService:/data
    10. networks:
    11. - dream_net
    12. depends_on:
    13. - redis
    14. - mysql
    15. redis:
    16. image: redis:6.0.8
    17. ports:
    18. - "16379:6379"
    19. volumes:
    20. - /app/redis/redis.conf:/etc/redis/redis.conf
    21. - /app/redis/data:/data
    22. networks:
    23. - dream_net
    24. command: redis-server /etc/redis/redis.conf
    25. mysql:
    26. image: mysql:5.7
    27. environment:
    28. MYSQL_ROOT_PASSWORD: '123456'
    29. MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
    30. MYSQL_DATABASE: 'mytest'
    31. MYSQL_USER: 'zmj'
    32. MYSQL_PASSWORD: 'zmj123'
    33. ports:
    34. - "13306:3306"
    35. volumes:
    36. - /app/mysql/db:/var/lib/mysql
    37. - /app/mysql/conf/my.cnf:/etc/my.cnf
    38. - /app/mysql/init:/docker-entrypoint-initdb.d
    39. networks:
    40. - dream_net
    41. command: --default-authentication-plugin=mysql_native_password #解决外部无法访问
    42. networks:
    43. dream_net:
    1. #查看刚才写的配置信息是否有误,不输出内容,就是没错
    2. docker-compose config -q
    3. cd /mydocker
    4. # 构建微服务的镜像,跟之前类似
    5. docker build -t zmj_docker:1.7 .
    6. # 启动所有docker-compose服务并后台运行
    7. docker-compose up -d
    8. # 停止所有docker-compose服务
    9. docker-compose stop

    19. Docker轻量级可视化工具Portainer 

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

    19.1 Portainer的安装

    1. # 运行portainer实例
    2. # --restart=always 表示docker重启后,这个容器实例也会跟着重启
    3. docker run -d -p 8000:8000 -p 9000:9000 --name portainer \
    4. --restart=always -v /var/run/docker.sock:/var/run/docker.sock \
    5. -v portainer_data:/data portainer/portainer

    http://192.168.235.135:9000

    用户: admin   密码至少八位,比如:111...aaa

     本地连接

    19.2 通过Portainer安装Nginx

     设置容器名称、镜像、端口

     

     

    20. Docker容器监控之CAdvisor+InfluxDB+Granfana

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

    20.1 安装CAdvisor+InfluxDB+Granfana

    1. mkdir -p /mydocker/cig
    2. cd /mydocker/cig
    3. vim docker-compose.yml
    1. version: '3.1'
    2. volumes:
    3. grafana_data: {}
    4. services:
    5. influxdb:
    6. image: tutum/influxdb:0.9
    7. restart: always
    8. environment:
    9. - PRE_CREATE_DB=cadvisor
    10. ports:
    11. - "8083:8083"
    12. - "8086:8086"
    13. volumes:
    14. - ./data/influxdb:/data
    15. cadvisor:
    16. image: google/cadvisor
    17. links:
    18. - influxdb:influxsrv
    19. command:
    20. -storage_driver=influxdb
    21. -storage_driver_db=cadvisor
    22. -storage_driver_host=influxsrv:8086
    23. restart: always
    24. ports:
    25. - "8080:8080"
    26. volumes:
    27. - /:/rootfs:ro
    28. - /var/run:/var/run:rw
    29. - /sys:/sys:ro
    30. - /var/lib/docker/:/var/lib/docker:ro
    31. grafana:
    32. user: "104"
    33. image: grafana/grafana
    34. user: "104"
    35. restart: always
    36. links:
    37. - influxdb:influxsrv
    38. ports:
    39. - "3000:3000"
    40. volumes:
    41. - grafana_data:/var/lib/grafana
    42. environment:
    43. - HTTP_USER=admin
    44. - HTTP_PASS=admin
    45. - INFLUXDB_HOST=influxsrv
    46. - INFLUXDB_PORT=8086
    47. - INFLUXDB_NAME=cadvisor
    48. - INFLUXDB_USER=root
    49. - INFLUXDB_PASS=root
    1. docker-compose config -q
    2. docker-compose up -d

    浏览cAdvisor收集服务
    http://192.168.235.135:8080/

     浏览influxdb存储服务
    http://192.168.235.135:8083/

     浏览grafana展现服务
    http://192.168.235.135:3000/

     20.2 grafana配置数据源

     

     20.3 grafana配置显示面板

     

     显示效果

     编辑下查询条件

     

    21. Docker安装RabbitMQ

    21.1 拉取镜像

    1. docker pull rabbitmq:3.8.27-management
    2. docker images rabbitmq
    3. #REPOSITORY TAG IMAGE ID CREATED SIZE
    4. #rabbitmq 3.8.27-management 75f0db0d49bf 10 months ago 253MB

     21.2 启动容器

    1. mkdir -p /mydocker/rabbitmq
    2. # 启动容器并且指定web管理的账户密码
    3. # 5672:5672 宿主机:docker容器中
    4. # 15672:15672 web页面管理访问地址
    5. docker run -d --hostname myrabbitmq --name rabbitmq \
    6. -p 15672:15672 -p 5672:5672 \
    7. -v /mydocker/rabbitmq/data:/data/rabbitmq \
    8. -e RABBITMQ_DEFAULT_USER=admin \
    9. -e RABBITMQ_DEFAULT_PASS=admin \
    10. rabbitmq:3.8.27-management

     21.3 进入容器

    docker exec -it rabbitmq /bin/bash
    1. # 开启web页面插件
    2. rabbitmq-plugins enable rabbitmq_management
    3. # 创建账号,add_user后面分别为:账户 密码
    4. rabbitmqctl add_user admin2 admin2
    5. # 设置用户角色
    6. rabbitmqctl set_user_tags admin2 administrator
    7. # 设置用户权限
    8. # rabbitmqctl set_permissions [-p ]
    9. rabbitmqctl set_permissions -p "/" admin2 ".*" ".*" ".*"
    10. # 查看用户列表
    11. rabbitmqctl list_users
    12. #Listing users ...
    13. #user tags
    14. #admin [administrator]
    15. #admin2 [administrator]

     21.4 登录管理页面 

     

    21.5 RabbitMQ重要概念

    RabbitMQ是一个由Erlang开发的AMQP(Advanved Message Queue)的开源实现。

    Message:消息。消息是不具名的,它由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成。这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等


    Publisher:指的是消息的生产者。也是一个向交换器发布消息的客户端应用程序。

    Consumer:指的是消息的消费者。表示一个从消息队列中取得消息的客户端应用程序。

    Exchange
    –消息交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。它指定消息按什么规则,路由到哪个队列。
    –Exchange有4种类型:direct(默认),fanout, topic, 和headers,不同类型的Exchange转发消息的策略有所区别

    Queue:消息队列。用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。
    –消息队列,提供了FIFO的处理机制,具有缓存消息的能力。rabbitmq中,队列消息可以设置为持久化,临时或者自动删除。
    –设置为持久化的队列,queue中的消息会在server本地硬盘存储一份,防止系统crash,数据丢失
    –设置为临时队列,queue中的数据在系统重启之后就会丢失
    –设置为自动删除的队列,当不存在用户连接到server,队列中的数据会被自动删除

    Binding:绑定。用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。
    –将一个特定的Exchange 和一个特定的Queue 绑定起来。
    –Exchange 和Queue的绑定可以是多对多的关系。

    Connection:网络连接,比如一个TCP连接。

    Channel:信道。多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内的虚拟连接。AMQP命令都是通过信道发过去的。不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说,建立和销毁TCP都是非常昂贵的开销,所以引入了信道的概念,以复用一条TCP连接。


    Broker:表示消息队列服务器实体。
    –它提供一种传输服务,它的角色就是维护一条从生产者到消费者的路线,保证数据能按照指定的方式进行传输


    virtual host(vhosts )虚拟主机。表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个vhost本质上就是一个mini版的RabbitMQ服务器,拥有自己的队列、交换器、绑定和权限机制。vhost是AMQP概念的基础,必须在连接时指定。RabbitMQ默认的vhost是/
    –在rabbitmq server上可以创建多个虚拟的message broker,又叫做virtual hosts (vhosts)
    –每一个vhost本质上是一个mini-rabbitmq server,分别管理各自的exchange,和bindings
    –vhost相当于物理的server,可以为不同app提供边界隔离
    –producer和consumer连接rabbit server需要指定一个vhost

    21.6 新建交换器

    新建三种类型的交换机

    21.7 新建队列

    新建四个队列

      

      

    21.8 绑定

    1)交换器exchage.directexchage.fanout分别绑定四个队列

       

      

     2)交换器exchage.topic绑定zmj开头的三个队列到路由键zmj.#

     

     

     2)交换器exchage.topic绑定news结尾的两个队列到路由键*.news

     21.9 Direct交换器发消息

     1)交换器exchange.direct发消息

    2比如路由键选择zmj,内容填写到Payload 

    3由于dicrect交换器是完全匹配路由键的,所以通过zmj路由键发送的消息,只有zmj队列可以收到消息

    4点击zmj队列进入到zmj队列里面,然后点击Get Message(s)获取发送信息

     

     21.10 fanout交换器发消息

     1)交换器exchange.fanout发消息

     2比如路由键选择dream.news,内容填写到Payload 

     3由于fanout交换器是不管路由键是什么,只要是与其绑定的队列,都可以收到消息

     4点击dream.news队列进入到dream.news队列里面,然后点击Get Message(s)获取发送信息

     21.11 topic交换器发消息

     1)交换器exchange.topic发消息

      2比如路由键选择dream.news,内容填写到Payload 

     3由于topic交换器是通过匹配规则来决定发送消息给队列,所以满足条件的是zmj.news和dream.news两个队列,即都是*.news

     4点击dream.news队列进入到dream.news队列里面,然后选择自动应答

    点击Get Message(s)两次获取发送信息,每获取一次,消息就会被删除

    22. Docker安装Elasticsearch

    22.1 安装

    1. #拉取elasticsearch镜像
    2. docker pull elasticsearch
    3. #查看elasticsearch的镜像ID
    4. docker images | grep elasticsearch
    5. #elasticsearch latest 5acf0e8da90b 4 years ago 486MB
    1. #-Xms256m -Xmx256m 测试环境设置初始堆内存为256M,最大堆内存为256M
    2. docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d \
    3. -p 9200:9200 -p 9300:9300 --name ES01 5acf0e8da90b

    http://192.168.1.200:9200

    22.2 测试

     参考:索引员工文档 | Elasticsearch: 权威指南 | Elastic

     1)增删改查遵循RESTful风格PUT可以新增文档将 HTTP 命令由 PUT 改为 GET 可以用来检索文档,同样的,可以使用 DELETE 命令来删除文档,以及使用 HEAD 指令来检查文档是否存在。如果想更新已存在的文档,只需再次 PUT

    1. ########################插入三条数据
    2. #megacorp 索引名称
    3. #employee 类型名称
    4. PUT /megacorp/employee/1
    5. {
    6. "first_name" : "John",
    7. "last_name" : "Smith",
    8. "age" : 25,
    9. "about" : "I love to go rock climbing",
    10. "interests": [ "sports", "music" ]
    11. }
    12. PUT /megacorp/employee/2
    13. {
    14. "first_name" : "Jane",
    15. "last_name" : "Smith",
    16. "age" : 32,
    17. "about" : "I like to collect rock albums",
    18. "interests": [ "music" ]
    19. }
    20. PUT /megacorp/employee/3
    21. {
    22. "first_name" : "Douglas",
    23. "last_name" : "Fir",
    24. "age" : 35,
    25. "about": "I like to build cabinets",
    26. "interests": [ "forestry" ]
    27. }

    2)查询一号员工: 192.168.1.200:9200/megacorp/employee/1

    3)查询所有员工: 192.168.1.200:9200/megacorp/employee/_search

     

     4)根据条件查询:192.168.1.200:9200/megacorp/employee/_search?q=last_name:Smith

    5)根据表达式查询:http://192.168.1.200:9200/megacorp/employee/_search

    1. {
    2. "query" : {
    3. "bool": {
    4. "must": {
    5. "match" : {
    6. "last_name" : "smith"
    7. }
    8. },
    9. "filter": {
    10. "range" : {
    11. "age" : { "gt" : 30 }
    12. }
    13. }
    14. }
    15. }
    16. }

     其他的参考:更复杂的搜索 | Elasticsearch: 权威指南 | Elastic

    23. Docker安装Zookeeper 

    23.1 安装ZK服务端

    1. docker pull zookeeper:3.5.7
    2. # 数据挂载目录
    3. mkdir -p /mydata/zookeeper/data
    4. # 配置挂载目录
    5. mkdir -p /mydata/zookeeper/conf
    6. # 日志挂载目录
    7. mkdir -p /mydata/zookeeper/logs
    1. # 启动ZooKeeper容器
    2. # -e TZ="Asia/Shanghai" # 指定上海时区
    3. # -d # 表示在一直在后台运行容器
    4. # -p 2181:2181 # 对端口进行映射,将本地2181端口映射到容器内部的2181端口
    5. # --name # 设置创建的容器名称
    6. # -v # 将本地目录(文件)挂载到容器指定目录;
    7. # --restart always #始终重新启动zookeeper
    8. docker run -d --name zookeeper --privileged=true -p 2181:2181 \
    9. -v /mydata/zookeeper/data:/data -v /mydata/zookeeper/conf:/conf \
    10. -v /mydata/zookeeper/logs:/datalog zookeeper:3.5.7
    1. cd /mydata/zookeeper/conf
    2. vim zoo.cfg
    3. #一般会生成默认,如果想修改配置,进入此文件修改

    23.2 通过客户端连服务端

    1. docker ps
    2. # CONTAINER ID IMAGE NAMES
    3. # 8c89711ae723 zookeeper:3.5.7
    4. docker exec -it 8c89711ae723 /bin/bash
    5. cd bin
    6. ./zkCli.sh -server 127.0.0.1:2181
    7. ls /services
    8. [cloud-provider-payment]

  • 相关阅读:
    操作系统识别
    jdk1.8.191 JVM内存参数 InitialRAMPercentage和MinRAMPercentage
    CycleGAN 论文泛读
    原型工具与代码实现的差距及改进设想
    Opencv实现目标检测
    Hadoop3.0大数据处理学习4(案例:数据清洗、数据指标统计、任务脚本封装、Sqoop导出Mysql)
    C语言变量、指针的内存关系
    docker问题解决记录
    Postman报错:Error:‌ NETERR:‌ getaddrinfo ENOTFOUND localhost
    【Python】pytorch,CUDA是否可用,查看显卡显存剩余容量
  • 原文地址:https://blog.csdn.net/qq_30426943/article/details/127839536