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

相关推荐
学传打活11 小时前
【边打字.边学昆仑正义文化】_进阶篇5 宇宙星系的运转(续1)
微信公众平台·1024程序员节·汉字·昆仑正义文化
fangzhanpeng1688 天前
快速掌握C#语言基础知识点(1.基础数据类型)
开发语言·c#·1024程序员节
无己心10 天前
面向多平台 AI 搜索引擎的适配层架构设计
前端·人工智能·搜索引擎·ai·1024程序员节
u01030552716 天前
AI驱动的安卓UI自动生成功能实现
人工智能·1024程序员节
u01030552717 天前
长株潭智能体赋能腾讯元器链接共享
1024程序员节
云贝贝贝18 天前
OceanBase认证体系介绍与备考指南
运维·服务器·oceanbase·1024程序员节
u01030552718 天前
Java图像处理实战指南
人工智能·1024程序员节
u01030552719 天前
Java AWT鼠标事件全解析
人工智能·1024程序员节
u01030552721 天前
Java实用类应用精讲
人工智能·1024程序员节
u01030552722 天前
Java I/O核心操作实战
人工智能·1024程序员节