Docker-基础

Docker-基础

一、Docker概述

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

docker架构

Docker使用了C/S体系架构,Docker客户端与Docker守护进程通信,Docker守护进程负责构建,运行和分发Docker容器。Docker客户端和守护进程可以在同一个系统上运行,也可以将Docker客户端连接到远程Docker守护进程。Docker客户端和守护进程使用REST API通过UNIX套接字或网络接口进行通信。

image-20201009152248511

1. Client(客户端)

Client即Docker客户端,也就是上一小节Docker Engine中介绍的docker CLI。开发者通过这个客户端使用Docker的相关指令与Docker守护进程进行交互,从而进行Docker镜像的创建、拉取和运行等操作。

2. DOCKER_HOST(Docker主机)

DOCKER_HOST即Docker内部引擎运行的主机,主要指Docker daemon(Docker守护进程)。可以通过Docker守护进程与客户端还有Docker的镜像仓库Registry进行交互,从而管理Images(镜像)和Containers(容器)等。

Images(镜像)

Docker镜像就是一个只读的模板,包含了一些创建Docker容器的操作指令。通常情况下,一个Docker镜像是基于另一个基础镜像创建的,并且新创建的镜像会额外包含一些功能配置。例如:开发者可以依赖于一个 Ubuntu 的基础镜像创建一个新镜像,并可以在新镜像中安装Apache等软件或其他应用程序。

Containers(容器)

Docker 容器属于镜像的一个可运行实例(镜像与容器的关系其实与 Java 中的类与对象相似),开发者可以通过API接口或者CLI命令行接口来创建、运行、停止、移动、删除一个容器,也可以将一个容器连接到一个或多个网络中,将数据存储与容器进行关联。

3. Registry(注册中心)

Registry即Docker注册中心,实质就是Docker镜像仓库,默认使用的是Docker官方远程注册中心Docker Hub,也可以使用开发者搭建的本地仓库。Registry中包含了大量的镜像,这些镜像可以是官网基础镜像,也可以是其他开发者上传的镜像。

我们在实际使用 Docker 时,除了会涉及图中的 3 个主要部分外,还会涉及很多Docker Objects(Docker对象),例如Images(镜像)、Containers(容器)、Networks(网络)、Volumes (数据卷)、Plugins(插件)等。其中常用的两个对象Image和Containers的说明如下。

二、Docker安装

2.1、安装

#1、卸载旧版本
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
#2、需要的安装包
yum install -y yum-utils
#3、设置镜像仓库
#国外镜像地址(不推荐,速度慢)
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
#国内阿里云镜像地址(推荐,速度快)
yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#4、更新yum软件索引包
yum makecache fast
#5、安装docker ce-社区办  ee-企业版
yum install docker-ce docker-ce-cli containerd.io
#安装指定docker版本
#yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
#6、启动docker
systemctl start docker
#7、查看docker安装的版本
docker version
#下面为docker version操作命令出现的信息,说明docker安装成功
Client: Docker Engine - Community
 Version:           19.03.13
 API version:       1.40
 Go version:        go1.13.15
 Git commit:        4484c46d9d
 Built:             Wed Sep 16 17:03:45 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.13
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       4484c46d9d
  Built:            Wed Sep 16 17:02:21 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.3.7
  GitCommit:        8fba4e9a7d01810a393d5d25a3621dc101981175
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
  
#8、运行镜像  
docker search hello-world   #查找hello-world镜像,得到所有的版本
docker run hello-world      #找到仓库中最新版本的镜像,运行
docker images      #查看镜像
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              bf756fb1ae65        9 months ago        13.3kB

docker run hello-world 的运行流程图:

image-20201009151303506

2.2、卸载

#1、卸载docker
yum remove docker-ce docker-ce-cli containerd.io
#2、删除docker资源
rm -rf /var/lib/docker    #docker的默认资源地址 /var/lib/docker

2.3、配置阿里云镜像加速器

sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://tdzq633y.mirror.aliyuncs.com"]
}
EOF

sudo systemctl daemon-reload

sudo systemctl restart docker

三、Docker的常用命令

3.1、帮助命令

3.2、镜像命令

当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载。

3.2.1、列出镜像列表

