Docker学习第四天——Docker存储与DockerFile

本文介绍了Docker的存储机制,包括Docker存储驱动如AUFS、overlay2和devicemapper,以及选择驱动的考量因素。此外,详细讨论了Docker卷的作用,作为持久化数据的首选方式,并展示了如何使用Dockerfile构建镜像,包括FROM、RUN、CMD和ENTRYPOINT等指令的用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Docker存储

        1、Docker存储驱动

1、Docker存储驱动与联合文件系统

• 联合文件系统(UnionFS)是一种为Linux、FreeBSD和NetBSD操作系统设计的,将其他文件系统合并到一个联合挂载点的文件系统。

• Docker引擎可以使用联合文件系统的多种变体

        ◇ AUFS

        ◇ OverlayFS

        ◇ Btrfs

        ◇ BFS

        ◇ DeviceMapper

• 联合文件系统实际上是由存储驱动实现的,相应的存储驱动有aufs、overlay、overlay2、devicemapper、btrfs、zfs、vfs等。

2、选择Docker存储驱动的总体原则(了解即可)

• 在最常用的场合使用具有最佳整体性能和稳定性的存储驱动。

• 如果内核支持多个存储驱动,则Docker会提供要使用的存储驱动的优先级列表。

• 优先使用Linux发行版默认的存储驱动。

• 一些存储驱动要求使用特定格式的底层文件系统,这可能会限制选择。

• 选择存储驱动还要取决于工作负载的特征和所需的稳定性级别。

3、主流的Docker存储驱动

• 对于所有当前支持的Linux发行版,overlay2存储驱动是首选。 CentOS和RHEL的最新版本现在已经支持overlay2存储驱动,并将overlay2作为推荐的存储驱动。

• 对于Docker 18.06或更早的版本,aufs存储驱动是首选。

• devicemapper存储驱动用于生产环境时需要配置为direct-lvm模式。

• btrfs和zfs存储驱动对底层文件系统(backing filesystem)有用。

• vfs存储驱动用于测试,适合那些没有“写时拷贝”的文件系统。

• 存储驱动的选择可能受到Docker版本、操作系统内核和发行版本的限制。

4、Docker版本所支持的存储驱动

• Docker引擎企业版和Docker EE

        ◇ 对于Docker引擎企业版和Docker EE来说,支持存储驱动的决定性资源是产品兼容性矩阵。建议用户迁移到overlay2存储驱动。

• Docker CE

        ◇ 对于Docker CE来说,只有部分配置被测试过,并且操作系统的内核不可能支持每个存储驱动。

        ◇ 最佳配置是使用带有支持overlay2存储驱动的内核的现代Linux发行版,并且对于大量的工作负载要使用Docker卷写入,而不是将数据写入容器的可写层。

• Docker for Mac和Docker for Windows

◇ 这两个版本的Docker仅用于开发,而不能用于生产环境,不支持定义存储驱动。

5、Docker存储驱动所支持的底层文件系统

 

6、选择存储驱动需考虑的其他事项

• 适合工作负载

        ◇ aufs、overlay和overlay2存储驱动的所有操作都在文件级而不是块级,能更有效地使用内存,但容器的可写层可能在写入繁重的工作负载中变得相当大。

        ◇ 块级存储驱动(如devicemapper、btrfs和zfs存储驱动)在写入繁重的工作负载时表现得更好。

        ◇ 写入大量的小数据,或有很多层的容器,或深层文件系统,overlay存储驱动比overlay2存储驱动性能更好。

        ◇ btrfs和zfs存储驱动需要更多内存。

        ◇ zfs存储驱动是高密度工作负载(如PaaS)的理想选择。

• 共享存储系统

        ◇ 多数情况下Docker可以在SAN、NAS、硬件RAID或其他共享存储系统上工作,但Docker并没有与它们紧密集成。

        ◇ 每个Docker存储驱动都基于Linux文件系统或卷管理器。

