飞天班第45节:Docker精通-3

2020/06/07

1、DockerFile(重点)

什么是DockerFile

Dockerfile 是一个用来构建镜像的脚本文件,文本内容包含一条条构建镜像所需的指令和说明。

第一步,你写了个java项目,打包成jar包

第二步,jar包+java环境通过dockerfile文件的指令构建,tag就是版本的区别,

一条条构建镜像所需的指令?有哪些指令

mysql的dockerfile

在dockerhub随便点进一个镜像的tag,就可以看到它的dockerfile(在github上),比如mysql

可以发现mysql的基础镜像是debian:buster-silm

centos的dockerfile

dockerhub上搜索centos的镜像,点其中一个tag,查看它的dockerfile

可以发现centos的基础镜像是scratch

scratch是所有镜像的根镜像,所有的docker镜像应该都是从dockerfile构建的!

DockerFile指令

完整命令如下: 在dockerfile指令中,会存在很多相似的指令,之后可以多注意一下! 参数追加规则!

workdir 设置工作目录,如tomcat镜像的默认工作目录是/usr/local/tomcat

官方文档学习:https://docs.docker.com/engine/reference/builder/

Dockerfile构建

1、每个关键字,必须是大写字母

2、指令是从上到下依次执行

3、# 代表注释

4、每个指令本质就是构建了一个新的镜像层!将它提交!

应用来说:

代码 =>.apk => 客户端下载运行

DockerFile、Docker镜像、Docker 容器 ( 理解:相当于软件三个不同的阶段 )

DockerFile 软件的原材料(代码)=> Build => Docker镜像(交付的产品)=> Run => Docker 容器(最终软件的运行状态!)

实战:CentOS

官方镜像:

1、编写DockerFile

一定需要有一个 DockerFile 文件、可以随意命名(但是不建议) 默认的名称 Dockerfile

[root@alibaba coding]# vim mydockerfile-centos
FROM centos:7.8.2003
MAINTAINER jude<747463168@qq.com>
ENV MYPATH /usr/local # 配置环境变量
WORKDIR $MYPATH
RUN yum -y install vim   # 编译镜像时运行的脚本
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH  # 容器的启动命令,就是docker run的时候要启动哪些命令
CMD ech "------end------"
CMD /bin/bash
[root@alibaba coding]# ls
mydockerfile-centos

2、构建镜像

通过Dockerfile进行构建镜像! docker build 别忘记后面的 . ,-f , 如果不要的情况下,文件名必须为 Dockerfile,-t 指定生成镜像的名称

[root@alibaba coding]# docker build --help

Usage:  docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile

Options:
      --add-host list           Add a custom host-to-IP mapping (host:ip)
      --build-arg list          Set build-time variables
      --cache-from strings      Images to consider as cache sources
      --cgroup-parent string    Optional parent cgroup for the container
      --compress                Compress the build context using gzip
      --cpu-period int          Limit the CPU CFS (Completely Fair Scheduler) period
      --cpu-quota int           Limit the CPU CFS (Completely Fair Scheduler) quota
  -c, --cpu-shares int          CPU shares (relative weight)
      --cpuset-cpus string      CPUs in which to allow execution (0-3, 0,1)
      --cpuset-mems string      MEMs in which to allow execution (0-3, 0,1)
      --disable-content-trust   Skip image verification (default true)
  -f, --file string             Name of the Dockerfile (Default is 'PATH/Dockerfile')
      --force-rm                Always remove intermediate containers
      --iidfile string          Write the image ID to the file
      --isolation string        Container isolation technology
      --label list              Set metadata for an image
  -m, --memory bytes            Memory limit
      --memory-swap bytes       Swap limit equal to memory plus swap: '-1' to enable unlimited swap
      --network string          Set the networking mode for the RUN instructions during build (default "default")
      --no-cache                Do not use cache when building the image
      --pull                    Always attempt to pull a newer version of the image
  -q, --quiet                   Suppress the build output and print image ID on success
      --rm                      Remove intermediate containers after a successful build (default true)
      --security-opt strings    Security options
      --shm-size bytes          Size of /dev/shm
  -t, --tag list                Name and optionally a tag in the 'name:tag' format
      --target string           Set the target build stage to build.
      --ulimit ulimit           Ulimit options (default [])
      