[root@zxone ~]# docker images   #列出本地存在影响列表
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mytomcat            1.0                 c82080e5255f        3 days ago          640MB
mycentos            1.0                 39a4c2226cd0        3 days ago          295MB
zxone/centos        1.0                 aac11c067c6f        3 days ago          215MB
nginx               latest              992e3b7be046        7 days ago          133MB
mysql               5.7                 ef08065b0a30        4 weeks ago         448MB
centos              latest              0d120b6ccaa8        2 months ago        215MB
hello-world         latest              bf756fb1ae65        9 months ago        13.3kB

  • REPOSITORY:表示镜像的仓库源
  • TAG:镜像的标签
  • IMAGE ID:镜像ID
  • CREATED:镜像创建时间
  • SIZE:镜像大小

3.2.2、搜索镜像

#使用命令search查询镜像,返回仓库上存在的镜像列表
docker search hello-world

image-20201013150955208

3.2.3、获取镜像

当我们在本地主机上使用一个不存在的镜像时 Docker 就会自动下载这个镜像。如果我们想预先下载这个镜像,我们可以使用 docker pull 命令来下载它。

[root@zxone ~]# docker pull hello-world   
Using default tag: latest
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete 
Digest: sha256:4cf9c47f86df71d48364001ede3a4fcd85ae80ce02ebad74156906caff5378bc
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest

image-20201013151259389

3.2.4、删除镜像

镜像删除使用 docker rmi 命令,比如我们删除 hello-world 镜像:

docker rmi hello-world         #需要把这个镜像运行启动的容器全部删除才能删除镜像
docker rmi $(docker images -q) #删除所有的镜像

image-20201013151532785

3.2.5、创建镜像

当我们从 docker 镜像仓库中下载的镜像不能满足我们的需求时,我们可以通过以下两种方式对镜像进行更改。

  • 1、从已经创建的容器中更新镜像,并且提交这个镜像
  • 2、使用 Dockerfile 指令来创建一个新的镜像

3.2.6、更新镜像

更新镜像之前,我们需要使用镜像来创建一个容器。

docker run -t -i ubuntu:15.10 /bin/bash

在运行的容器内使用 apt-get update 命令进行更新。

在完成操作之后,输入 exit 命令来退出这个容器。

此时 ID 为 e218edb10161 的容器,是按我们的需求更改的容器。我们可以通过命令 docker commit 来提交容器副本。

docker commit -m="has update" -a="xxxxx" e218edb10161 runoob/ubuntu:v2
sha256:70bf1840fd7c0d2d8ef0a42a817eb29f854c1af8f7c59fc03ac7bdee9545aff8

各个参数说明:

  • -m: 提交的描述信息
  • -a: 指定镜像作者
  • e218edb10161:容器 ID
  • runoob/ubuntu:v2: 指定要创建的目标镜像名

我们可以使用 docker images 命令来查看我们的新镜像 runoob/ubuntu:v2

3.3、容器命令

3.3.1、启动/退出容器

  • -d:让容器在后台运行。
  • -P:将容器内部使用的网络端口随机映射到我们使用的主机上。
  • -p:指定端口映射
#-i: 交互式操作。
#-t: 终端。
#--name 给启动的容器起一个名字
#centos: ubuntu 镜像。
#/bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。
[root@zxone ~]# docker run -it --name centos01 centos /bin/bash 
[root@64886e359a33 /]# exit
exit
[root@zxone ~]# docker ps    #查看运行中的容器
[root@zxone ~]# docker ps -a	#查看所有容器
[root@zxone ~]# docker stop <容器id>  #停止容器
[root@zxone ~]# docker start <容器id>	#启动容器
[root@zxone ~]# docker restart <容器id>	#重新启动容器
[root@zxone ~]# docker rm <容器id> #删除容器,命令docker ps -a 就查询不到这个容器了
#-d 后台运行容器
[root@zxone ~]# docker run -itd --name centos01 centos /bin/bash

3.3.2、进入容器

在使用 -d 参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:

  • docker attach
  • docker exec:推荐大家使用 docker exec 命令,因为此退出容器终端,不会导致容器的停止。
[root@zxone ~]# docker attach b3806743f966
[root@b3806743f966 /]# exit     #使用attach进入容器,然后在使用exit命令退出时,容器会停止
exit
[root@zxone ~]# docker ps
CONTAINER ID    IMAGE   COMMAND     CREATED   STATUS     PORTS        NAMES
[root@zxone ~]# docker start b3806743f966
b3806743f966
[root@zxone ~]# docker ps
CONTAINER ID  IMAGE    COMMAND      CREATED    STATUS     PORTS        NAMES
b3806743f966  centos   "/bin/bash"  2 minutes ago       Up 1 second   centos01
[root@zxone ~]# docker exec -it b3806743f966 /bin/bash
[root@b3806743f966 /]# exit 	#使用exec进入容器,然后在使用exit命令退出时,不会导致容器的停止
exit
[root@zxone ~]# docker ps
CONTAINER ID  IMAGE    COMMAND      CREATED      STATUS     PORTS        NAMES
b3806743f966  centos   "/bin/bash"  3 minutes ago   Up    51 second   centos01