• 稳定性

        ◇ overlay2、aufs、overlay和devicemapper存储驱动的稳定性更高。

• 测试工作负载

        ◇ 在不同的存储驱动上运行工作负载时,可以测试Docker的性能。

 2、Docker存储的挂载类型

1、Docker卷与存储驱动

• 默认在容器中创建的所有文件保存在可写的容器层中,这类存储的问题如下。

        ◇ 此类存储只在容器的生命周期内存在,会随着容器的删除而被删除。

        ◇ 如果主机上的其他进程需要访问容器中的数据,则很难从容器中获取数据。

        ◇ 容器的可写层与运行容器的主机紧密耦合,无法轻松地将数据转移到其他地方。

                ▪ 耦合:紧密切合,不可分割

                ▪ 解耦:降低耦合度,更容易移植

                ▪ 模块化:自顶向下逐层把系统划分成若干模块的过程,有多种属性,分别反映其内部特性。

                ▪ 微服务:将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。

        ◇ 写入容器的可写层需要Docker存储驱动来管理文件系统。

• 卷有助于解决这些问题。

        ◇ 卷本质上是Docker主机文件系统中的目录或文件,能够直接被挂载到容器的文件系统中。

        ◇ 对卷的读写操作会绕过存储驱动,并以本地主机的速度运行。

2、 Docker卷与存储驱动的关系

 3、选择合适的挂载类型

4、卷

• 卷存储在主机文件系统中,在Linux主机上默认就是/var/lib/docker/volumes目录。

• 可以以命名或匿名方式挂载卷。

• 卷由Docker创建并管理。

• 作为Docker容器或服务中持久化数据的首选方式,卷适合以下应用场合。

        ◇ 在多个正在运行的容器之间共享数据。

        ◇ 当Docker主机不能保证具有特定的目录结构时,卷有助于将Docker主机的配置与容器运行时解耦。

        ◇ 当需要将容器的数据存储到远程主机或云时。

        ◇ 当需要在两个Docker主机之间备份、恢复或迁移数据时,卷是更好的选择。

 3、使用Docker卷

1、卷的优势(相比绑定挂载)

• 卷比绑定挂载更容易备份和迁移。

• 可以通过Docker命令行或Docker API对卷进行管理。

• 卷在Linux容器和Windows容器中都可以工作。

• 在多个容器之间共享时,卷更为安全。

• 卷驱动支持在远程主机或云端存储卷,加密卷内容,以及增加其他功能。

• 新卷的内容可以由容器预填充。

