Docker(2)-容器数据卷-DockerFile-Docker网络

容器数据卷

1. 什么是容器数据卷

docker的理念回顾

将应用和环境打包成一个镜像!

数据?如果数据都在容器中,那么我们容器删除,数据就会丢失!需求:数据可以持久化

MySQL,容器删了,删库跑路!需求:MySQL数据可以存储在本地

容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!

这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux上面!

总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的!

2. 使用数据卷

方式一:直接使用命令来挂载 -v

docker run -it -v 主机目录:容器内目录

# 测试
[root@iz2zeakqdima07k787wct3z ~]# docker run -it -v /home/ceshi:/home centos /bin/bash

# 启动起来之后我们可以通过 docker inspect 容器id

测试文件的同步

再来测试!

  1. 停止容器
  2. 宿主机上修改文件
  3. 启动容器
  4. 容器内的数据依旧是同步的

好处:我们以后修改只需要在本地修改即可,容器内会自动同步

3. 实战:安装MySQL

思考:MySQL数据持久化的问题!

# 获取镜像
[root@iz2zeakqdima07k787wct3z ~]# docker pull mysql:5.7
# 运行容器,需要做数据挂载! # 安装启动MySQL,需要配置密码,这是注意点!
# 官方测试,docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

# 启动我们的
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
--name 容器名字
[root@iz2zeakqdima07k787wct3z ~]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

# 启动成功之后,我们在本地使用 sqlyog 来测试一下
# sqlyog-连接到服务器的3310 --- 3310和容器内的 3306 映射,这个时候我们就可以连接上了

# 在本地测试创建一个数据库,查看一下我们映射的路径是否OK!

假设我们将容器删除,发现,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能!

4. 具名和匿名挂载

# 匿名挂载
-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx

# 查看所有的 volume 的情况
[root@iz2zeakqdima07k787wct3z ~]# docker volume ls
local                   o213u0123jr019901hr3893rp23ju98123u08ujfd0812ju30821ue
# 这里发现,这种就是匿名挂载,我们在 -v 只写了容器内的路径,没有写容器外的路径!

