- Docker诞生背景
- Docker 介绍
- Docker安装与启动
- Docker底层原理
- Docker常用命令
- 2. 查看容器日志
- 3. 查看容器内运行的进程(图2)
- 4. 查看容器内部细节(图3)
- 5.进入正在运行的容器并进行交互(图4)
- 6. 重新进入容器(图5)
- 比较5与6的区别
- 7. 从容器内拷贝文件到宿主机(图6)
- Docker容器数据卷
- 通过-v命令直接添加 (需要在根目录下创建 containerData ),创建后修改容器内containerData 会同步到hostData ,反之亦是如此
docker run -it -v /hostData:/containerData 镜像名/ID
- 创建只读权限的文件 , 容器内只能读取这个文件, 但是不能修改. ro: readonly (ro:只读,rw:可读可写)
docker run -it -v /宿主机绝路路径目录:/容器内目录:ro 镜像名
- 容器间数据卷
- DockerFile解析
- 表示注释
- 把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下
- 把java与tomcat添加到容器中
- 安装vim编辑器
- 设置工作访问时候的WORKDIR路径,登录落脚点
- 配置java与tomcat环境变量
- 容器运行时监听的端口
- 启动时运行tomcat
- ENTRYPOINT [“/usr/local/apache-tomcat-9.0.8/bin/startup.sh” ]
- CMD [“/usr/local/apache-tomcat-9.0.8/bin/catalina.sh”,”run”]
- 1. 以安装mysql5.6为例(不知道什么原因5.7下不来)
- 2. 运行镜像,启动容器(端口3306,root用户密码:root,运行镜像:mysql5.6)
- 3. 进入msql内部测试登录
- 4.连接数据库的图形化界面
- 5. 备份数据库数据,之后我们可以通过直接读取这个sql文件恢复数据
- 1.下载最新版redis镜像
- 2.运行镜像(redis端口2333, -d后的redis不加参数默认为redis:latest)
- 注意本地数据卷与容器内数据卷目录的对应
- 3.上传redis.conf到本地数据卷所在目录
- 4. 运行redis的cil——shell命令行
- 远程连接 docker redis
- 1.下载镜像
- 2.运行镜像
- 3.访问 (如下图)
- 测试 运行一个tomcat
- 查看容器内部网络地址
- 发现容器启动的时候会得到一个 eth0@if91 ip地址,docker分配!
- 思考? linux能不能ping通容器内部! 可以 容器内部可以ping通外界吗? 可以!
- 获取tomcat01的ip 172.17.0.2
- 让tomcat02 ping tomcat01
- 结论:容器和容器之间是可以互相ping通
- -link示例:
- 运行一个tomcat03 —link tomcat02
- 3连接2
- 用tomcat03 ping tomcat02 可以ping通
- 2连接3
- 用tomcat02 ping tomcat03 ping不通
- docker network语法
- 我们直接启动的命令 —net bridge, 而这个就是我们得docker0
- bridge就是docker0
- docker0,特点:默认,域名不能访问。 —link可以打通连接,但是很麻烦!
- 我们可以 自定义一个网络
- —driver bridge
- —subnet 192.168.0.0/16 子网掩码
- —gateway 192.168.0.1 网关地址
- 创建网卡
- 通过脚本创建六个redis配置
- 通过脚本运行六个redis
- 1.复制jar和DockerFIle 到服务器
- 2.构建镜像
- 本文参考
Docker诞生背景
一款产品从开发到上线,从操作系统,到运行环境,再到应用配置。作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不得不面对的问题,特别是各种版本的迭代之后,不同版本环境的兼容,对运维人员都是考验 !
环境配置如此麻烦,换一台机器,就要重来一次,费力费时。很多人想到,能不能从根本上解决问题,软件可以带环境安装?也就是说,安装的时候,把原始环境一模一样地复制过来。
Docker镜像的设计,使得Docker得以打破过去”程序即应用” 的观念。透过镜像(images)将作业系统核心除外,运作应用程式所需要的系统环境,由下而上打包,达到应用程式跨平台间的无缝接轨运作。
Docker之所以发展如此迅速,也是因为它对此给出了一个标准化的解决方案!
Docker 介绍
Docker的主要目标是“Build,Ship and Run Any App, Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理, 使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到“一次封装,到处运行”。
总结:Docker是解决运行环境和配置问题的软件容器 , 方便做持续集中并有助于整体发布的容器虚拟化技术
虚拟机技术与容器虚拟化技术
虚拟机技术虚拟机(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))
- 安装依赖GCC(需要确保 虚拟机可以上外网 )
yum -y install gcc
yum -y install gcc-c++
- 卸载旧版本
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
- 安装需要的软件包
yum install -y yum-utils device-mapper-persistent-data lvm2
- 设置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)
- 更新yum软件包索引
yum makecache fast
- 安装Docker CE
yum -y install docker-ce docker-ce-cli containerd.io
- Docker启动管理命令
systemctl start docker 启动docker
systemctl daemon-reload 重新载入后台启动进程
service docker status 查看Docker容器状态
- 测试
docker version #查看版本
docker run hello-world #通过运行 hello-world 映像来验证是否正确安装了
docker images #查看docker容器已下载的镜像
到这里Docker就成功安装了!
Docker底层原理
Docker结构图
工作原理
Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上,然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。容器,是一个运行时环境,就是我们前面说到的集装箱。
Docker为什么比VM虚拟机快
(1) docker有着比虚拟机更少的抽象层
由于docker不需要Hypervisor实现硬件资源虚拟化, 运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。
(2) docker利用的是宿主机的内核,而不需要Guest OS
因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。因而避免引寻、加载操作系统内核返个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,返个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返个过程,因此新建一个docker容器只需要几秒钟。
Docker常用命令
帮助命令
docker version # 查看docker版本信息
docker info # 查看docker所有安装信息
docker --help # 查看docker帮助 ( 最为重要,学会利用帮助文档来学习 ,这是成为高手的必经之路!!! )
启动命令
systemctl start docker 启动docker
systemctl daemon-reload 重新载入后台启动进程
service docker status 查看Docker容器状态
镜像命令
# 1.列出本地镜像(图1)
docker images
# option说明
-a :列出所有镜像
-q:只列出镜像id
-digests :显示镜像的摘要信息
--no-trunc :显示相信信息
# 2.搜索某个镜像名字 (会在docker社区搜索相关的镜像, 而我们配置的阿里源只是帮我们同步了docker社区的镜像,图2)
docker search
# option说明
- s显示收藏数不小于指定值的镜像
--no-trunc :显示相信信息
- automated :只列出automated类型的镜像
# 3. 下载镜像(图3)
docker pull 镜像的名字:[TAG](不写默认为 lasted)
# 4. 删除镜像
docker rmi -f 镜像名/镜像id
docker rmi -f $(docker images -qa ) 递归删除所有镜像(通过id)
图1
各个选项说明
- REPOSITORY:表示镜像的仓库源
- TAG:镜像的标签
- IMAGE ID:镜像ID
- CREATED:镜像创建时间
- SIZE:镜像大小
- 同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。
- 如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像
容器命令
基础命令
我们要有镜像才可以创建容器,先下载一个centos镜像 (docke pull centos)
# 1. 新建并启动容器
docker run [OPTIONS] IMAGE [COMMOND] [ARGS...]
# OPTIONS 说明
--name="容器新名字": 为容器指定一个名称;
-d: 后台运行容器,并返回容器ID,也即启动守护式容器;
-i:以交互模式运行容器,通常与 -t 同时使用;
-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;
-P: 随机端口映射;
-p: 指定端口映射,有以下四种格式
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort #最常用,如 -p 8080:8080
containerPort
# eg: 使用镜像centos:latest以交互模式启动并进入一个容器,在容器内执行/bin/bash命令。
docker run -it centos /bin/bash 或 docker run -it 镜像id
# 2. 查询当前正在运行的容器(类比虚拟中的查看进程)
docker ps [OPTIONS]
# OPTIONS说明(常用):
-a :列出当前所有正在运行的容器+历史上运行过的
-l :显示最近创建的容器。
-n:显示最近n个创建的容器。
-q :静默模式,只显示容器编号。
--no-trunc :不截断输出。
# 3. 退出容器
exit 容器停止后退出
ctrl+p+q 容器不停止退出
# 4 .启动容器
docker start 容器ID/容器名
# 5. 重启容器
docker restart 容器ID/容器名
# 6. 停止容器
docker stop 容器ID/容器名
# 7. 强制停止容器
docker kill 容器ID/容器名
# 8. 删除指定的容器(如果没有停止, 删除后会停止)
docker rm 容器ID
# 9. 删除多个容器(特别是第二种 ,先查询所有运行的进程, 然后通过管道传到后面的删除操作中)
docker rm -f $(docker ps -a -q) 或 docker rm -f $(docker ps -aq)
docker ps -a -q | xargs docker rm
其他重要命令
# 1. 启动守护式容器(后台运行)
docker run -d 容器名
# 使用镜像centos:latest以后台模式启动一个容器
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:/容器内文件路径 /宿主机目的路径
![](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
<a name="YFXH4"></a>
## Docker常用命令图解
![](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)
<a name="D4L9f"></a>
# Docker镜像
<a name="vSvBo"></a>
## 镜像 / UnionFS(联合文件系统)
Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承. 基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。<br />**特性**<br />一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
- ![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)
**Dcoker镜像都是****只读****的 , 当启动容器时, 一个新的可写层被加载到镜像的顶部这一层被称为"容器层", "容器层"执行的都称为"镜像层"。**
<a name="5xXZq"></a>
## Docker镜像加载原理
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等等。
对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。
<a name="OAcZd"></a>
## Docker镜像Commit操作
```java
# 提交容器副本实质成为一个新的镜像
docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]
eg: 同时docker运行tomcat案例
# 1. 创建交互式界面 ( 相当于前台启动)
docker run -it -p 8888:8080 tomcat # 端口映射将8888作为docker的入口,映射到tomcat镜像的8080(图1,图2)
docker run -it -P tomcat #自动端口映射(通过 docker ps查看端口, 图3)
#后台启动(不会占用当前页面)
docker run -d -p 8888:8080 tomcat
# 2. 进入tomcat (如果前置启动,另开一个窗口 ,后置启动则直接进入)
# 查看运行容器ID
docker ps
# 进入根目录
docker exec -it 容器ID /bin/bash
/usr/local/tomcat# rm -rf webapps/docs/
# 删除后访问tomcat ,可以看到访问主页下的文档出现404(图4)
# 3. 提交容器副本实使之为一个新的镜像
# 查看运行容器ID
docker ps
# 提交容器
docker commit -a="fred" -m="del tomcat docs" 容器ID tomcat:v1.2
.. -a 为作者
.. -m 描述
.. tomcat:v1.2 发布版本名称
# 查看镜像(图5)
docker images
# 4.同时启动新镜像并和原来的对比
可以看到我们自己提交的新镜像也没有文档()
但是我们重新下载的tomcat是有的
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镜像文件 ,是有一系列命令和参数构成的脚本。类比理解:
# 1. 宿主机根目录下创建mydocker文件夹并进入
# 2. 在mydocker文件想创建DockerFile文件并编辑,内容如下(图1)
# volume test
FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "finished,--------success1"
CMD /bin/bash
说明:
出于可移植和分享的考虑,用-v 主机目录:容器目录这种方法不能够直接在Dockerfile中实现。
由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录。
3. 使用docker build命令创建一个镜像, 并挂载指定宿主机指定文件(Dockerfile一般位于构建上下文的根目录下,也可以通过-f指定到该文件的位置)
docker build -f /mydocker/DockerFile -t 自定义新镜像名称 .
4. 查看镜像
docker images
5.运行新镜像
docker run -it 定义的新镜像ID /bin/bash
6.通过镜像运行后生成的容器ID查看 (图2), 对应的主机映射的数据卷地址
docker ps
docker inspect 容器ID
7.测试添加卷和主机是否互通有无
在容器中创建文件, 看看主机中是否创建对应的文件
#在dataVolumeContainer1创建一个文件,再去宿主机上dataVolumeContainer1对应的文件路径查看是否存在(图3)
注意:
Docker挂载主机目录(第3步)Docker访问出现cannot open directory .: Permission denied
解决办法:在挂载目录后多加一个--privileged=true参数即可
图1
图2:查看运行的容器id相关信息 docker inspect 容器ID
图3 (测试添加卷和主机是否互通有无)
匿名挂载
(1)启动容器docker run -d -P --name nginx01 -v /etc/nginx nginx ``
-v 容器内路径
(2)查看所有卷的情况docker volume ls
【注】由上图可以看到,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
(2)查看一下这个卷docker volumn inspect juming-nginx 或 docker volumn inspect 容器ID
【注意】所有docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxx
容器间数据卷
命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享;
挂载数据卷的容器,称之为数据卷容器。
实现步骤
# 1. 以上一步所建镜像为模板 ,首先启动一个父容器dc01 ,在创建容器的数据卷文夹中创建一个文件(图1)
docker run -it --name dc01 zzyy/centos
touch dc01_add.txt
# 2. 创建子容器dc02,dc03继承自dc01 , 在创建容器的数据卷文夹中创建一个文件(图2)
docker run -it --name dc02 --volumes-from dc01 zzyy/centos
touch dc02_add.txt
docker run -it --name dc03 --volumes-from dc01 zzyy/centos
touch dc01=3_add.txt
# 3. 回到dc01可以看到所有数据都被共享了(图3)
# 4. 删除dc01, dc02修改后dc03是否可访问,可以 (图4)
# 5. 删除dc02dc03是否可以访问, 可以(图5)
# 6. 新建dc04继承dc03是否可以访问, 可以(图6)
结论
容器之间配置信息的传递, 数据卷的生命周期一直持续到没有容器使用它为止
DockerFile解析
构建步骤
1.编写Dockerfile文件
2.docker build
3.docker run
Dockerfile
格式
FROM scratch
ADD centos-8-container.tar.xz /
LABEL org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20190927"
CMD ["/bin/bash"]
Dockerfile
语法
- docker从基础镜像运行一个容器
- 执行一条指令并对容器做出修改
- 执行类似docker commit 的操作提交一个新的镜像层
- docker 再基于刚提交的镜像运行一个新容器
- 执行dockerfile 中的下一条执行, 直至所有指令都完成
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段
- Dockerfile是软件的原材料
- Docker镜像是软件的交付品
- Docker容器则可以认为是软件的运行态
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
1
Dockerfile:
需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
2
Docker镜像:
在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
3
Docker容器:
容器是直接提供服务的。
DockerFile保留字指令
CMD与ENTRYPOINT命令类似``,但也有些区别
:
- 执行docker run如果带有其他命令参数,将会覆盖CMD指令。执行docker run如果带有其他命令参数,不会覆盖ENTRYPOINT指令,而是相当于在后面直接加命令。
- ENTRYPOINT指令,往往用于设置容器启动后的第一个命令,这对一个容器来说往往是固定的。
- CMD指令,往往用于设置容器启动的第一个命令的默认参数,这对一个容器来说可以是变化的。
- docker run
往往用于给出替换CMD的临时参数 DockerFile构建镜像文件(案例1)
我们安装的centos精简版是没有vim和ifconfig等命令的支持的,这里我们通过编写Dockerfile令其支持这些功能。
- 搜索centos镜像并下载
docker search centos
docker pull centos
- 编写创建一个文件( /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
3. **编译运行centos( 注意最后的空格和点号)**
`docker build -f /mydoker/dockerfile_centos -t mycentos:1.3 .`
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`
#在容器中使用vim 和 ifconfig指令
![](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
<a name="WTXhF"></a>
## DockerFile构建镜像文件(案例2)
<a name="mHinN"></a>
### 自定义tomcat9
1. 创建存放生成镜像文件的目录
`mkdir -p /myuse/mydocker/tomcat9`
2. 创建相关文件(c.txt用于测试)
`touch c.txt`
3. 上传tomcat和jdk(一定要注意版本, 根据版本修改Dockerfile文件, 图1)
3. 创建并编辑Dockerfile(需要提前下载centos)
`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
5. 构建镜像(在存放这些文件的目录下,图2)
# 如果Dockerfile文件名称就是Dockerfile,可以省略参数 -f /Dockerfile所在位置的书写<br />`docker build -t mytomcat9 .`
6. 查看镜像并运行镜像( 图3,图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文件夹映射到tomcat的webapps目录下的test文件,且二者可以互通有无。 <br />`docker exec -it 容器ID /bin/bash` #进入容器根目录 ,可以访问相关页面
7. 访问成功后, 添加jsp文件与web.xml文件( a.jsp用于访问测试 ,web.xml用于令jsp页面可以编译)
`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”);%>
**web.xml**
<?xml version=”1.0” encoding=”UTF-8”?>
8. 重启服务, 访问a.jsp(图5)
# 查看当前容器id`docker ps (查看当前容器ID) docker ps -a (查看所有运行过的容器ID)`# 重启服务`docker restart 容器ID`# 访问a.jsp页面
![](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
<a name="YrFAd"></a>
# 发布镜像到阿里云
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
![](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)
图2
![](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)
图3
![](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)
图4
![](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)
图5
![](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
<a name="RG7qn"></a>
# 通过Docker安装软件
<a name="ppDj3"></a>
## 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
![](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)
<a name="pJFR1"></a>
## 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参数
<a name="4oHls"></a>
## 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
![](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)
<a name="b741af20"></a>
# Docker网络原理
<a name="y4Mfe"></a>
## 理解Docker0
学习之前清空下前面的docker 镜像、容器`$ docker rm -f $(docker ps -aq) # 删除全部容器 $ docker rmi -f $(docker images -aq) # 删除全部镜像`
测试通过`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)
**Docker 是如果处理容器网络访问的?**
测试 运行一个tomcat
$ docker run -d -P —name tomcat01 tomcat
查看容器内部网络地址
$ docker exec -it 容器id ip addr
发现容器启动的时候会得到一个 eth0@if91 ip地址,docker分配!
$ ip addr
1: lo:
思考? 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
**原理**<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)
再启动一个容器测试,发现又多了一对网络<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)
`# 我们发现这个容器带来网卡,都是一对对的# veth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连# 正因为有这个特性 veth-pair 充当一个桥梁,连接各种虚拟网络设备的# OpenStac,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术`<br />我们来测试下tomcat01和tomcat02是否可以ping通
获取tomcat01的ip 172.17.0.2
$ docker-tomcat docker exec -it tomcat01 ip addr
550: eth0@if551:
让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通
**网络模型图**<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中所有网络接口都是虚拟的,虚拟的转发效率高(内网传递文件)只要容器删除,对应的网桥一对就没了!
<a name="9l1Ef"></a>
## 自定义网络【推荐】
**思考一个场景**:我们编写了一个微服务,database url=ip: 项目不重启,数据ip换了,我们希望可以处理这个问题,可以通过名字来进行访问容器?
- **–link **可以实现容器名连接,但其本质是在hosts配置中添加映射,现在使用Docker已经不建议使用–link了! 不适用docker0(docker0特点:默认,域名不能访问。 --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不通
- **自定义网络【推荐】**
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
**网络模式**
- bridge :桥接 docker(默认,自己创建也是用bridge模式)<br />
- none :不配置网络,一般不用<br />
- host :和所主机共享网络<br />
- container :容器网络连通(用得少!局限很大)<br />
自定义网络--测试
我们直接启动的命令 —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
![](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;
![](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)
启动两个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
![](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)
在自定义的网络下,容器之间可以相互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 />**好处:**
- redis -不同的集群使用不同的网络,保证集群是安全和健康的<br />
- mysql-不同的集群使用不同的网络,保证集群是安全和健康的<br />
![](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)
<a name="Mfegi"></a>
## 网络连通
思考下图中的tomcat01和tomcat-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)
答案是不能!如下图所示<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)
因为它们根本不在一个网段。那么怎么样才能让他们连通呢?<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打通`**
此时查看一下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)
这次我们再去ping一下`docker exec -it tomcat-01 ping tomcat-net-01`,现在tomcat01已经可以ping通tomcat-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)
而未打通网络的tomcat-02依旧连不通`docker exec -it tomcat-02 ping tomcat-net-01`
<a name="NLVmU"></a>
## ![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)
<a name="lJScI"></a>
## 补充: 计算机IP地址划分
- 以常见的B类IP地址为例:B类IP地址范围128.1.0.1-191.254.255.254(二进制表示为:10000000 00000001 00000000 00000001 - 10111111 11111110 11111111 11111110)
- 如**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*254,254*254*254)
<a name="19cfC"></a>
## 实战:部署Redis集群
![](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
我们使用docker之后,所有的技术都会慢慢变得简单起来!
<a name="icGOc"></a>
## SpringBoot微服务打包Docker镜像
1. 构建SpringBoot项目
1. 打包运行 `mvn package`
1. 编写DockerFile
FROM java:8 COPY *.jar /app.jar CMD [“—server.port=8080”] EXPOSE 8080 ENTRYPOINT [“java”,”-jar”,”app.jar”]
4. 构建镜像
1.复制jar和DockerFIle 到服务器
2.构建镜像
$ docker build -t 镜像名:tag . ```
- 发布运行(以后我们使用了Docker之后,给别人交付就是一个镜像即可!)
关于Docker更深入的技术(compose,swarm等)后面再学习补充!
本文参考
1.博客文章:https://blog.csdn.net/qq_43371556/article/details/102631158,https://blog.csdn.net/danggang0317/article/details/113408905
2.b站狂神说教学视频【墙裂推荐】:https://www.bilibili.com/video/BV1og4y1q7M4?p=32&t=168