是什么

DockerFile 是用来构建Docker 镜像的文本文件,是由一条条 构建镜像所需的指令和参数构成的脚本

概述

10、DockerFile解析 - 图2

官网

https://docs.docker.com/engine/reference/builder/

构建三步骤

编写DockerFile 文件

docker build 命令构建镜像

docker run 依镜像运行容器实例

DockerFile构建过程解析

DockerFile内容基础知识

  1. 每条保留字指令都必须大写字母且后面要跟随至少一个参数
  2. 指令按照从上到下,顺序执行
  3. 表示注释

  4. 每条指令都会创建一个新的镜像层并对镜像进行提交

Docker执行DockerFile的大致流程

1)docker从基础镜像运行一个容器

2)执行一条指令并对容器作出修改

3)执行类似docker commit 的操作提交一个新的镜像层

4)docker 再基于刚提交的镜像运行一个新容器

5)执行dockerfile 中的下一条指令直到所有指令都执行完成

小总结

从应用软件的角度来看,Dockerfie、Docker镜像与Docker容器分别代表软件的三个不同阶段,
Dockerfile是软件的原材料
Docker镜像是软件的交
* Docker容器则可以认为是软件镜像的运行态,也即依照镜像运行的容器实例
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

image.png

DockerFile 常用保留字指令

参考tomcat8 的dockerfile 入门

https://registry.hub.docker.com/_/tomcat

