Docker Dockerfile(保姆级教程)

什么是 Docker Dockerfile?从零开始理解容器化开发的核心

如果你正在学习现代软件开发,那“Docker”这个词你一定不陌生。它像一个全能的“集装箱”,把应用程序连同它运行所需的一切环境打包在一起,无论你把它放到哪台机器上,都能稳定运行。而 Docker Dockerfile,就是这个集装箱的“建造图纸”——它告诉 Docker 如何一步步构建出一个完整的镜像。

想象一下,你开发了一个 Python 项目,依赖于特定版本的 Python、一些第三方库,还配置了环境变量。如果你直接把代码发给同事,对方可能因为环境不一致而报错。这时候,Docker Dockerfile 就能解决这个问题。它把整个运行环境“固化”成一个可复制的镜像,确保“开发环境”和“生产环境”完全一致。

Docker Dockerfile 是一个纯文本文件,文件名通常为 Dockerfile(首字母大写,无扩展名)。它由一系列指令组成,每一条指令都对应一次镜像层的构建。这些指令从上到下执行,最终生成一个完整的镜像。这个过程就像搭积木,每一步都为最终的容器打下基础。

Docker Dockerfile 的基本语法结构

Docker Dockerfile 的核心是“指令 + 参数”的组合。每一条指令都以大写字母开头,比如 FROM、RUN、COPY、EXPOSE 等。它们按顺序执行,每执行一次就生成一个镜像层。这种分层设计让镜像可以高效复用和缓存。

我们来看一个最简单的 Dockerfile 示例:

FROM ubuntu:22.04

LABEL maintainer="yourname@example.com"

RUN apt-get update && apt-get install -y curl

COPY hello.sh /app/

CMD ["/app/hello.sh"]

这里每一条指令的作用如下:

  • FROM:指定构建镜像的基础镜像。这是必须的第一条指令,没有基础镜像,就无法构建。就像盖房子要先打地基。
  • LABEL:为镜像添加元数据,比如作者、版本等,方便管理和追踪。
  • RUN:在构建过程中执行命令。这里我们用它来安装软件包。注意,apt-get update 是更新软件源列表,apt-get install -y 是自动确认安装,避免交互式输入。
  • COPY:将本地文件复制到镜像中。它和 ADD 类似,但 COPY 更安全,只支持本地文件,不会自动解压。
  • CMD:定义容器启动时默认执行的命令。它可以在运行时被覆盖,是“默认行为”。

常用指令详解与最佳实践

Docker Dockerfile 提供了丰富的指令来控制构建过程。掌握它们,才能写出高效、安全的镜像。

FROM:构建的起点

FROM python:3.11-slim

这条指令指定了使用 Python 3.11 的最小化版本镜像。slim 版本意味着它只包含运行 Python 所需的基本文件,体积小,适合生产环境。

💡 小贴士:尽量使用官方镜像(如 python:3.11-slim),避免自己从头构建基础环境,节省时间并减少安全风险。

RUN:执行命令的时机

RUN pip install requests flask

这个命令在构建阶段安装 Python 依赖。注意,多个命令可以合并成一行,使用 && 连接,这样可以减少镜像层数,提高构建效率。

⚠️ 重要:不要在 RUN 中使用 sudoapt-get install 时忘记 apt-get clean,否则会留下缓存文件,导致镜像体积过大。

COPY 与 ADD:文件复制的两种方式

COPY requirements.txt /app/
RUN pip install -r /app/requirements.txt

我们先复制 requirements.txt,再安装依赖。这样做是为了利用 Docker 的缓存机制:如果 requirements.txt 没变,Docker 就不会重新安装依赖,构建速度更快。

ADD 可以自动解压 URL 或压缩包,但功能复杂,容易出错,建议优先使用 COPY

EXPOSE:声明端口,不是开放端口

EXPOSE 8080

这条指令只是告诉用户这个镜像会使用 8080 端口。它不会自动在运行时打开端口。真正开放端口需要在 docker run 命令中使用 -p 参数。

✅ 正确用法:docker run -p 8080:8080 myapp

ENV:设置环境变量

ENV FLASK_ENV=development
ENV DATABASE_URL=sqlite:///app.db

这些环境变量可以在应用启动时被读取,比如 Flask 会根据 FLASK_ENV 自动启用调试模式。设置环境变量是配置应用的常用方式。

指令 作用 是否影响运行时
FROM 指定基础镜像
RUN 构建阶段执行命令
COPY 复制本地文件到镜像
EXPOSE 声明服务端口
ENV 设置环境变量
CMD 容器启动时默认执行的命令

构建与运行你的第一个 Docker 镜像

现在我们来实战一个完整的例子:创建一个简单的 Python Flask 应用,并用 Docker Dockerfile 打包。

首先创建项目目录:

mkdir flask-app
cd flask-app

创建 app.py

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return '<h1>Hello from Docker!</h1>'

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

创建 requirements.txt

Flask==2.3.3

创建 Dockerfile(内容如下):

FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY app.py .

EXPOSE 8080

CMD ["python", "app.py"]

📌 注释说明:

  • WORKDIR:设置当前工作目录,相当于 cd /app
  • --no-cache-dir:避免 pip 缓存,减少镜像体积
  • CMD ["python", "app.py"]:使用数组格式,避免 shell 解析问题

构建镜像:

docker build -t my-flask-app .

运行容器:

docker run -p 8080:8080 my-flask-app

打开浏览器访问 http://localhost:8080,你应该能看到 "Hello from Docker!"。

多阶段构建:减小镜像体积的利器

随着项目复杂度上升,镜像体积可能变得非常大。比如你在构建阶段安装了编译工具,但运行时根本不需要。这时,多阶段构建(Multi-stage Build)就派上用场了。

FROM python:3.11-slim as builder

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY app.py .

FROM python:3.11-slim

WORKDIR /app

COPY --from=builder /app /app

EXPOSE 8080

CMD ["python", "app.py"]

✅ 优势:最终镜像只包含运行所需的文件,体积小,安全性高。构建工具和中间文件被“丢弃”。

总结:Docker Dockerfile 是开发效率的加速器

Docker Dockerfile 不只是一个构建工具,它更是一种“环境即代码”的思维体现。通过它,你可以把开发、测试、部署的环境统一起来,避免“在我机器上能跑”的尴尬。

从基础镜像的选择,到文件复制、依赖安装、端口声明,每一步都值得认真思考。记住:构建镜像的过程,就是定义你应用运行环境的过程

当你熟练掌握 Docker Dockerfile 后,你会发现:不再需要反复配置环境,不再担心“环境不一致”问题,开发效率和部署稳定性都大幅提升。

现在就动手试试吧,用一个简单的 Dockerfile,把你的项目“装进集装箱”,让它在任何地方都能稳定运行。