# docker build 一个镜像
[root@alibaba coding]# docker build -f mydockerfile-centos -t mycentos:1.0 .

构建完成,通过docker images 命令查看自己构建的镜像mycentos:1.0

3、运行镜像

docker run 运行自己构建的镜像,默认进入工作目录是 /usr/local,且支持vim、ifconfig命令

发现docker run 只执行最后一个CMD命令 /bin/bash

4、docker history命令查看任何一个镜像的创建过程

发现最底下的那一层是镜像centos:7.8.2003,每一条命令执行完毕,提交一个新的镜像层!,前面我们说过镜像是分层的。

CMD 和 ENTRYPOINT 区别

启动容器的时候,我们都可以使用这两个命令来执行一个启动时的运行命令!

  • CMD : 设置容器的启动命令 ,Dockerfile 中有多个CMD 指令,但是只有最后一个会生效,CMD 默认的参数会被 docker run 参数替代!

  • ENTRYPOINT : 设置容器的入口 ENTRYPOINT 的参数 和 docker run 进行拼接!

CMD 指令:

[root@alibaba coding]# vim dockerfile-cmd-test
FROM centos:7.8.2003
CMD ["ls","-a"] 
# 构建镜像
[root@alibaba coding]# docker build -f dockerfile-cmd-test -t cmdtest:1.0 .
# run,参数替代,
[root@alibaba coding]# docker run cmdtest:1.0 -l # 会报错CMD不会拼接命令-l
[root@alibaba coding]# docker run cmdtest:1.0 ls -al

ENTRYPOINT:

[root@alibaba coding]# vim dockerfile-entrypoint-test
FROM centos:7.8.2003
ENTRYPOINT ["ls","-a"]
# 构建镜像
[root@alibaba coding]# docker build -f dockerfile-entrypoint-test -t  entrypoint .
# run
[root@alibaba coding]# docker run entrypoint:latest
[root@alibaba coding]# docker run entrypoint:latest -l # 会拼接命令为 ls -al

容器一启动,自动执行 jar包!执行项目,如下:

FROM java:8
# 拷贝当前目录下的jar包到容器内的/app.jar
COPY *.jar /app.jar
# 配置应用tomcat的端口
CMD ["--server.port=8080"]
# 暴露容器的端口
EXPOSE 8080
# 设置容器的入口程序,启动容器后就执行java命令启动程序
ENTRYPOINT ["java","-jar","/app.jar"]

小结:编写dockerfile=> 构建=> 运行!

实战:Tomcat

新电脑,装我们的tomcat的步骤:

1、下载 jdk 的包

2、安装jdk

3、配置环境变量

# 环境变量在末尾添加JAVA_Home
[root@alibaba jdk1.8.0_201]# vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.8.0_201
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin
# 使环境变量生效
[root@alibaba jdk1.8.0_201]# source /etc/profile
[root@alibaba jdk1.8.0_201]# java -version

4、下载tomcat的包

5、解压tomcat

使用dockerfile构建自己的tomcat镜像

1、需要有原材料,jdk-8u251-linux-x64.tar.gz 和apache-tomcat-9.0.36.tar.gz 上传到服务器,

# 建一个readme.md文件
[root@alibaba tomcat]# vim readme.md
hello,welcome,这是一个使用dockerfile构建的tomcat镜像@jude<747463168.com>

2、编写Dockerfile

[root@alibaba tomcat]# vim Dockerfile # 官方名称
FROM centos
MAINTAINER coding<24736743@qq.com>
# 复制一个文件到容器/usr/local目录内
COPY readme.md /usr/local/readme.md
# 自动解压到容器/usr/local目录下
ADD jdk-8u251-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.36.tar.gz /usr/local/
# 安装vim命令支持
RUN yum -y install vim
# 配置环境变量
ENV MYPATH /usr/local
# 工作目录
WORKDIR $MYPATH
# 配置JDK环境
ENV JAVA_HOME /usr/local/jdk1.8.0_251
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
# 配置tomcat
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.36
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.36

ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin:$CATALINA_HOME/lib
# 暴露容器内部端口8080
EXPOSE 8080
# 启动容器后执行命令:启动tomcat和打印日志
CMD /usr/local/apache-tomcat-9.0.36/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.36/bin/logs/catalina.out

