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的那些事_第1张图片

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

Docker的那些事_第2张图片

Docker的那些事_第3张图片

 Docker的那些事_第4张图片

4. 在Centos7上安装Docker

Install Docker Engine on CentOS | Docker Documentation

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

Docker的那些事_第5张图片

# 修改或新增docker配置文件
vim /etc/docker/daemon.json
#graph代表docker指定的安装目录
#registry-mirrors 指定加速器地址
{
"registry-mirrors": ["https://fujwmaum.mirror.aliyuncs.com"],
"graph":"/opt/docker"
}
# 设置为国内阿里云的镜像源
yum-config-manager --add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 更新yum软件包索引
yum makecache fast
# 安装Docker引擎
yum -y install docker-ce docker-ce-cli containerd.io
#加载镜像:
systemctl daemon-reload
#设置开机自启动
systemctl enable docker
#查看docker是否开机自启
systemctl list-unit-files | grep enable | grep docker
#docker.service                                enabled
# 启动Docker服务
systemctl start docker
ps -ef | grep docker
#root       5835      1  3 07:20 ?        00:00:00 /usr/bin/dockerd -H
#root       6040   4378  0 07:20 pts/0    00:00:00 grep --color=auto docker
# 查看Docker版本号
docker --version
#Docker version 20.10.21, build baeda1f
# 查看Docker版本详情
docker version
#Client: Docker Engine - Community
 #Version:           20.10.21
 #API version:       1.41
 #Go version:        go1.18.7
 #Git commit:        baeda1f
 #Built:             Tue Oct 25 18:04:24 2022
 #OS/Arch:           linux/amd64
 #Context:           default
 #Experimental:      true

# 试运行安装启动是否正常
docker run hello-world
#Unable to find image 'hello-world:latest' locally
#latest: Pulling from library/hello-world
#2db29710123e: Pulling fs layer 

cd /opt
ll
#total 2772
#drwx--x--x   4 root root      28 Nov 14 07:20 containerd
#drwx--x---  13 root root     167 Nov 14 07:55 docker
cd docker/
ll
#total 0
#drwx--x--x 4 root root 120 Nov 14 07:55 buildkit
#drwx--x--- 2 root root   6 Nov 14 07:55 containers
#drwx------ 3 root root  22 Nov 14 07:55 image
#drwxr-x--- 3 root root  19 Nov 14 07:55 network
#drwx--x--- 3 root root  40 Nov 14 07:55 overlay2
#drwx------ 4 root root  32 Nov 14 07:55 plugins
#drwx------ 2 root root   6 Nov 14 07:55 runtimes
#drwx------ 2 root root   6 Nov 14 07:55 swarm
#drwx------ 2 root root   6 Nov 14 07:55 tmp
#drwx------ 2 root root   6 Nov 14 07:55 trust
#drwx-----x 2 root root  50 Nov 14 07:55 volumes
# Docker停止并卸载
systemctl stop docker 
yum remove docker-ce docker-ce-cli containerd.io
rm -rf /opt/docker
rm -rf /opt/containerd

5. Docker操作命令

5.1 Docker帮助命令

#查看docker概要信息
docker info
#查看docker帮助文档
docker --help
docker 具体命令 --help

5.2 Docker镜像命令

5.2.1 docker镜像查看与搜索

# 列出本地主机上的镜像
docker images
#仓库源       标签版本号   镜像ID        创建时间         大小
#REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
#hello-world   latest    feb5d9fea6a5   14 months ago   13.3kB

# 搜索某个镜像,比如redis,并显示为2行
docker search --limit 2 redis
#名称                  描述                             点赞数量    是否官方   是否自动构建
#NAME                   DESCRIPTION                      STARS     OFFICIAL   AUTOMATED
#redis                  Redis is an open source key-value   11601     [OK]       
#redislabs/redisearch   Redis With the RedisSearch module    56 

# 查看镜像/容器/数据卷所占的空间
docker system df
#TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
#Images          2         1         104.2MB   104.2MB (99%)
#Containers      1         0         0B        0B
#Local Volumes   0         0         0B        0B
#Build Cache     0         0         0B        0B

# 展示本地的所有镜像
docker images -a
#REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
#hello-world   latest    feb5d9fea6a5   14 months ago   13.3kB

5.2.2 docker镜像的拉取 

#拉取镜像,不指定版本号则默认取最新版本
docker pull hello-world
#Using default tag: latest
docker pull redis:6.0.8
docker images -a
#REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
#hello-world   latest    feb5d9fea6a5   14 months ago   13.3kB
#redis         6.0.8     16ecd2772934   2 years ago     104MB

#查看镜像/容器/数据卷所占的空间
docker system df
#TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
#Images          2         1         104.2MB   104.2MB (99%)
#Containers      1         0         0B        0B
#Local Volumes   0         0         0B        0B
#Build Cache     0         0         0B        0B

 5.2.3 docker镜像的删除

docker images -a
#REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
#hello-world   latest    feb5d9fea6a5   14 months ago   13.3kB

# 删除某个或多个镜像,比如hello-world的镜像ID=feb5d9fea6a5
docker rmi feb5d9fea6a5
#Error response from daemon: conflict: unable to delete feb5d9fea6a5 (must be forced) - image is being used by stopped container f617daec0750
docker rmi -f feb5d9fea6a5
#Untagged: hello-world:latest
#Untagged: hello-world@sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f
#Deleted: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412
#删除全部镜像
docker rmi -f $(docker images -aq)

 5.2.4 docker镜像的导入

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

