Dockerfile 实战指南:解锁高效容器化开发

一、Dockerfile 简介

Dockerfile 是构建镜像的文本文件,通过一系列指令描述镜像构建过程,构建操作由 Docker daemon 进行,它会先验证语法,然后逐一运行指令,每次生成一个新的镜像层,直到构建出最终的镜像。
Dockerfile 集成了构建镜像所需的全部步骤,从选择基础镜像到运行容器,极大地简化了应用程序的部署和环境配置流程。通过 Dockerfile,开发者可以实现自动化、可重复、一致的构建过程,这对于团队协作和持续集成 / 持续部署流程至关重要。
Docker 镜像是一个特殊的分层文件系统,包含应用程序和必要的依赖环境,但并不包含任何的动态信息。构建一个镜像,实际上就是为镜像中的每一层创建相应的配置。因此,可以把构建的命令语句、参数配置等信息都写入一个脚本中,这样,“docker commit” 命令的无法重复的问题、镜像臃肿的问题就都被解决了。这个脚本就是 Dockerfile。

(一)什么是 Dockerfile?

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。构建一个镜像,就是为镜像中的每一层创建相应的配置,而 Dockerfile 则是将这些配置信息以指令的形式记录下来。Dockerfile 可以使用 “docker build” 命令进行编译。在编译过程中,每一条指令的内容就是描述该层应如何进行构建。当我们需要定制自己额外的需求时,只需要在 Dockerfile 文件的基础上添加或者修改指令,重新生成新的镜像即可。

(二)Dockerfile 示例

下面通过一个简单的示例来演示如何使用 Dockerfile。在这个示例中,将基于 Nginx 的镜像来构建一个新的镜像,并在该镜像中部署一个简单的 Web 网页。

  1. 创建一个文件 “Dockerfile”。在该文件中输入以下命令。
FROM nginx
RUN echo '<h1>This is a Demo HTML</h1>' >/usr/share/nginx/html/index.html
  1. 在 Dockerfile 所在的目录下执行 “docker build” 命令构建镜像。构建的过程如下图所示。提示:“docker build” 命令会在当前目录下寻找名为 “Dockerfile” 的文件,然后对该文件进行编译生成镜像。如果文件名不是 Dockerfile,则可以在使用 “docker build” 命令加上 “-f” 参数指定文件名称。

  2. 查看新生成的镜像,如下图所示。

  3. 使用新生成的镜像创建容器。
    docker run -d -p 7788:80 mynginx

  4. 使用浏览器访问宿主机的 7788 端口,可以看到如下图所示界面。

(三)Docker File 文件详解

下图展示了 Docker 镜像、容器和 Dockerfile 三者的关系。可以看出使用 Dockerfile 文件定义镜像,然后运行镜像启动容器。下表列出了一个完整的 Dockerfile 文件的组成部分。当完成了 Dockerfile 的编写后,使用 “docker build” 命令将会根据 Dockerfile 中上下文的内容构建新 Docker 镜像。整个构建的过程会被递归处理。因此,如果在 Dockerfile 中含有子路径或 URL 等信息,则它们都将被递归进行构建。
提示:在使用 “docker build” 进程镜像构建时,还可以通过 “-t” 参数指定生成镜像的仓库地址和标签等信息。Dockerfile 构建镜像的过程请参考下图。“docker build” 命令在使用 Dockerfile 生成镜像时,会通过 Docker 的守护进程执行 Dockerfile 中的每一条指令,并在每一步执行完成后生成一个新镜像。当所有的指令执行完成后,会输出最终镜像的 ID。当镜像最终生成后,Docker 的守护进程会自动清理 Docker 的上下文环境,并自动重用已生成的中间镜像,以加速构建的速度。图中方框的部分表明,在构建过程中使用到了 Dockerfile 的缓存机制。

二、Dockerfile 关键字详解

1. FROM 关键字

指定基础镜像,新镜像是基于哪个镜像构建的,建议使用官方镜像作为基础镜像,如 Alpine,体积小且严格控制。在 Dockerfile 中,FROM指令必须作为第一个指令出现,它为后续的构建步骤提供了基础环境。例如:FROM ubuntu:20.04,这里指定了以 Ubuntu 20.04 版本的镜像作为基础镜像。

2. MAINTAINER/LABEL 关键字

MAINTAINER指定维护者信息,例如:MAINTAINER John Doe <john.doe@example.com>。但按照官方文档描述,MAINTAINER已逐渐过时,目前更推荐使用LABEL来设置元数据。
LABEL用于给镜像打标签,相对MAINTAINER更灵活。可以设置多个元数据,一个LABEL是键值对,多个键值对之间使用空格分开,命令换行时使用反斜杠\。例如:LABEL version="1.0" description="This is a demo image" by="Developer Name"

3. RUN 关键字

