Docker诞生背景

一款产品从开发到上线,从操作系统,到运行环境,再到应用配置。作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不得不面对的问题,特别是各种版本的迭代之后,不同版本环境的兼容,对运维人员都是考验 !
环境配置如此麻烦,换一台机器,就要重来一次,费力费时。很多人想到,能不能从根本上解决问题,软件可以带环境安装?也就是说,安装的时候,把原始环境一模一样地复制过来。
Docker镜像的设计,使得Docker得以打破过去”程序即应用” 的观念。透过镜像(images)将作业系统核心除外,运作应用程式所需要的系统环境,由下而上打包,达到应用程式跨平台间的无缝接轨运作。
Docker之所以发展如此迅速,也是因为它对此给出了一个标准化的解决方案!

Docker 介绍

Docker的主要目标是“Build,Ship and Run Any App, Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理, 使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到“一次封装,到处运行”。
总结:Docker是解决运行环境和配置问题的软件容器 , 方便做持续集中并有助于整体发布的容器虚拟化技术
image.png

虚拟机技术与容器虚拟化技术

虚拟机技术
虚拟机(virtual machine)就是带环境安装的一种解决方案。 它可以在一种操作系统里面运行另一种操作系统,比如在Windows 系统里面运行Linux 系统。 应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样**缺点**:1 资源占用多 2 冗余步骤多 3 启动慢
容器虚拟化技术
Linux 容器(Linux Containers,缩写为 LXC)。 Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。 有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。 容器与虚拟机不同,不需要捆绑一整套操作系统,**只需要软件工作所需的核心库资源和设置。 系统因此而变得高效轻量**并保证部署在任何环境中的软件都能始终如一地运行。
二者区别
1.传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程。
2.而容器内的应用进程直接运行于宿主机( 即:所在主机,下面统称宿主机 ) 的内核和硬件,容器内没有自己的内核, 也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
3.每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。
Docker官网地址 : https://www.docker.com
Docker社区官方: https://hub.docker.com/

Docker安装与启动

前提条件:
Docker支持以下CentOS版本:CentOS 7 (64-bit)系统内核版本为 3.10 以上,CentOS 6.5 (64-bit) 系统内核版本为 2.6.32-431 或者更高版本
uname -r # 查看内核版本 (查到我的内核版本是 3.10.0-1160.el7.x86_64)
cat /etc/redhat-release #查看虚拟机系统版本 (我的虚拟机版本CentOS Linux release 7.9.2009 (Core))

  1. 安装依赖GCC(需要确保 虚拟机可以上外网 )

yum -y install gcc
yum -y install gcc-c++

  1. 卸载旧版本

yum -y remove docker docker-common docker-selinux docker-engine
官网版本
docker-client
docker-client-latest
docker-common
docker-latest
docker-latest-logrotate
docker-logrotate
docker-engine

  1. 安装需要的软件包

yum install -y yum-utils device-mapper-persistent-data lvm2

  1. 设置stable镜像仓库(正确推荐使用国内的阿里云镜像 )

yum-config-manager --add-repo [http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo](http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo)

  1. 更新yum软件包索引

yum makecache fast

  1. 安装Docker CE

yum -y install docker-ce docker-ce-cli containerd.io

  1. Docker启动管理命令

systemctl start docker 启动docker
systemctl daemon-reload 重新载入后台启动进程
service docker status 查看Docker容器状态

  1. 测试

docker version #查看版本
docker run hello-world #通过运行 hello-world 映像来验证是否正确安装了
docker images #查看docker容器已下载的镜像
image.png
到这里Docker就成功安装了!

Docker底层原理

Docker结构图

image.png

工作原理

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

Docker为什么比VM虚拟机快

(1) docker有着比虚拟机更少的抽象层
由于docker不需要Hypervisor实现硬件资源虚拟化, 运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。
(2) docker利用的是宿主机的内核,而不需要Guest OS
因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。因而避免引寻、加载操作系统内核返个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,返个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返个过程,因此新建一个docker容器只需要几秒钟。
image.png

Docker常用命令

帮助命令

  1. docker version # 查看docker版本信息
  2. docker info # 查看docker所有安装信息
  3. docker --help # 查看docker帮助 ( 最为重要,学会利用帮助文档来学习 ,这是成为高手的必经之路!!! )

启动命令

  1. systemctl start docker 启动docker
  2. systemctl daemon-reload 重新载入后台启动进程
  3. service docker status 查看Docker容器状态

镜像命令

  1. # 1.列出本地镜像(图1)
  2. docker images
  3. # option说明
  4. -a :列出所有镜像
  5. -q:只列出镜像id
  6. -digests :显示镜像的摘要信息
  7. --no-trunc :显示相信信息
  8. # 2.搜索某个镜像名字 (会在docker社区搜索相关的镜像, 而我们配置的阿里源只是帮我们同步了docker社区的镜像,图2)
  9. docker search
  10. # option说明
  11. - s显示收藏数不小于指定值的镜像
  12. --no-trunc :显示相信信息
  13. - automated :只列出automated类型的镜像
  14. # 3. 下载镜像(图3)
  15. docker pull 镜像的名字:[TAG](不写默认为 lasted)
  16. # 4. 删除镜像
  17. docker rmi -f 镜像名/镜像id
  18. docker rmi -f $(docker images -qa ) 递归删除所有镜像(通过id)

Docker详解 - 图6
图1
各个选项说明

  • REPOSITORY:表示镜像的仓库源
  • TAG:镜像的标签
  • IMAGE ID:镜像ID
  • CREATED:镜像创建时间
  • SIZE:镜像大小
  • 同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。
  • 如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像

Docker详解 - 图7
图2
Docker详解 - 图8
图3

容器命令