5.3 Docker容器命令

5.3.1 Docker容器的运行

#使用镜像ubuntu:latest以前台交互模式启动一个容器,在容器内执行/bin/bash命令
# -i: 前台交互式    -t: 终端
#/bin/bash:放在镜像名后的是命令,这里我们希望有个交互式Shell。
#如果退出,输入exit,则是退出后容器停止
#         输入Ctrl+p+q,则是退出后,容器继续运行
docker run -it ubuntu /bin/bash

#如果输入Ctrl+p+q,又想重新进入,比如容器ID=5760ab297b72
docker exec -it 5760ab297b72 /bin/bash
#用exec后,后面再输入exit退出,也不会让容器停止。因此推荐使用!

#vi a.txt  此时在ubuntu上输入vi命令发现命令不存在
#bash: vi: command not found
#在ubuntu上安装vim
apt-get update
apt-get -y install vim
exit
#提交容器副本使之成为一个新的镜像
#docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]
docker commit -m="vim cmd add" -a="zmj" 5760ab297b72 zmjubuntu:1.2
docker images
#REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
#zmjubuntu    1.2       838afddae82b   9 seconds ago   180MB

#停掉旧的容器,开启新的
docker stop 5760ab297b72
docker exec -it 838afddae82b /bin/bash
# vim abc.txt  此时就可以编辑了

#复制文件  
#docker cp 容器ID:容器内路径 目的主机路径
docker cp 5760ab297b72:/a.txt /home/zmj/

#镜像导出容器  
#docker export 容器ID > 文件名
docker export 5760ab297b72 > /home/zmj/ubuntu.tar.gz

#镜像导入容器   
#cat 路径文件名 | docker import - 镜像用户/镜像名:镜像版本号
cat /home/zmj/ubuntu.tar.gz | docker import - zmj/ubuntu

#使用镜像redis:6.0.8以后台守护式启动一个容器
# -d 后台守护式
docker run -d redis:6.0.8

#列出当前所有正在运行的容器
docker ps
#CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS     
#d5124db3104d   ubuntu    "/bin/bash"   7 minutes ago  Up 7 minutes
#e3063d7fa15c redis:6.0.8 "docker-ent" a minute ago    Up a minute

#查看容器日志,比如这个redis的容器ID=e3063d7fa15c
docker logs e3063d7fa15c
#查看容器内运行的进程
docker top e3063d7fa15c
##查看容器内部细节
docker inspect e3063d7fa15c

#使用镜像ubuntu:latest以交互模式启动一个容器,在容器内执行bash命令
#--name 指定容器名称。如果不指定会自动生成一个
docker run -it --name=ubuntu01 ubuntu bash

5.3.2 Docker容器的查看

#列出当前所有正在运行的容器
docker ps
#CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS     
#d5124db3104d   ubuntu    "/bin/bash"   7 minutes ago  Up 7 minutes
#e3063d7fa15c redis:6.0.8 "docker-ent" a minute ago    Up a minute

#查看容器日志,比如这个redis的容器ID=e3063d7fa15c
docker logs e3063d7fa15c
#查看容器内运行的进程
docker top e3063d7fa15c
##查看容器内部细节
docker inspect e3063d7fa15c

#列出当前所有正在运行+历史出现过的容器
docker ps -a
#CONTAINER ID IMAGE     COMMAND       CREATED          STATUS      NAMES
#8e1fa21791b2 ubuntu    "bash"    11 minutes ago    Up 11 minutes   ubuntu01                 
#d5124db3104d ubuntu  "/bin/bash" 43 minutes ago      Exited (0)    sweet_bassi        
#f617daec0750 feb5d9fea6a5 "/hello" 11 days ago       Exited (0)   vigorous_mahavira

#查看名称为idms-application-settle的容器ID
docker ps -aqf 'name=idms-application-settle'
#2f75d6a7ae9b
#查看名称为idms-application-finance的容器ID
docker ps -aqf 'name=idms-application-finance'
#7eca7355dbf5

5.3.3 Docker容器的启停删

#启动已经停止的容器   
docker start d5124db3104d
#重启启动容器
docker restart d5124db3104d
docker restart $(docker ps -aqf 'name=rabbitmq')
#停止容器
docker stop d5124db3104d
#强制停止容器
docker kill d5124db3104d
#删除已经停止的容器
docker rm f617daec0750
#删除所有容器
docker rm -f $(docker ps -a -q)

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

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

Docker的那些事_第6张图片

 Docker的那些事_第7张图片

 Docker的那些事_第8张图片

 Docker的那些事_第9张图片

# 开始上传镜像到阿里云
docker login --username=dream98 registry.cn-beijing.aliyuncs.com

docker tag 838afddae82b \
registry.cn-beijing.aliyuncs.com/zmjdream/zmjubuntu:1.2

docker push registry.cn-beijing.aliyuncs.com/zmjdream/zmjubuntu:1.2

docker images
#REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
#zmjubuntu     1.2       838afddae82b   16 minutes ago   180MB
#registry.cn-beijing.aliyuncs.com/zmjdream/zmjubuntu 1.2   838afddae82b
#ubuntu       latest    ba6acccedd29   13 months ago     72.8MB

# 为了看从阿里云下载镜像,先强制删除
docker rmi -f 838afddae82b

