【愚公系列】2022年01月 Docker容器 Dockerfile详解

2022-12-01 09:50:44 浏览数 (1)

文章目录

  • 前言
  • 一、Dockerfile的基本结构
  • 二、Dockerfile文件指令说明
    • 1.使用 Dockerfile 定制镜像
  • 三、其他命令详解
    • 1:ENV
    • 2:COPY
    • 3:ADD
    • 4:EXPOSE
    • 5:USER
    • 6:WORKDIR
    • 7:RUN
      • 7.1 shell执行
      • 7.2 exec执行
    • 8:CMD
    • 9:ENTRYPOINT
  • 总结

前言

Dockerfile是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker通过读取Dockerfile中的指令自动生成映像。

docker build命令用于从Dockerfile构建映像。可以在docker build命令中使用-f标志指向文件系统中任何位置的Dockerfile。

例:

代码语言:javascript复制
docker build -f /path/to/a/Dockerfile

一、Dockerfile的基本结构

Docker以从上到下的顺序运行Dockerfile的指令。为了指定基本映像,第一条指令必须是FROM。一个声明以#字符开头则被视为注释。可以在Docker文件中使用RUN,CMD,FROM,EXPOSE,ENV等指令。

二、Dockerfile文件指令说明

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

1.使用 Dockerfile 定制镜像

1、下面以定制一个 nginx 镜像(构建好的镜像内会有一个 /usr/share/nginx/html/index.html 文件)

在一个空目录下,新建一个名为 Dockerfile 文件,并在文件内添加以下内容:

代码语言:javascript复制
FROM nginx
RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html

2、FROM 和 RUN 指令的作用

FROM:定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。 RUN:用于执行后面跟着的命令行命令。有以下俩种格式: shell 格式:

代码语言:javascript复制
RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。

exec 格式:

代码语言:javascript复制
RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

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

代码语言:javascript复制
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 层镜像。可简化为以下格式:

代码语言:javascript复制
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 层镜像。

开始构建镜像 在 Dockerfile 文件的存放目录下,执行构建动作。

以下示例,通过目录下的 Dockerfile 构建一个 nginx:v3(镜像名称:镜像标签)。

代码语言:javascript复制
$ docker build -t nginx:v3 .

三、其他命令详解

1:ENV

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

格式:

代码语言:javascript复制
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

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

代码语言:javascript复制
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"

2:COPY

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

格式:

代码语言:javascript复制
COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",...  "<目标路径>"]

[–chown=:]:可选参数,用户改变复制到容器内文件的拥有者和属组。

<源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:

代码语言:javascript复制
COPY hom* /mydir/
COPY hom?.txt /mydir/

<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

3:ADD

格式:ADD

代码语言:javascript复制
ADD <src>... <dest>
ADD ["<src>",... "<dest>"] 用于支持包含空格的路径

示例:

代码语言:javascript复制
ADD hom* /mydir/          # 添加所有以"hom"开头的文件
ADD hom?.txt /mydir/      # ? 替代一个单字符,例如:"home.txt"
ADD test relativeDir/     # 添加 "test" 到 `WORKDIR`/relativeDir/
ADD test /absoluteDir/    # 添加 "test" 到 /absoluteDir/

4:EXPOSE

格式:

代码语言:javascript复制
EXPOSE <port> [<port>...]

示例:

代码语言:javascript复制
EXPOSE 80 443
EXPOSE 8080    
EXPOSE 11211/tcp 11211/udp

注:EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口

5:USER

格式:

代码语言:javascript复制
USER user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER uid:group

示例:

代码语言:javascript复制
USER www

注:使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。

6:WORKDIR

格式:

代码语言:javascript复制
WORKDIR /path/to/workdir

示例:

代码语言:javascript复制
WORKDIR /a  (这时工作目录为/a)
WORKDIR b  (这时工作目录为/a/b)
WORKDIR c  (这时工作目录为/a/b/c)

注:通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。

7:RUN

RUN用于在镜像容器中执行命令,其有以下两种命令执行方式:

7.1 shell执行

格式:

代码语言:javascript复制
RUN <command>

7.2 exec执行

格式:

代码语言:javascript复制
RUN ["executable", "param1", "param2"]

示例:

代码语言:javascript复制
 RUN ["executable", "param1", "param2"]
 RUN apk update
 RUN ["/etc/execfile", "arg1", "arg1"]

注:RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定–no-cache参数,如:docker build --no-cache

8:CMD

格式:

代码语言:javascript复制
CMD ["executable","param1","param2"] (执行可执行文件,优先)
CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
CMD command param1 param2 (执行shell内部命令)

示例:

代码语言:javascript复制
CMD echo "This is a test." | wc -
CMD ["/usr/bin/wc","--help"]

注:CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。

9:ENTRYPOINT

格式:

代码语言:javascript复制
ENTRYPOINT ["executable", "param1", "param2"] (可执行文件, 优先)
ENTRYPOINT command param1 param2 (shell内部命令)

示例:

代码语言:javascript复制
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]

注:ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。

总结

关键字

作用

FROM

指定基础镜像

MAINTAINER

作者的信息

RUN

执行什么命令

EXPOSE

容器对外暴露的端口

WORKDIR

进入到容器后进入到哪个目录

ENV

配置环境变量

ADD

将文件拷贝到镜像中并解压

COPY

将文件拷贝到镜像中

VOLUME

配置数据卷

CMD

容器启动时候执行的命令

ENTRYPOINT

容器启动时候执行的命令

0 人点赞