EP7 Dockerfile

104 阅读7分钟

EP7 Dockfile

介绍

Dockerfile是由一系列命令和参数构成的脚本,一个Dockerfile里面包含了构建整个image的完整命令。Docker通过docker [image] build执行Dockerfile中的一系列命令自动构建image。

官方详细文档

Dockerfile格式

Dockerfile由多条指令组成,image builder时顺序执行各个指令,每条指令在编译镜像时执行相应的程序完成某些功能,由指令+参数组成,以逗号分隔,#作为注释起始符,虽说指令不区分大小写,但是一般指令使用大写,参数使用小写。

Dockerfile组成部分

组成部分命令
基础镜像信息FROM
维护者信息MAINTAINER
镜像操作指令RUN、COPY、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等
容器启动时执行指令CMD、ENTRYPOINT

Dockerfile常用命令

image.png image.png

FROM

构建的镜像设置基础镜像
格式:

FROM <image> [AS <name>]
FROM <image>[:<tag>] [AS <name>]
FROM <image>[@<digest>] [AS <name>]

示例:

FROM openjdk:8-jdk-alpine

说明

FROM指令初始化新的构建阶段,并为后续指令设置基础镜像,因此,Dockerfile文件必须以FROM指令开头。 而指定的镜像可以使任何有效的镜像(推荐使用公共仓库的镜像,因为拉取更为容易)。

注1:在Dockerfile文件中ARG是唯一一个可以用于FROM之前的指令。 注2:tag和digest是可选的,如果不提供则使用latest。

MAINTAINER(已废弃)

作者信息

格式:

MAINTAINER <name>

该指令已经废弃,可以使用新指令LABEL

LABEL

为镜像添加元数据

格式:

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

示例:

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

ARG

指定用户在docker build --build-arg =时可以使用的参数。

格式:

ARG <name>[=<default value>]

示例:

ARG SITE
ARG BUILD_USER=www

说明 构建参数在定义的时候生效而不是在使用的时候。如下面第三行开始的GENE_VERSION才是用户构建参数传递过来的GENE_VERSION

FROM centos:7.9
# 此处获取不到用户传来的user
RUN wget http://xxx.xxx.xxx/gene-server-${GENE_VERSION}.jar
ARG GENE_VERSION

可以使用ARG或ENV指令指定RUN指令可用的变量。使用ENV指令定义的环境变量始终覆盖同名的ARG指令。

FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER v1.0.0
# 始终是v1.0.0
RUN echo $CONT_IMG_VER 

ENV

设置环境变量

格式:

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

示例:

ENV MODE="cluster" \
    PREFER_HOST_MODE="ip"\
    BASE_DIR="/home/nacos" \
    CLASSPATH=".:/home/nacos/conf:$CLASSPATH" \
    CLUSTER_CONF="/home/nacos/conf/cluster.conf" \
    FUNCTION_MODE="all" \
    JAVA_HOME="/usr/lib/jvm/java-1.8.0-openjdk" \
    NACOS_USER="nacos" \
    JAVA="/usr/lib/jvm/java-1.8.0-openjdk/bin/java" \
    JVM_XMS="1g" \
    JVM_XMX="1g" \
    JVM_XMN="512m" \
    JVM_MS="128m" \
    JVM_MMS="320m" \
    NACOS_DEBUG="n" \
    TOMCAT_ACCESSLOG_ENABLED="false" \
    TIME_ZONE="Asia/Shanghai"

说明 在构建的镜像中设置环境变量,在后续的Dockerfile指令中可以直接使用,也可以固化在镜像里,在容器运行时仍然有效。 如果value中存在空格,需要转义(\)或用引号("")括起来

可以在容器运行时指定环境变量,替换镜像中的已有变量,docker run --env =。

RUN

构建镜像时执行的命令

格式:

RUN <command>  #shell形式
RUN ["executable", "param1", "param2"]

示例:

RUN set -x \
    && yum update -y \
    && yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel wget iputils nc  vim libcurl

说明 RUN有两种执行方式:

  • shell形式: 命令在 shell 中运行,/bin/sh -c <command>(Linux) 或cmd /S /C <command> (Windows)
  • exec形式:exec形式将直接执行命令,可以避免shell字符串修改或所在容器没有sh命令的情况.

ADD

构建镜像时,复制上下文中的文件到镜像内。

格式:

ADD <src>... <dest>
ADD ["<src>",... "<dest>"] 用于支持包含空格的路径

示例:

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

说明 将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget. <src>可以是文件、目录,也可以是文件URL。可以使用模糊匹配(wildcards,类似shell的匹配),可以指定多个<src>,必须是在上下文目录和子目录中, 无法添加../a.txt这样的文件。如果<src>是个目录,则复制的是目录下的所有内容,但不包括该目录。如果<src>是个可被docker识别的压缩包, docker会以tar -x的方式解压后将内容复制到<desct><dest>可以是绝对路径,也可以是相对WORKDIR目录的相对路径。

COPY

功能类似ADD,但是是不会自动解压文件,也不能访问网络资源

格式:

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