#从阿里云下载镜像
docker pull registry.cn-beijing.aliyuncs.com/zmjdream/zmjubuntu:1.2
docker images
#REPOSITORY                                           TAG     IMAGE ID 
#registry.cn-beijing.aliyuncs.com/zmjdream/zmjubuntu   1.2   838afddae82b

# 运行这个新镜像,并打开前台终端
docker run -it 838afddae82b /bin/bash
vim abc.txt

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

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

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

#2. 运行私有库Registry  
# /home/zmj/mydockerregistry/:/tmp/registry 宿主机绝对路径:容器内目录
# --privileged=true  放开权限
docker run -d -p 5000:5000  \
-v /home/zmj/mydockerregistry/:/tmp/registry \
--privileged=true registry

docker run -it ubuntu /bin/bash
apt-get update
apt-get install net-tools
Ctrl+q+P

docker ps
#CONTAINER ID  IMAGE    COMMAND          CREATED      STATUS                              
#e5d1e3d49053   ubuntu  "/bin/bash"  6 minutes ago   Up 6 minutes                             
#a325d994340a   registry "/entrypoint.sh /etc…"      Up 6 minutes

#3. 提交容器副本使之成为一个新的镜像
docker commit -m="ifconfig cmd add" -a="zmj" e5d1e3d49053 zmjubuntu:1.2
docker images
#REPOSITORY      TAG       IMAGE ID       CREATED         SIZE
#zmjubuntu       1.2       4b2e6f89ecaf   3 minutes ago   114MB

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

#5. 将新镜像zmjubuntu:1.2修改符合私服规范的Tag
docker tag  zmjubuntu:1.2  192.168.235.130:5000/zmjubuntu:1.2

docker images
#REPOSITORY                       TAG       IMAGE ID       SIZE
#192.168.235.130:5000/zmjubuntu   1.2       4b2e6f89ecaf   114MB
#zmjubuntu                        1.2       4b2e6f89ecaf   114MB
#registry                        latest    b8604a3fe854   26.2MB
#6. 修改配置文件使之支持http
vim /etc/docker/daemon.json
#insecure-registries docker默认不允许http方式推送镜像,通过配置选项来取消这个限制
{
"registry-mirrors": ["https://fujwmaum.mirror.aliyuncs.com"],
"graph":"/opt/docker",
"insecure-registries": ["192.168.235.130:5000"]
}
#7. 重启docker让配置生效
systemctl restart docker

#8. 运行私有库Registry
docker run -d -p 5000:5000  \
-v /home/zmj/mydockerregistry/:/tmp/registry \
--privileged=true registry

#9. 推送到私有库
docker push 192.168.235.130:5000/zmjubuntu:1.2

#10. curl验证私服库上有什么镜像
curl -XGET http://192.168.235.130:5000/v2/_catalog
#{"repositories":["zmjubuntu"]}

#11.为了看pull效果,先删除掉本地zmjubuntu镜像
docker rmi -f 4b2e6f89ecaf

#12. 拉取刚才上传到私有库的镜像
docker pull 192.168.235.130:5000/zmjubuntu:1.2
docker images
#REPOSITORY                         TAG       IMAGE ID      SIZE
#192.168.235.130:5000/zmjubuntu     1.2       4b2e6f89ecaf  114MB

#13. 运行刚才拉取的镜像,并前台终端显示
docker run -it 4b2e6f89ecaf /bin/bash

8. Docker容器数据卷

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

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

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

#在容器内创建一个文件
cd /tmp/mydockerdata/
touch rongqinei.txt
ll
#-rw-r--r-- 1 root root  0 Dec  2 11:43 rongqinei.txt
#在宿主机查看
cd /tmp/myhostdata/
ll
#-rw-r--r-- 1 root root 0 Dec  2 03:43 rongqinei.txt
#在宿主机此路径下创建一个文件
touch suzhuji.txt
#在容器内查看
ll
#-rw-r--r-- 1 root root  0 Dec  2 11:43 rongqinei.txt
#-rw-r--r-- 1 root root  0 Dec  2 11:43 suzhuji.txt

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

docker ps
#CONTAINER ID IMAGE   COMMAND       CREATED           STATUS          NAMES
#5a998ec5e7c8  ubuntu  "/bin/bash"  an hour ago   Up About an hour   myubuntu
docker stop 5a998ec5e7c8

#宿主机在/tmp/myhostdata/下新建一个文件
touch suzhuji2.txt

docker start 5a998ec5e7c8
docker exec -it 5a998ec5e7c8 /bin/bash

#容器内查看
cd /tmp/mydockerdata/
ll
#-rw-r--r-- 1 root root  0 Dec  2 11:43 rongqinei.txt
#-rw-r--r-- 1 root root  0 Dec  2 11:43 suzhuji.txt
#-rw-r--r-- 1 root root  0 Dec  2 12:50 suzhuji2.txt

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

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

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

#删除所有容器
docker rm -f $(docker ps -a -q)

#这个作为父容器
docker run -it --name myubuntu --privileged=true 
-v /tmp/myhostdata:/tmp/mydockerdata ubuntu /bin/bash

#这个作为子容器
#--volumes-from  继承父容器的卷规则
docker run -it  --privileged=true \
--volumes-from myubuntu  --name myubuntuchild ubuntu

9. Docker安装Tomcat 

  这里安装稳定版的Tomcat8

# 搜索Tomcat镜像
docker search tomcat

# 拉取tomcat8镜像到本地
docker pull billygoo/tomcat8-jdk8

