软件部署-Docker容器化技术(二)

上一期分享了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制作

  1. 考虑到我们项目都是基于oraclejdk开发,尝试构建一个(基本)适用于所有java项目的基础镜像。

  2. 从docker仓库拉取镜像不稳定:要么访问不到docker官方相关地址,要么配的docker镜像源又不稳定

  1. 实际工作中,服务器可能不一定有外网。

所以这里的思路也是,编写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 主要遇到的问题

  1. 第一节说到,在国内,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后,就没这个问题了。

  1. 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。

  1. 找不到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 网络上。

• 这个内部网络可以被看作是一个私有的子网,只有通过该网络连接的容器才能彼此通信。

  1. Host 模式:

• 在这种模式下,容器会直接使用宿主机(Host)的网络栈,而不是创建自己的网络堆栈。

• 这对于需要直接访问宿主机网络的应用程序来说很有用,但是也会失去 Docker 网络隔离带来的好处。

  1. None 模式:

• 如果你不希望你的容器有任何网络访问能力,可以选择 none 模式。

• 在这种模式下,容器不会被分配 IP 地址,也不会被允许与其他容器或者外部网络通信。

  1. Container 模式:

• 这种模式下,新创建的容器将会共享另一个正在运行的容器的网络命名空间。

• 这意味着两个容器可以共享 IP 地址,并且可以通过环回接口进行通信。

  1. Custom Networking 自定义网络:

• 用户可以创建自己的网络,并且控制容器之间的连接方式。

• Docker 允许用户创建不同类型的网络,例如 overlay 网络,这使得容器可以在跨主机的环境中进行通信。

  1. 端口映射:使用 -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 的作用

  1. 容器间通信:

• docker0 网络接口允许容器之间通过内部网络进行通信。当容器启动时,默认会被连接到 docker0 网络上,这样容器之间就可以通过内部 IP 地址进行通信。

  1. 外部网络访问:

• docker0 网络接口还允许外部网络访问容器内的服务。通过 NAT(网络地址转换),宿主机可以将来自外部网络的请求转发到 docker0 网络中的相应容器 上。

  1. 网络隔离:

• 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多了一层网络,另外还有数据安全性问题(可以通过挂载保障数据安全), 可能是一个性能瓶颈或隐患。

相关推荐
长潇若雪10 分钟前
结构体(C 语言)
c语言·开发语言·经验分享·1024程序员节
DARLING Zero two♡1 小时前
关于我、重生到500年前凭借C语言改变世界科技vlog.12——深入理解指针(2)
c语言·开发语言·科技·1024程序员节
独行soc1 小时前
#渗透测试#SRC漏洞挖掘# 信息收集-Shodan进阶之Jenkins组件
安全·jenkins·安全威胁分析·1024程序员节·shodan
dawn1912282 小时前
Java 中的正则表达式详解
java·开发语言·算法·正则表达式·1024程序员节
黑不拉几的小白兔2 小时前
PTA L1系列题解(C语言)(L1_097 -- L1_104)
数据结构·算法·1024程序员节
小言从不摸鱼2 小时前
【Python】元组、字典与集合详解:数据容器的实战应用
人工智能·python·1024程序员节
魔法自动机3 小时前
Unity3D学习FPS游戏(3)玩家第一人称视角转动和移动
unity·1024程序员节·fps
Ylucius3 小时前
14天速成前端 ------学习日志(已完结)------ 后端程序员学习了解前端
java·开发语言·前端·vue.js·学习·状态模式·1024程序员节
清酒伴风(面试准备中......)3 小时前
计算机网络——开放系统互连参考模型
网络·计算机网络·1024程序员节