构建过程中运行的命令,有 shell 格式和 exec 格式两种。
shell 格式:RUN <command>,命令在 shell 中运行,默认情况下在 Linux 上是/bin/sh -c,在 Windows 上是cmd /S /C。例如:RUN apt-get update
exec 格式:RUN ["executable", "param1", "param2"]。例如:RUN ["npm", "install"]

4. WORKDIR 关键字

指定进入容器时的目录。使用WORKDIR可以设置容器内的工作目录,后续的指令将在这个目录下执行。例如:WORKDIR /app,如果目录不存在,会自动创建。

5. ENV 关键字

设置容器内环境变量,方便访问程序。通过ENV可以设置环境变量,这些变量在构建过程和容器运行时都有效。例如:ENV NODE_ENV production,在后续的指令中可以使用这个环境变量,如RUN echo $NODE_ENV

6. ADD 关键字

将宿主机资源拷贝进镜像中,会自动解压缩,还能从远程读取资源。ADD指令可以将宿主机上的文件或目录复制到镜像中。如果源是一个压缩文件,它会自动解压缩。例如:ADD myfile.tar.gz /app,会将myfile.tar.gz解压缩到容器的/app目录下。同时,ADD还支持从远程 URL 获取资源,例如:ADD http://example.com/file.txt /app,会从指定 URL 下载文件并复制到容器的/app目录。

7. COPY 关键字

将宿主机资源拷贝到镜像中,只支持读取构建所在宿主机资源,更透明。COPYADD功能类似,但不会自动解压缩文件,也不能从远程读取资源。例如:COPY myfile.txt /app,只会将宿主机上的myfile.txt复制到容器的/app目录。Docker 开发者推荐在满足同等功能的情况下,尽量使用COPY指令,以避免ADD指令可能带来的意外情况。

8. VOLUME 关键字

挂载数据卷,根据构建出来的镜像运行容器时,默认有构建时挂载信息。VOLUME指令用于在容器中创建一个数据卷,这个数据卷可以被多个容器共享,并且数据写入不会影响镜像层。例如:VOLUME /data,在容器运行时,可以将宿主机上的目录挂载到这个数据卷上,实现数据的持久化存储。

9. EXPOSE 关键字

指定运行容器时对外暴露的端口。EXPOSE指令用于指定容器在运行时要对外暴露的端口。例如:EXPOSE 8080,这只是声明了容器要暴露的端口,但要让外部能够访问这些端口,还需要在运行容器时使用-p参数进行端口映射。

10. CMD 关键字

指定启动容器时要执行的命令,只有最后一个会生效,创建容器时指定命令会覆盖 CMD 命令。CMD指令用于指定容器启动时默认执行的命令和参数。如果 Dockerfile 中有多个CMD指令,只有最后一个会生效。并且,在创建容器时,可以通过命令行参数覆盖CMD指定的命令。例如:CMD ["node", "app.js"],如果在运行容器时使用docker run <image> bash,则会覆盖CMD指定的命令,执行bash命令。

11. ENTRYPOINT 关键字

指定启动容器时要执行的命令,可以追加命令,执行时机同 CMD。ENTRYPOINT指令用于指定容器启动时要执行的命令,与CMD不同的是,ENTRYPOINT指定的命令不会被docker run命令行参数覆盖,而是会将这些参数作为附加参数传递给ENTRYPOINT指定的命令。例如:ENTRYPOINT ["node"],如果运行容器时使用docker run <image> app.js,则容器会执行node app.js

12. ARG 关键字

定义变量,和写代码时定义变量一样。ARG用于在构建镜像时定义变量,这些变量可以在后续的指令中使用。例如:ARG BUILD_ENV=production,在RUN指令中可以使用这个变量,如RUN if [ "$BUILD_ENV" = "production" ]; then npm install --production; else npm install; fi

13. ONBUILD 关键字

基于父镜像构建新镜像时,父镜像的 ONBUILD 会被触发。ONBUILD指令用于在构建新镜像时,当新镜像基于包含ONBUILD指令的父镜像构建时,父镜像的ONBUILD指令会被触发执行。例如:ONBUILD RUN echo "This is triggered when building a child image",当一个新镜像基于这个镜像构建时,这个命令会被执行。

三、Dockerfile 实战案例

1. 构建 Flask 镜像

使用 Python 和 Flask 构建一个简单的 Web 应用,通过 Dockerfile 构建镜像并启动容器,在网页输入服务器 IP 和端口即可看到输出。
首先创建一个 Flask 应用,以下是一个简单的示例:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello from Flask!'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

然后编写 Dockerfile:

FROM python:3.10
WORKDIR /app
COPY..
RUN pip install flask
EXPOSE 5000
CMD ["python", "your_flask_app.py"]

在项目目录下执行以下命令构建镜像:

docker build -t flask-app.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若涵的理解

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值