3、构建镜像

[root@alibaba tomcat]# docker build -t coding/tomcat .

docker image命令查看镜像

启动运行tomcat

[root@alibaba tomcat]# docker run -d -p 9090:8080 --name codingtomcat -v /home/coding/tomcat/webapps:/usr/local/apache-tomcat-9.0.36/webapps/test -v /home/coding/tomcat/logs:/usr/local/apache-tomcat-9.0.36/logs coding/tomcat
5ddf6c85a6aac4ccb6abe03caab5cdfe6f5e78c079ef396c1c4ed546be5b92d4

# 运行后挂载的webapps与logs目录
[root@alibaba tomcat]# ls
apache-tomcat-9.0.36.tar.gz  Dockerfile  jdk1.8.0_201  jdk-8u201-linux-x64.tar.gz  logs  readme.md  webapps

外网访问

小结:

制作镜像、运行挂载,东西都没有问题了!本地docker我们到此彻底玩转!

发布镜像到DockerHub

官方镜像仓库地址 DockerHub!

地址:https://hub.docker.com/

1、注册 DockerHub!

2、登录 DockerHub!

3、本地docker 登录仓库

# 看登录登出命令
[root@alibaba tomcat]# docker --help
...
login       Log in to a Docker registry
logout      Log out from a Docker registry
...
pull        Pull an image or a repository from a registry
push        Push an image or a repository to a registry

4、push测试

# 登录后,push测试
[root@alibaba tomcat]# docker push coding/tomcat:lastest

5、本地镜像有问题,没有账号名称! tag!

# 需要修改名字
[root@alibaba tomcat]# docker tag 14113680e4b6 kuangshen/tocmat:1.0
# 重新push

发布镜像到本地仓库

https://docs.docker.com/engine/reference/commandline/push/

使用本地服务器作为镜像仓库

 # 拉取镜像
 docker pull registry
 
 # 创建容器
 docker run -d -p 5000:5000 registry
 
 # 配置私有仓库地址
 [root@alibaba tomcat]# vim /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://dyv68vb0.mirror.aliyuncs.com"],
"insecure-registries": ["http://47.113.95.179:5000"]
}

# 重启daemon进程
systemctl daemon-reload
# 重启docker
systemctl restart docker

# 启动仓库

访问http://47.113.95.179:5000/v2/_catalog

[root@alibaba tomcat]# curl localhost:5000/v2/_catalog
{"repositories":[]}

push测试

# 标记
[root@alibaba tomcat]# docker tag 25821f0bd151 47.113.95.179:5000/codingtomcat
# 推送
[root@alibaba tomcat]# docker push 47.113.95.179:5000/codingtomcat

下载镜像

[root@helloworld ~]# docker pull 47.113.95.179:5000/codingtomcat
Using default tag: latest
Error response from daemon: Get https://47.113.95.179:5000/v2/: http: server gave HTTP response to HTTPS client

问题使用http不安全,无法拉取

如何删除本地仓库上的镜像

# 查看仓库容器的配置文件
[root@alibaba tomcat]# docker exec -it 00b75ac66ff7 cat /etc/docker/registry/config.yml

# 修改配置文件 增加delete 字段
[root@alibaba tomcat]# docker exec -it 00b75ac66ff7 vi /etc/docker/registry/config.yml
version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
  delete:
    enabled: true
http:        
  addr: :5000                        
  headers:                           
    X-Content-Type-Options: [nosniff]
health:          
  storagedriver: 
    enabled: true
    interval: 10s
    threshold: 3
    
# 重启容器,生效配置
[root@alibaba tomcat]# docker restart 00b75ac66ff7

# 获取镜像摘要信息
curl --header "Accept:application/vnd.docker.distribution.manifest.v2+json" -I -XGET http://镜像地址/v2/镜像名称/manifests/镜像版本 

