liwya 发表于 2019-2-21 07:17:21

docker之Dockerfile

Dockerfile 简介
  从之前 docker commit 的学习中,我们可以了解到,镜像的定制实际上就是定制每一层所
添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚
本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。
  Dockerfile是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。它们简化了从头到尾的流程并极大的简化了部署工作。Dockerfile从FROM命令开始,紧接着跟随者各种方法,命令和参数。其产出为一个新的可以用于创建容器的镜像。

Dockerfile 语法
  Dockerfile 语法示例
Dockerfile语法由两部分构成,注释和命令+参数,一个简单的例子:

# Print "Hello docker!"
RUN echo "Hello docker!"
Dockerfile 命令
http://i2.运维网.com/images/blog/201809/12/55f25f014443d7c9fd710b6f10444b37.png
FROM

  FROM命令可能是最重要的Dockerfile命令。改命令定义了使用哪个基础镜像启动构建流程。基础镜像可以为任意镜像。如果基础镜像没有被发现,Docker将试图从Docker image index来查找该镜像。FROM命令必须是Dockerfile的首个命令。


# Usage: FROM
FROM ubuntu
  注:FROM scratch
这是Docker 种存在的特殊镜像 。这个镜像是虚拟的概念并不实际存在,表示一个空白的镜像。对于 Linux 下静态编译的程序,并不需要有操作系统提供运行支持,所需的一切库都已经在可执行文件里了,因此 FROM scratch 会让镜像体积更加小巧。
  RUN 执行命令

  RUN命令是Dockerfile执行命令的核心部分。它接受命令作为参数并用于创建镜像。不像CMD命令,RUN命令用于创建镜像(在之前commit的层之上形成新的层)。其格式有两种:

  shell 格式: RUN,就像直接在命令行中输入的命令一样。

RUN echo 'Hello, Docker!' > /usr/share/nginx/html/index.html
  exec 格式:
RUN ["可执行文件", "参数1", "参数2"] ,这更像是函数调用中的格式。
  Dockerfile 中每一个指令都会建立一层, RUN 也不例外。每一个 RUN 的行为,就和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束后, commit 这一层的修改,构成新的镜像。

FROM debian:jessie
RUN apt-get update
RUN apt-get install -y gcc libc6-dev make
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz"
RUN mkdir -p /usr/src/redis
RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
RUN make -C /usr/src/redis
RUN make -C /usr/src/redis install
  上面的这种写法,创建了 7 层镜像,这是完全没有意义的。结果就是产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过127 层
  上面的 Dockerfile 正确的写法应该是这样:

FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps

[*]之前所有的命令只有一个目的,就是编译、安装 redis 可执行文件。这里仅仅使用一个 RUN 指令,并使用 && 将各个所需命令串联起来。将其简化为了1 层。
[*]Dockerfile 支持 行尾添加 \ 的命令换行,以及行首 # 进行注释的格式。
[*]最后清理了所有下载、展开的文件,并且还清理了 apt 缓存文件。镜像是多层存储,每一层的东西并不会在下一层被删除,因此镜像构建时,任何无关的东西都应该清理掉。
  ADD
ADD命令有两个参数,源和目标。它的基本作用是从源系统的文件系统上复制文件到目标容器的文件系统。如果源是一个URL,那该URL的内容将被下载并复制到容器中。

# Usage: ADD
ADD /my_app_folder /my_app_folder
  CMD
和RUN命令相似,CMD可以用于执行特定的命令。和RUN不同的是,这些命令不是在镜像构建的过程中执行的,而是在用镜像构建容器后被调用。

# Usage 1: CMD application "argument", "argument", ..
CMD "echo" "Hello docker!"
  ENTRYPOINT
配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。
  每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效。
  ENTRYPOINT 帮助你配置一个容器使之可执行化,如果你结合CMD命令和ENTRYPOINT命令,你可以从CMD命令中移除“application”而仅仅保留参数,参数将传递给ENTRYPOINT命令。

# Usage: ENTRYPOINT application "argument", "argument", ..
# Remember: arguments are optional. They can be provided by CMD
# or during the creation of a container.
ENTRYPOINT echo
# Usage example with CMD:
# Arguments set with CMD can be overridden during *run*
CMD "Hello docker!"
ENTRYPOINT echo
  ENV
ENV命令用于设置环境变量。这些变量以”key=value”的形式存在,并可以在容器内被脚本或者程序调用。这个机制给在容器中运行应用带来了极大的便利。

# Usage: ENV key value
ENV SERVER_WORKS 4
  EXPOSE
EXPOSE用来指定端口,使容器内的应用可以通过端口和外界交互。

# Usage: EXPOSE
EXPOSE 8080
  MAINTAINER
我建议这个命令放在Dockerfile的起始部分,虽然理论上它可以放置于Dockerfile的任意位置。这个命令用于声明作者,并应该放在FROM的后面。

# Usage: MAINTAINER
MAINTAINER authors_name
  USER
USER命令用于设置运行容器的UID。

# Usage: USER
USER 751
  VOLUME
VOLUME命令用于让你的容器访问宿主机上的目录。

# Usage: VOLUME ["/dir_1", "/dir_2" ..]
VOLUME ["/my_files"]
  WORKDIR
WORKDIR命令用于设置CMD指明的命令的运行目录。

# Usage: WORKDIR /path
WORKDIR ~/


页: [1]
查看完整版本: docker之Dockerfile