题目
什么是 Dockerfile?
答案
Dockerfile 是一个文本文件,包含了一系列**指令(Instructions)**,用于定义如何自动构建一个 **Docker 镜像**。镜像可以看作是一个轻量级、可执行的软件包,包含运行应用程序所需的一切(代码、运行时环境、系统工具、库等)。通过 Dockerfile,开发者可以精确描述镜像的构建步骤,确保环境一致性。
### Dockerfile 的核心作用
1. **标准化环境**:消除“在我机器上能运行”的问题,确保开发、测试、生产环境一致。
2. **自动化构建**:通过一条命令(`docker build`)即可生成镜像,无需手动配置。
3. **分层存储**:每个指令生成一个镜像层,层复用提升构建效率和存储优化。
### Dockerfile 的常见指令
以下是 Dockerfile 的关键指令及其用途:
| **指令** | **作用** | **示例** |
| :------------- | :----------------------------------------------------------- | :-------------------------------------------------------- |
| `FROM` | 指定基础镜像(必须作为第一条指令)。 | `FROM ubuntu:22.04` |
| `RUN` | 在镜像中执行命令(安装软件、配置环境等)。 | `RUN apt-get update && apt-get install -y nginx` |
| `COPY` / `ADD` | 将文件从宿主机复制到镜像中(`ADD` 支持自动解压和远程 URL)。 | `COPY ./app /app` |
| `WORKDIR` | 设置工作目录(后续指令的默认执行路径)。 | `WORKDIR /app` |
| `ENV` | 设置环境变量。 | `ENV NODE_ENV=production` |
| `EXPOSE` | 声明容器运行时监听的端口(需通过 `-p` 映射到宿主机)。 | `EXPOSE 80` |
| `CMD` | 指定容器启动时默认执行的命令(只能有一条,可被 `docker run` 覆盖)。 | `CMD ["nginx", "-g", "daemon off;"]` |
| `ENTRYPOINT` | 类似 `CMD`,但参数不可被 `docker run` 覆盖(通常与 `CMD` 结合使用)。 | `ENTRYPOINT ["java", "-jar"]` + `CMD ["app.jar"]` |
| `USER` | 指定运行容器时的用户(避免使用 root 提升安全性)。 | `USER node` |
| `VOLUME` | 定义数据卷挂载点(持久化数据或共享数据)。 | `VOLUME /data` |
| `HEALTHCHECK` | 定义容器健康检查规则(检测服务是否正常)。 | `HEALTHCHECK --interval=30s CMD curl -f http://localhost` |
### Dockerfile 示例
以下是一个 SpringBoot 应用的 Dockerfile 示例:
```yaml
# ========== 第一阶段:构建应用 ==========
# 使用 Maven 官方镜像作为构建环境
FROM maven:3.8.6-openjdk-17 AS builder
# 设置工作目录
WORKDIR /app
# 先复制 POM 文件(利用 Docker 缓存层加速构建)
COPY pom.xml .
# 下载依赖(如果 pom.xml 未变化,会复用该层缓存)
RUN mvn dependency:go-offline -B
# 复制源代码
COPY src ./src
# 构建应用(打包为 JAR)
RUN mvn package -DskipTests
# ========== 第二阶段:运行应用 ==========
# 使用轻量级 OpenJDK 运行时镜像
FROM openjdk:17-jdk-alpine
# 设置容器内工作目录
WORKDIR /app
# 从构建阶段复制生成的 JAR 包
COPY --from=builder /app/target/*.jar app.jar
# 设置非 root 用户(安全最佳实践)
RUN addgroup -S springboot && adduser -S springboot -G springboot
USER springboot
# 暴露端口(与 application.properties 中配置的端口一致)
EXPOSE 8080
# 健康检查(可选)
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/actuator/health || exit 1
# 启动命令(可配置 JVM 参数)
ENTRYPOINT ["java", "-jar", "app.jar"]
# 如果需要指定 JVM 内存参数:
# ENTRYPOINT ["java", "-Xmx512m", "-jar", "app.jar"]
```
### Dockerfile 构建与运行
使用以下命令根据 Dockerfile 构建镜像并运行容器:
```bash
# 构建镜像
docker build -t my-spring-app:1.0 .
# 运行容器(映射端口 8080)
docker run -d -p 8080:8080 --name my-app my-spring-app:1.0
```