[root@alibaba tomcat]# curl --header "Accept:application/vnd.docker.distribution.manifest.v2+json" -I -XGET http://localhost:5000/v2/codingtomcat/manifests/latest
HTTP/1.1 200 OK
Content-Length: 1373
Content-Type: application/vnd.docker.distribution.manifest.v2+json
Docker-Content-Digest: sha256:d1f34ec22fe18c640a4e5af347f7b1e8e68914a6fd41a7fc7f56c80c154fe86b
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:d1f34ec22fe18c640a4e5af347f7b1e8e68914a6fd41a7fc7f56c80c154fe86b"
X-Content-Type-Options: nosniff
Date: Tue, 16 Jun 2020 15:01:30 GMT

# 删除私有仓库上的镜像
curl -I -XDELETE 私有仓库地址/v2/镜像名称/manifests/镜像对应sha256值

[root@alibaba tomcat]# curl -I -XDELETE http://localhost:5000/v2/codingtomcat/manifests/sha256:d1f34ec22fe18c640a4e5af347f7b1e8e68914a6fd41a7fc7f56c80c154fe86b
HTTP/1.1 202 Accepted  
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Tue, 16 Jun 2020 15:05:38 GMT
Content-Length: 0

发现其实还是删除不了的,自己的服务器做镜像仓库用起来有点费劲。

发布镜像到阿里云(建议)

1、登录阿里云,找到容器镜像服务

首先要自己开通容器镜像服务

2、创建命名空间,唯一确定你!

3、创建镜像仓库!选择私有或者公开,选择本地仓库

4、上传镜像

点进仓库,看操作指南写得很清楚,包括如何上传镜像和拉取镜像

  • 登录 docker login 阿里云仓库

    docker login --username=xxxx registry.cn-shenzhen.aliyuncs.com
    

  • 镜像打标签

docker tag [ImageId] registry.cn-shenzhen.aliyuncs.com/icoding-jude/icoding-study:redis-1.0
  • 推送镜像到阿里云仓库
docker push registry.cn-shenzhen.aliyuncs.com/icoding-jude/icoding-study:redis-1.0

5、推送完后就可以在我们的官方仓库查看了

仓库类型是私有的,需要登录docker才能pull,公有的直接pull。

在另外一台服务器上拉取刚上传的镜像

docker pull registry.cn-shenzhen.aliyuncs.com/icoding-jude/icoding-study:redis-1.0

把仓库类型改为私有,再尝试拉取失败,需要docker login登录

docker login登录仓库后,拉取成功

6、登出docker 阿里云仓库

[root@alibaba ~]# docker logout registry.cn-shenzhen.aliyuncs.com

总结

记住这幅图,到目前为止,Docker使用没有任何问题了!

2、IDEA整合Docker

自己写一个项目,使用docker来发布!交付,就是一个镜像而已!(应用 + 环境)

1、项目打包本地运行通过

web层接口定义HelloController

@RestController
public class HelloController {

	@GetMapping("/hello")
	public String hello(){
		return "hello,coding";
	}
}

package打jar包

2、编写Dockerfile,

先安装docker的插件(有提示功能),安装完后重启idea,让插件生效

3、构建镜像

把jar包和Dockerfile上传到服务器

[root@alibaba idea-app]# ls
Dockerfile  hello-0.0.1-SNAPSHOT.jar
# .代表当前目录
[root@alibaba idea-app]# docker build -t helloapp .

4、运行镜像通过

# -d 后台运行 -P随机暴露端口
[root@alibaba idea-app]# docker run -d -P helloapp
6572d2298ca013d679d8cc3753af17e93dd88aa4c827fafb2d6f569350367c27

# 访问测试
[root@alibaba idea-app]# curl localhost:32772/hello
hello,coding
[root@alibaba idea-app]#

5、发布镜像!

可以把镜像上传到阿里云镜像仓库了

小结

在使用了docker之后,以后的一切交付产品都使用docker来完成即可!

3、Docker网络

理解docker0

# 查看本地ip
[root@alibaba www]# ip addr

 # 分析3个网络
 lo 127.0.0.1 # 本地回环地址
 eth0 172.17.90.138 # 阿里云的私有ip 
 docker0 172.18.0.1 # docker的网卡
 # docker怎么处理容器间的访问的?

