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常用命令
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
运行并进入容器,执行vim命令可以看到vim已经安装到centos中了.
% docker run -it cy_centos
[root@a47ab9ad1a87 ~]# vim sss
[root@a47ab9ad1a87 ~]#