Docker 容器技术 — Image 与 Dockerfile

目录

Docker Image

Docker Image 就是一个只读的文件,作为创建 Docker Container 的模板。镜像是容器的基石,容器基于镜像启动,镜像就像是容器的源代码,保存了用于容器启动的各种条件。

Docker 支持通过扩展现有镜像,继而创建新的镜像。实际上,Docker Hub 中 99% 的镜像都是通过在 base image 中安装和配置需要的软件构建出来的。

在这里插入图片描述

Docker Image 是一个层叠的只读文件系统,结构如下:

  • bootfs(引导文件系统):与 Linux Kernel 交互的引导系统。
  • rootfs(root 文件系统):根文件系统,即 base image,可以是一种或多种操作系统,如:Ubuntu 或 CentOS,rootfs 永远是只读状态。
  • unionFS(联合文件系统):即所有 base image 之上的文件系统。Docker 应用了 union mount(联合加载技术),一次可以加载多个只读文件系统到 rootfs 之上,从外面看到的只是一个文件系统。union mount 将各层文件系统叠加到一起,使最终呈现出来的文件系统包含了所有底层文件系统和目录,这样的文件系统就是镜像。

一个镜像可以放到另一个镜像的顶部,位于下边的镜像叫做父镜像,依次类推,最底部的镜像叫做 base image,指的就是 rootfs,即 Ubuntu 或 CentOS 等。

当使用 Image 启动一个 Container 后,一个新的可写的文件系统被加载到镜像的顶部,即:可写层,通常也称作 “容器层”,“容器层” 之下的都叫 “镜像层”。

在这里插入图片描述

Container 中运行的程序就是在这个 “容器层” 中执行的。第一次启动 Container 时,“容器层” 是空的,当文件系统发生变化,都会应用到这一层。如果想修改一个文件,该文件首先会从 “容器层” 下边的 “镜像只读层” 复制到可写层,该文件的只读版本依然存在,但是已经被可写层中的该文件副本所隐藏。这个是 Docker 重要的写时复制(copy on write)机制。

在这里插入图片描述

  • Docker Image 的生命周期
    在这里插入图片描述

Dockerfile

每个 Docker Container 都从一个 Dockerfile 开始。Dockerfile 是一个使用易于理解的语法编写的文本文件,描述如何生成 Docker Image,指定了容器的操作系统、编程语言、环境变量、文件位置、网络端口和其他组件等配置信息,当然还指定了容器启动后要执行的内容。

Docker Image 是 Docker Container 的 “内容载体”,本质是一个可移植文件,包含容器将运行哪些软件组件以及如何运行的规范,每个 Container 都是一个 Image 的实例。因为 Dockerfile 可能包含关于从在线资源库获取某些软件包的说明,所以需要注意指定正确的版本,否则 Dockerfile 可能会根据调用的时间不同生成不一致的镜像。但是一旦创建了一个 Image,它就是静态的。

  • 编写 Dockerfile
# vim Dockerfile

FROM centos
RUN yum install openssh-server -y 
RUN echo "root:123456" |chpasswd
RUN /etc/init.d/sshd start 
CMD ["/usr/sbin/sshd","-D"]
  • 构建镜像
ocker image build  -t centos .
  • . 表示 Dockerfile 在当前路径

Dockerfile 指令

Dockerfile 指令大小写不敏感的,但通常使用大写,使用 # 作为注释,每一行只支持一条指令,每条指令可以携带多个参数。

Dockerfile 指令根据作用可以分为两种:

  • 构建指令:用于构建 Image,其指定的操作不会在运行 Image 的容器上执行;
  • 设置指令:用于设置 Image 的属性,其指定的操作将在运行 Image 的容器中执行。

在这里插入图片描述

构建指令

FROM(指定 base image)

必须在 Dockerfile 头部指定,后续的指令都依赖 FROM 指定的 base image。

该指令有两种格式:

# 指定 base image 为该 image 的最后修改的版本。
FROM <image>       

# 指定 base image 为该 image 的一个 tag 版本。
FROM <image>:<tag>  

MAINTAINER(指定镜像创建者信息)

指定 image 的创建者,当使用 docker inspect 查看时,会输出中有相应的字段记录该信息。

MAINTAINER <name>

RUN(指定构建镜像时执行的指令)

RUN 可以运行任何被 base image 支持的指令,例如:软件管理命令。

  • base image 为 ubuntu,则使用 apt install。
  • base image 为 centos,则使用 yum install。

该指令有两种格式:

RUN <command> (the command is run in a shell - `/bin/sh -c`)
RUN ["executable", "param1", "param2" ... ]  (exec form)

设置指令