基础命令

  1. 我们要有镜像才可以创建容器,先下载一个centos镜像 (docke pull centos)
  2. # 1. 新建并启动容器
  3. docker run [OPTIONS] IMAGE [COMMOND] [ARGS...]
  4. # OPTIONS 说明
  5. --name="容器新名字": 为容器指定一个名称;
  6. -d: 后台运行容器,并返回容器ID,也即启动守护式容器;
  7. -i:以交互模式运行容器,通常与 -t 同时使用;
  8. -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;
  9. -P: 随机端口映射;
  10. -p: 指定端口映射,有以下四种格式
  11. ip:hostPort:containerPort
  12. ip::containerPort
  13. hostPort:containerPort #最常用,如 -p 80808080
  14. containerPort
  15. # eg: 使用镜像centos:latest以交互模式启动并进入一个容器,在容器内执行/bin/bash命令。
  16. docker run -it centos /bin/bash docker run -it 镜像id
  17. # 2. 查询当前正在运行的容器(类比虚拟中的查看进程)
  18. docker ps [OPTIONS]
  19. # OPTIONS说明(常用):
  20. -a :列出当前所有正在运行的容器+历史上运行过的
  21. -l :显示最近创建的容器。
  22. -n:显示最近n个创建的容器。
  23. -q :静默模式,只显示容器编号。
  24. --no-trunc :不截断输出。
  25. # 3. 退出容器
  26. exit 容器停止后退出
  27. ctrl+p+q 容器不停止退出
  28. # 4 .启动容器
  29. docker start 容器ID/容器名
  30. # 5. 重启容器
  31. docker restart 容器ID/容器名
  32. # 6. 停止容器
  33. docker stop 容器ID/容器名
  34. # 7. 强制停止容器
  35. docker kill 容器ID/容器名
  36. # 8. 删除指定的容器(如果没有停止, 删除后会停止)
  37. docker rm 容器ID
  38. # 9. 删除多个容器(特别是第二种 ,先查询所有运行的进程, 然后通过管道传到后面的删除操作中)
  39. docker rm -f $(docker ps -a -q) docker rm -f $(docker ps -aq)
  40. docker ps -a -q | xargs docker rm

其他重要命令

  1. # 1. 启动守护式容器(后台运行)
  2. docker run -d 容器名
  3. # 使用镜像centos:latest以后台模式启动一个容器
  4. docker run -d centos

问``题``:通过``**docker ps -a**`` 进行查看, 会发现容器退出了???

  • 因为 Docker容器后台运行, 就必须有一个前台进程,容器发现自己没有提供服务,就会自动停止。
  • 容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。这个是docker的机制问题。最佳的解决方案是,将你要运行的程序以前台进程的形式运行。 ```java

    2. 查看容器日志

    docker logs -f -t —tail 容器ID

eg :(图1) docker run -d centos /bin/sh -c “while true;do echo hello testLogs;sleep 2;done” docker logs -tf —tail 10 02c81778b0e0

-t 是加入时间戳 -f 跟随最新的日志打印 —tail 数字 显示最后多少条

3. 查看容器内运行的进程(图2)

docker top 容器ID

4. 查看容器内部细节(图3)

docker inspect 容器ID

5.进入正在运行的容器并进行交互(图4)

docker exec -it 容器ID /bin/bash

6. 重新进入容器(图5)

docker attach 容器ID bashShell(不写的话默认 /bin/bash下)

比较5与6的区别

attach 直接进入容器启动命令终端, 不会启动新的线程 exec 是在容器中打开新的终端, 并且可以启动新的线程

7. 从容器内拷贝文件到宿主机(图6)

docker cp 容器ID:/容器内文件路径 /宿主机目的路径

  1. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626161660742-5ff38a68-1a6e-4755-9870-f6f4caf1ce59.png#align=left&display=inline&height=164&margin=%5Bobject%20Object%5D&originHeight=219&originWidth=912&size=0&status=done&style=none&width=684)<br />图1<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626161690367-40077f9d-09eb-4093-a428-b87785dd24d3.png#align=left&display=inline&height=127&margin=%5Bobject%20Object%5D&originHeight=195&originWidth=1045&size=0&status=done&style=none&width=682)<br />图2<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626161728589-3c661c3a-f46e-40ab-bbc8-554838731438.png#align=left&display=inline&height=365&margin=%5Bobject%20Object%5D&originHeight=533&originWidth=1002&size=0&status=done&style=none&width=686)<br />图3<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626161744190-74e27474-edda-4a54-9675-156eef43d782.png#align=left&display=inline&height=153&margin=%5Bobject%20Object%5D&originHeight=194&originWidth=867&size=0&status=done&style=none&width=683)<br />图4![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626161781374-0f60de2c-6d63-4375-9b84-563ef0ead76b.png#align=left&display=inline&height=230&margin=%5Bobject%20Object%5D&originHeight=300&originWidth=887&size=0&status=done&style=none&width=679)<br />图5<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626161905921-7810109d-c758-4d37-9142-f4505f5782aa.png#align=left&display=inline&height=102&margin=%5Bobject%20Object%5D&name=image.png&originHeight=130&originWidth=865&size=100245&status=done&style=none&width=680)<br />图6
  2. <a name="YFXH4"></a>
  3. ## Docker常用命令图解
  4. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626162012629-436a076a-b448-40f4-9b76-52c03f4be4a9.png#align=left&display=inline&height=475&margin=%5Bobject%20Object%5D&originHeight=633&originWidth=897&size=0&status=done&style=none&width=673)
  5. <a name="D4L9f"></a>
  6. # Docker镜像
  7. <a name="vSvBo"></a>
  8. ## 镜像 / UnionFS(联合文件系统)
  9. Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承. 基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。<br />**特性**<br />一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
  10. - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626162442059-a08ef95c-767f-428e-9d2e-18e0de081565.png#align=left&display=inline&height=254&margin=%5Bobject%20Object%5D&name=image.png&originHeight=508&originWidth=1011&size=224906&status=done&style=none&width=506)
  11. **Dcoker镜像都是****只读****的 , 当启动容器时, 一个新的可写层被加载到镜像的顶部这一层被称为"容器层", "容器层"执行的都称为"镜像层"。**
  12. <a name="5xXZq"></a>
  13. ## Docker镜像加载原理
  14. docker的镜像实际上由一层一层的文件系统组成,这种层级的文件构成文件系统UnionFS。<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626162533574-7fc423cb-25d5-4c9b-af0e-c8917ff9a63d.png#align=left&display=inline&height=304&margin=%5Bobject%20Object%5D&originHeight=304&originWidth=442&size=0&status=done&style=none&width=442)<br />**bootfs(boot file system) 主要包含****bootloader****和****kernel**<br />bootloader主要作用是引导加载kernel, Linux刚启动时会加载bootfs文件系统,Docker镜像的最底层是bootfs。<br />这一层与典型的Linux/Unix系统是一样的,包含boot加载器和内核**kernel**。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
  15. 对于一个精简的OSrootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Hostkernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs
  16. <a name="OAcZd"></a>
  17. ## Docker镜像Commit操作
  18. ```java
  19. # 提交容器副本实质成为一个新的镜像
  20. docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]
  21. eg: 同时docker运行tomcat案例
  22. # 1. 创建交互式界面 ( 相当于前台启动)
  23. docker run -it -p 8888:8080 tomcat # 端口映射将8888作为docker的入口,映射到tomcat镜像的8080(图1,图2)
  24. docker run -it -P tomcat #自动端口映射(通过 docker ps查看端口, 图3)
  25. #后台启动(不会占用当前页面)
  26. docker run -d -p 8888:8080 tomcat
  27. # 2. 进入tomcat (如果前置启动,另开一个窗口 ,后置启动则直接进入)
  28. # 查看运行容器ID
  29. docker ps
  30. # 进入根目录
  31. docker exec -it 容器ID /bin/bash
  32. /usr/local/tomcat# rm -rf webapps/docs/
  33. # 删除后访问tomcat ,可以看到访问主页下的文档出现404(图4)
  34. # 3. 提交容器副本实使之为一个新的镜像
  35. # 查看运行容器ID
  36. docker ps
  37. # 提交容器
  38. docker commit -a="fred" -m="del tomcat docs" 容器ID tomcat:v1.2
  39. .. -a 为作者
  40. .. -m 描述
  41. .. tomcat:v1.2 发布版本名称
  42. # 查看镜像(图5)
  43. docker images
  44. # 4.同时启动新镜像并和原来的对比
  45. 可以看到我们自己提交的新镜像也没有文档()
  46. 但是我们重新下载的tomcat是有的

