Dockerfile各命令详解。
Dockerfile命令解析
FROM 用于指定基准镜像,为后续的指令运行于基准镜像提供的运行环境。必须为Dockerfile文件开篇的第一个非注释行。
语法:
- FROM [:]
- FROM @ # :指定作为base image的名称,digest指定hash码
MAINTAINER 用于溯源,填入DockerFile维护者信息。
语法:
- MAINTAINER xxx
ARG 定义变量,此处填入应用名称。
语法:
- ARG APP_NAME=name
使用时需用 符 号 , 如 符号,如 符号,如APP_NAME
ENV 用于为镜像定义所需要的环境变量。
语法:
- ENV
一次只能设置一个变量,之后所有内容均会被视作其的组成部分
- ENV =…
一次可设置多个变量,每个变量为一个"="的键值对,如果中有空格,可以用反斜线\转义,也可用引号进行标识;另外,反斜线也可用于续行。当定义多个变量时,建议使用这种方式,以便在同一层中完成所有功能
- 该命令可被Dockerfile文件中位于其后的其它指令(如ADD、COPY等)所调用,调用格式为KaTeX parse error: Expected 'EOF', got '}' at position 14: variable_name}̲或variable_name
RUN 镜像构建的时候需要运行的命令,此处用于创建相关文件夹。
语法:
RUN
RUN [“”,“”,“”] #注意要使用双引号,单引号可能会出错
- 第一种格式,通常是一个shell命令,且以"/bin/sh -c"来运行它,当作shell子进程来运行,这意味此进程在容器的PID不为1,不能接收Unix信号,因此,当使用docker stop 命令停止容器时,此进程接收不到SIGTERM信号。
- 第二种中的参数是一个JSON格式的数组,其中为要运行命令,后面为传递给命令的选项或参数;然而,命令不会以"/bin/sh -c"来发起,也就是直接由内核来创建,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行; 不过,如果想使用shell来操作,可以使用以下格式:RUN [“/bin/bash”,“-c”,“”,“”]
COPY 从宿主机把文件复制到目标镜像中
语法:
- COPY …
- COPY [“”,…“”]
: 要复制的源文件或目录,支持使用通配符(一般是当前工作目录)
: 目标路径,即正在创建的image的文件系统路径,建议为使用绝对路径,否则以WORKDIR为其起始路径
注:在路径中有空白字符时,通常使用第二种格式文件复制准则
- 必须是build上下文中的路径,不能是其父目录的文件
- 如果是目录,目录自身不会被复制,其内部文件或子目录都会被复制。 (目录自身不会被复制,如cp -r tmp/* /tmp)
- 如果指定了多个,或在中使用了通配符,则必须是一个目录,且必须以/结尾,不加会报错
- 如果事先不存在,它将会自动创建
ADD 类似于COPY指令,ADD支持使用tar文件和URL路径。此处是将jar包封装进镜像。
语法:
ADD …
ADD [“”,…“”]
–src 表示指定源文件的路径, --dest 表示目标文件的路径。
- 为URL且不以/结尾,则指定的文件将被下载并被创建为;如果以/结尾,则URL指定的文件将被下载并保存到/目录下
- 是一个本地压缩格式tar文件,它将被展开为一个目录,类似于"tar -x"命令; 但是,通过URL获取的tar文件不会自动展开
- 有多个,或使用了通配符,则必须是一个以/结尾的目录路径,如果不以/结尾,则其被视作一个普通文件,的内容被直接写入到
WORKDIR 用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD指定设定工作目录
语法:
- WORKDIR
VOLUME 用于在image中创建一个挂载点目录,用来挂载Docker host上的卷或其它容器上的卷
语法:
VOLUME
VOLUME |‘’‘’
- 如果挂载点目录路径下此前在文件存在,docker run命令会在卷挂载完成后将此前所有文件复制到新挂载的卷中
卷有两种格式:绑定挂载卷和docker管理卷,dockerfile中只能用docker管理的卷,即指定容器中的路径,而不能指定宿主机的目录
EXPOSE 待暴露端口,用于为容器打开指定要监听的端口以实现与外部通信
语法:
- EXPOSE [/][[/]…]
- 用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议
- EXPOSE指令可一次指定多个端口,例如EXPOSE 112/udp 112/tcp
CMD 用于指定该容器启动的时候运行的命令,若有多个的情况则只有最后一个会生效且该命令可被替代。
语法:
- CMD
自动运行为shell子进程,最大的坏处是id不为1,无法使用docker stop去停止,因为它接收不到信号,接信号都是进程号为1的进程,因为它是一个超管进程,可以让它为1
- CMD [“”,“”,“”]
直接启动为用户id为1的进程,可以接收处理shell的信号
- CMD [“”,“”]
用于 ENTRYPOINT 指令提供默认参数
- 类似于RUN指令,CMD指令也可用于运行任何命令或应用程序。不过二者的运行时间点不同,RUN指令运行于映像文件构建过程中,而CMD指令运行基于Dockerfile构建出新映像文件启动一个容器时
- CMD指令的首要目的在于为启动容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过CMD指定的命令其可以被docker run的命令选项所覆盖
ENTRYPOINT 用于指定该容器启动的时候运行的命令,可追加命令,若有多个的情况则只有最后一个会生效。
语法:
ENTRYPOINT
ENTRYPOINT [“<executable”,“”,“”]
- ENTRYPOINT可以实现类似于CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序。与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖。并且这些命令行参数会被当参数传递给ENTRYPOINT指定的程序
- docker run命令中的 --entrypoint选项的参数 可覆盖ENTRYPOINT指令指定的程序
- docker run 命令传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令最后做为其参数使用
JAVA的Dockerfile模版
设置了动态变量:包名APP_NAME
和内存JAVA_OPTS
,可以在打包时用命令注入。
# java语言环境基础镜像
FROM openjdk:8u212-jre
# 维护者
MAINTAINER xxx
# 时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
#设置变量 JAVA_OPTS(填入内存)
ENV JAVA_OPTS=""
# 将jar包封装进镜像并添加日志
ARG APP_NAME=""
RUN mkdir /config
RUN mkdir /root/${APP_NAME}/
RUN mkdir /root/${APP_NAME}/logs
ADD wii-*-app/target/*.jar /${APP_NAME}/app.jar
ADD wii-*-app/src/main/resources/* /config/
VOLUME /logs/${APP_NAME}
ENTRYPOINT java -server ${JAVA_OPTS}-Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF-8 -jar ${APP_NAME}/app.jar
命令示例:
docker build -t app -f Dockerfile --build-arg JAVA_OPTS="-server -Xms512m -Xmx512m" --build-arg APP_NAME=app .
JVM常见参数(可以通过JAVA_OPTS设置)
-server:一定要作为第一个参数,在多个CPU时性能佳
-Xms:初始Heap大小,使用的最小内存,cpu性能高时此值应设的大一些
-Xmx:java heap最大值,使用的最大内存
-XX:PermSize:设定内存的永久保存区域
-XX:MaxPermSize:设定最大内存的永久保存区域
-XX:MaxNewSize:
+XX:AggressiveHeap 会使得 Xms没有意义。这个参数让jvm忽略Xmx参数,疯狂地吃完一个G物理内存,再吃尽一个G的swap。
-Xss:每个线程的Stack大小
-verbose:gc 现实垃圾收集信息
-Xloggc:gc.log 指定垃圾收集日志文件
-Xmn:young generation的heap大小,一般设置为Xmx的3、4分之一
-XX:+UseParNewGC :缩短minor收集的时间
-XX:+UseConcMarkSweepGC :缩短major收集的时间