实际场景:

开发了很多的微服务项目,都需要连接数据库, url 地址,容器重启==> 每次url都会发生变化!(使用容器名连接 !)

如果可以直接指定ip就好了!

容器之间是否可以ping通!不能直接ping通,需要把容器放到同一个网络

原理

发现启动一个容器,本地就会多一个网卡,418与419一对网卡(容器内与宿主机)对应

宿主机与容器是可以ping通的

 # linux服务器是可以和容器内的应用ping通的!tomcat01的ip是172.18.0.2
 [root@kuangshen idea-app]# ping 172.18.0.2
 PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
 64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.069 ms

再启动一个tomcat容器

发现又多一对网卡420与421,420是容器内的网卡,421上宿主机上的网卡,它们是绑定的关系,从图中可以看出:420: eth0@if421,

421: veth139bf0a@if420。同时从图中发现491,421分别代表tomcat01和tomcat02,都连接到docker0 网卡上

得出结论:

 # linux      <=>     容器
 419:@if418        418:eth0@if419
 421:@if420        420:eth0@if421
 
 # 每一次启动,容器都会产生一对网卡!
 # 序号依次递增!
 # linux 这样一对虚拟设备接口! 这叫 veth-pair 技术 

顾名思义,veth-pair 就是一对的虚拟设备接口,和 tap/tun 设备不同的是,它都是成对出现的。一端连着协议栈,一端彼此相连着。如下图所示:

正因为有这个特性,它常常充当着一个桥梁,连接着各种虚拟网络设备,典型的例子像“两个 namespace 之间的连接”,“Bridge、OVS 之间的连接”,“Docker 容器之间的连接” 等等,以此构建出非常复杂的虚拟网络结构,比如 OpenStack Neutron。

发现,容器是可以互相ping通的,但是要通过ip地址!使用容器名就不行

# 默认docker0网卡,容器间使用容器名是无法ping通的,要使用ip地址
[root@kuangshen idea-app]# docker exec -it tomcat02 ping tomcat01
 ping: tomcat01: Name or service not known

结论:tomcat1 和 tomcat2 实际上,共用了一个路由! docker0,任何一个容器默认启动的时候都是docker0网络。docker0 就会给容器分配一个可用ip,自增!

16是后面两位可以改变的意思,8+8=16,范围是172.18.0.0 - 172.18.255.255,所以默认docker0 最多可以分配 65535

如果是8,范围是172.18.0.0 - 172.18.0.255

比如之后要自己创建一个网络,这些都是可以自己配置的!

–link容器互联

jdbc:mysql://172.18.0.2:3306 , 每次启动容器,ip都会变!

jdbc:mysql://容器名:3306 , 每次启动容器,容器名不变即可!

 # 直接使用容器名是无法ping通过的,需要使用--link参数
 [root@kuangshen idea-app]# docker exec -it tomcat02 ping tomcat01
 ping: tomcat01: Name or service not known
 
 # 使用--link,tomcat03在启动的时候连接到 tomcat02
 [root@kuangshen idea-app]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
 714c8b810584248a595f9e7d033038fa7ddc05c77110d96ee88abe78019755b0
 [root@kuangshen idea-app]# docker ps
 CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                     NAMES
 714c8b810584        tomcat              "catalina.sh run"   3 seconds ago        Up 2 seconds        0.0.0.0:32773->8080/tcp   tomcat03
 10175c786309        tomcat              "catalina.sh run"   About a minute ago   Up About a minute   0.0.0.0:32772->8080/tcp   tomcat02
 2f39a5a6588d        tomcat              "catalina.sh run"   About a minute ago   Up About a minute   0.0.0.0:32771->8080/tcp   tomcat01

# tomcat03 --link 连接到了一个容器之后,这时候才可以ping通容器名!
[root@kuangshen idea-app]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.18.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.18.0.3): icmp_seq=1 ttl=64 time=0.092 ms
64 bytes from tomcat02 (172.18.0.3): icmp_seq=2 ttl=64 time=0.068 ms