Docker详解 - 图9
图1
Docker详解 - 图10
图2
Docker详解 - 图11
图3
Docker详解 - 图12
图4
Docker详解 - 图13
图5

Docker容器数据卷

用于容器的持久化和容器间的继承与共享数据

容器—宿主机数据卷

1.直接命令添加

通过-v命令直接添加 (需要在根目录下创建 containerData ),创建后修改容器内containerData 会同步到hostData ,反之亦是如此
docker run -it -v /hostData:/containerData 镜像名/ID

创建只读权限的文件 , 容器内只能读取这个文件, 但是不能修改. ro: readonly (ro:只读,rw:可读可写)
docker run -it -v /宿主机绝路路径目录:/容器内目录:ro 镜像名

2.通过DockerFile添加

Dockerfile是用来构建Docker镜像文件 ,是有一系列命令和参数构成的脚本。类比理解:
Docker详解 - 图14

  1. # 1. 宿主机根目录下创建mydocker文件夹并进入
  2. # 2. mydocker文件想创建DockerFile文件并编辑,内容如下(图1)
  3. # volume test
  4. FROM centos
  5. VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
  6. CMD echo "finished,--------success1"
  7. CMD /bin/bash
  8. 说明:
  9. 出于可移植和分享的考虑,用-v 主机目录:容器目录这种方法不能够直接在Dockerfile中实现。
  10. 由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录。
  11. 3. 使用docker build命令创建一个镜像, 并挂载指定宿主机指定文件(Dockerfile一般位于构建上下文的根目录下,也可以通过-f指定到该文件的位置)
  12. docker build -f /mydocker/DockerFile -t 自定义新镜像名称 .
  13. 4. 查看镜像
  14. docker images
  15. 5.运行新镜像
  16. docker run -it 定义的新镜像ID /bin/bash
  17. 6.通过镜像运行后生成的容器ID查看 (图2), 对应的主机映射的数据卷地址
  18. docker ps
  19. docker inspect 容器ID
  20. 7.测试添加卷和主机是否互通有无
  21. 在容器中创建文件, 看看主机中是否创建对应的文件
  22. #在dataVolumeContainer1创建一个文件,再去宿主机上dataVolumeContainer1对应的文件路径查看是否存在(图3
  23. 注意:
  24. Docker挂载主机目录(第3步)Docker访问出现cannot open directory .: Permission denied
  25. 解决办法:在挂载目录后多加一个--privileged=true参数即可

Docker详解 - 图15
图1

Docker详解 - 图16

图2:查看运行的容器id相关信息 docker inspect 容器ID
image.png
image.png
图3 (测试添加卷和主机是否互通有无)

对比与总结
Docker详解 - 图19

匿名挂载

(1)启动容器
docker run -d -P --name nginx01 -v /etc/nginx nginx ``
-v 容器内路径
Docker详解 - 图20
(2)查看所有卷的情况
docker volume ls
Docker详解 - 图21
【注】由上图可以看到,VOLUME NAME 有的是随机生成的字符串,对于这种就是匿名挂载,因为-v的时候只写了容器内的路径看,而没有写容器外的路径