3.3.3、导出和导入容器

导出容器

如果要导出本地某个容器,可以使用 docker export 命令。

docker export 1e560fca3906 > ./home/docker/app.tar    #导出到本地的地址和名称  

导入容器

可以使用 docker import 从容器快照文件中再导入为镜像,以下实例将快照文件 ubuntu.tar 导入到镜像 test/ubuntu:v1:

cat docker/app.tar | docker import - test/app:v1

也可以通过指定 URL 或者某个目录来导入

docker import http://example.com/exampleimage.tgz example/imagerepo

3.3.4、删除容器

删除容器使用 docker rm 命令:

docker rm -f  <容器id>
docker rm -f  $(docker ps -aq)  #删除docker ps -a 查询出来的所有容器
docker container prune  #清理掉所有处于终止状态的容器

3.4、常用其他命令

image-20201009153141339

3.5、实例

在docker安装redis

[root@zxone ~]#docker pull redis:6.0    #拉取镜像
[root@zxone ~]#docker run -itd --name myredis -p 6379:6379 redis:6.0  #运行redis容器
[root@zxone ~]# docker exec -it myredis /bin/bash   #进入容器
root@4316428b7944:/data# redis-cli
127.0.0.1:6379> set a 1
OK
127.0.0.1:6379> get a
"1"

四、容器数据卷

4.1、什么是容器数据卷

4.2、使用容器数据卷

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