# 但是反过来tomcat02是无法连接tomcat03的,说明 --link 连接是单向的
[root@kuangshen idea-app]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known

如果在docker0情况下,我们可以使用–link 让容器之间可以使用容器名来ping通,连接成功!

–link 是一个单向连接!

原理:

进入容器tomcat03,查看配置文件/etc/hosts ,发现–link本质是在/etc/hosts配置文件上配置了映射。tomcat02上的/etc/hosts没有配置tomcat03的ip地址映射,所以tocmat02无法通过容器名直接连接到tocmat03。

备注: --link 过时 了,它是单向连接的,不推荐大家使用!
# 强制删除全部的容器
docker rm -f $(docker ps -qa) 

自定义一个网卡

我们可以把elasticsearch集群放在一个网络里,redis集群放在一个网络,mysql集群放在一个网络

 # 创建一个容器,就自动多一对网卡
 # 删除一个容器,自动减少,id还是自增!
 # docker run 不指定 网络,默认就是docker0
 docker0:
 1、默认的
 2、容器名访问,访问不了的!
 3、--link访问域名!麻烦,简陋,每个都配置!
 
 4、使用 docker network

查看所有网络

网络模式

Docker网络模式 配置 说明
host模式 –net=host 容器和宿主机共享Network namespace。主机!
container模式 –net=container:NAME_or_ID 容器和另外一个容器共享Network namespace。 kubernetes中的pod就是多个容器共享一个Network namespace。
none模式 –net=none 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。自己设置
bridge模式 –net=bridge (默认为该模式)路由器,自动划分ip!

1、自己创建网卡

[root@alibaba ~]# docker network --help
Usage:  docker network COMMAND
Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks

# 查看帮助命令 docker network create --help 
# --subnet 是子网范围,--gateway 是网关
[root@alibaba ~]# docker network create --drive bridge --subnet 192.167.0.0/16 --gateway 192.167.0.1 mynet2

2、使用自己的网络 –net,启动容器

# 创建启动一个容器,并指定网络mynet2
[root@alibaba ~]# docker run -d -P --name tomcat01 --net mynet tomcat:9.0
[root@alibaba ~]# docker run -d -P --name tomcat02 --net mynet tomcat:9.0
# 查看网络mynet2的详细信息
docker network inspect mynet

3、使用容器名相互ping通

[root@alibaba ~]# docker exec -it tomcat01 ping tomcat02
[root@alibaba ~]# docker exec -it tomcat02 ping tomcat01

自定义网络的一个好处!我们没有配置任何东西,他自己就可以相互ping通,比docker0强大!

使用自定义的网络,docker自身就帮我们维护了所有容器之间的连通,我们通常会这样来使用docker网络搭建项目环境!

网络连通

# 创建启动容器tomcat03,tomcat04, 不指定网络,默认是docker0,容器间只能通过ip地址相互ping通,无法通过容器名ping通
[root@alibaba ~]# docker run -d -P --name tomcat03 tomcat:9.0
5c0a620ca3d83cf542551299aad1bf295be5287a5b7cad658f9e7e9f88c91a80
[root@alibaba ~]# docker run -d -P --name tomcat04 tomcat:9.0
34668e99b2cf5bdf5992bc4a9ca074cdbcae501b398ee4e12c0f06aa10a75efa

# tomcat01,tomcat02在网络mynet,tomcat03,tomcat04在网络docker0

在不同网络中的tomcat可以通过ip地址相互ping通,但无法通过容器名相互ping通(自定义网络可以,docker0需要通过–link单向连接实现容器名ping通)

将容器tomcat03也加入网络mynet! 一个容器多个IP !

# 查看帮助命令
[root@alibaba ~]# docker network connect --help
Usage:  docker network connect [OPTIONS] NETWORK CONTAINER
Connect a container to a network
Options:
--alias strings           Add network-scoped alias for the container
--driver-opt strings      driver options for the network
--ip string               IPv4 address (e.g., 172.30.100.104)
--ip6 string              IPv6 address (e.g., 2001:db8::33)
--link list               Add link to another container
--link-local-ip strings   Add a link-local address for the container

 # 通过 docker network connet 连通
