Docker之Dockerfile用法

一、Dockerfile简介

Dockerfile用于自动化创建Docker镜像。 Docker通过阅读Dockerfile中的指令代码来构建镜像文件。

1、Dockerfile编写示例

# 基础镜像node:8.11-slim
FROM node:8.11-slim

#帮助信息了,类似于代码的注释信息
LABEL "about"="This file is just am example to demonstarte the LABEL"

#环境变量
ENV workdirectory /usr/node

#工作目录
WORKDIR $workdirectory
WORKDIR app

#复制文件
COPY package.json .

RUN ls -ll

# command executable and version
ENTRYPOINT ["node"]

2、Dockerfile编写思路

首先是,准备原镜像;

然后是,准备环境。比如需要的依赖文件、环境变量、工作目录、暴露的端口、用户等;

最后是,运行容器时执行的命令。

二、Dockerfile常用指令

1、FROM

FROM指令是构建镜像的初始阶段,它指明了基础镜像的来源,后续的操作都是基于该镜像。因此,有效的Dockerfile必须从FROM指令开始。

RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'

2、MAINTAINER(不推荐)

MAINTAINER指令设置生成图像的作者字段。

MAINTAINER <name>

不过,MAINTAINER并不推荐使用,更推荐使用LABEL来指定镜像作者,例如:

#示例:
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"

3、LABEL

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

Label 指令可以向镜像中添加元数据信息。 Label 以是键值对形式表示,中间用空格进行分隔。 若在 LABEL 值中包含空格,那么在命令行解析中使用引号和反斜杠。 示例如下:

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."

一个镜像中可以有多个标签。 也可以在一行中指定多个标签。

#一行中指定多个标签
LABEL multi.label1="value1" multi.label2="value2" other="value3"

LABEL multi.label1="value1" \
      multi.label2="value2" \
      other="value3"

4、RUN

执行命名并创建新的Image Layer。有以下两种格式:

  • shell 格式:
# <命令行命令> 等同于,在终端操作的 shell 命令。
RUN <command>
  • exec 格式:
RUN ["executable", "param1", "param2"]

RUN ["可执行文件", "参数1", "参数2"]

注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

FROM centos
RUN yum install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz
以上执行会创建 3 层镜像。可简化为以下格式:
FROM centos
RUN yum install wget \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && tar -xvf redis.tar.gz

如上,以 && 符号连接命令,这样执行后,只会创建 1 层镜像。

5、COPY

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",...  "<目标路径>"]

这个---- chown 特性只支持用于构建 Linux 容器的 Dockerfiles,不支持 Windows 容器。

6、ADD(不推荐)

ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

ADD [--chown=<user>:<group>] <源路径1>...  <目标路径>
ADD [--chown=<user>:<group>] ["<源路径1>",...  "<目标路径>"]
  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

7、ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

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

以下示例设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:

ENV NODE_VERSION 7.2.0

RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
  && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"

8、VOLUME

Volume 指令创建具有指定名称的挂载点,并将其标记为保存来自本机主机或其他容器的外部挂载的卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

作用:

  • 避免重要的数据,因容器重启而丢失,这是非常致命的。
  • 避免容器不断变大。

格式:

VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。

Dockerfile示例:

FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol

9、EXPOSE

Expose 指令通知 Docker 容器在运行时监听指定的网络端口。 您可以指定端口是否侦听 TCP 或 UDP,如果没有指定协议,则默认为 TCP。

EXPOSE <port> [<port>/<protocol>...]

默认情况下,EXPOSE 假设为 TCP。您也可以指定 UDP:

EXPOSE 80/udp

10、WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

WORKDIR <工作目录路径>

11、CMD

设置容器启动后默认执行的命令和参数,需要注意的是docker run指定了其他的命令,CMD命令将会被忽略。如果定义了多个CMD,只有最后一个会执行。

[root@xtank test]# docker build -t centos-run-shell .
Sending build context to Docker daemon  3.072kB
Step 1/3 : FROM centos
 ---> 470671670cac
Step 2/3 : ENV name Docker
 ---> Using cache
 ---> 09255c3a6fef
Step 3/3 : RUN echo "hello $name"
 ---> Running in 2b2494da2824
hello Docker
Removing intermediate container 2b2494da2824
 ---> 91fa3518d762
Successfully built 91fa3518d762
Successfully tagged centos-run-shell:latest

[root@xtank test]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos-run-shell    latest              91fa3518d762        5 seconds ago       237MB

[root@xtank test]# docker run 91fa3518d762
hello Docker

#docker run指定了其他的命令,CMD命令将会被忽略,没有再打印hello Docker
[root@xtank test]# docker run -it 91fa3518d762 /bin/bash
[root@10b796f0c34f /]# 

12、ENTRYPOINT

设置容器启动时运行的命令。让容器以应用程序或者服务的形式运行。它不会被忽略,一定会执行。

[root@xtank test]# docker build -t centos-shell .
Sending build context to Docker daemon  3.072kB
Step 1/3 : FROM centos
 ---> 470671670cac
Step 2/3 : ENV name Docker
 ---> Running in 33d9099aae96
Removing intermediate container 33d9099aae96
 ---> 09255c3a6fef
Step 3/3 : ENTRYPOINT echo "hello $name"
 ---> Running in 137f62845b79
Removing intermediate container 137f62845b79
 ---> a87036aba148
Successfully built a87036aba148
Successfully tagged centos-shell:latest

[root@xtank test]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos-shell        latest              a87036aba148        5 seconds ago       237MB

#设置容器启动时运行的命令,容器启动时会执行
[root@xtank test]# docker run a87036aba148
hello Docker

#设置容器启动时运行的命令,容器启动时一定会执行
[root@xtank test]# docker run -it a87036aba148 /bin/bash
hello Docker

注意:Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效。

三、参考

DockerFile示例:https://github.com/docker-library

DockerFile官方说明:https://docs.docker.com/engine/reference/builder/#from

菜鸟教程:https://www.runoob.com/docker/docker-dockerfile.html

posted @ 2020-05-24 20:35  xyztank  阅读(653)  评论(0编辑  收藏  举报