具名挂载

(1) 启动容器
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
核心语法:docker run -d -P --name `` -v 卷名:容器内路径 镜像ID 或 镜像名 /bin/bash

Docker详解 - 图22
(2)查看一下这个卷
docker volumn inspect juming-nginx 或 docker volumn inspect 容器ID
【注意】所有docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxx

容器间数据卷

命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享;
挂载数据卷的容器,称之为数据卷容器。
实现步骤

  1. # 1. 以上一步所建镜像为模板 ,首先启动一个父容器dc01 ,在创建容器的数据卷文夹中创建一个文件(图1)
  2. docker run -it --name dc01 zzyy/centos
  3. touch dc01_add.txt
  4. # 2. 创建子容器dc02,dc03继承自dc01 , 在创建容器的数据卷文夹中创建一个文件(图2)
  5. docker run -it --name dc02 --volumes-from dc01 zzyy/centos
  6. touch dc02_add.txt
  7. docker run -it --name dc03 --volumes-from dc01 zzyy/centos
  8. touch dc01=3_add.txt
  9. # 3. 回到dc01可以看到所有数据都被共享了(图3)
  10. # 4. 删除dc01, dc02修改后dc03是否可访问,可以 (图4)
  11. # 5. 删除dc02dc03是否可以访问, 可以(图5)
  12. # 6. 新建dc04继承dc03是否可以访问, 可以(图6)
  13. 结论
  14. 容器之间配置信息的传递, 数据卷的生命周期一直持续到没有容器使用它为止

Docker详解 - 图23
图1
Docker详解 - 图24
图2
Docker详解 - 图25
图3
Docker详解 - 图26
图4
Docker详解 - 图27
图5
Docker详解 - 图28
图6

DockerFile解析

构建步骤

1.编写Dockerfile文件
2.docker build
3.docker run

Dockerfile格式

  1. FROM scratch
  2. ADD centos-8-container.tar.xz /
  3. LABEL org.label-schema.schema-version="1.0" \
  4. org.label-schema.name="CentOS Base Image" \
  5. org.label-schema.vendor="CentOS" \
  6. org.label-schema.license="GPLv2" \
  7. org.label-schema.build-date="20190927"
  8. CMD ["/bin/bash"]

Dockerfile语法

  • 每条保留字指令都必须为大写字母且后面至少跟一个参数
  • 指令从上到下, 顺序执行
  • 表示注释

  • 每条指令都会创建一个新的镜像层, 并提交

    Docker执行DockerFile的大致流程

  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器做出修改
  3. 执行类似docker commit 的操作提交一个新的镜像层
  4. docker 再基于刚提交的镜像运行一个新容器
  5. 执行dockerfile 中的下一条执行, 直至所有指令都完成

从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段

  • Dockerfile是软件的原材料
  • Docker镜像是软件的交付品
  • Docker容器则可以认为是软件的运行态

Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
Docker详解 - 图29

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

DockerFile保留字指令

Docker详解 - 图30
CMD与ENTRYPOINT命令类似``,但也有些区别

  • 执行docker run如果带有其他命令参数,将会覆盖CMD指令。执行docker run如果带有其他命令参数,不会覆盖ENTRYPOINT指令,而是相当于在后面直接加命令。
  • ENTRYPOINT指令,往往用于设置容器启动后的第一个命令,这对一个容器来说往往是固定的。
  • CMD指令,往往用于设置容器启动的第一个命令的默认参数,这对一个容器来说可以是变化的。
  • docker run 往往用于给出替换CMD的临时参数

    DockerFile构建镜像文件(案例1)

    我们安装的centos精简版是没有vim和ifconfig等命令的支持的,这里我们通过编写Dockerfile令其支持这些功能。
  1. 搜索centos镜像并下载