# 查看是否有拉取到的tomcat
docker images billygoo/tomcat8-jdk8
#REPOSITORY              TAG       IMAGE ID       CREATED       SIZE
#billygoo/tomcat8-jdk8   latest    30ef4019761d   4 years ago   523MB

# 查看主机8080端口有没有被占用
ss -antup | grep 8080

# 使用tomcat镜像创建容器实例
# 运行镜像
# -d 后台守护模式
# -p 小写,主机端口:docker容器端口
docker run -d -p 8080:8080 --name mytomcat8 billygoo/tomcat8-jdk8

 10. Docker安装MySQL

# 拉取MySQL5.7镜像
docker pull mysql:5.7

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

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

#重启mysql容器实例
docker restart mysql

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

11. Docker安装MySQL主从复制

11.1 配置MySQL主服务器

# 新建MySQL容器实例-主服务器
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

docker ps
#CONTAINER ID   IMAGE      STATUS          PORTS          NAMES                                      
#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

# 修改完配置文件,需重启
docker restart mysql-master
docker ps

# 进入mysql-master容器
docker exec -it mysql-master /bin/bash
mysql -uroot -proot
-- mysql> master容器实例内创建数据同步用户
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';

11.2 配置MySQL从服务器

# 新建MySQL容器实例-从服务器
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
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

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

11.3 从MySQL主服务器查看状态

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

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

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

-- 再次查看主从同步状态,都是YES
--mysql> 
show slave status \G;
--             Slave_IO_Running: Yes
--            Slave_SQL_Running: Yes

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

create database dbtest;
use dbtest;
create table t_test(id int,name varchar(20));
insert into t_test values(1,'master');
select * from t_test;
--id name
--1  master

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

use dbtest;
select * from t_test;
--id name
--1  master

12. Docker安装Redis

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

13. Docker中Redis集群配置

13.1 新建6个docker容器redis实例

# --name redis-node-1    容器名称
# --net host             使用宿主机的IP和端口
# --privileged=true      获取宿主机root用户权限
# redis:6.0.8            redis镜像和版本号
# --cluster-enabled yes  开启redis集群
# --appendonly yes       开启持久化
# --port 6381            redis端口号
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

13.2 构建集群关系

#随便进入一个实例,比如redis-node-1
docker exec -it redis-node-1 /bin/bash

# --cluster-replicas 1 表示为每个master创建一个slave节点
redis-cli --cluster create 192.168.235.130:6381 192.168.235.130:6382 \
192.168.235.130:6383 192.168.235.130:6384 192.168.235.130:6385 \
192.168.235.130:6386 --cluster-replicas 1

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

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

 13.3 查看集群状态

#宿主机或外部设备连接6381端口的Redis,以集群的方式
# -c 集群的方式
redis-cli -p 6381 -c

127.0.0.1:6381> set k1 v1
#-> Redirected to slot [12706] located at 192.168.235.130:6383
#OK

127.0.0.1:6381> cluster info
#cluster_slots_assigned:16384
#cluster_slots_ok:16384
#cluster_known_nodes:6
#cluster_current_epoch:6

127.0.0.1:6381> cluster nodes
#30181254fa5875f82c3fc3ef21f24cf7f53b56c0 192.168.235.130:6381@16381 myself,master - 0 1670068681000 1 connected 0-5460.....

redis-cli --cluster check 192.168.235.130:6381
#192.168.235.130:6381 (30181254...) -> 0 keys | 5461 slots | 1 slaves.
#192.168.235.130:6383 (f3bd197d...) -> 1 keys | 5461 slots | 1 slaves.
#192.168.235.130:6382 (232e1ef2...) -> 0 keys | 5462 slots | 1 slaves.
#[OK] 1 keys in 3 masters

13.4 主从容错切换迁移

# 停掉节点1,模拟宕机
docker stop redis-node-1
#等待1分钟后
#这次连6382端口的Redis
#6386端口的Redis由原来的slave变成了master
#6381端口的Redis显示为fail
redis-cli -p 6382 -c
127.0.0.1:6382> CLUSTER nodes
#b205b77c378323c79 192.168.235.130:6386@16386 master - 0 1670074592353 7 connected
#30181254fa5875f82 192.168.235.130:6381@16381 master,fail - 1670074369387

# 启动节点1,模拟已经修复
docker start redis-node-1
#等待1分钟后
#再次连6382端口的Redis
#6386端口的Redis彻底变成了master
#6381端口的Redis显示为只能变成是slave
redis-cli -p 6382 -c
127.0.0.1:6382> CLUSTER nodes
#b205b77c378323c79 192.168.235.130:6386@16386 master - 0 1670075158169 7 connected 0-5460
#30181254fa5875f82 192.168.235.130:6381@16381 slave

# 停掉节点6,模拟宕机
docker stop redis-node-6
#等待1分钟后
#这次连6382端口的Redis
#6381端口的Redis再次变成了master
#6386端口的Redis显示为fail
redis-cli -p 6382 -c
127.0.0.1:6382> CLUSTER nodes
#b205b77c378323c79 192.168.235.130:6386@16386 master,fail - 1670075633613 1670075628493
#30181254fa5875f82 192.168.235.130:6381@16381 master - 0 1670075690000 8 connected

# 启动节点6,模拟已经修复
docker start redis-node-6
#等待1分钟后
#再次连6382端口的Redis
#6381端口的Redis彻底变成了master
#6386端口的Redis显示为只能变成是slave
redis-cli -p 6382 -c
127.0.0.1:6382> CLUSTER nodes
#b205b77c378323c79 192.168.235.130:6386@16386 slave 30181254fa5875f82  8 connected
#30181254fa5875f82 192.168.235.130:6381@16381 master - 0 1670075963000 8 connected