#docker运行centos,-v 主机目录:docker容器目录 
docker run -it -v /home/ceshi:/home centos /bin/bash
#通过inspect 容器id 查看运行的容器
docker inspect 1efc76b9d29f
#在容器信息中会出现Mounts这一项挂载内容
"Mounts": [
            {
                "Type": "bind",
                "Source": "/home/ceshi",       #主机内地址
                "Destination": "/home",		   #docker容器内地址
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

这样就将 主机目录:docker容器内目录 双向同步绑定。

4.3、实例

#1、拉取mysql镜像
docker pull mysql:5.7
#2、运行mysql镜像
#官方:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
#-d 后台运行
#-p 端口映射  主机端口:容器端口
#-v 数据卷挂载 可以多个
#-e 环境配置,MYSQL_ROOT_PASSWORD为mysql密码
#--name 容器名字
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


4.4、匿名和具名挂载

4.4.1、匿名挂载

docker run -P -v juming-nginx:/etc/nginx --name nginx01 nginx

4.4.1、具名挂载

docker run -P -v juming-nginx:/etc/nginx --name nginx02 nginx

docker volume ls
DRIVER   VOLUME NAME
local    ce89be7f4e2d5a4685b2da2c93bf4189d64ccfd44c07e2e3a708a46eebd775bb #匿名
local    juming-nginx #具名
#查看具名挂载的信息
[root@zxone ~]# docker volume inspect juming-nginx
[
    {
        "CreatedAt": "2020-10-09T17:04:38+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",  #具体的挂载地址
        "Name": "juming-nginx",
        "Options": null,
        "Scope": "local"
    }
]

三种挂载:

-v 卷名:容器内目录       #具名径挂载(一般使用具名挂载)
-v 主机目录:容器内目录     #指定路径挂载
-v 容器内目录    	    #匿名挂载

4.5、DockerFile

方式二:使用DockerFile挂载数据卷

#dockerfile文件内容
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "-----------end------"
CMD /bin/bash

执行dockerfile

# -f dockerfile的路径
# -t 生成的镜像名称
docker build -f /home/docker-file-test/dockerfile1 -t zxone/centos:1.0 .  #最后的. 不能少

Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos
 ---> 0d120b6ccaa8
Step 2/4 : VOLUME ["volume01","volume02"]
 ---> Running in 7484e5b21f8c
Removing intermediate container 7484e5b21f8c
 ---> 87a782ccfde9
Step 3/4 : CMD echo "-----------end------"
 ---> Running in 8fda12bf10a0
Removing intermediate container 8fda12bf10a0
 ---> b205c8aab45b
Step 4/4 : CMD /bin/bash
 ---> Running in ad9e2cf16a61
Removing intermediate container ad9e2cf16a61
 ---> aac11c067c6f
Successfully built aac11c067c6f
Successfully tagged zxone/centos:1.0

#查看镜像 存在根据dockerfile创建的zxone/centos 镜像
docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
zxone/centos        1.0                 aac11c067c6f        About a minute ago   215MB

#运行zxone/centos镜像 ,可以看到volume01 和 volume02 目录,这是挂载的数据卷(属于匿名挂载)
[root@zxone docker-file-test]# docker run -it aac11c067c6f
[root@7cf487bddb8d /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var	   volume02
dev  home  lib64  media       opt  root  sbin  sys  usr  volume01

#在宿主机上查看数据卷
docker inspect 7cf487bddb8d #容器ID

"Mounts": [
            {
                "Type": "volume",
                "Name": "a164f072e68f6fdb171d786fd9cda23c4f95fe939e81135acf001551c17ba107",
                "Source": "/var/lib/docker/volumes/a164f072e68f6fdb171d786fd9cda23c4f95fe939e81135acf001551c17ba107/_data",
                "Destination": "volume01",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "3a8567cab2dcaad853319fb870847a0301fc774b3a19606785d08b91bce1d11b",
                "Source": "/var/lib/docker/volumes/3a8567cab2dcaad853319fb870847a0301fc774b3a19606785d08b91bce1d11b/_data",
                "Destination": "volume02",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

#查看容器内和宿主机数据卷的同步,通过dockerfile实现卷挂载         
cd /var/lib/docker/volumes/XXXX/_data

4.6、数据卷容器

#通过 --volumes-from 命令多个容器实现挂载同步数据
#比如:
#1、启动mysql01
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

#2、启动mysql02
docker run -d -p 3311:3306 -v /home/mysql/conf:/etc/mysql/conf.d 
-v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 
--volumes-from mysql01 mysql:5.7

#3、启动mysql03
docker run -d -p 3312:3306 -v /home/mysql/conf:/etc/mysql/conf.d 
-v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql03 
--volumes-from mysql01 mysql:5.7
#这样使得mysql01、mysql02、mysql03共享了同一个数据卷的数据/home/mysql/data中的数据
#如果mysql01容器删除,mysql02、mysql03中的数据不会存在变化,因为/home/mysql/data中的数据没有变化
#相当于备份拷贝机制




五、DockerFile

5.1、DockerFile介绍

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

构建步骤:

  • 1).编写一个dockerfile文件
  • 2).docker build 构建一个镜像
  • 3).docker run 运行一个镜像
  • 4).docker push 发布镜像(Dockerhub和阿里云镜像仓库)

5.2、DockerFile构建过程

基础知识:

1、每个保留关键字(指令)都必须是大写字母

2、从上到下按照顺序执行

3、#表示注释

4、每一个指令都会创建一个新的镜像层,并提交。

img

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

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

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

5.3、DockerFile指令

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

img

创建自己的centos镜像,首先创建一个DockerFile文件

#DockerFile文件 内容
FROM centos
MAINTAINER zxone     

ENV MYPATH /usr/local     #配置环境变量
WORKDIR $MYPATH		#进入容器之后直接就到了工作目录

RUN yum -y install vim			#给基础镜像添加vim插件
RUN yum -y install net-tools	#给基础镜像 ifconfig命令等	

EXPOSE 80			#暴露端口

CMD echo $MYPATH
CMD echo "------------end------------"
CMD /bin/bash

通过DockerFile文件mydockerfile-centos构建镜像mycentos

docker build -f mydockerfile-centos -t mycentos:1.0 .
docker images  #查看镜像
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
mycentos            1.0                 39a4c2226cd0        About a minute ago   295MB
docker run -it 39a4c2226cd0 #启动容器,验证
docker history 39a4c2226cd0 #查看镜像的历史

image-20201009234543517

5.4、实战创建一个Tomcat镜像

5.4.1、新建Dockerfile

FROM centos             #基础镜像
MAINTAINER zxone		#作者信息
#拷贝readme.txt说明
COPY readme.txt /usr/local/readme.txt
#加入jdk和tomcat,到了/usr/local/ 目录会自动解压
ADD jdk-8u261-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.37.tar.gz /usr/local/
#加入vim插件
RUN yum -y install vim
#设置工作目录
ENV MYPATH /usr/local
WORKDIR $MYPATH
#配置环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_261
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.37
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.37
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#暴露端口
EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.37/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.37/logs/catalina.out

5.4.2、利用Dockerfile构建镜像

#如果文件名称是:Dockerfile 则不需要-f指定DockerFile文件, 默认找Dockerfile文件
docke build -t mytomcat:1.0 .
#查询构建成功的镜像
docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mytomcat            1.0                 c82080e5255f        31 minutes ago      640MB

5.4.3、运行镜像

#可以使用-v命令设置数据卷,
docker run -d --name diytomcat -p 8090:8080 mytomcat:1.0

#浏览器输入宿主IP:8090验证tomcat是否成功启动

image-20201010150246909

5.4.4、发布镜像

可以将自己新建的镜像发布到dockerHub或者阿里云镜像库。

需要先登录dockerHub或者阿里云镜像库,然后docker push 镜像:tag

六、Docker网络

6.1、docker0网络

阿里云linux服务器存在三个网络

#lo :本地回环地址
#eth0 :阿里云内网地址
#docker0 :docker0地址
[root@zxone home]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:16:3e:06:82:4d brd ff:ff:ff:ff:ff:ff
    inet 172.18.40.159/20 brd 172.18.47.255 scope global dynamic eth0
       valid_lft 312045955sec preferred_lft 312045955sec
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:3c:8a:b1:15 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

6.2、veth pair

veth pair充当一个桥梁,连接各种虚拟设备。

安装运行tomcat容器

docker run -d -P --name tomcat01 tomcat  #后台运行tomcat
docker exec -it tomcat01 ip addr      # ip addr查询容器内的地址

#lo:docker0地址 127.0.0.1
#eth0@if81:tomcat01容器地址 172.17.0.2
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
80: eth0@if81: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

#本地linux ping容器地址,可以ping通
ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.061 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.041 ms

#在运行一个tomcat02
docker run -d -P --name tomcat02 tomcat
#tomcat02 ping 172.17.0.2 tomcat01  可以ping 通。结论:两个容器之间是可以通信的
#tomcat01,tomcat02 公用一个路由docker0
docker exec -it tomcat02 ping 172.17.0.2 
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.043 ms

#但是直接tomcat02 ping tomcat01是ping不通的
docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known

#再次查看主机ip addr
#两个tomcat 容器就会新增两对网络81: vethe11d492@if80 和 83: vethdba7f4d@if82 
#docker就是这样使用veth pair设备连接宿主机网络与容器网络。
ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:16:3e:06:82:4d brd ff:ff:ff:ff:ff:ff
    inet 172.18.40.159/20 brd 172.18.47.255 scope global dynamic eth0
       valid_lft 312044434sec preferred_lft 312044434sec
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:3c:8a:b1:15 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
81: vethe11d492@if80: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 96:f8:b3:1e:b4:9a brd ff:ff:ff:ff:ff:ff link-netnsid 0
83: vethdba7f4d@if82: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether d2:e6:d6:66:dc:03 brd ff:ff:ff:ff:ff:ff link-netnsid 1


#需要解决tomcat02 ping tomcat01是ping不通的
docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known
#再启动一个tomcat03时使用--link tomcat02,然后tomcat03 ping tomcat02 可以ping通
docker run -d -P --name tomcat03 --link tomcat02 tomcat
docker exec -it tomcat03 ping tomcat02 #tomcat03 ping tomcat02 可以ping通
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.077 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.046 ms
#但是反过来tomcat02 ping tomcat03 是不可以ping通的
docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known

#tomcat03 ping tomcat02 的原理是因为在tomcat03容器的/etc/hosts文件中存在tomcat02的地址映射
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.17.0.3	tomcat02 34542a3c3516
172.17.0.4	695a4eeff44d

6.4、自定义网络

image-20201014225640095

6.4.1、网络模式

  • bridge:桥接docker(默认)
  • none:不配置网络
  • host:和宿主机共享网络
  • container:容器网络连通
#创建一个网络
#--driver bridge  网络模式
#--subnet 192.168.0.0/16  子网掩码
#--gateway 192.168.0.1  路由,网关
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
33c734a366fcffe91b9cb62bc26ff61e8b24c204841ed8cc9ccdc659f944508e
#查看网络,创建的mynet网络存在
docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
7b68f4376a1d        bridge              bridge              local
08e934c7d648        host                host                local
33c734a366fc        mynet               bridge              local
8ff0b0130dfe        none                null                local

image-20201014232821525

测试

通过使用自定义的网络mynet 启动两个容器tomcat01 tomcat02,然后tomcat01 tomcat02相互通过容器名是可以ping同的。

[root@zxone home]# docker run -d -P --name tomcat01 --net mynet tomcat
295f47531e32611ed9c4c1e099f3d086b6e4050c98de2fda2d389f4820acbe08
[root@zxone home]# docker run -d -P --name tomcat02 --net mynet tomcat
701f8c0031b30be96b84eba9911f93771ec8d3a9840987d848ecbf8f0aee3853

[root@zxone home]# docker exec -it tomcat02  ping tomcat01 
PING tomcat01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.046 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.045 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.044 ms

[root@zxone home]# docker exec -it tomcat01  ping tomcat02
PING tomcat02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.029 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.047 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.047 ms


6.5、网络联通

容器分别连接找各自网络(比如自定义多个网络),现在容器之间需要跨网络连接。使用命令:docker network connect [OPTIONS] NETWORK CONTAINER

#tomcat03是另外一个自定义网络下的容器,现在将tomcat03 加入到mynet网络下,这样tomcat03 就连接mynet网络下容器了
docker network connect  mynet tomcat03             

七、部署Redis集群

7.1、新建一个redis的网络

[root@zxone home]#  docker network create redis --subnet 172.38.0.0/16
3fc4705601a15e4fb166fd1ba7008d0a8bbaff49c452ec68d393043796f8d897
[root@zxone home]#  docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
7b68f4376a1d        bridge              bridge              local
08e934c7d648        host                host                local
33c734a366fc        mynet               bridge              local
8ff0b0130dfe        none                null                local
3fc4705601a1        redis               bridge              local

[root@zxone home]# docker network inspect redis          #查询redis网络信息
[
    {
        "Name": "redis",
        "Id": "3fc4705601a15e4fb166fd1ba7008d0a8bbaff49c452ec68d393043796f8d897",
        "Created": "2020-10-19T22:26:02.261189338+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": {}
    }
]

7.2、新建redis的配置文件

#创建shell脚本创建redis集群配置文件,redis.sh 内容如下:
[root@zxone dockerredis]# cat redis.sh 
#!/bin/bash
for port in $(seq 1 6);
do 
mkdir -p /home/dockerredis/node-${port}/conf
touch /home/dockerredis/node-${port}/conf/redis.conf
cat << EOF >/home/dockerredis/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}       #172.38.0.1${port}  是因为docker创建的网络redis在这个网段内
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done 