docker search centos
docker pull centos

  1. 编写创建一个文件( /mydoker/dockerfile_centos ), 编写Dockerfile ,内容如下 ``` FROM centos MAINTAINER timepauseqq_43371556@csdn.net

ENV MYPATH /usr/local WORKDIR $MYPATH

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

EXPOSE 80

CMD echo $MYPATH CMD echo “install vim and ifconfig commond plug-in components success” CMD /bin/bash

  1. 3. **编译运行centos( 注意最后的空格和点号)**
  2. `docker build -f /mydoker/dockerfile_centos -t mycentos:1.3 .`
  3. 4. 测试:
  4. #查看镜像是否新增<br />`docker images`<br />#解决镜像名<none><none>问题<br />`docker tag 镜像ID name:tag 如:docker tag f8ebaa92d089 mycentos:v1.1`<br />#运行制作的新镜像<br />`docker run -it mycentos:1.3`
  5. #在容器中使用vim 和 ifconfig指令
  6. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626168370356-2d4d3065-b3c0-48fc-a401-ecde75aaf6ea.png#align=left&display=inline&height=234&margin=%5Bobject%20Object%5D&originHeight=312&originWidth=948&size=0&status=done&style=none&width=711)<br />图1<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626168398541-76e0d274-58e2-47d3-89ad-cbc1314032c8.png#align=left&display=inline&height=300&margin=%5Bobject%20Object%5D&originHeight=326&originWidth=772&size=0&status=done&style=none&width=711)<br />图2
  7. <a name="WTXhF"></a>
  8. ## DockerFile构建镜像文件(案例2)
  9. <a name="mHinN"></a>
  10. ### 自定义tomcat9
  11. 1. 创建存放生成镜像文件的目录
  12. `mkdir -p /myuse/mydocker/tomcat9`
  13. 2. 创建相关文件(c.txt用于测试)
  14. `touch c.txt`
  15. 3. 上传tomcatjdk(一定要注意版本, 根据版本修改Dockerfile文件, 1)
  16. 3. 创建并编辑Dockerfile(需要提前下载centos)
  17. `vim Dockerfile`<br />Dockerfile

FROM centos MAINTAINER chychy@qq.com

把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下

COPY c.txt /usr/local/cincontainer.txt

把java与tomcat添加到容器中

ADD jdk-8u11-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.27.tar.gz /usr/local/

安装vim编辑器

RUN yum -y install vim

设置工作访问时候的WORKDIR路径,登录落脚点

ENV MYPATH /usr/local WORKDIR $MYPATH

配置java与tomcat环境变量

ENV JAVA_HOME /usr/local/jdk1.8.0_11 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.27 ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.27 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

容器运行时监听的端口

EXPOSE 8080

启动时运行tomcat

ENTRYPOINT [“/usr/local/apache-tomcat-9.0.8/bin/startup.sh” ]

CMD [“/usr/local/apache-tomcat-9.0.8/bin/catalina.sh”,”run”]

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

  1. 5. 构建镜像(在存放这些文件的目录下,图2)
  2. # 如果Dockerfile文件名称就是Dockerfile,可以省略参数 -f /Dockerfile所在位置的书写<br />`docker build -t mytomcat9 .`
  3. 6. 查看镜像并运行镜像( 3,图4)
  4. `docker images #查看镜像`<br />`docker run -d -p 8080:8080 --name myt9 -v /myuse/mydocker/tomcat9/test:/usr/local/apache-tomcat-9.0.27/webapps/test -v /myuse/mydocker/tomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.27/logs --privileged=true mytomcat9 #运行镜像`<br /> 【注意】这里配置了容器卷的映射,宿主机的test文件夹映射到tomcatwebapps目录下的test文件,且二者可以互通有无。 <br />`docker exec -it 容器ID /bin/bash` #进入容器根目录 ,可以访问相关页面
  5. 7. 访问成功后, 添加jsp文件与web.xml文件( a.jsp用于访问测试 ,web.xml用于令jsp页面可以编译)
  6. `vim a.jsp`<br />`mkidr WEB-INF`<br />`vim /WEB-INF/web.xml`<br />**a.jsp**

<%@ page language=”java” contentType=”text/html; charset=UTF-8” pageEncoding=”UTF-8”%> <!DOCTYPE html PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “http://www.w3.org/TR/html4/loose.dtd">

—————-welcome—————— <=”i am in docker tomcat self “%>

<% System.out.println(“=============docker tomcat self”);%>
  1. **web.xml**