[root@alibaba ~]# docker network connect mynet tomcat03
[root@alibaba ~]# docker network inspect mynet

这样就可以实现容器跨网络访问!

网络就是基础问题;计算机网络原理没有问题!

Redis集群部署

上图3主3从

下去测试即可!主要理解docker网络,可以配置集群隔离,保证我们集群的安全性,每个服务集群有自己的网络!

1、自定义一个网络redis-net

[root@alibaba ~]# docker network create --subnet 172.38.0.0/16 --gateway 172.38.0.1 redis-net
c549a717573c11e698a0303657dc5502c0ec8da7940ed3d9099d9e67c94e5d2c

2、使用脚本启动6个redis容器

# 脚本注意不能有空格
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf 
touch /mydata/redis/node-${port}/conf/redis.conf 
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
requirepass redisjude666 # master开启密码保护,默认是没有密码的
masterauth redisjude666 # replica同master交互密码
EOF

docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis-net --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \

done

6个redis的配置文件和数据目录

3、创建集群

# 进入一个redis,注意这里是 sh命令
[root@alibaba ~]# docker exec -it redis-1 /bin/sh

# 创建集群(创建成功!)
# -a 是redis的密码
redis-cli -a redisjude666  --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1

4、连接集群

# 进入一个redis,连接集群 (-c 连接集群!)
redis-cli -c

# 查看集群信息
127.0.0.1:6379> cluster info

# 查看节点
127.0.0.1:6379> cluster nodes


5、高可用测试

# set a b  (选择一个容器进行set)
# 停止到存值的容器 (删除容器)
# 然后再次get a,发现依旧可以获取值 (自动转移到从机,依旧可以获得值)
# 查看节点,发现高可用完全没问题

set 一个key ,该key存储到了172.38.0.13 (容器redis-3), slot 槽点分片

进入容器redis-2,get a 会自动跳到 172.38.0.13 获取值,现在尝试把redis-3容器停掉,

[root@alibaba /]# docker stop redis-3
redis-3

依旧可以获取值

redis-3已失去连接,从节点redis-4 成为了 master 节点,实现了高可用。

redis集群的关闭与重启

集群的关闭

我这里使用docker安装,直接docker stop 容器关闭

[root@alibaba ~]# docker stop redis-6 redis-5 redis-4 redis-2  redis-1

其他redis集群的搭建方式,可以kill id 关闭redis实例

# 查找redis实例进程号
ps -ef | grep redis

# 关闭redis进程,使用kill -9 ${进程号},如果需要关闭多个进程,进程号之间空格隔开即可
kill -9 10252 10257 10262 10267 10272 10294

# 也可以批量kill
pkill -9 redis

集群的重新启动

  • 保留原来的数据

    逐个关闭redis实例,再逐个的启动即可。

  • 丢弃原来的数据

关闭实例,清空实例中数据存放目录的所有内容,然后逐个启动实例,在任意一个实例上执行集群的创建命令即可,本质上就是创建一个新的集群 清空数据存储目录内容:

rm -rf /opt/redis/cluster/7001/data/*
rm -rf /opt/redis/cluster/7002/data/*
rm -rf /opt/redis/cluster/7003/data/*
rm -rf /opt/redis/cluster/7004/data/*
rm -rf /opt/redis/cluster/7005/data/*
rm -rf /opt/redis/cluster/7006/data/*

启动实例

redis-server /opt/redis/cluster/7001/redis.conf
redis-server /opt/redis/cluster/7002/redis.conf
redis-server /opt/redis/cluster/7003/redis.conf
redis-server /opt/redis/cluster/7004/redis.conf
redis-server /opt/redis/cluster/7005/redis.conf
redis-server /opt/redis/cluster/7006/redis.conf

创建实例

# -a cyclone 是redis的密码
redis-cli -a redisjude666 --cluster create --cluster-replicas 1 192.168.220.11:7001 192.168.220.11:7002 192.168.220.11:7003 192.168.220.11:7004 192.168.220.11:7005 192.168.220.11:7006

参考文章:https://www.cnblogs.com/paul8339/p/11987345.html

Post Directory