CMD(设置容器启动时执行的操作)

一个 Dockerfile 只能由一条 CMD 指令,如果有多个,则仅执行最后一条。CMD 指定执行的操作类型可以是二进制程序、自定义脚本,或操作系统指令。

该指令有 3 种格式:

CMD ["executable","param1","param2"] (like an exec, this is the preferred form)
CMD command param1 param2 (as a shell)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)

其中,ENTRYPOINT 指定一个可执行程序或脚本的路径,该程序会脚本会以 param1 和 param2 作为参数。那么也会要求 Dockerfile 中必须编写了 ENTRYPOINT 指令。

ENTRYPOINT(设置容器启动时执行的操作)

该指令有两种格式:

ENTRYPOINT ["executable", "param1", "param2"] (like an exec, the preferred form)
ENTRYPOINT command param1 param2 (as a shell)

ENTRYPOINT 指令的使用分为两种情况:

  1. 独自使用:当独自使用时,如果同一个 Dockerfile 也编写了 CMD 命令,且 CMD 是一个完整的可执行的命令,那么 CMD 指令和 ENTRYPOINT 指令会互相覆盖只有最后一个 CMD 或者 ENTRYPOINT 有效。
  2. 和 CMD 指令配合使用:用来指定 ENTRYPOINT 的默认参数,这时 CMD 指令不是一个完整的可执行命令,仅仅是参数部分,因为 ENTRYPOINT 指令只能使用 JSON 方式指定执行命令,而不能指定参数。例如:
FROM ubuntu
CMD ["-l"]
ENTRYPOINT ["/usr/bin/ls"]

USER(设置启动容器的用户)

默认为 root 用户。指定 memcached 的运行用户例如:

ENTRYPOINT ["memcached"]
USER daemon
# 或
ENTRYPOINT ["memcached", "-u", "daemon"]

EXPOSE(设置容器需要映射到宿主机的端口)

该指令会将容器中的端口映射成宿主机中的某个端口,外部可以通过宿主机的 IP:Port 来访问容器的服务 Socket。

要实现这个效果需要两个步骤:

  1. 首先在 Dockerfile 中使用 EXPOSE 指令设置需要映射的容器端口。EXPOSE 指令可以一次设置多个端口号。
  2. 然后在运行容器的时使用 -p 选项加上 EXPOSE 所设置的端口。可以配套的多次使用 -p 选项。
# 映射一个端口
EXPOSE port1

# 相应的运行容器使用的命令 [主机端口:容器端口]
docker run -p host_port1:port1 image

这样 EXPOSE 设置的端口号会被随机映射成宿主机中的一个端口号了。当然,也可以指定需要映射到宿主机的具体端口号,这时首先就需要确保宿主机上的端口号没有被占用。

ENV(设置环境变量)

ENV <key> <value>

设置了环境变量之后,后续的 RUN 指令就都可以使用了,容器启动后,可以通过 docker inspect 指令查看这个环境变量,也可以通过指令 docker run --env key=value 设置或修改指定的环境变量。

ADD(设置从 HostSrc 复制文件到 ContainerDest)

注意,所有从宿主机拷贝到容器中的文件或目录的权限为均为 0755,uid 和 gid 为 0。

ADD <src> <dest>
  • src 的路径是 docker build 目录的相对路径,也可以是一个远程的文件 URL。
  • dest 是容器的绝对路径。
  • 如果 src 是文件且 dest 中不使用 “/” 斜杠结束,则会将 dest 也视为文件,src 的内容会写入 dest。
  • 如果 src 是文件且 dest 中使用 “/” 斜杠结束,则会将 src 文件拷贝到 dest 目录下。
  • 如果 src 是一个目录,那么会将该目录下的所有文件添加到 dest 中,不包括 src 目录本身。
  • 如果 src 是文件且是可识别的压缩格式,则进行解压缩(注意压缩格式)。

VOLUME(设置卷的挂载点)

设置卷的挂载点是为了让容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用。

容器本身使用的文件系统是 AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失,即:容器的无状态性,或者称之为不变性。

所以,当容器中的应用需要持久化数据时就可以使用 VOLUME 指令来挂载一个宿主机的目录到容器,使用宿主机的文件系统来进行持久化。

FROM base
VOLUME ["/tmp/data"]

WORKDIR(设置目录的切换)

相当于 cd 命令,可以多次切换,对 RUN、CMD、ENTRYPOINT 指令生效。

# 在 /p1/p2 下执行 vim a.txt
WORKDIR /p1 WORKDIR p2 RUN vim a.txt

猜你喜欢

转载自blog.csdn.net/Jmilk/article/details/108895101
今日推荐