概述
本章,您将学习 Docker 当中一个重要的文本文件 —— Dockerfile。
Q:什么是 Dockerfile?有什么用?
Dockerfile:用来构建 Docker 镜像的文本文件,该文件的内容类比 GNU/Linux 当中的 Shell 脚本,其由一条又一条构建镜像所需的指令和参数构成。Dockerfile 文件的内容需要遵循特定的格式和指令集,请参阅 这里。
前面使用过 docker commit 这种方式,它可以在原始镜像生成的容器实例的基础之上生成增强版镜像,这种方式对于一些简单操作是没问题的,但是面对复杂的操作就会很麻烦(因为每次都要 commit 提交)。为了提高使用者的使用效率,Docker 当中引入了 Dockerfile ,您可以在文本文件中写入您需要的功能清单(相当于实现多次 commit 提交),最后构建成适合生产环境的增强版镜像。

构建镜像并生成容器实例的三个步骤:
- 编写 Dockerfile 文件
- 使用
docker build命令构建镜像 - 使用
docker run命令生成容器实例
Dockerfile 基础知识
在正式编写 Dockerfile 之前,您需要了解这些:
- Dockerfile 当中的指令(Instruction)关键字 必须大写 且每个指令至少书写一个参数(Arguments)
- 构建镜像时,docker 会按照从上到下的顺序读取 Dockerfile 文件内容且按照顺序依次执行
- # 开头表示注释行
- 每条指令都会创建一个只读的镜像层并且进行 commit 提交。多个镜像层最终堆叠成一个完整镜像
Dockerfile 中常见的指令关键字
FROM- 该关键字出现在 Dockerifle 的首行,代表构建的镜像是基于哪个原始镜像(基础镜像)。ENV- 构建镜像过程中设置的环境变量。环境变量以键值对的方式出现,例如ENV MY_NAME="John Doe"或者ENV MY_NAME "John Doe"。通常而言,该关键字出现在FROM关键字之后。WORKDIR- 容器创建完成后,通过docker exec或docker run进入到容器内部时默认的工作目录。MAINTAINER- 设置生成镜像的 "Author" 字段,该关键字已经被弃用,请使用LABEL关键字作为替代RUN- 容器实例构建成镜像时需要执行的命令,RUN有两种格式:- shell 格式 -
RUN [OPTIONS] <command> ... - exec 格式 -
RUN [OPTIONS] [ "<command>", ... ]
- shell 格式 -
EXPOSE- 容器实例对外暴露的端口,如果未指定端口协议,则默认为 TCPSTOPSIGNA- 容器实例退出时发出的信号,可以具体的信号名称,也可以数字。默认为 15(SIGTERM)USER- 指定运行容器时的用户名或 UID。在该指令之后的RUN指令也会使用该用户进行执行。不书写该指令,则默认用户为 rootVOLUME- 数据持久化时需要设置容器实例内的映射目录(也称数据卷、挂载点),请注意!不是设置宿主机的映射目录。ADD- 将宿主机目录下的文件复制到容器实例中且自动解压 .tar 归档文件。语法如下(src 必须与 Dockerfile 位于同一个目录下):ADD [OPTIONS] <src> ... <dest>ADD [OPTIONS] ["<src>", ... "<dest>"]
COPY- 将宿主机的目录或目录下的文件拷贝到容器实例中,类似于ADD指令CMD- 容器实例启动之后要运行的命令。请注意不要将它和RUN指令混淆。在一个 Dockerfile 文件中您可以指定多个CMD指令,但是仅最后一个生效。在格式上,该指令同样也支持 shell 格式与 exec 格式。该指令会被docker run后面的命令覆盖掉ENTRYPOINT- 类似于CMD指令,指容器实例启动之后要运行的命令,但是该指令不会被docker run后面的命令覆盖掉。- 若和
CMD一起使用,则ENTRYPOINT指令所处的位置需要在CMD指令之前,此时的CMD指令的含义不再是运行命令,而是将CMD里面的内容变成了传递给ENTRYPOINT的参数。
- 若和
在 Github 网站,我们可以找到 Tomcat 镜像的 Dockerfile 文件(去掉了注释行):
FROM eclipse-temurin:21-jre-jammy
ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME
ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR
ENV TOMCAT_MAJOR 10
ENV TOMCAT_VERSION 10.1.55
ENV TOMCAT_SHA512 f36af12391a277e5c3a802a8e1a2a1e4354cd461b547d2e1a33ac0ab88d707d3fb2591e034a17b7d3a6b965a4c977a97dbf29bb81a3867e85aeec3d8d189e22e
COPY --from=tomcat:10.1.55-jdk21-temurin-jammy $CATALINA_HOME $CATALINA_HOME
RUN set -eux; \
apt-get update; \
xargs -rt apt-get install -y --no-install-recommends < "$TOMCAT_NATIVE_LIBDIR/.dependencies.txt"; \
rm -rf /var/lib/apt/lists/*
RUN set -eux; \
nativeLines="$(catalina.sh configtest 2>&1)"; \
nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')"; \
nativeLines="$(echo "$nativeLines" | sort -u)"; \
if ! echo "$nativeLines" | grep -E 'INFO: Loaded( APR based)? Apache Tomcat Native library' >&2; then \
echo >&2 "$nativeLines"; \
exit 1; \
fi
EXPOSE 8080
ENTRYPOINT []
CMD ["catalina.sh", "run"]
Dockerfile 编写案例
需求:
- 基于 Rocky Linux 8.9 镜像
- 需要有
vim命令 - 准备 Nginx 的一些依赖包,源代码编译最新版的 Nginx
基本操作步骤:
-
第一步:拉取基础镜像——
docker pull rockylinux:8.9.20231119 -
第二步:在宿主机中准备 .tar.gz 的 nginx 归档压缩包并存放在 /tmp/nginx/ 目录中
-
第三步:在 /tmp/nginx/ 目录中新增名称为 Dockerfile 的文件,其内容为:
FROM rockylinux:8.9.20231119 ENV WORK_PATH /usr/local/nginx RUN mkdir -p "$WORK_PATH" WORKDIR $WORK_PATH # 安装 dnf RUN yum -y install dnf # 安装 vim RUN dnf -y install vim # 一些必要的依赖包 RUN dnf -y update \ && dnf -y install tar gzip bzip2 zip mtr gcc gcc-c++ openssl openssl-devel make pcre pcre-devel # 新建目录 RUN mkdir -p /usr/local/src # 添加必要的用户 RUN groupadd -r nginx \ && useradd -r -g nginx -s /sbin/nologin nginx # 复制宿主机的 .tar.gz 到容器实例中 COPY nginx-1.31.1.tar.gz /tmp/ # 解压 RUN tar -vxf /tmp/nginx-1.31.1.tar.gz -C /usr/local/src/ # 开始编译 nginx RUN cd /usr/local/src/nginx-1.31.1/ && ./configure --prefix=/usr/local/nginx/ \ --user=nginx \ --group=nginx \ --with-http_ssl_module \ --with-http_stub_status_module \ --with-http_gzip_static_module \ && make && make install ENTRYPOINT ["/usr/local/nginx/sbin/nginx"] CMD ["-g", "daemon off;"] EXPOSE 80/TCP 443/TCP # 这里使用默认信号 15 (SIGTERM) STOPSIGNAL SIGTERM -
第四步:使用
docker build命令构建自定义的增强版镜像,在您的终端执行:Shell > cd /tmp/nginx/ && docker build -t mynginx:latest . [+] Building 40.8s (16/16) FINISHED docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 1.05kB 0.0s => [internal] load metadata for docker.io/library/rockylinux:8.9.20231119 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [ 1/11] FROM docker.io/library/rockylinux:8.9.20231119 0.0s => [internal] load build context 0.0s => => transferring context: 42B 0.0s => CACHED [ 2/11] RUN mkdir -p "/usr/local/nginx" 0.0s => CACHED [ 3/11] WORKDIR /usr/local/nginx 0.0s => CACHED [ 4/11] RUN yum -y install dnf 0.0s => CACHED [ 5/11] RUN dnf -y install vim 0.0s => CACHED [ 6/11] RUN dnf -y update && dnf -y install tar gzip bzip2 zip mtr gcc gcc-c++ openssl openssl-devel m 0.0s => CACHED [ 7/11] RUN mkdir -p /usr/local/src 0.0s => [ 8/11] RUN groupadd -r nginx && useradd -r -g nginx -s /sbin/nologin nginx 0.6s => [ 9/11] COPY nginx-1.31.1.tar.gz /tmp/ 0.1s => [10/11] RUN tar -vxf /tmp/nginx-1.31.1.tar.gz -C /usr/local/src/ 0.6s => [11/11] RUN cd /usr/local/src/nginx-1.31.1/ && ./configure --prefix=/usr/local/nginx/ --user=nginx --group=n 39.3s => exporting to image 0.2s => => exporting layers 0.2s => => writing image sha256:57ba773840045be8f168980d808b455c81a2bbb91a86b3c4aedb9708f10b1fad 0.0s => => naming to docker.io/library/mynginx:latest 0.0sdocker build命令的选项说明:-t- 设置构建需要的步骤或阶段。如您所见,我们共需要 11 个步骤来完成镜像的构建。.- 这里的点并不表示 Dockerfile 文件的路径位置,而是表示 构建镜像所需的上下文(由于构建镜像需要在服务端的 Docker 引擎上,因此需要将本地的文件上传给 Docker 引擎,即所谓的上下文),这也解释了为什么使用COPY ./nginx-1.31.1.tar.gz /tmp/这种方式是无法工作的。上面的输出信息中有这样的一行 —— "transferring context"
-
第五步:验证镜像。
Shell > docker images REPOSITORY TAG IMAGE ID CREATED SIZE mynginx latest 57ba77384004 10 minutes ago 823MB rockylinux 8.9.20231119 c79048e50f5f 2 years ago 198MB Shell > docker run -d -p 80:80 -p 443:443 --name="new" mynginx:latest Shell > docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c168d4d6db06 mynginx:latest "/usr/local/nginx/sb…" 3 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp new获取网页内容:
Shell > curl http://192.168.100.20:80
版权声明:「自由转载-保持署名-非商业性使用-禁止演绎 3.0 国际」(CC BY-NC-ND 3.0)
用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论