注意:需要复制的目录一定要放在Dockerfile文件的同级目录下。因为构建环境将会上传到Docker守护进程,而复制是在Docker守护进程中进行的。任何位于构建环境之外的东西都是不可用的。COPY指令的目的的位置则必须是容器内部的一个绝对路径。

WORKDIR

工作目录,类似于cd命令

格式:

WORKDIR /path/to/workdir

示例:

WORKDIR /a
WORKDIR b
WORKDIR c

说明

为接下来的Dockerfile指令指定当前工作目录,受影响的指令有:RUN、CMD、ENTRYPOINT、COPY和ADD,可多次使用,如果使用的是相对路径,则相对的是上一个工作目录,类似shell中的cd命令。

VOLUME

指定镜像内的目录为数据卷。

格式:

VOLUME ["/data"]

示例:

VOLUME ["/data"]
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"

说明

创建容器卷

EXPOSE

指定于外界交互的端口

格式:

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

示例:

EXPOSE 80 443
EXPOSE 8080    
EXPOSE 11211/tcp 11211/udp

说明

EXPOSE指令让docker容器在运行的时候监听指定的端口,可以指定端口是upd还是tcp协议,如果没有指定则默认tcp协议。 EXPOSE指令并不会发布端口,如果发布端口,则需要在docker run时使用-p来发布和映射一个或多个容器端口、或者使用-P来发布所有公开的端口并将它们映射到高阶端口。

CMD

设置容器的启动命令

格式:

CMD ["executable","param1","param2"] (exec格式,首选)
CMD ["param1","param2"] (如果设置了ENTRYPOINT,则给ENTRYPOINT提供默认参数)
CMD command param1 param2 (执行shell内部命令)

示例:

CMD echo "This is a test." | wc -l
CMD ["/usr/bin/wc","--help"]

说明

构建镜像后调用,也就是在容器启动时才进行调用。 Dockerfile中只能有一条CMD命令,如果写了多条则最后一条生效。

注意:命令行参数可以覆盖 CMD 指令的设置,但是只能是重写,却不能给 CMD 中的命令通过命令行传递参数。 一般的镜像都会提供容器启动时的默认命令,但是有些场景中用户并不想执行默认的命令。用户可以通过命令行参数的方式覆盖 CMD 指令提供的默认命令。比如通过下面命令创建的镜像:

FROM ubuntu
CMD [ "top" ]

在启动容器时我们通过命令行指定参数 ps aux 覆盖默认的 top 命令: docker run test ps -ef此时容器启动后只会执行ps -ef命令而不是 top命令

ENTRYPOINT

为容器指定默认执行的任务。

格式:

ENTRYPOINT ["executable", "param1", "param2"] (exec模式, 首选)
ENTRYPOINT command param1 param2 (shell内部命令)

示例:

ENTRYPOINT [ "top", "-b" ]

说明

CMD和ENTRYPOINT至少得使用一个。ENTRYPOINT应该被当做docker的可执行程序,CMD应该被当做ENTRYPOINT的默认参数。 docker run ...会把之后的参数传递给ENTRYPOINT,覆盖CMD指定的参数。可以用docker run --entrypoint 来重置默认的ENTRYPOINT。

Build

写好了Dockerfile文件,就可以通过docker build命令制作镜像了。 命令:

docker build -t <imageName:tag> <DockerfilePath>

自定义构建nginx

官方的centos镜像是没有vim命令的

root@84729f35fe1b:/# top
bash: vim: command not found

我们自定义构建一个centos默认安装上vim命令 编写Dockerfile

FROM centos:7.9.2009
LABEL MAINTAINER="chenrui"
RUN yum update -y && yum install -y vim
WORKDIR /root
CMD ["/bin/bash"]

构建镜像

% docker build -t cy_centos .
[+] Building 236.7s (7/7) FINISHED
 => [internal] load build definition from Dockerfile                                                                                                                                                                                  0.0s
 => => transferring dockerfile: 162B                                                                                                                                                                                                  0.0s
 => [internal] load .dockerignore                                                                                                                                                                                                     0.0s
 => => transferring context: 2B                                                                                                                                                                                                       0.0s
 => [internal] load metadata for docker.io/library/centos:7.9.2009                                                                                                                                                                    0.0s
 => [1/3] FROM docker.io/library/centos:7.9.2009                                                                                                                                                                                      0.0s
 => [2/3] RUN yum update -y && yum install -y vim                                                                                                                                                                                   233.0s
 => [3/3] WORKDIR /root                                                                                                                                                                                                               0.0s
 => exporting to image                                                                                                                                                                                                                3.4s
 => => exporting layers                                                                                                                                                                                                               3.4s
 => => writing image sha256:30fabe27b3569652c02d99bdf0d66e69edd67d74efdb0c95a0a0c07a63468d62                                                                                                                                          0.0s
 => => naming to docker.io/library/cy_centos

image.png 运行并进入容器,执行vim命令可以看到vim已经安装到centos中了.

% docker run -it cy_centos
[root@a47ab9ad1a87 ~]# vim sss
[root@a47ab9ad1a87 ~]#