#给redis.sh 脚本授权
[root@zxone dockerredis]# chmod +x ./redis.sh 
#执行redis.sh 脚本,创建了node-1到node-6 6个文件和redis配置文件
[root@zxone dockerredis]# ./redis.sh 
[root@zxone dockerredis]# ll
total 28
drwxr-xr-x 3 root root 4096 Oct 19 22:48 node-1
drwxr-xr-x 3 root root 4096 Oct 19 22:48 node-2
drwxr-xr-x 3 root root 4096 Oct 19 22:48 node-3
drwxr-xr-x 3 root root 4096 Oct 19 22:48 node-4
drwxr-xr-x 3 root root 4096 Oct 19 22:48 node-5
drwxr-xr-x 3 root root 4096 Oct 19 22:48 node-6
-rwxr-xr-x 1 root root  420 Oct 19 22:47 redis.sh

#执行脚本之后得到6个集群redis.conf 配置文件内容
[root@zxone conf]# cat 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.11
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes

7.3、启动redis集群

#1、拉取redis镜像
[root@zxone dockerredis]# docker pull redis
Using default tag: latest
latest: Pulling from library/redis
bb79b6b2107f: Pull complete 
1ed3521a5dcb: Pull complete 
5999b99cee8f: Pull complete 
f99a38f44786: Pull complete 
d6fc863042e2: Pull complete 
9bd1af4eae13: Pull complete 
Digest: sha256:33ca074e6019b451235735772a9c3e7216f014aae8eb0580d7e94834fe23efb3
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest
[root@zxone dockerredis]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat              latest              891fcd9c5b3a        5 days ago          647MB
redis               latest              bd571e6529f3        5 days ago          104MB