# 具名挂载
[root@iz2zeakqdima07k787wct3z ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
879e2a05282d6f5245ecddaebdb57d4d8210704d45f9ecf7e57ca249b07f6e8d
[root@iz2zeakqdima07k787wct3z ~]# docker volume ls
DRIVER              VOLUME NAME
local               juming-nginx

# 通过 -v 卷名:容器内路径
# 查看一下这个卷

所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/XXXX/_data

我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用的具名挂载

# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载
-v 容器内路径        #匿名挂载
-v 卷名:容器内路径     # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载

拓展:

# 通过 -v 容器内路径,ro rw 改变读写权限
ro      readonly    # 只读
rw      readwrite   # 可读可写

# 一旦设置了容器权限,容器对我们挂载出来的内容就有限定了!
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx

# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作的!

5. 初识Dockerfile

Dockerfile 就是用来构建 docker 镜像的构建文件!命令脚本!先体验一下!

# 创建一个dockerfile文件,名字可以随机 建议 Dockerfile
[root@iz2zeakqdima07k787wct3z home]# mkdir docker-test-volume
[root@iz2zeakqdima07k787wct3z home]# ls
ceshi  docker-test-volume  mysql  rgh.java  test.java  www
[root@iz2zeakqdima07k787wct3z home]# cd docker-test-volume/
[root@iz2zeakqdima07k787wct3z docker-test-volume]# vim dockerfile1
# 文件中的内容 指令(大写) 参数
FROM centos

VOLUME ["volum01","volum02"]

CMD echo "----end----"
CMD /bin/bash
# 这里的每个指令,就是镜像的一层

这个卷和外部一定有一个同步的目录!

查看一下卷挂载的路径

测试一下刚才的文件是否同步出去了!

这种方式我们未来使用的非常多,因为我们通常会构建自己的镜像!

假设构建镜像时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径!

6. 数据容器卷

多个mysql同步数据!

# 启动3个容器,通过我们刚才自己写的镜像启动
[root@iz2zeakqdima07k787wct3z /]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
rgh/centos            1.0                 f6a19068fc9c        About an hour ago   215MB
tomcat02              1.0                 7d44ce4e447c        4 hours ago         652MB
centos                latest              831691599b88        8 days ago          215MB
tomcat                9.0                 2eb5a120304e        2 weeks ago         647MB
tomcat                latest              2eb5a120304e        2 weeks ago         647MB
nginx                 latest              2622e6cca7eb        2 weeks ago         132MB
mysql                 5.7                 9cfcce23593a        2 weeks ago         448MB
portainer/portainer   latest              cd645f5a4769        3 weeks ago         79.1MB
elasticsearch         7.6.2               f29a1ee41030        3 months ago        791MB
[root@iz2zeakqdima07k787wct3z /]# docker run -it --name docker01 rgh/centos:1.0
# Ctrl + p + q
[root@iz2zeakqdima07k787wct3z /]# docker run -it --name docker02 --volumes-from docker01 rgh/centos:1.0
# 测试,可以删除docker01,查看一下docker02和docker03是否还可以访问这个文件
# 测试依旧可以访问

多个mysql实现数据共享

[root@iz2zeakqdima07k787wct3z ~]# docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

[root@iz2zeakqdima07k787wct3z ~]# docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-form mysql01 mysql:5.7

# 这个时候可以实现两个容器数据同步

结论:

容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。

但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!

DockerFile

dockerfile 是用来构建docker镜像的文件!命令参数脚本!

构建步骤:

  1. 编写一个 dockerfile 文件
  2. docker build 构建成为一个镜像
  3. docker run 运行镜像
  4. docker push 发布镜像(DockerHub、阿里云镜像仓库!)

很多官方镜像都是基础包,很多功能都没有,我们通常会自己搭建自己的镜像!

官方既然可以制作镜像,那我们也可以!

1. DockerFile构建过程

基础知识

  1. 每个保留关键字(指令)都必须是大写字母
  2. 执行从上到下顺序执行
  3. # 表示注释
  4. 每个指令都会创建提交一个新的镜像层,并提交

dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!

Docker镜像逐渐成为了企业交付的标准,必须掌握!

DockerFile:构建文件,定义了一切的步骤,源代码

DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品!

Docker容器:容器就是镜像运行起来提供服务的

2. DockerFile的指令

FROM            # 基础镜像,一切从这里开始构建
MAINTAINER      # 镜像是谁写的,姓名+邮箱
RUN             # 镜像构建的时候需要运行的命令
ADD             # 步骤,tomcat镜像,这个tomcat压缩包!添加内容
WORKDIR         # 镜像的工作目录
VOLUME          # 挂载的目录
EXPOST          # 暴露端口配置
CMD             # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT      # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD         # 当构建一个被继承的 DockerFile 这个时候就会运行 ONBUILD 的指令。触发指令。
COPY            # 类似ADD,将我们的文件拷贝到镜像中
ENV             # 构建的时候设置环境变量

3. 实战测试

Docker Hub 中 99% 镜像都是从这个基础镜像过来的 FROM scratch ,然后配置需要的软件和配置来进行的构建

创建一个自己的centos

# 创建文件夹
[root@iz2zeakqdima07k787wct3z home]# mkdir dockerfile
[root@iz2zeakqdima07k787wct3z home]# ls
ceshi  dockerfile  docker-test-volume  mysql  rgh.java  test.java  www
[root@iz2zeakqdima07k787wct3z home]# cd dockerfile/
[root@iz2zeakqdima07k787wct3z dockerfile]# ls
# 1. 编写dockerfile的文件
[root@iz2zeakqdima07k787wct3z dockerfile]# vim mydockerfile-centos
[root@iz2zeakqdima07k787wct3z dockerfile]# cat mydockerfile-centos 
FROM centos
MAINTAINER rgh<386045673@qq.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash
[root@iz2zeakqdima07k787wct3z dockerfile]# 
# 2. 通过这个文件构建镜像
# 命令 docker build -f dockerfile文件路径 -t 镜像名:[tag]
[root@iz2zeakqdima07k787wct3z dockerfile]# docker build -f mydockerfile-centos -t mycentos:0.1 .

Successfully built 662e5307e229
Successfully tagged mycentos:0.1
# 3. 测试运行

对比:之前的原生的centos

我们增加之后的镜像

我们可以列出本地镜像的变更历史

我们平时拿到一个镜像,可以研究一下它是怎么做的了?

CMD 和 ENTRYPOINT区别

CMD             # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT      # 指定这个容器启动的时候要运行的命令,可以追加命令

测试cmd

# 编写 dockerfile 文件
[root@iz2zeakqdima07k787wct3z dockerfile]# vim dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]
# 构建镜像
[root@iz2zeakqdima07k787wct3z dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM centos
 ---> 831691599b88
Step 2/2 : CMD ["ls","-a"]
 ---> Running in 599c30194db4
Removing intermediate container 599c30194db4
 ---> 21002a840f44
Successfully built 21002a840f44
Successfully tagged cmdtest:latest
# run 运行,发现我们的 ls -a 命令生效了
[root@iz2zeakqdima07k787wct3z dockerfile]# docker run 21002a840f44
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
# 想追加一个命令 -l    ls -al
[root@iz2zeakqdima07k787wct3z dockerfile]# docker run 21002a840f44 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.

# cmd的情况下 -l 替换了 CMD ["ls","-a"] 命令,-l 不是命令所以报错

测试ENTRYPOINT

[root@iz2zeakqdima07k787wct3z dockerfile]# vim dockerfile-cmd-entrypoint
FROM centos
CMD ["ls","-a"]
[root@iz2zeakqdima07k787wct3z dockerfile]# docker build -f dockerfile-cmd-entrypoint -t entrypoint-test .
Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM centos
 ---> 831691599b88
Step 2/2 : ENTRYPOINT ["ls","-a"]
 ---> Running in 82d1ebd7d27d
Removing intermediate container 82d1ebd7d27d
 ---> 6b36f25bbfb0
Successfully built 6b36f25bbfb0
Successfully tagged entrypoint-test:latest
[root@iz2zeakqdima07k787wct3z dockerfile]# docker run 6b36f25bbfb0
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
# 我们的追加命令,是直接拼接在我们的 ENTRYPOINT 命令的后面!
[root@iz2zeakqdima07k787wct3z dockerfile]# docker run 6b36f25bbfb0 -l
total 56
drwxr-xr-x   1 root root 4096 Jun 26 07:01 .
drwxr-xr-x   1 root root 4096 Jun 26 07:01 ..
-rwxr-xr-x   1 root root    0 Jun 26 07:01 .dockerenv
lrwxrwxrwx   1 root root    7 May 11  2019 bin -> usr/bin
drwxr-xr-x   5 root root  340 Jun 26 07:01 dev
drwxr-xr-x   1 root root 4096 Jun 26 07:01 etc
drwxr-xr-x   2 root root 4096 May 11  2019 home
lrwxrwxrwx   1 root root    7 May 11  2019 lib -> usr/lib
[root@iz2zeakqdima07k787wct3z dockerfile]# 

DockerFile中很多命令都十分的相似,我们需要了解它们的区别,我们最好的学习就是对比他们然后测试效果

4. 实战:Tomcat镜像

  1. 准备镜像文件 tomcat压缩包,jdk压缩包

  1. 编写dockerfile文件,官方命名Dockerfile,build会自动寻找这个文件,就不需要 -f 指定了!

    FROM centos
    MAINTAINER rgh<386045673@qq.com>
    
    COPY readme.txt /usr/local/readme.txt
    
    ADD jdk-8u152-linux-x64.tar.gz /usr/local/
    ADD apache-tomcat-8.5.24.tar.gz /usr/local/
    
    RUN yum -y install vim
    
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    
    ENV JAVA_HOME /usr/local/jdk1.8.0_152
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.24
    ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.24
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
    
    EXPOSE 8080
    
    CMD /usr/local/apache-tomcat-8.5.24/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.24/bin/logs/catalina.out
    
  2. 构建镜像

    # docker build -t diytomcat .
    
    [root@iz2zeakqdima07k787wct3z tomcat]# docker run -d -p 9090:8080 --name rghtomcat -v /home/rgh/build/tomcat/test:/usl/local/apache-tomcat-8.5.24/webapps/test -v /home/rgh/build/tomcat/tomcatlogs/:/usl/local/apache-tomcat-8.5.24/logs diytomcat
    
    
  3. 启动镜像

  4. 访问测试

  5. 发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布)

      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="http://java.sun.com/xml/ns/javaee"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                                   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
               version="2.5">
    
      </web-app>
    
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>Hello,RGH</title>
    </head>
    <body>
    Hello World!<br/>
    <%
    System.out.println("----my test web logs-----");
    %>
    </body>
    </html>
    

发现:项目部署成功,可以直接访问OK!

我们以后开发的步骤:需要掌握Dokcerfile的编写!我们之后的一切都是使用docker镜像来发布运行!

5. 发布自己的镜像

DockerHub

  1. 地址 https://hub.docker.com/ 注册自己的账号

  2. 确定这个账号可以登陆

  3. 在我们服务器上提交自己的镜像

    [root@iz2zeakqdima07k787wct3z tomcat]# docker login --help
    
    Usage:   docker login [OPTIONS] [SERVER]
    
    Log in to a Docker registry.
    If no server is specified, the default is defined by the daemon.
    
    Options:
      -p, --password string   Password
          --password-stdin    Take the password from stdin
      -u, --username string   Username
      
    [root@iz2zeakqdima07k787wct3z tomcat]# docker login -u ruanguohui
    Password: 
    WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
    Configure a credential helper to remove this warning. See
    https://docs.docker.com/engine/reference/commandline/login/#credentials-store
    
    Login Succeeded
    
  4. 登陆完毕后就可以提交镜像了,就是一步 docker push

    [root@iz2zeakqdima07k787wct3z tomcat]# docker push diytomcat
    The push refers to repository [docker.io/library/diytomcat]
    c385be13b942: Preparing 
    e348f8d69a0a: Preparing 
    e048a134c37e: Preparing 
    579df485af18: Preparing 
    eb29745b8228: Preparing 
    denied: requested access to the resource is denied # 拒绝
    # push 遇到的问题?
    [root@iz2zeakqdima07k787wct3z tomcat]# docker push ruanguohui/diytomcat:2.0
    The push refers to repository [docker.io/ruanguohui/diytomcat]
    An image does not exist locally with the tag: ruanguohui/diytomcat
    # 解决,增加一个tag
    [root@iz2zeakqdima07k787wct3z tomcat]# docker tag c0794e0071c6 ruanguohui/tomcat:1.0
    # docker push 上去即可!自己发布的镜像尽量带上版本号
    [root@iz2zeakqdima07k787wct3z tomcat]# docker push ruanguohui/tomcat:1.0
    

提交的时候也是按照镜像的层级来进行提交的。

阿里云镜像服务器上

  1. 登陆阿里云

  2. 找到容器镜像服务

  3. 创建命名空间

  1. 创建容器镜像

  1. 浏览阿里云

docker push registry.cn-beijing.aliyuncs.com/test-ruanguohui/ruanguohui-demo:[镜像版本号]

小结

Docker网络

1. 理解Docker0

清空所有环境

# 清空所有容器
docker rm -f $(docker ps -aq)
# 清空所有镜像
docker rmi -f $(docker images -aq)

测试

三个网络

# 问题:docker 是如何处理容器网络访问的?
[root@iz2zeakqdima07k787wct3z ~]# docker run -d -P --name tomcat01 tomcat
# 查看容器的内部网络地址   ip addr ,发现容器启动的时候会得到一个 eth0@if87 ip地址,docker分配的
# exec:执行 -it:交互模式执行
[root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
86: eth0@if87: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
# 思考,linux 能不能 ping 同容器内部
[root@iz2zeakqdima07k787wct3z ~]# 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.110 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.090 ms
64 bytes from 172.18.0.2: icmp_seq=3 ttl=64 time=0.090 ms
# linux 可以ping通docker容器内部

原理

  1. 我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0桥接模式,使用的技术是 veth-pair 技术!

  1. 再启动一个容器测试,发现又多了一对网卡!

# 我们发现这个容器带来网卡,都是一对对的
# veth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连
# 正因为有这个特性,evth-pair充当一个桥梁,连接各种虚拟网络设备的
# Openstac,Docker容器之间的连接,OVS的连接,都是使用 veth-pair 技术
  1. 我们来测试下 tomcat01和tomcat02 是否可以ping通

    [root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat02 ping 172.18.0.2
    # 结论:容器和容器之间是可以互相ping通的
    

结论:tomcat01 和 tomcat02是公用的一个路由器,docker0。

所有的容器在不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用IP

小结

Docker使用的是Linux的桥接,宿主机中是一个Docker容器的网桥 docker0

Docker 中的所有的网络接口都是虚拟的。虚拟的转发效率高!(内网传递文件)

只要容器删除,对应网桥一对就没了!

2. --link

思考一个场景,我们编写了一个微服务,database url=ip:,项目不重启,数据库IP换掉了,我们希望可以处理这个问题,可以通过名字来访问容器?

[root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known
# 如何解决呢?
# 通过--link 就可以解决网络连通问题
[root@iz2zeakqdima07k787wct3z ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
4e824c3691317b00c0e752e21226430973de0f7b99c4ebc2c11b1d538042a573
[root@iz2zeakqdima07k787wct3z ~]# 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.142 ms
64 bytes from tomcat02 (172.18.0.3): icmp_seq=2 ttl=64 time=0.094 ms
64 bytes from tomcat02 (172.18.0.3): icmp_seq=3 ttl=64 time=0.106 ms
# 反向可以ping通吗?
[root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known

探究:inspect!

# 查看 hosts 配置,在这里原理发现!
[root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.3  tomcat02 dd58d47f44b0
172.18.0.4  4e824c369131

本质探究:--link 就是我们在hosts配置中增加了一个 172.18.0.3 tomcat02 dd58d47f44b0

我们现在玩Docker 已经不建议使用 --link了!

自定义网络!不适用docker0!

自定义网络!不适用docker0!

docker0问题:他不支持容器名连接访问!

3. 自定义网络

查看所有的docker网络

网络模式:

bridge:桥接 docker (默认,自己创建也使用bridge 模式)

none:不配置网络

host:和宿主机共享网络

container:容器网络连通!(用的少!局限很大)

测试:

[root@iz2zeakqdima07k787wct3z ~]# docker rm -f $(docker ps -aq)
# 我们直接启动的命令 --net bridge,而这个就是我们的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 tomcat --net bridge tomcat
# docker0特点,默认,域名不能访问,--link可以打通连接!
# 我们可以自定义一个网络!
# --driver bridge
# --subnet 192.168.0.0/16
# --gateway 192.168.0.1
[root@iz2zeakqdima07k787wct3z ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
97ffb25e7d237cf835799ded68e898f14df0238edad893ff94f1c36ba301ee6c
[root@iz2zeakqdima07k787wct3z ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
fa839e57d074        bridge              bridge              local
365c15486a05        host                host                local
97ffb25e7d23        mynet               bridge              local
fb1e21f22d8a        none                null                local
[root@iz2zeakqdima07k787wct3z ~]# 

我们自己的网络就创建好了

[root@iz2zeakqdima07k787wct3z ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
f2f53454947289774201b5c5e7ca37e87f5192757033522a061888596992677c
[root@iz2zeakqdima07k787wct3z ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
6bf0fdad1c734216e68b698af62e91c5f2db2c8afb9d42a0de7efdf321fd7612
[root@iz2zeakqdima07k787wct3z ~]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "97ffb25e7d237cf835799ded68e898f14df0238edad893ff94f1c36ba301ee6c",
        "Created": "2020-06-27T17:43:51.170257885+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "6bf0fdad1c734216e68b698af62e91c5f2db2c8afb9d42a0de7efdf321fd7612": {
                "Name": "tomcat-net-02",
                "EndpointID": "5b4ff32db373b566847e69286e441f0efa2f54324b5c5be39c70957aad26ad8e",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            },
            "f2f53454947289774201b5c5e7ca37e87f5192757033522a061888596992677c": {
                "Name": "tomcat-net-01",
                "EndpointID": "c60878eff346f9e01f81354393534dde67141510a7ea49d2351c0a4f3bec525c",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
# 再次测试ping连接
[root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.126 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.100 ms
^C
--- 192.168.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.100/0.113/0.126/0.013 ms
# 现在不使用--link也可以ping名字了!
[root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.082 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.118 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.096 ms

我们自定义的网络docker都帮我们维护好了对应的关系,推荐我们平时这样使用网络!

好处:

redis - 不同的集群使用不同的网络,保证集群是安全和健康的

mysql - 不同的集群使用不同的网络,保证集群是安全和健康的

网络连通

# 测试打通 tomcat01 - mynet
[root@iz2zeakqdima07k787wct3z ~]# docker network connect mynet tomcat01
# 连通之后就是将 tomcat01 放到了 mynet 网络下

# 一个容器两个IP地址
# 阿里云服务器,公网IP,私网IP
# 01 连通
[root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.120 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.100 ms
# 02 是依旧打不通的
[root@iz2zeakqdima07k787wct3z ~]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known

结论:假设要跨网络操作别人,就需要使用 docker network connect 连通!

4. 实战:部署Redis集群

[root@iz2zeakqdima07k787wct3z ~]# docker rm -f $(docker ps -aq)
[root@iz2zeakqdima07k787wct3z ~]# docker network create redis --subnet 172.38.0.0/16
0b04ad3dc26d3d3951c7a210b2a49e1c27b57faf69a122e3bea65b6e20a4da5e
[root@iz2zeakqdima07k787wct3z ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
fa839e57d074        bridge              bridge              local
365c15486a05        host                host                local
97ffb25e7d23        mynet               bridge              local
fb1e21f22d8a        none                null                local
0b04ad3dc26d        redis               bridge              local
[root@iz2zeakqdima07k787wct3z ~]# docker network inspect redis
[
    {
        "Name": "redis",
        "Id": "0b04ad3dc26d3d3951c7a210b2a49e1c27b57faf69a122e3bea65b6e20a4da5e",
        "Created": "2020-06-29T10:38:10.140768409+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.38.0.0/16"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
# 通过脚本创建六个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
EOF
done

docker run -p 6371:6379 -p 16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /mydata/redis/node-2/data:/data \
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /mydata/redis/node-3/data:/data \
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /mydata/redis/node-4/data:/data \
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /mydata/redis/node-5/data:/data \
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
# 创建集群
[root@iz2zeakqdima07k787wct3z conf]# docker exec -it redis-1 /bin/sh
/data # redis-cli --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
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.38.0.15:6379 to 172.38.0.11:6379
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
M: de7260f699404b3ba4f3ccd3203d304ce2062085 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
M: 6fffc21e8ccef5565124fa55f1a6f83e8a2ae609 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: 6e90db525d03538a646de43a943437cbd1319931 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: 3c1b3a9ef855d3267ab8b6f68bdda515da1b2556 172.38.0.14:6379
   replicates 6e90db525d03538a646de43a943437cbd1319931
S: e2ada3facb95d3b86f02a1a696990ae7ef8059f5 172.38.0.15:6379
   replicates de7260f699404b3ba4f3ccd3203d304ce2062085
S: 136a386bb4690f2d7949d2fc6dfacd748029567e 172.38.0.16:6379
   replicates 6fffc21e8ccef5565124fa55f1a6f83e8a2ae609
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
....
>>> Performing Cluster Check (using node 172.38.0.11:6379)
M: de7260f699404b3ba4f3ccd3203d304ce2062085 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: e2ada3facb95d3b86f02a1a696990ae7ef8059f5 172.38.0.15:6379
   slots: (0 slots) slave
   replicates de7260f699404b3ba4f3ccd3203d304ce2062085
M: 6fffc21e8ccef5565124fa55f1a6f83e8a2ae609 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
M: 6e90db525d03538a646de43a943437cbd1319931 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 136a386bb4690f2d7949d2fc6dfacd748029567e 172.38.0.16:6379
   slots: (0 slots) slave
   replicates 6fffc21e8ccef5565124fa55f1a6f83e8a2ae609
S: 3c1b3a9ef855d3267ab8b6f68bdda515da1b2556 172.38.0.14:6379
   slots: (0 slots) slave
   replicates 6e90db525d03538a646de43a943437cbd1319931
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
# redis-cli 单击 -c 集群
/data # redis-cli -c
# cluster info 查看集群信息
127.0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:139
cluster_stats_messages_pong_sent:145
cluster_stats_messages_sent:284
cluster_stats_messages_ping_received:140
cluster_stats_messages_pong_received:139
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:284
127.0.0.1:6379> 

Docker搭建Redis集群完成

我们使用了docker之后,所有的技术都会慢慢的变的简单起来!

SpringBoot微服务打包Docker镜像

  1. 构架SpringBoot项目

  2. 打包应用

  3. 编写dockerfile

    FROM java:8
    
    COPY *.jar /app.jar
    
    CMD ["--server.port=8080"]
    
    EXPOSE 8080
    
    ENTRYPOINT ["java","-jar","/app.jar"]
    
  4. 构建镜像

  5. 发布运行!

[root@iz2zeakqdima07k787wct3z ~]# cd /home
[root@iz2zeakqdima07k787wct3z home]# ls
ceshi  dockerfile  docker-test-volume  mysql  rgh  rgh.java  test.java  www
[root@iz2zeakqdima07k787wct3z home]# mkdir idea
[root@iz2zeakqdima07k787wct3z home]# ls
ceshi  dockerfile  docker-test-volume  idea  mysql  rgh  rgh.java  test.java  www
[root@iz2zeakqdima07k787wct3z home]# cd idea/
[root@iz2zeakqdima07k787wct3z idea]# ls
demo-0.0.1-SNAPSHOT.jar  Dockerfile
[root@iz2zeakqdima07k787wct3z idea]# docker build -t rgh666 .
Sending build context to Docker daemon   16.5MB
Step 1/5 : FROM java:8
8: Pulling from library/java
5040bd298390: Pull complete 
fce5728aad85: Pull complete 
76610ec20bf5: Pull complete 
60170fec2151: Pull complete 
e98f73de8f0d: Pull complete 
11f7af24ed9c: Pull complete 
49e2d6393f32: Pull complete 
bb9cdec9c7f3: Pull complete 
Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d
Status: Downloaded newer image for java:8
 ---> d23bdf5b1b1b
Step 2/5 : COPY *.jar /app.jar
 ---> 14ced70e2b66
Step 3/5 : CMD ["--server.port=8080"]
 ---> Running in 76e95c24c32c
Removing intermediate container 76e95c24c32c
 ---> 53155ec64b62
Step 4/5 : EXPOSE 8080
 ---> Running in 01f0e326df36
Removing intermediate container 01f0e326df36
 ---> 769f12470d42
Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"]
 ---> Running in 5e64fa2ea56e
Removing intermediate container 5e64fa2ea56e
 ---> 5da2e4111e93
Successfully built 5da2e4111e93
Successfully tagged rgh666:latest
[root@iz2zeakqdima07k787wct3z idea]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
rgh666              latest              5da2e4111e93        13 seconds ago      660MB
tomcat              latest              2eb5a120304e        2 weeks ago         647MB
redis               5.0.9-alpine3.11    3661c84ee9d0        2 months ago        29.8MB
java                8                   d23bdf5b1b1b        3 years ago         643MB
[root@iz2zeakqdima07k787wct3z idea]# docker run -d -P --name rgh-springboot-web rgh666
bccf17124951508c309a8c85505e072492cea5fa726f23f7154c01fc33706825
[root@iz2zeakqdima07k787wct3z idea]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
bccf17124951        rgh666              "java -jar /app.jar …"   11 seconds ago      Up 11 seconds       0.0.0.0:32778->8080/tcp   rgh-springboot-web
[root@iz2zeakqdima07k787wct3z idea]# curl localhost:32778
{"timestamp":"2020-06-29T07:02:55.100+00:00","status":404,"error":"Not Found","message":"","path":"/"}[root@iz2zeakqdima07k787wct3z idea]# curl localhost:32778/hello
hello,ruanguohui[root@iz2zeakqdima07k787wct3z idea]# 

以后我们使用了docker之后,给别人交付的就是一个镜像即可!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,154评论 5 464
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,252评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,107评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,985评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,905评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,256评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,978评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,611评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,891评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,910评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,736评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,516评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,995评论 3 301
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,132评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,447评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,034评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,242评论 2 339