13.5 主从扩容

# 再增加两个节点
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 6387

docker 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

docker ps

# 进入redis-node-7
docker exec -it redis-node-7 /bin/bash

#将新增的6387节点作为master节点加入原集群
redis-cli --cluster add-node 192.168.235.130:6387 192.168.235.130:6381

# 检查集群情况,会看到6387已经是master,目前还没有slave,此时槽号也为空
redis-cli --cluster check 192.168.235.130:6381
#192.168.235.130:6381 (30181254...) -> 0 keys | 5461 slots | 1 slaves.
#192.168.235.130:6382 (232e1ef2...) -> 0 keys | 5462 slots | 1 slaves.
#192.168.235.130:6383 (f3bd197d...) -> 1 keys | 5461 slots | 1 slaves.
#192.168.235.130:6387 (68d7de26...) -> 0 keys | 0 slots | 0 slaves.
#[OK] 1 keys in 4 masters.
#M: 68d7de26299d486f121311270d89a360142172d0 192.168.235.130:6387
#   slots: (0 slots) master

# 重新分派槽号 
# 16384 / 4 = 4096  
# nodeID填写6387对应的ID=68d7de26299d486f121311270d89a360142172d0
# 键入“all”将所有节点用作哈希槽的源节点
redis-cli --cluster reshard 192.168.235.130:6381
# How many slots do you want to move (from 1 to 16384)? 
4096
# What is the receiving node ID? 
68d7de26299d486f121311270d89a360142172d0
#Please enter all the source node IDs.
#  Type 'all' to use all the nodes as source nodes for the hash slots.
#  Type 'done' once you entered all the source nodes IDs.
#Source node #1: 
all
#Do you want to proceed with the proposed reshard plan (yes/no)?
yes

# 检查集群情况,会看到6387目前还没有slave,此时槽号有4096个,其他三个也是4096个了
# 另外一个现象是6387的槽号是分了三段。原因是重新分配成本太高,其他三个是在原来各自的基础上做的减法,6387所获得是其他三个节点每个都拿出来一部分给它的
redis-cli --cluster check 192.168.235.130:6381
#192.168.235.130:6381 (30181254...) -> 0 keys | 4096 slots | 1 slaves.
#192.168.235.130:6382 (232e1ef2...) -> 0 keys | 4096 slots | 1 slaves.
#192.168.235.130:6383 (f3bd197d...) -> 1 keys | 4096 slots | 1 slaves.
#192.168.235.130:6387 (68d7de26...) -> 0 keys | 4096 slots | 0 slaves.
#M: 68d7de26299d486f121311270d89a360142172d0 192.168.235.130:6387
#   slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master

#为主节点6387分配从节点6388
#redis-cli --cluster add-node ip:新加的slave端口 ip:master端口 \
#--cluster-slave --cluster-master-id master主机节点ID
redis-cli --cluster add-node 192.168.235.130:6388 192.168.235.130:6387 \
--cluster-slave --cluster-master-id 68d7de26299d486f121311270d89a360142172d0

#检查集群情况,会看到6387,此时槽号有4096个,且也有了一个6388端口号的slave
redis-cli --cluster check 192.168.235.130:6381
#192.168.235.130:6381 (30181254...) -> 0 keys | 4096 slots | 1 slaves.
#192.168.235.130:6382 (232e1ef2...) -> 0 keys | 4096 slots | 1 slaves.
#192.168.235.130:6383 (f3bd197d...) -> 1 keys | 4096 slots | 1 slaves.
#192.168.235.130:6387 (68d7de26...) -> 0 keys | 4096 slots | 1 slaves.
#S: 81c8446a8a94481efcf2de1bab000ccdb997fbce 192.168.235.130:6388
#   slots: (0 slots) slave
#   replicates 68d7de26299d486f121311270d89a360142172d0
#M: 68d7de26299d486f121311270d89a360142172d0 192.168.235.130:6387
#   slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
#   1 additional replica(s)

13.6 主从缩容

# 检查集群情况
# 6387的从服务器个数此时显示为1
# 并拿到从服务器6388的节点ID=81c8446a8a94481efcf2de1bab000ccdb997fbce
redis-cli --cluster check 192.168.235.130:6381
#192.168.235.130:6387 (68d7de26...) -> 0 keys | 4096 slots | 1 slaves.
#S: 81c8446a8a94481efcf2de1bab000ccdb997fbce 192.168.235.130:6388
#   slots: (0 slots) slave

# 将6388删除
redis-cli --cluster del-node 192.168.235.130:6388 \
81c8446a8a94481efcf2de1bab000ccdb997fbce

# 检查集群情况
# 6387的从服务器个数此时显示为0,有4096个槽号
# 6387的节点ID=68d7de26299d486f121311270d89a360142172d0
# 6381的节点ID=30181254fa5875f82c3fc3ef21f24cf7f53b56c0
redis-cli --cluster check 192.168.235.130:6382
#192.168.235.130:6382 (232e1ef2...) -> 0 keys | 4096 slots | 1 slaves.
#192.168.235.130:6387 (68d7de26...) -> 0 keys | 4096 slots | 0 slaves.
#192.168.235.130:6381 (30181254...) -> 0 keys | 4096 slots | 1 slaves.
#192.168.235.130:6383 (f3bd197d...) -> 1 keys | 4096 slots | 1 slaves.
#M: 68d7de26299d486f121311270d89a360142172d0 192.168.235.130:6387
#   slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
#M: 30181254fa5875f82c3fc3ef21f24cf7f53b56c0 192.168.235.130:6381
#   slots:[1365-5460] (4096 slots) master
#   1 additional replica(s)