#2、新建一个redis集群启动脚本 runredis.sh 
[root@zxone dockerredis]# cat runredis.sh 
#!/bin/bash
for port in $(seq 1 6)
do
 docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /home/dockerredis/node-${port}/data:/data \
-v /home/dockerredis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis redis-server /etc/redis/redis.conf; \
done

#3、给runredis.sh 授权,执行脚本
[root@zxone dockerredis]# chmod +x ./runredis.sh 
[root@zxone dockerredis]# ./runredis.sh 
c9969729f17fbc25009dffe8b617663ba7f32cfa29f2f8687d2854593595ec15
7b7dce0911831e503ffef22fd2eb0fb218aa5326072da9b40242c9e709dd9937
16e04f2915ad649f7990ac612fd75eef121cd47a2093cfc9d35204bbe462ca96
2248f90bcec0e5b4c4bfff300cdd70f348991edbb62fe13d155526a961210797
6fa98d2bb53619e2f6efdd42a7a6f4c76da2d3d0ab01bff7341750de6060e0fb
2931cbfad6c70eb8c8c969e53cfac22491c6e35836453163b9cabd4f1bc6c059

#4、	查看容器,6个redis容器已经全部启动
[root@zxone dockerredis]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                              NAMES
2931cbfad6c7        redis               "docker-entrypoint.s…"   27 seconds ago      Up 26 seconds       0.0.0.0:6376->6379/tcp, 0.0.0.0:16376->16379/tcp   redis-6
6fa98d2bb536        redis               "docker-entrypoint.s…"   27 seconds ago      Up 27 seconds       0.0.0.0:6375->6379/tcp, 0.0.0.0:16375->16379/tcp   redis-5
2248f90bcec0        redis               "docker-entrypoint.s…"   28 seconds ago      Up 27 seconds       0.0.0.0:6374->6379/tcp, 0.0.0.0:16374->16379/tcp   redis-4
16e04f2915ad        redis               "docker-entrypoint.s…"   28 seconds ago      Up 27 seconds       0.0.0.0:6373->6379/tcp, 0.0.0.0:16373->16379/tcp   redis-3
7b7dce091183        redis               "docker-entrypoint.s…"   28 seconds ago      Up 28 seconds       0.0.0.0:6372->6379/tcp, 0.0.0.0:16372->16379/tcp   redis-2
c9969729f17f        redis               "docker-entrypoint.s…"   29 seconds ago      Up 28 seconds       0.0.0.0:6371->6379/tcp, 0.0.0.0:16371->16379/tcp   redis-1