<?xml version=”1.0” encoding=”UTF-8”?>

  1. 8. 重启服务, 访问a.jsp(图5)
  2. # 查看当前容器id`docker ps (查看当前容器ID) docker ps -a (查看所有运行过的容器ID)`# 重启服务`docker restart 容器ID`# 访问a.jsp页面
  3. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626231000622-51c98e03-4b69-4bab-b268-58e05dba93f9.png#align=left&display=inline&height=104&margin=%5Bobject%20Object%5D&originHeight=104&originWidth=921&size=0&status=done&style=none&width=921)图1<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626231255560-0dadec88-ed0a-40c9-bc3a-77199f2c5ee0.png#align=left&display=inline&height=386&margin=%5Bobject%20Object%5D&name=image.png&originHeight=515&originWidth=1062&size=194928&status=done&style=none&width=797)<br />图2<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626231311387-dda26648-8bbe-4029-8c64-9e1d73645cd8.png#align=left&display=inline&height=193&margin=%5Bobject%20Object%5D&name=image.png&originHeight=258&originWidth=1063&size=111648&status=done&style=none&width=797)<br />图3<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626231351572-7f5b7ea5-1a71-412d-b9db-c8ac4c05360f.png#align=left&display=inline&height=274&margin=%5Bobject%20Object%5D&name=image.png&originHeight=365&originWidth=1071&size=229616&status=done&style=none&width=803)<br />图4<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626231403628-d50f2857-3201-48fb-aa62-2fc0a094c6f8.png#align=left&display=inline&height=147&margin=%5Bobject%20Object%5D&name=image.png&originHeight=168&originWidth=880&size=46443&status=done&style=none&width=772)<br />图5
  4. <a name="YrFAd"></a>
  5. # 发布镜像到阿里云
  6. 1.登陆阿里云, 进入容器镜像服务(可以通过下方地址注册登录跳转到容器镜像服务)<br />[https://cr.console.aliyun.com/cn-hangzhou/instances/repositories](https://cr.console.aliyun.com/cn-hangzhou/instances/repositories)<br />2. 创建镜像仓库(图1)<br />3. 在docker中登陆 ,根据图2, 图3中的操作指南进行操作<br />4. 将正在运行的容器创建成一个镜像(图4) <br />`docker commit [OPTIONS]`<br />说明:<br />-a :提交的镜像作者;<br />-m :提交时的说明文字;<br />5.将镜像推送到阿里云的镜像仓库(最好是根据阿里云上的操作指南)<br />`docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/timepause/mydocker:[镜像版本号]`<br />`sudo docker push registry.cn-hangzhou.aliyuncs.com/timepause/mydocker:[镜像版本号]`<br />6. 搜索镜像 ,下载镜像(图5, 图6)<br />`docker pull (复制的)镜像地址`<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626267964589-75d379da-0b74-48a0-8493-9196b5aa62ed.png#align=left&display=inline&height=379&margin=%5Bobject%20Object%5D&originHeight=803&originWidth=1627&size=0&status=done&style=none&width=767)<br />图1
  7. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626268040531-ab462e3b-5379-4203-b580-904ddecd3aab.png#align=left&display=inline&height=62&margin=%5Bobject%20Object%5D&originHeight=121&originWidth=1492&size=0&status=done&style=none&width=761)
  8. 2
  9. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626267991538-73ab4915-b8a0-4dfb-a57d-6589b96e6733.png#align=left&display=inline&height=477&margin=%5Bobject%20Object%5D&originHeight=738&originWidth=1176&size=0&status=done&style=none&width=760)
  10. 3
  11. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626268066845-5c7d487a-3af4-484f-999c-140f609c0829.png#align=left&display=inline&height=220&margin=%5Bobject%20Object%5D&originHeight=220&originWidth=718&size=0&status=done&style=none&width=718)
  12. 4
  13. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626268082225-cc765cfc-bde5-45cd-8a8d-c0e05640ae7f.png#align=left&display=inline&height=320&margin=%5Bobject%20Object%5D&originHeight=710&originWidth=1704&size=0&status=done&style=none&width=768)
  14. 5
  15. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626268107441-99d46496-5cfa-40bc-be22-97fe88bd8402.png#align=left&display=inline&height=255&margin=%5Bobject%20Object%5D&originHeight=557&originWidth=1681&size=0&status=done&style=none&width=771)<br />图6
  16. <a name="RG7qn"></a>
  17. # 通过Docker安装软件
  18. <a name="ppDj3"></a>
  19. ## MySQL

1. 以安装mysql5.6为例(不知道什么原因5.7下不来)

docker pull mysql:5.6

2. 运行镜像,启动容器(端口3306,root用户密码:root,运行镜像:mysql5.6)

docker run -p 3306:3306 —name mysql -v /datebase/mysql/conf:/etc/mysql/conf.d -v /datebase/mysql/logs:/logs -v /datebase/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.6

3. 进入msql内部测试登录

docker ps

进入mysql的当前目录下

docker exec -it MySQL运行成功后的容器ID/name /bin/bash

输入账号密码

mysql -u 账号 -p(然后根据提示输入密码)

4.连接数据库的图形化界面

Mysql 解决连接客户端时出现1251 client does not support …问题

ALTER USER ‘root’@’%’ IDENTIFIED WITH mysql_native_password BY ‘mysql密码’; ALTER USER ‘root’@’localhost’ IDENTIFIED WITH mysql_native_password BY ‘mysql密码’;

5. 备份数据库数据,之后我们可以通过直接读取这个sql文件恢复数据

docker exec myql服务容器ID sh -c ‘ exec mysqldump —all-databases -uroot -p”root” ‘ > /datebase/all-databases.sql

  1. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626268400322-ebe497e9-e97c-4713-88f1-48e0ce152d70.png#align=left&display=inline&height=290&margin=%5Bobject%20Object%5D&originHeight=387&originWidth=944&size=0&status=done&style=none&width=708)
  2. <a name="pJFR1"></a>
  3. ## Redis

1.下载最新版redis镜像

docker pull redis

2.运行镜像(redis端口2333, -d后的redis不加参数默认为redis:latest)

注意本地数据卷与容器内数据卷目录的对应

docker run -p 2333:6379 -v /myuse/myredis/data:/data -v /myuse/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf -d redis redis-server /usr/local/etc/redis/redis.conf —appendonly yes

3.上传redis.conf到本地数据卷所在目录

本地数据卷坐在目录 : /myuse/myredis/conf 文件地址(太大了 ,这里放不下) : https://download.csdn.net/download/qq_43371556/11889084

4. 运行redis的cil——shell命令行

docker exec -it 运行着Rediis服务的容器ID redis-cli

远程连接 docker redis

docker exec -it redis_s redis-cli -h 192.168.1.100 -p 6379 -a your_password //如果有密码 使用 -a参数

  1. <a name="4oHls"></a>
  2. ## RabbitMQ

1.下载镜像

docker pull rabbitmq:3.7.7-management

2.运行镜像

docker run -d —name rabbitmq3.7.7 -p 5672:5672 -p 15672:15672 -v pwd/data:/var/lib/rabbitmq —hostname myRabbit -e RABBITMQ_DEFAULT_VHOST=/ -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin df80af9ca0c9

-d 后台运行容器; —name 指定容器名; -p 指定服务运行的端口(5672:应用访问端口;15672:控制台Web端口号); -v 映射目录或文件; —hostname 主机名(RabbitMQ的一个重要注意事项是它根据所谓的 “节点名称” 存储数据,默认为主机名); -e 指定环境变量;(RABBITMQ_DEFAULT_VHOST:默认虚拟机名;RABBITMQ_DEFAULT_USER:默认的用户名;RABBITMQ_DEFAULT_PASS:默认用户名的密码)

3.访问 (如下图)

http://ip:15672 账号 :admin 密码: admin

  1. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626268622878-9209724b-018a-407a-9985-6292670e00e7.png#align=left&display=inline&height=356&margin=%5Bobject%20Object%5D&originHeight=709&originWidth=1297&size=0&status=done&style=none&width=652)
  2. <a name="b741af20"></a>
  3. # Docker网络原理
  4. <a name="y4Mfe"></a>
  5. ## 理解Docker0
  6. 学习之前清空下前面的docker 镜像、容器`$ docker rm -f $(docker ps -aq) # 删除全部容器 $ docker rmi -f $(docker images -aq) # 删除全部镜像`
  7. 测试通过`ip addr`访问ip地址<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626270009301-5f9e67c5-cccd-4395-b0a2-d839e9eb64f9.png#align=left&display=inline&height=217&margin=%5Bobject%20Object%5D&originHeight=217&originWidth=856&size=0&status=done&style=none&width=856)
  8. **Docker 是如果处理容器网络访问的?**

测试 运行一个tomcat

$ docker run -d -P —name tomcat01 tomcat

查看容器内部网络地址

$ docker exec -it 容器id ip addr

发现容器启动的时候会得到一个 eth0@if91 ip地址,docker分配!

$ ip addr 1: lo: 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 261: eth0@if91: 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通容器内部! 可以 容器内部可以ping通外界吗? 可以!

$ 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 64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.074 ms

  1. **原理**<br />1、我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要按照了docker,就会有一个docker0桥接模式,使用的技术是veth-pair技术!(veth-pair参考:[https://www.cnblogs.com/bakari/p/10613710.html](https://www.cnblogs.com/bakari/p/10613710.html))<br />再次测试 ip addr<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626270310041-d58ee26d-fc38-41a7-b6cc-a7efbcf2e704.png#align=left&display=inline&height=392&margin=%5Bobject%20Object%5D&originHeight=492&originWidth=1063&size=0&status=done&style=none&width=846)
  2. 再启动一个容器测试,发现又多了一对网络<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626270399653-b0b63968-8bff-4bcb-9ce1-0ac51a6c9220.png#align=left&display=inline&height=298&margin=%5Bobject%20Object%5D&originHeight=378&originWidth=1072&size=0&status=done&style=none&width=844)
  3. `# 我们发现这个容器带来网卡,都是一对对的# veth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连# 正因为有这个特性 veth-pair 充当一个桥梁,连接各种虚拟网络设备的# OpenStac,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术`<br />我们来测试下tomcat01tomcat02是否可以ping

获取tomcat01的ip 172.17.0.2

$ docker-tomcat docker exec -it tomcat01 ip addr
550: eth0@if551: 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

让tomcat02 ping tomcat01

$ docker-tomcat 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.098 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.071 ms

结论:容器和容器之间是可以互相ping通

  1. **网络模型图**<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626270531094-c3cd1841-f5d7-412d-a147-a8dba4904ce4.png#align=left&display=inline&height=504&margin=%5Bobject%20Object%5D&originHeight=640&originWidth=1001&size=0&status=done&style=none&width=789)<br />Docker中所有网络接口都是虚拟的,虚拟的转发效率高(内网传递文件)只要容器删除,对应的网桥一对就没了!
  2. <a name="9l1Ef"></a>
  3. ## 自定义网络【推荐】
  4. **思考一个场景**:我们编写了一个微服务,database url=ip: 项目不重启,数据ip换了,我们希望可以处理这个问题,可以通过名字来进行访问容器?
  5. - **–link **可以实现容器名连接,但其本质是在hosts配置中添加映射,现在使用Docker已经不建议使用–link了! 不适用docker0docker0特点:默认,域名不能访问。 --link可以打通连接,但是很麻烦!docker0问题:不支持容器名连接访问!)

-link示例:

$ docker exec -it tomcat02 ping tomca01 # ping不通 ping: tomca01: Name or service not known

运行一个tomcat03 —link tomcat02

$ docker run -d -P —name tomcat03 —link tomcat02 tomcat 5f9331566980a9e92bc54681caaac14e9fc993f14ad13d98534026c08c0a9aef

3连接2

用tomcat03 ping tomcat02 可以ping通

$ docker exec -it tomcat03 ping tomcat02 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.115 ms 64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.080 ms

2连接3

用tomcat02 ping tomcat03 ping不通

  1. - **自定义网络【推荐】**

docker network语法

docker network connect — Connect a container to a network create — Creates a new network with a name specified by the disconnect — Disconnects a container from a network inspect — Displays detailed information on a network ls — Lists all the networks created by the user prune — Remove all unused networks rm — Deletes one or more network

  1. **网络模式**
  2. - bridge :桥接 docker(默认,自己创建也是用bridge模式)<br />
  3. - none :不配置网络,一般不用<br />
  4. - host :和所主机共享网络<br />
  5. - container :容器网络连通(用得少!局限很大)<br />
  6. 自定义网络--测试

我们直接启动的命令 —net bridge, 而这个就是我们得docker0

bridge就是docker0

$ docker run -d -P —name tomcat01 tomcat 等价于 => docker run -d -P —name tomcat01 —net bridge tomcat

docker0,特点:默认,域名不能访问。 —link可以打通连接,但是很麻烦!

我们可以 自定义一个网络

—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

  1. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626327167605-df2d99ba-f702-411c-8ed2-9988e8b5a38f.png#align=left&display=inline&height=197&margin=%5Bobject%20Object%5D&originHeight=197&originWidth=1244&size=0&status=done&style=none&width=1244)

$ docker network inspect mynet;

  1. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626327193857-5358fa8b-eb88-4834-8639-9268d565b5f0.png#align=left&display=inline&height=682&margin=%5Bobject%20Object%5D&originHeight=682&originWidth=848&size=0&status=done&style=none&width=848)
  2. 启动两个tomcat,再次查看网络情况

[root@izuf6hlvm1mj8gdbdctw0rz ~]# docker run -d -P —name tomcat-net-01 —net mynet tomcat d84b618132cb597df982508f14992b5c752dfebb12fcabb1f9ffe39ead356d6d

[root@izuf6hlvm1mj8gdbdctw0rz ~]# docker run -d -P —name tomcat-net-02 —net mynet tomcat 146ee8b0ad2d89d8e77870b9a93f5f1da742c2e9e696a9a3f798b8146607d5cf

  1. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626327308208-47cdb866-a264-48fe-a2e2-323b19947e48.png#align=left&display=inline&height=737&margin=%5Bobject%20Object%5D&originHeight=893&originWidth=1011&size=0&status=done&style=none&width=834)
  2. 在自定义的网络下,容器之间可以相互ping通!**既可以ping ip地址,也可以直接ping容器名称。**<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626327392980-1e20b94e-cc73-4d53-bc23-73873b78a563.png#align=left&display=inline&height=376&margin=%5Bobject%20Object%5D&originHeight=386&originWidth=854&size=0&status=done&style=none&width=832)<br />我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络!**<br />**好处:**
  3. - redis -不同的集群使用不同的网络,保证集群是安全和健康的<br />
  4. - mysql-不同的集群使用不同的网络,保证集群是安全和健康的<br />
  5. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626327557049-2def9b29-97e8-43a3-b72c-193239141472.png#align=left&display=inline&height=228&margin=%5Bobject%20Object%5D&originHeight=344&originWidth=876&size=0&status=done&style=none&width=581)
  6. <a name="Mfegi"></a>
  7. ## 网络连通
  8. 思考下图中的tomcat01tomcat-net-01可以连通吗?<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626327700647-03a20af1-a6c3-4b8a-a478-41da55bb5b16.png#align=left&display=inline&height=395&margin=%5Bobject%20Object%5D&originHeight=395&originWidth=706&size=0&status=done&style=none&width=706)
  9. 答案是不能!如下图所示<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626327747795-1e2ac30d-62f7-415e-b0eb-aad33c7b2f2f.png#align=left&display=inline&height=132&margin=%5Bobject%20Object%5D&originHeight=203&originWidth=1200&size=0&status=done&style=none&width=781)
  10. 因为它们根本不在一个网段。那么怎么样才能让他们连通呢?<br />**答案**:假设要跨网络操作别人,就需要使用`docker network connect` 连通!<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626327883223-23f0d1f6-4a80-4568-8669-3746da172517.png#align=left&display=inline&height=396&margin=%5Bobject%20Object%5D&originHeight=370&originWidth=736&size=0&status=done&style=none&width=787)<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626327901261-a6e965cd-2bc0-427b-8ccc-8f9e47ac3afe.png#align=left&display=inline&height=289&margin=%5Bobject%20Object%5D&originHeight=301&originWidth=819&size=0&status=done&style=none&width=786)<br />需要将容器和网络打通<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626328086886-4ad9c397-9187-4f83-a01e-d3791a71112c.png#align=left&display=inline&height=245&margin=%5Bobject%20Object%5D&name=image.png&originHeight=490&originWidth=1134&size=99147&status=done&style=none&width=567)<br />**`docker network connect mynet tomcat-01 #执行命令,将网络mynet和tomcat01打通`**
  11. 此时查看一下mynet的信息`docker inspect mynet ` 发现tomcat01直接被写进了mynet的配置,分配了指定的ip<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626328282922-ad155222-21fc-4215-a086-f1ea8cd75911.png#align=left&display=inline&height=614&margin=%5Bobject%20Object%5D&originHeight=811&originWidth=981&size=0&status=done&style=none&width=743)
  12. 这次我们再去ping一下`docker exec -it tomcat-01 ping tomcat-net-01`,现在tomcat01已经可以pingtomcat-net-01<br />![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626328538694-2b0c1d3e-e441-4b08-8d52-f6e91c444921.png#align=left&display=inline&height=205&margin=%5Bobject%20Object%5D&originHeight=230&originWidth=830&size=0&status=done&style=none&width=739)
  13. 而未打通网络的tomcat-02依旧连不通`docker exec -it tomcat-02 ping tomcat-net-01`
  14. <a name="NLVmU"></a>
  15. ## ![image.png](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626328720942-b1a8929d-c27d-4153-8ed2-181de2081b17.png#align=left&display=inline&height=60&margin=%5Bobject%20Object%5D&name=image.png&originHeight=86&originWidth=1064&size=13286&status=done&style=none&width=740)
  16. <a name="lJScI"></a>
  17. ## 补充: 计算机IP地址划分
  18. - 以常见的BIP地址为例:BIP地址范围128.1.0.1-191.254.255.254(二进制表示为:10000000 00000001 00000000 00000001 - 10111111 11111110 11111111 11111110
  19. - 如**192**.**168**.**0**.**1 **一共四段,转换成二进制每段就是**8**位。192.168.0.1/8(表示仅最后一段可用,范围为192.168.0.1 - 192.168.0.254,最多可连254台主机,同理,192.168.0.1/16 192.168.0.1/24(分别表示最后2 最后3段可用,可连最大物理主机数约为254*254254*254*254
  20. <a name="19cfC"></a>
  21. ## 实战:部署Redis集群
  22. ![](https://cdn.nlark.com/yuque/0/2021/png/22103819/1626328831476-97ab94f7-b367-41fc-a740-be0ed0876b87.png#align=left&display=inline&height=466&margin=%5Bobject%20Object%5D&originHeight=575&originWidth=945&size=0&status=done&style=none&width=766)

创建网卡

docker network create redis —subnet 172.38.0.0/16

通过脚本创建六个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

通过脚本运行六个redis

for port in $(seq 1 6);\ docker run -p 637${port}:6379 -p 1667${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 —ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf docker exec -it redis-1 /bin/sh #redis默认没有bash 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

  1. 我们使用docker之后,所有的技术都会慢慢变得简单起来!
  2. <a name="icGOc"></a>
  3. ## SpringBoot微服务打包Docker镜像
  4. 1. 构建SpringBoot项目
  5. 1. 打包运行 `mvn package`
  6. 1. 编写DockerFile

FROM java:8 COPY *.jar /app.jar CMD [“—server.port=8080”] EXPOSE 8080 ENTRYPOINT [“java”,”-jar”,”app.jar”]

  1. 4. 构建镜像

1.复制jar和DockerFIle 到服务器

2.构建镜像

$ docker build -t 镜像名:tag . ``` Docker详解 - 图31

  1. 发布运行(以后我们使用了Docker之后,给别人交付就是一个镜像即可!)

关于Docker更深入的技术(compose,swarm等)后面再学习补充!

本文参考

1.博客文章:https://blog.csdn.net/qq_43371556/article/details/102631158https://blog.csdn.net/danggang0317/article/details/113408905
2.b站狂神说教学视频【墙裂推荐】:https://www.bilibili.com/video/BV1og4y1q7M4?p=32&t=168