# 将6387的槽号都给6381
redis-cli --cluster reshard 192.168.235.130:6381
#How many slots do you want to move (from 1 to 16384)? 
4096
#What is the receiving node ID?
30181254fa5875f82c3fc3ef21f24cf7f53b56c0
#Please enter all the source node IDs.
#  Type 'all' to use all the nodes as source nodes for the hash slots.
#  Type 'done' once you entered all the source nodes IDs.
#Source node #1:
68d7de26299d486f121311270d89a360142172d0
#Source node #2:
done
#Do you want to proceed with the proposed reshard plan (yes/no)?
yes

# 检查集群情况
# 6387显示此时已经是0个槽,0个slave
# 6381显示此时已经是8192个槽
redis-cli --cluster check 192.168.235.130:6381
#192.168.235.130:6381 (30181254...) -> 0 keys | 8192 slots | 1 slaves.
#192.168.235.130:6382 (232e1ef2...) -> 0 keys | 4096 slots | 1 slaves.
#192.168.235.130:6383 (f3bd197d...) -> 1 keys | 4096 slots | 1 slaves.
#192.168.235.130:6387 (68d7de26...) -> 0 keys | 0 slots | 0 slaves.
#M: 68d7de26299d486f121311270d89a360142172d0 192.168.235.130:6387
#   slots: (0 slots) master
#M: 30181254fa5875f82c3fc3ef21f24cf7f53b56c0 192.168.235.130:6381
#   slots:[0-6826],[10923-12287] (8192 slots) master
#   1 additional replica(s)

#将6387删除
redis-cli --cluster del-node 192.168.235.130:6387 \
68d7de26299d486f121311270d89a360142172d0

# 检查集群情况
# 6387已经被删除
redis-cli --cluster check 192.168.235.130:6381
#192.168.235.130:6381 (30181254...) -> 0 keys | 8192 slots | 1 slaves.
#192.168.235.130:6382 (232e1ef2...) -> 0 keys | 4096 slots | 1 slaves.
#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等命令,让其具备

docker search centos
#拉取一个centos镜像
docker pull centos:7

#才204MB,这个里面是不包含vim/ifconfig/java等命令的
docker images
#REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
#centos       7         eeb6ee3f44bd   14 months ago   204MB

mkdir /myfile
cd /myfile
wget https://mirrors.yangxingzhen.com/jdk/jdk-8u171-linux-x64.tar.gz
# 编辑文件,必须是大写的D
vim Dockerfile
#FROM 当前新镜像是基于哪个镜像,指定一个已经存在的镜像作为模板,第一条必须是from
FROM centos:7
#MAINTAINER 镜像维护者的姓名和邮箱地址
MAINTAINER zmj
 
ENV MYPATH /usr/local
#WORKDIR 指定在创建容器后,终端默认登录进来后的工作目录,一个落脚点
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 将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包
#    是相对路径jar,把jdk-8u171-linux-x64.tar.gz添加到容器中
#    安装包必须要和Dockerfile文件在同一位置
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 当前容器对外暴露出的端口
EXPOSE 80
 
#CMD 指定容器启动后要做什么
#    可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换
CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash
# 构建,名称centos7java8,标签1.5,后面加个点
docker build -t centos7java8:1.5 .

docker images
#REPOSITORY     TAG       IMAGE ID       CREATED          SIZE
#centos7java8   1.5       97cffc20b22e   44 seconds ago   1.25GB
#centos         7         eeb6ee3f44bd   14 months ago    204MB

#运行新建的镜像
docker run -it 97cffc20b22e /bin/bash
java -version
#java version "1.8.0_171"

15. 虚悬镜像

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

# 如果Dockerfile文件内容有误,或是执行异常,就会出现镜像名称和TAG都显示为none的镜像
# 这里模拟一个
cd /myfile
cat>Dockerfile <<-EOF
from ubuntu
CMD echo 'action is success'
EOF
docker build .

#已经出现一个虚悬镜像
docker image ls -f dangling=true
#REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
#           c0100057060b   22 hours ago   72.8MB

#虚悬镜像已经失去存在价值,可以删除
#另外还存在一定的安全隐患,建议删除
docker image prune

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

16.1 先打包成jar 

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

Docker的那些事_第10张图片

Docker的那些事_第11张图片

新建一个目录 

Docker的那些事_第12张图片  

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

Docker的那些事_第13张图片

 Docker的那些事_第14张图片

Docker的那些事_第15张图片

 Docker的那些事_第16张图片

 Docker的那些事_第17张图片

16.3 编写Dockerfile

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

16.4 构建并运行镜像

# 打包成镜像文件
docker build -t zmj_docker:1.6 .

docker images
#REPOSITORY     TAG       IMAGE ID       CREATED          SIZE
#zmj_docker     1.6       ce2ae8cdbb79   48 seconds ago   565MB

#后台运行镜像
docker run -d -p 6001:6001 zmj_docker:1.6

#测试一下,可以访问
curl 127.0.0.1:6001/order/index
服务端口号: 	6001	d42caf1b-2148-4dd5-8770-e6a0b3aee5d6