#5、进入其中一个redis容器内
[root@zxone dockerredis]# docker exec -it redis-1 /bin/sh
# pwd
/data
# ls
appendonly.aof	nodes.conf
#执行创建集群的命令,创建一个副本。就会成功创建一个redis集群,3主3从。
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: 1b110449b00aebc36a1c891569dc6899e0214d15 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
M: 55a531cfc5433c17b84e54427b1c90720f3cf1e3 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: 80f7f00d7597f52f5d4d602f362badcbc371f8c4 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: 44392d1fec245d0d37b447daeb4ec869c7c051e7 172.38.0.14:6379
   replicates 80f7f00d7597f52f5d4d602f362badcbc371f8c4
S: c314511de10a93a68a75eb68edc860a57492d3d6 172.38.0.15:6379
   replicates 1b110449b00aebc36a1c891569dc6899e0214d15
S: 1f6e6e0356181d270f305d13c3901a54a938d7bd 172.38.0.16:6379
   replicates 55a531cfc5433c17b84e54427b1c90720f3cf1e3
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: 1b110449b00aebc36a1c891569dc6899e0214d15 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: c314511de10a93a68a75eb68edc860a57492d3d6 172.38.0.15:6379
   slots: (0 slots) slave
   replicates 1b110449b00aebc36a1c891569dc6899e0214d15
M: 80f7f00d7597f52f5d4d602f362badcbc371f8c4 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 44392d1fec245d0d37b447daeb4ec869c7c051e7 172.38.0.14:6379
   slots: (0 slots) slave
   replicates 80f7f00d7597f52f5d4d602f362badcbc371f8c4
S: 1f6e6e0356181d270f305d13c3901a54a938d7bd 172.38.0.16:6379
   slots: (0 slots) slave
   replicates 55a531cfc5433c17b84e54427b1c90720f3cf1e3
M: 55a531cfc5433c17b84e54427b1c90720f3cf1e3 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
# redis-cli -c   #进入redis集群
127.0.0.1:6379> cluster info   #查看redis集群信息
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:317
cluster_stats_messages_pong_sent:323
cluster_stats_messages_sent:640
cluster_stats_messages_ping_received:318
cluster_stats_messages_pong_received:317
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:640

