是什么
Dockerfile是用来构建Docker镜像的构建文件,由一系列命令和参数构成的脚本。
Centos:
https://hub.docker.com/_/centos
scratch是所有镜像的祖先,类似于 java的Object
FROM scratch ADD centos-8-x86_64.tar.xz / LABEL org.label-schema.schema-version="1.0" org.label-schema.name="CentOS Base Image" org.label-schema.vendor="CentOS" org.label-schema.license="GPLv2" org.label-schema.build-date="20200809" CMD ["/bin/bash"]
tomcat:
https://hub.docker.com/_/tomcat
FROM openjdk:8-jdk-buster ENV CATALINA_HOME /usr/local/tomcat ENV PATH $CATALINA_HOME/bin:$PATH RUN mkdir -p "$CATALINA_HOME" WORKDIR $CATALINA_HOME # let "Tomcat Native" live somewhere isolated ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR
...此处省略中间代码
RUN set -eux; savedAptMark="$(apt-mark showmanual)"; apt-get update; apt-get install -y --no-install-recommends gnupg dirmngr wget ca-certificates ; ... ...此处省略中间代码 ... EXPOSE 8080 CMD ["catalina.sh", "run"]
DockerFile构建过程解析
Dockerfile内容基础知识
- 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
- 指令按照从上到下,顺序执行
- #表示注释
- 每条指令都会创建一个新的镜像层,并对镜像进行提交
- docker从基础镜像运行一个容器
- 执行一条指令并对容器作出修改
- 执行类似docker commit的操作提交一个新的镜像层
- docker再基于刚提交的镜像运行一个新容器
- 执行dockerfile中的下一条指令直到所有指令都执行完成
小总结:
从应用软件的角度来看,Dockerfile、 Docker镜像与Docker容器分别代表软件的三个不同阶段:
- Dockerfile是软件的原材料、制作步骤
- Docker镜像是软件的交付品
- Docker容器则可以认为是软件的运行态
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
保留字指令
FROM 基础镜像,当前新镜像是基于哪个镜像的
MAINTAINER 镜像维护者的姓名和邮箱地址
RUN 容器构建时需要运行的命令
EXPOSE 当前容器对外暴露出的端口
WORKDIR 指定在创建容器后,终端默认登陆进来的工作目录,一个落脚点
ENV 用来在构建过程中设置环境变量 // 查下作用范围
ADD 将宿主机目录下的文件拷贝进镜像,且ADD命令会自动处理URL和解压tar压缩包
COPY 类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中<源路径>的文件/目录复制到新的一层镜像内的<目标路径>位置
COPY src dest COPY ["src" "dest"]
VOLUME 容器数据卷,用于数据保存和持久化工作
CMD 它主要作用是默认的容器启动执行命令 Dockerfile中可以有多个CMD指令,但只有最后一个生效,如果我们在docker run时指定了命令或者Dockerfile中有ENTRYPOINT,那么CMD就会被覆盖。 CMD 指令的三种用法: shell格式: CMD <命令> 参数1 参数2 如:CMD echo "hello cmd!" 命令command默认是在"/bin/sh -c"下执行 exec格式: CMD ["可执行文件", "参数1", "参数2" ...] 如:CMD ["/bin/bash", "-c", "echo 'hello cmd!'"] // 官网推荐写法
参数列表格式: CMD ["参数1", "参数2" ...],在指定了ENTRYPOINT指令后,用CMD指定具体的参数。
ENTRYPOINT 指定一个容器启动时要运行的命令,ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数。
ENTRYPOINT才是正统地用于定义容器启动以后的执行体的,其实我们从名字也可以理解,这个是容器的“入口”。
ENTRYPOINT两种用法:
shell格式: ENTRYPOINT ["executable", "param1", "param2"] // 官网推荐写法
如:CMD ["p in cmd"]
ENTRYPOINT ["echo"]
exec格式:ENTRYPOINT command param1 param2 // 在这种模式下,任何run和cmd的参数都无法被传入到entrypoint里
如:CMD ["p in cmd"]
ENTRYPOINT echo
如果docker run命令后面有东西,那么后面的全部都会作为entrypoint的参数。如果run后面没有额外的东西,但是cmd有,那么cmd的全部内容会作为entrypoint的参数,这同时是cmd的第二种用法。
这也是网上说的entrypoint不会被覆盖。当然如果要在docker run里面覆盖,也是有办法的,使用--entrypoint即可。
具体区别可参考: CMD与ENTRYPOINT的区别
CMD 命令可以被替代;ENTRYPOINT 可以追加命令
总结下一般该怎么使用:
一般还是会用ENTRYPOINT的中括号形式作为docker容器启动以后的默认执行命令,里面放的是不变的部分,可变部分比如命令参数可以使用CMD的形式提供默认版本,也就是docker run里面没有任何参数时使用的默认参数。
如果我们想用默认参数,就直接run,否则想用其他参数,就run里面加参数。
ONBUILD 当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的ONBUILD被触发