17. Docker网络

17.1 Docker网络的作用

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

 17.2 Docker网络模式

Docker的那些事_第18张图片

17.3 Docker网络相关命令 

# 观察网络,发现会多一个名字为docker0的虚拟网桥,并且IP是172.17.0.1
ifconfig
#docker0: flags=4099  mtu 1500
#        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
#        ether 02:42:01:c4:01:8c  txqueuelen 0  (Ethernet)
#        RX packets 0  bytes 0 (0.0 B)
#        RX errors 0  dropped 0  overruns 0  frame 0
#        TX packets 0  bytes 0 (0.0 B)
#        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

# 查看docker网络模式,默认会创建三大网络模式
docker network ls
#NETWORK ID     NAME      DRIVER    SCOPE
#5c6d08db6309   bridge    bridge    local
#6183fe01b81c   host      host      local
#13186cff8686   none      null      local

# 创建一个网络
docker network create network_test

# 删除一个网络
docker network rm network_test

docker run -it --name u1 ubuntu bash
# 按Ctrl+Q+P退出

docker run -it --name u2 ubuntu bash
# 按Ctrl+Q+P退出


# 查看u2的网络源数据,内部IP=172.17.0.3
docker inspect u2 | tail -n 20
#            "Networks": {
#                "bridge": {
#                    "IPAMConfig": null,
#                    "Links": null,
#                    "Aliases": null,
#                    "NetworkID": #"5c6d08db6309cd42c10f484cf635765ae5ed02e2293e2e49d0d40ee051bf7803",
#                    "EndpointID": #"9b43344db5e119c2960b25372b12240c99dd2e906b971ac064e3ee6a4da97caf",
#                    "Gateway": "172.17.0.1",
#                    "IPAddress": "172.17.0.3"

# 查看u1的网络源数据,内部IP=172.17.0.2
docker inspect u1 | tail -n 20
#            "Networks": {
#                "bridge": {
#                    "IPAMConfig": null,
#                    "Links": null,
#                    "Aliases": null,
#                    "NetworkID": #"5c6d08db6309cd42c10f484cf635765ae5ed02e2293e2e49d0d40ee051bf7803",
#                    "EndpointID": #"e6e3d6256806317a106c91fce44fccb720272c09c9dd6ca632344fdd05e24a84",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2"
###结论:docker容器实例不同,内部IP也不同
###      另外如果实例停了再开,原来的内部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、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。

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

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

17.7 自定义Docker网络

# 创建网络名为zmj_network
docker network create zmj_network

# 两个实例都加入到刚才创建的新网络中
docker run -d -p 8081:8080 --network zmj_network  --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --network zmj_network  --name tomcat82 billygoo/tomcat8-jdk8


docker exec -it tomcat81 bash
ping tomcat82
#PING tomcat82 (172.19.0.3) 56(84) bytes of data.
#64 bytes from tomcat82.zmj_network (172.19.0.3): icmp_seq=1 ttl=64 time=0.286 ms
#64 bytes from tomcat82.zmj_network (172.19.0.3): icmp_seq=2 ttl=64 time=0.350 ms

docker exec -it tomcat82 bash
ping tomcat81
#PING tomcat81 (172.19.0.2) 56(84) bytes of data.
#64 bytes from tomcat81.zmj_network (172.19.0.2): icmp_seq=1 ttl=64 time=0.056 ms
#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下载安装

vim /etc/hosts
# 140.82.112.4 github.com
systemctl daemon-reload

curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

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

docker-compose --version
#docker-compose version 1.29.2, build 5becea4c

18.3 不使用Docker-compose容器编排

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

server.port=6001
# ========================alibaba.druid相关配置=====================
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.235.135:13306/mytest?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.druid.test-while-idle=false
# ========================redis相关配置=====================
spring.redis.database=0
spring.redis.host=192.168.235.135
spring.redis.port=16379
spring.redis.password=
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
# ========================mybatis相关配置===================
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.zmj.springbootdemo.entity
# ========================swagger=====================
spring.swagger2.enabled=true
# 运行单独的mysql容器实例
docker run -p 13306:3306 --name mysql5.7 --privileged=true \
-v /home/zmj/mysql/conf:/etc/mysql/conf.d \
-v /home/zmj/mysql/logs:/logs \
-v /home/zmj/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

docker exec -it mysql5.7 /bin/bash
mysql -uroot -p
mysql> create database mytest;

# 运行单独的redis容器实例
docker run  -p 16379:6379 --name redis1608 --privileged=true \
-v /app/redis/redis.conf:/etc/redis/redis.conf \
-v /app/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf

cd /mydocker
# 构建微服务的镜像,跟之前类似
docker build -t zmj_docker:1.7 .

docker exec -it redis1608 /bin/bash
 redis-cli

docker images
#REPOSITORY              TAG       IMAGE ID       CREATED          SIZE
#zmj_docker              1.7       0d3ea131cc72   19 seconds ago   642MB
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无关。这里只展示修改部分

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

编写docker-compose.yml文件

cd /mydocker
vim docker-compose.yml
version: "3"
 