127.0.0.1:6379> cluster nodes #查看集群nodes信息 3主3从
c314511de10a93a68a75eb68edc860a57492d3d6 172.38.0.15:6379@16379 slave 1b110449b00aebc36a1c891569dc6899e0214d15 0 1603121747539 1 connected
80f7f00d7597f52f5d4d602f362badcbc371f8c4 172.38.0.13:6379@16379 master - 0 1603121747539 3 connected 10923-16383
44392d1fec245d0d37b447daeb4ec869c7c051e7 172.38.0.14:6379@16379 slave 80f7f00d7597f52f5d4d602f362badcbc371f8c4 0 1603121747000 3 connected
1b110449b00aebc36a1c891569dc6899e0214d15 172.38.0.11:6379@16379 myself,master - 0 1603121747000 1 connected 0-5460
1f6e6e0356181d270f305d13c3901a54a938d7bd 172.38.0.16:6379@16379 slave 55a531cfc5433c17b84e54427b1c90720f3cf1e3 0 1603121746539 2 connected
55a531cfc5433c17b84e54427b1c90720f3cf1e3 172.38.0.12:6379@16379 master - 0 1603121746539 2 connected 5461-10922

7.4、操作redis集群

#1、操作redis。先设置一个a的健值。
127.0.0.1:6379> set a 1
-> Redirected to slot [15495] located at 172.38.0.13:6379
OK
172.38.0.13:6379> get a
"1"
172.38.0.13:6379> 
#2、停止172.38.0.13 这个redis
#可以查到172.38.0.13这个网段是redis-3这个容器在使用
[root@zxone data]# docker inspect redis-3
"Networks": {
                "redis": {
                    "IPAMConfig": {
                        "IPv4Address": "172.38.0.13"
                    },
                    "Links": null,
                    "Aliases": [
                        "16e04f2915ad"
                    ],
                    "NetworkID": "3fc4705601a15e4fb166fd1ba7008d0a8bbaff49c452ec68d393043796f8d897",
                    "EndpointID": "dfa7f3693540ce6f04efcc6a5bc05765b5fe78ca5865f75cbe54adced6bb9fc2",
                    "Gateway": "172.38.0.1",
                    "IPAddress": "172.38.0.13",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:26:00:0d",
                    "DriverOpts": null
                }
            }

#停止redis-3这个容器
docker stop redis-3

停止redis-3容器之后,推出redis-3,再进去redis集群,执行get a命令,可以从得到172.38.0.14:6379这个redis上获取到值。

查看nodes信息,172.38.0.13已经停止,现在172.38.0.14是master

image-20201019234634359

八、SpringBoot微服务打包docker镜像部署

8.1、构建SpringBoot项目

​ 构建一个最简单的springboot项目,本地运行

8.2、打包应用

执行package命令,打成jar,然后java -jar 运行jar包

8.3、编写Dockerfile

FROM java:8

COPY *.jar /app.jar

CMD ["--server.port=8080"]

EXPOSE 8080

ENTRYPOINT ["java","-jar","/app.jar"]

8.4、构建镜像

上传jar和Dockerfile到linux中

[root@zxone springboot]# ll
total 17184
-rw-r--r-- 1 root root      122 Oct 20 00:44 Dockerfile
-rw-r--r-- 1 root root 17591766 Oct 20 00:44 dockertest-1.0-SNAPSHOT.jar
#利用Dockerfile构建镜像springweb
[root@zxone springboot]# docker build -t springweb:1.0 .

#构建镜像完成之后,得到springweb镜像
[root@zxone springboot]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
springweb           1.0                 fc8ab2fb6f8d        6 seconds ago       661MB
tomcat              latest              891fcd9c5b3a        5 days ago          647MB
redis               latest              bd571e6529f3        5 days ago          104MB
java                8                   d23bdf5b1b1b        3 years ago         643MB

8.5、发布运行

#运行容器
[root@zxone springboot]# docker run -d -P --name springweb-1 springweb:1.0 
2bcca6ca2e0862f328873659cedd4d3b5d1ef89c30816591087bdb91d173eb88
#查看端口
[root@zxone springboot]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                              NAMES
2bcca6ca2e08        springweb:1.0       "java -jar /app.jar …"   9 seconds ago       Up 8 seconds        0.0.0.0:32776->8080/tcp                            springweb-1
#请求
[root@zxone springboot]# curl localhost:32776
{"timestamp":"2020-10-19T16:49:17.982+0000","status":404,"error":"Not Found","message":"No message available","path":"/"}

[root@zxone springboot]# curl localhost:32776/hello/docker
hello world docker[root@zxone springboot]# 

#能够正常返回请求,说明正常运行,达到目标

posted @ 2020-10-20 00:53  zxone公子  阅读(307)  评论(0编辑  收藏  举报