2、-v选项(本章重点

• 作用:将主机的卷挂载到容器中。

• 语法:docker run -v [host-src:]container-dest[:<options>]

        ◇ 对于命名卷,第1个字段是卷的名称,并且在指定主机上是唯一的;对于匿名卷,第1个字段被省略。

        ◇ 第2个字段container-dest是容器中被挂载的文件或目录的路径,必须采用绝对路径的形式。

        ◇ 第3个字段是可选的,是一个逗号分隔的选项列表。

        ◇ 可将同一卷挂载到多个容器上,以实现容器间的数据共享。

• 示例:将卷myvol2挂载到容器中的/app目录。

        docker run -d --name devtest -v myvol2:/app nginx:latest

3、创建和管理卷:docker volume

通过docker volume命令在任何容器之外单独创建和管理卷

示例:        创建卷: docker volume create my-vol

                   列出当前的卷: docker volume ls

                   查看卷的详细信息: docker volume inspect my-vol

                   删除卷: docker volume rm my-vol

 

二、DockerFile

1、YAML文件 语法特点(语法结构)

• YAML大小写敏感。

• 使用缩进表示层级关系。

• 缩进只能使用空格,不能使用TAB,不要求空格个数,但相同层级应当左对齐。

• 使用符号“#”表示注释,YAML中只有行注释。

• 字符串可以不用引号标注。

• 每个“:”与它后面所跟的参数之间都需要有一个空格。

• YAML文件可以由一或多个文档组成,并用“---”符号分隔。

• 部分关键字有驼峰式写法

2、DockerFile相关基本知识

1、DockerFile简要

• Dockerfile是由一系列指令和参数构成的脚本文件,每一条指令构建一层。

• 镜像的定制实际上就是定制每一层所要添加的配置和文件。

• Dockerfile的格式:

        ◇ # Comment

        ◇ INSTRUCTION arguments

• INSTRUCTION表示指令,不区分大小写,建议大写。arguments表示指令的参数。

• Dockerfile文件必须以FROM指令开头,定义构建镜像的基础镜像。

• 以“#”符号开头的行都将被视为注释。

• Docker可使用解析器指令escape设置转义字符。

2、通过DockerFile构建镜像

• 构建上下文:docker build

        ◇ 上下文是由文件路径(本地文件系统上的目录)或一个URL(Git仓库位置)定义的一组文件。

        ◇ 构建上下文以递归方式处理,本地路径包括其中的任何子目录,URL包括仓库及其子模块。

• 镜像构建过程

        ◇ 构建过程中一开始将整个上下文递归地发送给守护进程。

        ◇ 要使用构建上下文中的文件,Dockerfile引用由指令(如COPY)指定的文件。

        ◇ 使用-f选项显式指定Dockerfile文件的具体位置:

▪ docker build -f /path/to/a/Dockerfile .

        ◇ 可以指定构建成功之后要保存的新镜像的仓库名和标签:

        ◇ docker build -t shykes/myapp .

        ◇ Docker守护进程逐一运行Dockerfile中的指令,每条指令被独立执行并创建一个新镜像。

        ◇ 只要有可能,Docker将重用过程中的中间镜像(缓存),以加速构建过程。

• 构建上下文示例

(1)为构建上下文创建一个目录并切换到该目录。

mkdir myproject && cd myproject

(2)将内容“hello”写入一个名为hello的文本文件。

echo "hello" > hello

(3)创建一个Dockerfile并在其中运行cat命令。

echo -e "FROM busybox\nCOPY /hello /\nRUN cat /hello" > Dockerfile

(4)从构建上下文(.)构建镜像。

docker build -t helloapp:v1 .

3、DockerFile常用指令 

1、 FROM指令——设置基础镜像

◇ FROM指令的用法有以下3种格式:

        ▪ FROM <image> [AS <name>]

        ▪ FROM <image>[:<tag>] [AS <name>]

        ▪ FROM <image>[@<digest>] [AS <name>]

◇ FROM指令为后续指令设置基础镜像,可以在同一个Dockerfile文件中多次出现,以创建多个镜像层。

◇ image参数指定任何有效的镜像,特别是可以从公有仓库拉取的镜像。

◇ FROM指令AS <name>是可选的,可以用来对此构建阶段指定一个名称。

◇ tag或digest的值是可选的。如果省略其中任何一个,构建器将默认使用latest。

2、 RUN指令——运行命令

◇ RUN指令的用法有以下两种格式:

        ▪ RUN <command>

        ▪ RUN ["executable", "param1", "param2"]

◇ 第1种是shell格式,命令在shell环境中运行。

◇ 第2种是exec格式,不会启动shell环境。

◇ RUN指令将在当前镜像顶部的新层中执行命令,并提交结果。

◇ exec格式可以避免shell字符串转换。

◇ shell格式中的默认shell可以使用SHELL命令来更改。

◇ 第一个字段为命令,后面为参数或选项

3、 CMD指令——指定容器启动时默认执行的命令

◇ CMD指令的用法有以下3种格式:

        ▪ CMD ["executable","param1","param2"]

        ▪ CMD ["param1","param2"]

        ▪ CMD command param1 param2

◇ 第1种是首选的exec格式。

◇ 第2种提供给ENTRYPOINT指令的默认参数。

◇ 第3种是shell格式。

◇ 一个Dockerfile文件中若有多个CMD指令,则只有最后一个CMD有效。

◇ CMD指令的主要目的是为运行中的容器提供默认值。

4、 LABEL指令——向镜像添加标记(元数据)

◇ LABEL指令的语法格式如下:

        ▪ LABEL <key>=<value> <key>=<value> <key>=<value> ...

◇ 每个标记(元数据)以键值对的形式表示。要在其中包含空格,应使用引号和反斜杠。

◇ 一个镜像可以有多个标记。可以将多个标记合并到单个LABEL指令中以减少层数。

◇ 基础镜像或父镜像中包含的标记会被镜像继承。

◇ 类似inode,不存储镜像实际内容,常用于多容器管理。

5、EXPOSE指令——声明容器运行时侦听的网络端口

◇ EXPOSE指令的语法格式如下:

        ▪ EXPOSE <port> [<port>...]

◇ EXPOSE指令通知Docker容器在运行时侦听指定的网络端口。

◇ EXPOSE指令不会发布该端口,只是起到声明作用。

6、ENV指令——指定环境变量

◇ ENV指令的用法有以下两种格式:

        ▪ ENV <key> <value>

        ▪ ENV <key>=<value> ...

◇ ENV指令以键值对的形式定义环境变量。

◇ 第1种格式将单个变量设置为一个值。

◇ 第2种格式允许一次设置多个变量,可以使用等号(=),而第1种形式不使用。

7、COPY指令——将源文件复制到容器

◇ COPY指令的用法有以下两种格式:

        ▪ COPY [--chown=<user>:<group>] <src>... <dest>

        ▪ COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

◇ --chown选项只能用于构建Linux容器,不能在Windows容器上工作。

◇ COPY指令将指定的源路径(由<src>参数指定)的文件或目录复制到容器文件系统中指定的目的路径(由<dest>参数指定)。

◇ 可以指定多个源路径,但文件和目录的路径将被视为相对于构建上下文的源路径。

◇ 目的路径是绝对路径,或者是相对于工作目录(由WORKDIR指令指定)路径。

8、 ADD指令——将源文件复制到容器

◇ ADD指令的用法有以下两种格式:

        ▪ ADD [--chown=<user>:<group>] <src>... <dest>

        ▪ ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

◇ 它与COPY指令的功能基本相同,不同之处有两点:

        ▪ 源可以使用URL指定。

        ▪ 归档文件在复制过程中能够被自动解压缩。

◇ 如果源是具有可识别的压缩格式的本地Tar归档文件,则将其解包为目录。来自远程URL的资源不会被解压缩。

9、ENTRYPOINT指令——配置容器的默认入口

◇ ENTRYPOINT指令的用法有以下两种格式:

        ▪ ENTRYPOINT ["executable", "param1", "param2"]

        ▪ ENTRYPOINT command param1 param2

◇ 第1种是首选的exec格式。

◇ 第2种是shell格式。

◇ ENTRYPOINT指令用于配置容器运行的可执行文件。

◇ 在Dockerfile中只有最后一个ENTRYPOINT指令会起作用。

10、 VOLUME指令——创建挂载点

◇ VOLUME指令的语法格式如下:

        ▪ VOLUME ["/data"]

◇ VOLUME指令创建具有指定名称的挂载点,并将其标记为从本机主机或其他容器保留外部挂载的卷。

11、 WORKDIR指令——配置工作目录

◇ WORKDIR指令的语法格式如下:

        ▪ WORKDIR /path/to/workdir

◇ WORKDIR指令为Dockerfile中的任何RUN、CMD、ENTRYPOINT、COPY和ADD指令设置工作目录。

◇ 可以在一个Dockerfile文件中多次使用该指令。

12、 USER指令——设置运行镜像时使用的用户名

◇ USER指令的用法有以下两种格式:

        ▪ USER <user>[:<group>] or

        ▪ USER <UID>[:<GID>]

◇ USER指令设置运行镜像时使用的用户名(或UID)和可选的用户组(或GID)。

◇ 用户没有主要组时,镜像(或下一条指令)将以root组的身份运行。

13、 ARG指令——定义变量

◇ ARG指令的语法格式如下:

        ▪ ARG <name>[=<default value>]

◇ ARG指令定义一个变量(可称为构建时变量。

◇ 一个Dockerfile文件可以包括一个或多个ARG指令。

14、 SHELL指令——指定命令的shell格式

◇ SHELL指令的语法格式如下:

        ▪ SHELL ["executable", "parameters"]

◇ SHELL指令用于指定命令的shell格式以覆盖默认的shell。

◇ SHELL指令可以多次出现。每个SHELL指令覆盖所有先前的SHELL指令,并影响所有后续指令。

15、 Dockerfile指令的exec和shell格式

◇ RUN、CMD和ENTRYPOINT指令都会用到这两种格式。

◇ exec格式的一般用法如下:

        ▪ <指令> ["executable", "param1", "param2", ...]

◇ 采用exec格式要使用环境变量。

◇ shell 格式一般用法如下:

        ▪ <指令> <command>

◇ 指令执行时shell格式底层会调用/bin/sh -c 来执行命令。

◇ CMD和ENTRYPOINT指令首选exec格式。RUN指令则选择两种格式都可以。

◇ exec格式作为JSON数组解析,必须在单词之外使用双引号而不是单引号。

16、 RUN、CMD和ENTRYPOINT指令的区别和联系

◇ RUN指令执行命令并创建新的镜像层,经常用于安装应用程序和软件包。

◇ Dockerfile应该至少为CMD或ENTRYPOINT指令指定一个命令。

◇ CMD指令的主要目的是为运行容器提供默认值,即默认执行的命令及其参数,但当运行带有替代参数的容器时,CMD指令将被覆盖。

◇ 当使用容器作为可执行文件时,应该定义ENTRYPOINT指令。

◇ 可以考虑使用ENTRYPOINT指令的exec格式设置默认命令和参数,然后使用CMD指令的任何格式设置额外的默认值。

◇ ENTRYPOINT指令中的参数始终会被使用,而CMD指令的额外参数可以在容器启动时被动态替换掉。

4、构建使用DockerFile实例

        实例:基于couchbase/centos7-systemd创建dockerfile,要求能使用nginx访问自己创建的测试网站。

        下面是构建流程:

1、建立一个目录用作DockerFile的上下文并准备所需文件:

[root@goodwood ~]# mkdir nginx-dockerfile  && cd nginx-dockerfile
[root@goodwood nginx-dockerfile]# vim index.html
test

2、编写DockerFile:

[root@goodwood nginx-dockerfile]# vim Dockerfile
FROM couchbase/centos7-systemd
RUN yum install -y nginx
EXPOSE 80
COPY index.html /usr/share/nginx/html/
ENTRYPOINT ["nginx","-g","daemon off;"]

3、使用Docker build命令构建镜像

[root@goodwood nginx-dockerfile]# docker build -t nginx-on-centos .
[+] Building 70.9s (8/8) FINISHED                                                             
 => [internal] load .dockerignore                                                        0.0s
 => => transferring context: 2B                                                          0.0s
 => [internal] load build definition from Dockerfile                                     0.0s
 => => transferring dockerfile: 431B                                                     0.0s
 => [internal] load metadata for docker.io/couchbase/centos7-systemd:latest              0.0s
 => CACHED [1/3] FROM docker.io/couchbase/centos7-systemd                                0.0s
 => [internal] load build context                                                        0.0s
 => => transferring context: 102B                                                        0.0s
 => [2/3] RUN yum install -y nginx                                                      70.0s
 => [3/3] COPY index.html /usr/share/nginx/html/                                         0.0s
 => exporting to image                                                                   0.9s
 => => exporting layers                                                                  0.9s
 => => writing image sha256:d44ad31867249c63c136b038aaef7af69c29f8f86bab5c3412f6010c173  0.0s 
 => => naming to docker.io/library/nginx-on-centos                                       0.0s 
[root@goodwood nginx-dockerfile]# docker images                                               
REPOSITORY                  TAG       IMAGE ID       CREATED         SIZE
nginx-on-centos             latest    d44ad3186724   7 seconds ago   688MB

4、基于该镜像启动容器并进行测试

[root@goodwood nginx-dockerfile]# docker run -itd -P nginx-on-centos
22d4b5c1d6a2759eb45bd0e3441071a541e1cdd4b30713f2741645b491d34641
[root@goodwood nginx-dockerfile]# docker ps -a
CONTAINER ID   IMAGE                       COMMAND                   CREATED          STATUS          PORTS                                     NAMES
22d4b5c1d6a2   nginx-on-centos             "nginx -g 'daemon of…"   3 seconds ago    Up 2 seconds    0.0.0.0:32768->80/tcp, :::32768->80/tcp   angry_sammet

5、尝试访问对应ip地址

 

 三、相关面试题

1、简述Linux文件系统和Docker文件系统?

Linux 文件系统: bootfs rootfs 组成, bootfs 主要包含 bootloader kernel bootloader 主要是引 导加载kernel ,当 kernel 被加载到内存之后 bootfs 就被卸载掉了。 rootfs 包含的就是典型 linux 系统 中/dev,/proc,/bin,/etc 等标准目录。
Docker 文件系统: Docker 容器是建立在 Aufs 分层文件系统基础上的, Aufs 支持将不同的目录挂载到同 一个虚拟文件系统下,并实现一种layer 的概念。 Aufs 将挂载到同一虚拟文件系统下的多个目录分别设置 成read-only read-write 以及 whiteout-able 权限。 docker 镜像中每一层文件系统都是 read-only
2、 简述 Docker 网络模式?
        Docker使用 Linux Namespaces 技术来进行资源隔离,其中 Network Namespace 实现隔离网络。
        一个Network Namespace 提供了一份独立隔离的网络环境,包括网卡、路由、 Iptable 规则等, Docker
网络有如下四种模式:
host 模式: host 模式下容器将不会获得独立的 Network Namespace ,该模式下与宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,不会配置独有的 IP 等,而是使用宿主机的 IP和端口。
container 模式: Container 网络模式是 Docker 中一种较为特别的网络的模式,处于 container 模 式下的 Docker 容器会共享其他容器的网络环境,因此,两个或以上的容器之间不存在网络隔离, 而配置container 模式的容器又与宿主机以及除此之外其他的容器存在网络隔离。
none 模式: none 模式下, Docker 容器拥有自己的 Network Namespace ,但是,并不为 Docker 容 器进行任何网络配置和构造任何网络环境。Docker 容器采用了 none 网络模式,那么容器内部就只 能使用loopback 网络设备,不会再有其他的网络资源。 Docker Container none 网络模式意味着 不给该容器创建任何网络环境,容器只能使用127.0.0.1 的本机网络。
bridge 模式: bridge 模式是 Docker 默认的网络设置,此模式会为每一个容器分配 Network
Namespace 、设置 IP 等,并将该宿主机上的 Docker 容器连接到一个虚拟网桥上。
3、 简述 Docker 跨主机通信的网络实现方式?
docker 跨主机通信按原理可通过以下三种方式实现:
· 直接路由方式:直接在不同宿主机之间添加静态路由;
· 桥接方式(如pipework ): 通过静态指定容器 IP 为宿主机 IP 同一个网络的形式,即可实现。
· Overlay 隧道方式: 使用 overlay 网络实现, Overlay 网络指在现有网络层之上叠加的虚拟化技术, 实现应用在网络上的承载,并能与其他网络业务分离,并且以基于IP 的网络技术为主,如 flannel 、 ovs+gre。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值