services:
  microService:
    image: zmj_docker:1.7
    container_name: ms01
    ports:
      - "6001:6001"
    volumes:
      - /app/microService:/data
    networks: 
      - dream_net 
    depends_on: 
      - redis
      - mysql
 
  redis:
    image: redis:6.0.8
    ports:
      - "16379:6379"
    volumes:
      - /app/redis/redis.conf:/etc/redis/redis.conf
      - /app/redis/data:/data
    networks: 
      - dream_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: 'mytest'
      MYSQL_USER: 'zmj'
      MYSQL_PASSWORD: 'zmj123'
    ports:
       - "13306:3306"
    volumes:
       - /app/mysql/db:/var/lib/mysql
       - /app/mysql/conf/my.cnf:/etc/my.cnf
       - /app/mysql/init:/docker-entrypoint-initdb.d
    networks:
      - dream_net
    command: --default-authentication-plugin=mysql_native_password #解决外部无法访问
 
networks: 
   dream_net: 
#查看刚才写的配置信息是否有误,不输出内容,就是没错
docker-compose config -q

cd /mydocker
# 构建微服务的镜像,跟之前类似
docker build -t zmj_docker:1.7 .

# 启动所有docker-compose服务并后台运行
docker-compose up -d

# 停止所有docker-compose服务
docker-compose stop

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

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

19.1 Portainer的安装

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

http://192.168.235.135:9000Docker的那些事_第19张图片

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

Docker的那些事_第20张图片

 本地连接

19.2 通过Portainer安装Nginx

Docker的那些事_第21张图片

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

Docker的那些事_第22张图片

 Docker的那些事_第23张图片

 Docker的那些事_第24张图片

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

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

20.1 安装CAdvisor+InfluxDB+Granfana

mkdir -p /mydocker/cig
cd /mydocker/cig
vim 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
  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 -d

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

Docker的那些事_第25张图片

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

Docker的那些事_第26张图片

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

Docker的那些事_第27张图片

 20.2 grafana配置数据源

Docker的那些事_第28张图片

 

Docker的那些事_第29张图片

 20.3 grafana配置显示面板

Docker的那些事_第30张图片

 Docker的那些事_第31张图片

 显示效果

Docker的那些事_第32张图片

 编辑下查询条件Docker的那些事_第33张图片

 Docker的那些事_第34张图片

21. Docker安装RabbitMQ

21.1 拉取镜像

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

 21.2 启动容器

mkdir -p /mydocker/rabbitmq

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

 21.3 进入容器

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

 21.4 登录管理页面 

Docker的那些事_第35张图片

 Docker的那些事_第36张图片

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

Docker的那些事_第37张图片

21.6 新建交换器

新建三种类型的交换机

Docker的那些事_第38张图片Docker的那些事_第39张图片

Docker的那些事_第40张图片

21.7 新建队列

新建四个队列

Docker的那些事_第41张图片  Docker的那些事_第42张图片

Docker的那些事_第43张图片  Docker的那些事_第44张图片

21.8 绑定

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

Docker的那些事_第45张图片

 Docker的那些事_第46张图片  Docker的那些事_第47张图片

Docker的那些事_第48张图片  Docker的那些事_第49张图片

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

 Docker的那些事_第50张图片

 Docker的那些事_第51张图片

Docker的那些事_第52张图片

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

Docker的那些事_第53张图片

Docker的那些事_第54张图片

 21.9 Direct交换器发消息

 1)交换器exchange.direct发消息

Docker的那些事_第55张图片

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

Docker的那些事_第56张图片

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

Docker的那些事_第57张图片

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

 Docker的那些事_第58张图片

 21.10 fanout交换器发消息

 1)交换器exchange.fanout发消息

Docker的那些事_第59张图片

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

Docker的那些事_第60张图片

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

Docker的那些事_第61张图片

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

Docker的那些事_第62张图片

 21.11 topic交换器发消息

 1)交换器exchange.topic发消息

Docker的那些事_第63张图片

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

Docker的那些事_第64张图片

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

Docker的那些事_第65张图片

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

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

Docker的那些事_第66张图片

22. Docker安装Elasticsearch

22.1 安装

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

http://192.168.1.200:9200

Docker的那些事_第67张图片

22.2 测试

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

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

########################插入三条数据
#megacorp 索引名称
#employee 类型名称
PUT /megacorp/employee/1
{
    "first_name" : "John",
    "last_name" :  "Smith",
    "age" :        25,
    "about" :      "I love to go rock climbing",
    "interests": [ "sports", "music" ]
}

PUT /megacorp/employee/2
{
    "first_name" :  "Jane",
    "last_name" :   "Smith",
    "age" :         32,
    "about" :       "I like to collect rock albums",
    "interests":  [ "music" ]
}

PUT /megacorp/employee/3
{
    "first_name" :  "Douglas",
    "last_name" :   "Fir",
    "age" :         35,
    "about":        "I like to build cabinets",
    "interests":  [ "forestry" ]
}

Docker的那些事_第68张图片

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

Docker的那些事_第69张图片

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

 Docker的那些事_第70张图片

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

Docker的那些事_第71张图片

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

{
    "query" : {
        "bool": {
            "must": {
                "match" : {
                    "last_name" : "smith" 
                }
            },
            "filter": {
                "range" : {
                    "age" : { "gt" : 30 } 
                }
            }
        }
    }
}

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

23. Docker安装Zookeeper 

23.1 安装ZK服务端

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

23.2 通过客户端连服务端

  docker ps
# CONTAINER ID   IMAGE                                                             NAMES
# 8c89711ae723   zookeeper:3.5.7

docker exec -it 8c89711ae723 /bin/bash

cd bin
./zkCli.sh -server 127.0.0.1:2181

ls /services
[cloud-provider-payment]

你可能感兴趣的:(运维,开发工具,docker,容器,运维)