tomcat 的dockerfile 文件链接:https://github.com/docker-library/docs/tree/master/tomcat/README.md#supported-tags-and-respective-dockerfile-links

  1. #
  2. # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
  3. #
  4. # PLEASE DO NOT EDIT IT DIRECTLY.
  5. #
  6. FROM amazoncorretto:8
  7. ENV CATALINA_HOME /usr/local/tomcat
  8. ENV PATH $CATALINA_HOME/bin:$PATH
  9. RUN mkdir -p "$CATALINA_HOME"
  10. WORKDIR $CATALINA_HOME
  11. # let "Tomcat Native" live somewhere isolated
  12. ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib
  13. ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR
  14. # see https://www.apache.org/dist/tomcat/tomcat-10/KEYS
  15. # see also "versions.sh" (https://github.com/docker-library/tomcat/blob/master/versions.sh)
  16. ENV GPG_KEYS A9C5DF4D22E99998D9875A5110C01C5A2F6059E7
  17. ENV TOMCAT_MAJOR 10
  18. ENV TOMCAT_VERSION 10.0.14
  19. ENV TOMCAT_SHA512 c2d2ad5ed17f7284e3aac5415774a8ef35434f14dbd9a87bc7230d8bfdbe9aa1258b97a59fa5c4030e4c973e4d93d29d20e40b6254347dbb66fae269ff4a61a5
  20. RUN set -eux; \
  21. \
  22. # http://yum.baseurl.org/wiki/YumDB.html
  23. if ! command -v yumdb > /dev/null; then \
  24. yum install -y yum-utils; \
  25. yumdb set reason dep yum-utils; \
  26. fi; \
  27. # a helper function to "yum install" things, but only if they aren't installed (and to set their "reason" to "dep" so "yum autoremove" can purge them for us)
  28. _yum_install_temporary() { ( set -eu +x; \
  29. local pkg todo=''; \
  30. for pkg; do \
  31. if ! rpm --query "$pkg" > /dev/null 2>&1; then \
  32. todo="$todo $pkg"; \
  33. fi; \
  34. done; \
  35. if [ -n "$todo" ]; then \
  36. set -x; \
  37. yum install -y $todo; \
  38. yumdb set reason dep $todo; \
  39. fi; \
  40. ) }; \
  41. _yum_install_temporary gzip tar; \
  42. \
  43. ddist() { \
  44. local f="$1"; shift; \
  45. local distFile="$1"; shift; \
  46. local mvnFile="${1:-}"; \
  47. local success=; \
  48. local distUrl=; \
  49. for distUrl in \
  50. # https://issues.apache.org/jira/browse/INFRA-8753?focusedCommentId=14735394#comment-14735394
  51. "https://www.apache.org/dyn/closer.cgi?action=download&filename=$distFile" \
  52. # if the version is outdated (or we're grabbing the .asc file), we might have to pull from the dist/archive :/
  53. "https://downloads.apache.org/$distFile" \
  54. "https://www-us.apache.org/dist/$distFile" \
  55. "https://www.apache.org/dist/$distFile" \
  56. "https://archive.apache.org/dist/$distFile" \
  57. # if all else fails, let's try Maven (https://www.mail-archive.com/users@tomcat.apache.org/msg134940.html; https://mvnrepository.com/artifact/org.apache.tomcat/tomcat; https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/)
  58. ${mvnFile:+"https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/$mvnFile"} \
  59. ; do \
  60. if curl -fL -o "$f" "$distUrl" && [ -s "$f" ]; then \
  61. success=1; \
  62. break; \
  63. fi; \
  64. done; \
  65. [ -n "$success" ]; \
  66. }; \
  67. \
  68. ddist 'tomcat.tar.gz' "tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz" "$TOMCAT_VERSION/tomcat-$TOMCAT_VERSION.tar.gz"; \
  69. echo "$TOMCAT_SHA512 *tomcat.tar.gz" | sha512sum --strict --check -; \
  70. ddist 'tomcat.tar.gz.asc' "tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz.asc" "$TOMCAT_VERSION/tomcat-$TOMCAT_VERSION.tar.gz.asc"; \
  71. export GNUPGHOME="$(mktemp -d)"; \
  72. for key in $GPG_KEYS; do \
  73. gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
  74. done; \
  75. gpg --batch --verify tomcat.tar.gz.asc tomcat.tar.gz; \
  76. tar -xf tomcat.tar.gz --strip-components=1; \
  77. rm bin/*.bat; \
  78. rm tomcat.tar.gz*; \
  79. command -v gpgconf && gpgconf --kill all || :; \
  80. rm -rf "$GNUPGHOME"; \
  81. \
  82. # https://tomcat.apache.org/tomcat-9.0-doc/security-howto.html#Default_web_applications
  83. mv webapps webapps.dist; \
  84. mkdir webapps; \
  85. # we don't delete them completely because they're frankly a pain to get back for users who do want them, and they're generally tiny (~7MB)
  86. \
  87. nativeBuildDir="$(mktemp -d)"; \
  88. tar -xf bin/tomcat-native.tar.gz -C "$nativeBuildDir" --strip-components=1; \
  89. _yum_install_temporary \
  90. apr-devel \
  91. gcc \
  92. make \
  93. openssl11-devel \
  94. ; \
  95. ( \
  96. export CATALINA_HOME="$PWD"; \
  97. cd "$nativeBuildDir/native"; \
  98. aprConfig="$(command -v apr-1-config)"; \
  99. ./configure \
  100. --libdir="$TOMCAT_NATIVE_LIBDIR" \
  101. --prefix="$CATALINA_HOME" \
  102. --with-apr="$aprConfig" \
  103. --with-java-home="$JAVA_HOME" \
  104. --with-ssl=yes \
  105. ; \
  106. nproc="$(nproc)"; \
  107. make -j "$nproc"; \
  108. make install; \
  109. ); \
  110. rm -rf "$nativeBuildDir"; \
  111. rm bin/tomcat-native.tar.gz; \
  112. \
  113. # mark any explicit dependencies as manually installed
  114. find "$TOMCAT_NATIVE_LIBDIR" -type f -executable -exec ldd '{}' ';' \
  115. | awk '/=>/ && $(NF-1) != "=>" { print $(NF-1) }' \
  116. | xargs -rt readlink -e \
  117. | sort -u \
  118. | xargs -rt rpm --query --whatprovides \
  119. | sort -u \
  120. | tee "$TOMCAT_NATIVE_LIBDIR/.dependencies.txt" \
  121. | xargs -r yumdb set reason user \
  122. ; \
  123. \
  124. # clean up anything added temporarily and not later marked as necessary
  125. yum autoremove -y; \
  126. yum clean all; \
  127. rm -rf /var/cache/yum; \
  128. \
  129. # sh removes env vars it doesn't support (ones with periods)
  130. # https://github.com/docker-library/tomcat/issues/77
  131. find ./bin/ -name '*.sh' -exec sed -ri 's|^#!/bin/sh$|#!/usr/bin/env bash|' '{}' +; \
  132. \
  133. # fix permissions (especially for running as non-root)
  134. # https://github.com/docker-library/tomcat/issues/35
  135. chmod -R +rX .; \
  136. chmod 777 logs temp work; \
  137. \
  138. # smoke test
  139. catalina.sh version
  140. # verify Tomcat Native is working properly
  141. RUN set -eux; \
  142. nativeLines="$(catalina.sh configtest 2>&1)"; \
  143. nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')"; \
  144. nativeLines="$(echo "$nativeLines" | sort -u)"; \
  145. if ! echo "$nativeLines" | grep -E 'INFO: Loaded( APR based)? Apache Tomcat Native library' >&2; then \
  146. echo >&2 "$nativeLines"; \
  147. exit 1; \
  148. fi
  149. EXPOSE 8080
  150. CMD ["catalina.sh", "run"]

FROM: 基础镜像,当前新镜像是基于那个镜像,指定一个已经存在的镜像作为模版,第一条必须是from

FROM [—platform=] 10、DockerFile解析 - 图4 [AS ]
Or
FROM [—platform=] 10、DockerFile解析 - 图5[:] [AS ]
Or
FROM [—platform=] 10、DockerFile解析 - 图6[@] [AS ]

MAINTAINER(官网已弃用): 镜像维护者的姓名和邮箱地址

MAINTAINER

RUN:容器构建时需要运行的命令

shell格式

RUN : RUN 后面直接跟命令
例:RUN yum -y install vim

exec格式

RUN [“executable”, “param1”, “param2”]
例:RUN [“/bin/bash”, “-c”, “echo hello”] == RUN /bin/bash -c echo hello

RUN是在docker build时运行

EXPOSE [/…]
例: EXPOSE 80/udp

EXPOSE: 当前容器对外暴露出的端口

WORKDIR:指定在容器后,终端默认登陆的进来工作目录,一个落脚点

WORKDIR /path/to/workdir
例:WORKDIR /a

USER:指定该镜像以什么用户去执行,如果都不指定,默认是root

USER [:]
or
USER [:]

ENV: 用来在构建镜像过程中设置环境变量

ENV =
例:ENV MY_NAME=”John Doe”
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy

可以在后续命令中使用,$变量名,获取变量信息,$MY_CAT

ADD:将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包

COPY:拷贝文件和目录到镜像中

COPY [—chown=:]
COPY [—chown=:] [““,… ““]

VOLUME:容器数据卷,用于数据保存和持久化工作

VOLUME [“/data”]
例:FROM ubuntu
RUN mkdir /myvol
RUN echo “hello world” > /myvol/greeting
VOLUME /myvol

CMD:指定容器启动后要干的事情

CMD command param1 param2
例:CMD echo “This is a test.” | wc -
CMD [“param1”,”param2”] (as default parameters to ENTRYPOINT)
例:CMD [“/usr/bin/wc”,”—help”]

注意

image.png
在Dockerfile中只能有一个CMD指令。如果你列出了多个CMD,那么只有最后一个CMD将生效。

和RUN命令的区别

CMD 是在docker run 时运行
RUN 是 在docker build 时运行

ENTRYPOINT:指定容器启动时要运行的命令

ENTRYPOINT [“executable”, “param1”, “param2”]
ENTRYPOINT command param1 param2
类似于CMD ,但是ENTRYPOINT 不会被 docker run 后面的命令覆盖,而且这些命令会被当作参数送给 ENTRYPOINT 指令指定的程序

优点

缺点

案例

自定义镜像mycentosjava8

来取cenos镜像

docker pull centos

要求

1、Centos镜像具备vim+ifconfig+jdk8
2、jdk 下载镜像地址 - 官网: https://www.oracle.com/java/technologies/javase/javase8u211-later-archive-downloads.html, 根据自己需要,下载对应的版本

编写

在根目录创建 myfile 文件夹,上传 jdk的jdk-8u301-linux-x64.tar.gz

mkdir myfile

创建DockerFile 文件, 注意 F 是小写 : 一定是 Dockerfile

vim DockerFile

# 手动敲的
FROM centos
MAINTAINER ljx<1506095514@qq.com>

ENV MYPATH /usr/local
WORKDIR  $MYPATH

# 安装 vim 编辑器
RUM yum -y install vim

# 安装ifconfig 命令查看网络IP
RUM yum -y install net-tools

# 安装 java8 及lib库
RUM ym -y install glibc.i686
RUM mkdir /usr/local/java

# ADD 是相对路径jar,把 jdk-8u301-linux-x64.tar.gz 添加到容器中,安装包必须要和DockerFile 文件在同一位置
ADD jdk-8u301-linux-x64.tar.gz /usr/local/java/

# 配置Java 环境变量 , 注意jdk1.8.0_301  这个是根据解压出来的文件夹命名
ENV JAVA_HOME /usr/local/java/jdk1.8.0_301
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tool.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH

EXPOSE 80
CMD echo $MYPATH
CMD echo "success -----------ok"
CMD /bin/bash


# 拷贝的
FROM centos
MAINTAINER ljx<1506095514@qq.com>
ENV MYPATH /usr/local 
WORKDIR $MYPATH 
#安装vim编辑器 
RUN yum -y install vim 
#安装ifconfig命令查看网络IP
RUN yum -y install net-tools 
#安装 java8及 Lib库 
RUN yum -y install glibc.i686 
RUN mkdir /usr/local/java 

#ADD 是相对路径jar,把jdk-8u171-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置 
ADD jdk-8u301-linux-x64.tar.gz  /usr/local/java/ 

#配置java环境变量  注意jdk1.8.0_301  这个是根据解压出来的文件夹命名
ENV JAVA_HOME /usr/local/java/jdk1.8.0_301
ENV JRE_HOME $JAVA_HOME/jre 
ENV CLASSPATH $JAVALHOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH 
ENV PATH $JAVA_HOME/bin:$PATH 

EXPOSE 80
CMD echo $MYPATH
CMD echo "success -----------ok"
CMD /bin/bash

构建

docker build -t 新镜像名字:TAG . 注意上面TAG 后面有个空格,有个点

docker build -t centosjava8:1.5 .
出现如下错误,找不到Dockerfile的文件,查看文件名是否错误,一定是 Dockerfile
unable to prepare context: unable to evaluate symlinks in Dockerfile path: lstat /myfile/Dockerfile: no such file or directory
修改文件名的命令
mv DockerFile Dockerfile
image.png

运行

docker run -it e5d7b4d533de /bin/bash

测试相关命令
ifconfig

再体会下UnionFS(联合文件系统)

虚悬镜像

是什么

仓库名、标签都是 的镜像,俗称dangling image
创建一个测试文件夹,在文件内创建一个test文件夹,再在文件内创建一个Dockerfile 文件
Dockerfile 创建一个

FROM ubuntu
CMD echo 'action  is  success'

构建
docker build .

image.png

查看

 docker image ls -f dangling=true

删除

docker image prune
image.png

自定义镜像myubuntu

小总结