上一期分享了Docker的一些基本内容,这一期主要对构建基础镜像和Docker网络、文件挂载再展开分享下,可能不一定做得很好,主要是在学习的过程中有一些自己的总结和思考,和大家一起学习。
名词说明:这里的宿主机是指liunx虚拟机。
1.基础镜像
1.1 dockerfile语法回顾
上一节讲了dockerfile,回顾下:
######
FROM 指定基础镜像
WORKDIR 设置工作目录
COPY 拷贝文件
RUN shell命令
CMD | ENTRYPOINT 容器启动时执行指令,和RUN不同的是,RUN是构建镜像时执行的
######
EXPOSE 容器内端口
VOLUME 一般是映射到匿名卷,感兴趣的可以自行了解
###### 还有一些环境指定命令,感兴趣的可以自行了解
ARG
ENV
######
LABLE 感兴趣的可以自行了解
ONBUILD 当前镜像构建时不会执行,基于当前镜像构建镜像时会执行
######
第一句就是基础镜像。
1.2 基础镜像怎么选
1.2.1 docker hub
回顾一下:基于上一篇的内容我们知道,当我们使用docker pull image命令的时候,docker首选会从本地查找有没有这个镜像,如果本地有,就用本地的;如果本 地没有,则从docker仓库获取。简单的流程图说明
我们知道,docker官方仓库有很多镜像(不过现在dockerhub好像进不去了)
在docker官方hub上搜索centos镜像,可以在github上看到dockerfile是怎么编写的
可以看到,这是一个纯净的centos,它的基础镜像是scratch(dockerhub上90%的基础镜像都来源此镜像)。不同的应用有不同的镜像,那么编写dockerfile的开 始:基础镜像的选择就比较重要了。
1.2.2 基础镜像分类
Docker Hub 上有非常多的高质量的官方镜像(docker团队制作的)。
有应用镜像,如 nginx、redis、mongo、mysql、httpd、tomcat 等;
有方便运行各种语言代码的编程语言镜像,如 node、oraclejdk,openjdk、python、ruby、golang 等。
还有更为基础的操作系统镜像,如 ubuntu、debian、centos、fedora、alpine 等。
镜像选择基本原则
- 官方镜像优于非官方的镜像,如果没有官方镜像,则尽量选择Dockerfile开源的
- 固定版本tag而不是每次都使用latest:比如java基础镜像,以java8为例,见得多的有openjdk:8-jdk-alpine。这里就指定了tag为8-jdk-alpine
- 尽量选择体积小的镜像:比如java基础镜像,以java8为例,有8-jdk-alpine(基于 Alpine Linux,镜像体积相对更小,适合对镜像大小有严格要求的场景。),还有8-jdk-slim(基于 Debian 的 slim 版本,体积更小,适合生产环境),还有8-jdk(全功能版本)
1.2.3 java项目基础镜像
上一篇我们说到,一般java项目,基础镜像是jre或jdk。造成我们不太清楚怎么选java基础镜像主要有以下几个原因: 1.由于Oracle JDK license问题,Docker官方的Java基础镜像使用的是OpenJDK而不是Oracle JDK 2.jdk有很多版本,而且镜像还有体积大小之分 3.java项目还可以在tomcat中运行 为此我们选择java镜像的时候就会感到头痛,好像总是需要查一下才知道用什么镜像。根据这一段时间内的学习,一般有两个办法:
这里以openjdk8,简单说下8-jdk-alpine和8-jdk的区别
上面我们说到,alpine是一个基础的操作系统镜像,那么从字面意思可以了解到,带了alpine和没带alpine的区别应该就是:带了alpine的镜像不仅有java环境, 还有基础的操作系统,可以执行一些简单的系统命令;没带alpine的镜像就是一个简单的jdk环境。下面实操验证下区别:
启动带alpine的镜像,看能执行ip addr命令不:
启动后进入容器
启动不带alpine的镜像,看能执行ip addr命令不:
启动后进入容器
基于上面的结果,也可以给我们选择镜像作为一个参考,如果就是跑项目,那不需要带操作系统环境,用对应版本即可。
1.2.4 web项目基础镜像
上一篇我们说到,一般web项目,基础镜像是NGINX,其实也可以是tomcat,甚至是Nodejs。根据我们部门目前的web项目,基本都可以使用NGINX基础镜像。至 于tomcat或Nodejs感兴趣的可以自行了解。
说到NGINX基础镜像,还是老问题,到底用哪个版本,是不是每次又要去查一下才知道用什么镜像,以下是几个常用的NGINX基础镜像,可供选择
• nginx:latest (默认是最新的稳定版)
• nginx:stable (当前的稳定版本)
• nginx:mainline (最新的主线版本)
• nginx:alpine (基于 Alpine Linux 的版本)
• nginx:alpine-lts (基于 Alpine LTS 版本)
可能又有疑问,nginx不是也有版本嘛,那应该用哪个版本呢,关于这个问题,因为现在dockerhub访问不到了,不太清楚有哪些版本,比如1.23.4这个版本,你可 以选择nginx:1.23.4,或者nginx:1.23.4-alpine 根据这段时间的学习和了解,使用情况较多的有3种:
1.使用最新稳定版
2.指定具体的版本
3.指定具体版本的alpine版本
当然也可以自己制作一个NGINX基础镜像。
总结:使用恰当的基础镜像是一个好的开始,如果基础镜像使用不当可能需要遇到一些问题,可能要实际遇到再根据实际情况解决。
1.3 如何构建一个Java项目的(基本)通用基础镜像
开始前的说明:尽管docker hub上有官方oraclejdk,我们可以使用。然而制作镜像和使用基础镜像不一样,制作镜像需要编写Dockerfile,因为官方基础镜像 (基本)也是通过Dockerfile制作的,所以这里的制作,是要先把jdk包下下来再解压,从而完成。(猜测官方oraclejdk镜像制作也差不多)
从上一篇可以了解到,我们构建了镜像后,可以以它作为基础镜像构建新的镜像。上一篇又说到,oraclejdk开发的java项目部署在docker,用openjdk镜像基本是没 什么问题,但在这里,出于下面三点选择oraclejdk8制作
-
考虑到我们项目都是基于oraclejdk开发,尝试构建一个(基本)适用于所有java项目的基础镜像。
-
从docker仓库拉取镜像不稳定:要么访问不到docker官方相关地址,要么配的docker镜像源又不稳定
- 实际工作中,服务器可能不一定有外网。
所以这里的思路也是,编写Dockerfile制作oraclejdk8镜像后,java项目以它作为基础镜像。
1.3.1 下载 Oracle JDK 8
开发一般装的都是oraclejdk8,可能也有11的,这里以oraclejdk8为例。因为从官方下载jdk8 tar包时要求登录,然后从别的地方找了一个安装包并上传到liunx上
1.3.2 创建 Dockerfile
ADD 命令不仅可以复制文件,还可以从 URL 下载文件,并且它可以自动解压某些压缩文件(如 .tar 文件),官方centos镜像也是用了ADD命令上传并解压centos文 件。
解释说明:
1.为什么基础镜像是centos7,其实用apline镜像应该也可以,感兴趣的可以试试。一开始用的也是apline镜像,只不过遇到很多问题(下面罗列了一些),搞了2 天,后面换成了centos7镜像。
2.为什么没有启动命令:因为build出来的镜像用于基础镜像,它不是一个目标镜像,目标镜像是以它为基础镜像的java项目镜像。
1.3.3 使用此镜像
镜像构建成功
使用前先验证下java环境。正常
可以看到,这个镜像有五百多M,以apline镜像作为基础镜像可能会小点,如果对镜像大小有要求,可以考虑换基础镜像。
编写dockerfile,以此作为基础镜像,拿外委项目管理项目构建并启动验证。
构建镜像(鏡像有六百多M)
启动并访问
正常
1.3.4 主要遇到的问题
- 第一节说到,在国内,docker相关源不太稳定,上面也说了这也是我们选择制作镜像的原因。拉取镜像时经常会报lookup do.nark.eu.org on 223.5.5.5:53: no such host这个错
这个错的原因其实比较清晰,就是说通过DNS服务器查找do.nark.eu.org on这个地址找不到,结合上一篇这边配置的docker镜像加速器和DNS配置,猜测可能 是这个do.nark.eu.org on这个域名不稳定。本机ping发现也找不到
在虚拟机上nslookup命令也找不到
这种情况下,个人一般的办法是,重启下本机网络(因为虚拟机网络和本机是桥接的)、重启下虚拟机网络或虚拟机、等一会再试,一般可以解决,但有时候 也不能解决,这种情况下可以尝试改下虚拟机DNS地址或docker镜像加速地址。
2.报No such file or directory
出现这个问题的原因是dockerfile中设置工作目录后,没有把jdk8包拷贝到工作目录,后面改了dockerfile后,就没这个问题了。
- failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "java": executable file not found in $PATH:unknown
出现这个问题的原因是JAVA环境变量设置有误,就跟我们电脑设置java环境变量一样,要设置JAVA_HOME、JRE_HOME,PATH。
- 找不到java
出现这个问题的原因也还是JAVA环境变量设置有误。
上面说到我们使用oralcejdk8制作此镜像,但是也可以用openjdk8制作,有以下几点原因:
1)Oracle JDK 的官方 Docker 镜像主要集中在 OpenJDK(这一点是官方说法,至于怎么论证,感兴趣的话额可以自定了解)
2)虽然 Oracle JDK 也有 Docker 镜像,但通常更推荐使用 OpenJDK 的镜像,因为它们是免费的,并且对于大多数用途来说,OpenJDK 和 Oracle JDK 之间的差异 并不显著。
3)Oracle JDK 的许可条款可能要求商业用途购买许可证,因此在生产环境中使用 Oracle JDK 时,一般要遵守 Oracle 的许可协议。 考虑到这些因素,很多时候也可以使用openjdk。
总结:使用oraclejdk制作基础镜像并用于其它项目可用,能够帮助我们日常开发和使用。
1.4 使用maven插件生成Java项目的镜像
开始前的说明: 1.不管是在主机还是虚拟机上用,都要装Docker。 2.使用插件生成镜像,其实只是一种方式,使用插件可以简化一些工作,但最基础的Dockerfile还是要多学习,毕竟那是基础。
使用插件生成 Dockerfile 可以简化开发过程,并帮助自动化创建镜像的过程。在 Java 开发中,尤其是使用 Maven 或 Gradle 作为构建工具时,有许多插件可以帮助 你构建 Docker 镜像。
以下是几种常用的方式:
1.Maven 插件:fabric8-maven-pluginfabric8-maven-plugin 是一个流行的 Maven 插件(当然也有其它插件),它可以用来生成 Dockerfile 并构建 Docker 镜像。
2.使用 Gradle 插件生成 DockerfileGradle 插件:org.jetbrains.gradle.pluginGradle 也有类似的插件来生成 Dockerfile 并构建 Docker 镜像。
3.使用 Spring Boot 插件生成 Dockerfile 镜像。
在上一篇7.4小节中的方式,是使用Spring Boot插件的方式,因为我们的项目基本都是Spring Boot项目,所以这里用这种方式。 配置 pom.xml,下面是一个例子
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<!-- 打jar包 -->
<!-- <goal>repackage</goal> -->
<!-- 构建镜像 -->
<goal>build-image</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- docker地址 -->
<dockerHost>http://IP:PORT</dockerHost>
<!-- 镜像名称 -->
<dockerImageName>springbootdemo</dockerImageName>
上面的dockerHost,是配置远程Docker服务地址。因为本机没有装docker,是在虚拟机上装的,所以要指定Docker服务的地址,说到这里,其实有三种方式:要么 本机装Docker;要么联通到虚拟机Docker;要么在虚拟机装maven,把项目代码放到虚拟机上构建。考虑到虚拟机已经装了docker,所以选择在虚拟机装maven的 方式构建。
1.4.1 编写pom文件
这里使用了spotify公司的docker镜像构建插件,用了上面构建的oraclejdk8镜像。
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<!-- 打jar包 -->
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<imageName>springboot-demo</imageName>
<baseImage>oraclejdk8</baseImage>
1.4.2 执行以下命令,构建Docker镜像:
mvn clean package docker:build
执行后,下载依赖并构建镜像
因为是初次使用,所以下载依赖包比较慢。
构建成功。可以看到构建的日志打印
查看打出来的jar包和在本机上是否差不多。是差不多的
执行docker images查看构建的镜像
1.4.3 启动镜像并验证
总结:使用maven插件能够帮助我们构建镜像,方便日常开发和使用。
2.docker网络简单窥探
docker网络是docker中比较重要的一个环节,日常使用、容器互联,docker编排(compose)、docker流水线(CI/CD)都离不开网络。
通过本节,我们会了解到docke网络和容器网络是怎么一回事。
为什么docker有网络,个人理解,docker作为当前流行的容器化技术,要满足各种应用运行,并且容器之间以及容器与外部世界之间可能还要通信,就比如上一篇 说到的,运行docker容器时,可以使用 -p 参数来进行端口映射,这样容器内的服务就可以被宿主机上的服务所访问。那么docker肯定是有网络的。
通过查阅资料,Docker 引擎内置了几种不同的网络模式来满足不同场景下的需求。以下是 Docker 网络的一些关键概念和它们的作用:
1. Bridge 模式:
• 默认情况下,每个 Docker 安装都会有一个名为 bridge 的内部网络接口。这个网络接口允许 Docker 容器通过它互相通信。
• 当你启动一个容器时,如果没有指定任何网络相关选项,那么这个容器就会自动连接到 bridge 网络上。
• 这个内部网络可以被看作是一个私有的子网,只有通过该网络连接的容器才能彼此通信。
- Host 模式:
• 在这种模式下,容器会直接使用宿主机(Host)的网络栈,而不是创建自己的网络堆栈。
• 这对于需要直接访问宿主机网络的应用程序来说很有用,但是也会失去 Docker 网络隔离带来的好处。
- None 模式:
• 如果你不希望你的容器有任何网络访问能力,可以选择 none 模式。
• 在这种模式下,容器不会被分配 IP 地址,也不会被允许与其他容器或者外部网络通信。
- Container 模式:
• 这种模式下,新创建的容器将会共享另一个正在运行的容器的网络命名空间。
• 这意味着两个容器可以共享 IP 地址,并且可以通过环回接口进行通信。
- Custom Networking 自定义网络:
• 用户可以创建自己的网络,并且控制容器之间的连接方式。
• Docker 允许用户创建不同类型的网络,例如 overlay 网络,这使得容器可以在跨主机的环境中进行通信。
- 端口映射:使用 -p 参数来进行端口映射,这样容器内的服务就可以被宿主机上的服务所访问。
通过docker network ls,可以看到docker使用了哪几个网络模式:
所以这里讲解的是Bridge模式。
2.1 docker0介绍
要说网络,肯定要先说网卡,那么docker应该也会有一个网卡。
1.lo网卡,本地回环(loopback)接口,127.0.0.1是回环地址
2.ens32网卡,安装centos时安装的网卡,192.168.10.111是centos内网IP
3.docker0网卡,docker帮我们生成的网卡,172.17.0.1是docker的IP
docker0 是 Docker 引擎在宿主机上创建的一个虚拟网络接口(通常是一个虚拟网桥),用于管理 Docker 容器之间的网络通信。docker0 是 Docker 默认的桥接网 络,它允许容器之间通过内部网络进行通信,并且允许外部网络访问容器内的服务。
docker0 的作用
- 容器间通信:
• docker0 网络接口允许容器之间通过内部网络进行通信。当容器启动时,默认会被连接到 docker0 网络上,这样容器之间就可以通过内部 IP 地址进行通信。
- 外部网络访问:
• docker0 网络接口还允许外部网络访问容器内的服务。通过 NAT(网络地址转换),宿主机可以将来自外部网络的请求转发到 docker0 网络中的相应容器 上。
- 网络隔离:
• docker0 网络接口提供了一定程度的网络隔离,使得容器内的网络环境相对独立于宿主机和其他容器
个人认为:docker0的网卡对应的IP在windows看不到,因为是虚拟机再虚拟出来的;虚拟机使用的ens32网卡对应的IP在windows看不到,因为虚拟机是使用桥接模式和windows互联
而NAT模式对应的网卡VMnet8,在windows可以看到
2.2 容器网络查看
因为这里要查看容器网卡信息,所以使用带有alpine的镜像,也就是上面说的openkjdk:8-jdk-alpine
2.2.1 启动一个java项目
查看容器内部IP地址,发现这个IP地址和docker0网卡的IP在同一个网段。它的网卡叫eth0@if7,并且前面的序号是6。
退出容器,ping这个地址,发现可以ping通
通过ip addr查看虚拟机网卡情况,发现多了一个网卡,并且序号是7,后面的数字是6。
2.2.2 再启动一个java项目
查看容器内部IP地址,发现这个IP地址和docker0网卡的IP也在同一个网段。它的网卡叫eth0@if13,并且前面的序号是12。
退出容器,ping这个地址,发现可以ping通
通过ip addr查看虚拟机网卡情况,发现多了一个网卡,并且序号是13,后面的数字是12。
发现:启动容器后,带来的网卡是一对对的。
划重点:
Docker使用的是evth-pair技术,一段连接协议,一段连接彼此。
正是因为有这个特性,evth-pair充当一个桥梁,连接各种虚拟设备。
想更多了解evth-pair技术,可以参照这篇文章:https://www.cnblogs.com/bakari/p/10613710.html (https://www.cnblogs.com/bakari/p/10613710.html)
2.2.3 容器间网络互联简述
容器间的网络互联在Docker应用中是一个比较常见的需求,尤其在构建微服务架构或需要容器间通信的应用场景中。是怎么做的呢?
2.2.3.1 通过IP连接的原理
上面说到Docker可以连接到容器,那么容器间是否互通呢:
先说结果:通的
试一下第2个容器(ip 172.17.0.4)能不能ping通第一个容器,发现是通的
试一下第1个容器(ip 172.17.0.2)能不能ping通第二个容器,发现是通的
原理类似下面这个图(在一台docker中启动了两个容器):
一个容器访问另一个容器并不是直接连接,而是通过docker0连接的。当我们在一个容器内ping另一个容器时,先到docker0,docker0查找自己的路由表, 发现记录了要ping的另一个容器的IP,就通过docker0桥接过去了。
2.2.3.2 通过link方式连接
如果要通过服务名联通,比如在微服务场景,可能需要通过服务名联通。又怎么做?这里说下容器link方式。
先启动两个java程序(大写的-P表示随机端口):
再启动一个java程序,并通过--link连通demo2
原理:demo3在本地配置了demo2的配置
其中172.17.0.4是自己的IP,后面的id是容器的Id。
2.3 docker0和容器间的网络关系
上面说到,docker使用evth-pair技术作为网络设置,具体又是怎样的?第2节的情况类似下面这张图(在一台docker中启动了两个容器)每个容器和docker0都有 一个evth-pair:
结论:
1.docker使用的是liunx的桥接,容器的网络通过docker0创建虚拟网卡并分配网络,然后通过evth-pair技术连接。
2.容器间的网络也是通过docker0转发,docker0相当于一个路由器。
3.docker中的所有网络接口都是虚拟的。
4.只要容器删除,对应一堆网桥就没了。
通过docker network inspect docker0的id(上面有,通过docker network ls查看docker0的id)查看网络情况:
还可以进入docker数据存储目录/var/lib/docker/查看docker网络配置文件:
总结:docker使用的是liunx的桥接,容器的网络通过docker0创建虚拟网卡并分配网络,然后通过evth-pair技术连接;一个容器访问另一个容器并不是直接连 接,而是通过docker0连接的;
3.Docker volume简单使用
docker数据卷和挂载也是docker日常使用比较重要的一个环节,配置文件或日志查看,持久化等都和挂载有关。
通过docker可以看到volume在Management Commands中:
我们可以通过volume实现文件挂载。
docker挂载为了解决什么问题:数据同步,数据持久化、配置文件同步等。如果一个mysql容器产生了数据,然后把容器删了,那容器数据也就丢失了,这是非常 可怕的。
3.1 docker数据卷
volume就是卷的意思,个人理解:类似比如我们电脑的磁盘。docker作为一个成熟的容器化技术,肯定也会有数据存储,虽然容器内也有工作目录,但工作目录和 数据卷又不是一个东西,docker为了更方便管理数据,提供了数据卷功能,也就是存储数据。
docker数据卷目录在/var/lib/docker/volumes目录:
3.2 docker挂载
3.2.1 容器文件挂载到宿主机目录
上面说到,为了更好管理容器内部的文件,于是docker提供了挂载的使用。比如将一个mysql容器内的文件,假设在/usr/mysql目录,同步到liunx宿主机上,类似下 面这张图:
-v path1:path2 这种是指定路径挂载,表示将容器目录path2挂载到指定目录path1(path1使用绝对路径)
-v path 这种是默认挂载,表示将容器目录path挂载到/var/lib/docker/volumes/目录下。
3.2.1.1 首先/home目录没有ceshi目录
启动nginx容器,把容器内的/home目录挂载到宿主机/home/ceshi目录
然后再查看宿主机/home目录,发现会多一个ceshi目录出来
再看下容器/home目录
3.2.1.2 验证在宿主机/home/ceshi目录和容器/home目录新建文件,两边是否一致
在宿主机/home/ceshi新建一个文件
再看容器/home目录下有没有这个文件:有的
在容器/home目录下编辑a.txt,看宿主机/home/ceshi下的文件是否同步更新:已更新
反之同理。
3.2.1.3 查看docker卷目录文件情况是否新增文件:
内容为空
因为这里是指定路径挂载,把容器内目录指定挂载到/home/ceshi目录,使用-v,会在/var/lib/docker/volumes会新建一个文件夹(文件夹有无具体的名称会在3.2.3 讲解),如果没有指定路径,文件会同步到volumes下的目录;如果指定了路径,文件就在指定路径下。
3.2.1.4 停止或删除容器,查看宿主机/home/ceshi目录下的文件是否还在:是的
这里演示了将容器内的一个目录挂载到宿主机,其实可以挂载两个或多个,使用多个-v,感兴趣的可以自行了解。
3.2.2 容器间文件挂载
上面说到容器文件可以挂载到宿主机目录,那么容器间的文件是否也通过挂载可以同步呢?
答案是可以的:可以通过命名卷(Named Volumes)、临时容器、数据卷容器等方式
容器间文件挂载一般用于各服务读取同一份配置,重要文件备份等。
这里使用数据卷容器方式。其它方式感兴趣的可以自行了解。
3.2.2.1 先启动一个nginx镜像,并挂载docker01目录
3.2.2.2 容器nginx02 volumes-from nginx01(挂载数据卷容器到源容器)
并且不会在/var/lib/docker/volumes目录下生成文件夹
3.2.2.3 容器nginx03 volumes-from nginx01(挂载数据卷容器到目标容器)
并且不会在/var/lib/docker/volumes目录下生成文件夹
3.2.2.4 在容器nginx01 docker1目录新建文件,查看nginx02和nginx03是否同步:是同步的
3.2.2.5 停止或删除容器nginx01,容器nginx02和容器nginx03内的共享目录是否还在
停止:容器nginx02和容器nginx03内的共享目录还在
删除:容器nginx02和容器nginx03内的共享目录还在
3.2.2.6 停止容器nginx02或容器nginx03,另一个容器里内的共享目录是否还在
停止容器nginx02:nginx03内的共享目录还在
停止容器nginx03:nginx02内的共享目录还在
删除容器nginx03:nginx02内的共享目录还在
这里创建了源容器和目标容器,其实它们都是使用数据卷容器,只是一个普遍的叫法,没有特别的含义。
通过上面的操作,可以看到数据源容器是一种文件复制的概念。
3.2.3 匿名挂载、具名挂载、指定路径挂载
上面说到,使用-v实现文件挂载,那么挂载还区分具名、匿名和指定路径挂载,这是区别:
比如下面展示了匿名挂载、具名挂载,然后在3.1.1中试了指定路径挂载:
上面我们用了docker volume ls命令,查看docker挂载的情况,发现:
匿名挂载,VOLUME NAME那里是一堆id:上面3.2.2.1就是匿名挂载,然后在/var/lib/docker/volumes目录下会生成一个文件夹。
具名挂载,VOLUME NAME那里是指定的名字:
指定路径挂载,在3.2.1中指定路径挂载,命令是-v path1:path2,这里也是-v path1:path2,两者的区别就是:指定路径挂载的话,path1是绝对路径,如果path1不 是绝对路径的话,就是具名挂载。
进到/var/lib/docker/volumes目录下查看挂载的文件夹:
这里同样也验证了3.2.2.2和3.2.2.3中说的,使用--volumes-from时,虽然也指定了-v,但是/var/lib/docker/volumes不会生成文件夹。
扩展:docker挂载还可以指定读写权限,ro表示readonly、rw表示readwrite,指定权限是对容器内文件的权限,挂载到容器外不做限制。比如设置ro权限,表示容 器内对那个目录下的文件只有只读权限,不能编辑,挂载到的容器外目录可读可写。
总结:docker挂载有很多的应用场景:比如通过挂载将数据持久化本地、通过容器间挂载共享一份配置文件(在微服务场景,一般各微服务的注册中心和服务发现 是同一份配置)、将容器内的日志文件挂载到宿主机,便于日志管理、通过容器间挂载共享静态文件等。对于我们开发也是比较好的,我们常常需要频繁修改配置 文件或源代码,通过挂载数据卷可以实时反映这些修改。
4.问题讨论
1.上面网络章节说到docker使用桥接模式,但是在编写dockerfile时并未指定过网络相关的内容。因为默认是桥接模式,还有主机模式等,应该可以设置。
2.上面网络章节演示了一台机器内的docker,容器互联与docker的连接,在实际应用和生产环境中,可能在多台机器内部署了docker,比如一台部署Enruka和 registry,一台部署Mysql,一台部署微服务,那么不同机器内docker容器能否互相连接。答案是肯定的。只是这里没有做实践。要求服务器在同一台内网,使用桥 接模式或主机模式应该都可以。
3.实际生产部署,对于数据库部署,可能不会用docker,而是直接部署。因为用docker多了一层网络,另外还有数据安全性问题(可以通过挂载保障数据安全), 可能是一个性能瓶颈或隐患。