首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Dockerfile 构建镜像:从入门到实践

Dockerfile 构建镜像:从入门到实践

原创
作者头像
贺公子之数据科学与艺术
发布2026-08-05 08:56:47
发布2026-08-05 08:56:47
1950
举报
文章被收录于专栏:云平台云平台

1. 引言

使用 Dockerfile 构建镜像,本质就是把你的应用环境“写”进一个文件,再通过一条命令生成镜像。本文将从最核心的流程讲起,带你掌握常用指令和实用技巧,帮助你快速上手 Docker 镜像构建。

2. 核心流程

下面通过流程图来直观展示整个构建过程:

代码语言:mermaid
复制
flowchart TD
  A["编写 Dockerfile"] --> B["执行 docker build"]
  B --> C["Docker 守护进程解析指令"]
  C --> D["逐层构建镜像层"]
  D --> E["输出最终镜像"]

2.1 编写 Dockerfile

Dockerfile 是一个文本文件,里面包含了一条条构建镜像所需的指令。下面是一个基于 Node.js 应用的示例:

代码语言:dockerfile
复制
# 基础镜像
FROM node:18-alpine

# 设置工作目录
WORKDIR /app

# 复制依赖文件
COPY package*.json ./
RUN npm install

# 复制源码
COPY . .

# 声明端口
EXPOSE 3000

# 启动命令
CMD ["node", "app.js"]

2.2 构建镜像

在 Dockerfile 所在目录执行以下命令即可构建镜像:

代码语言:bash
复制
docker build -t my-app:v1 .
  • -t:给镜像起名字和标签(name:tag
  • 末尾的 .:指定构建上下文为当前目录

如果文件名不叫 Dockerfile,可以用 -f 指定:

代码语言:bash
复制
docker build -f MyDockerfile -t my-app .

3. 常用指令速览

下表列出了 Dockerfile 中最常用的指令及其作用:

指令

说明

FROM

指定基础镜像

WORKDIR

设定工作目录,后续命令都在此目录下执行

COPY

把宿主机文件复制到镜像中

RUN

在构建时执行命令,例如安装依赖

CMD

容器启动时的默认命令,一个 Dockerfile 中只能有一个有效 CMD

ENTRYPOINT

容器入口点,常与 CMD 配合使用

ENV

设置环境变量

EXPOSE

声明容器监听的端口

4. 实用技巧

4.1 多阶段构建

多阶段构建允许你先在一个中间阶段编译或构建应用,再将最终产物复制到更精简的运行镜像中,从而大幅减小最终镜像的体积。

代码语言:dockerfile
复制
# 第一阶段:构建
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# 第二阶段:运行
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/main.js"]

4.2 利用构建缓存

Docker 会逐层缓存构建结果。把不经常变动的层(如 npm install)放在前面,把改动频繁的 COPY . . 往后放,可以充分利用缓存,加快后续构建速度。

4.3 .dockerignore 文件

类似于 .gitignore.dockerignore 文件用于忽略不需要打包进镜像的文件或目录,例如 node_modules.git 等。这不仅能加快构建速度,还能避免敏感文件泄露。

示例 .dockerignore

代码语言:plain
复制
node_modules
.git
.env
Dockerfile
.dockerignore

5. 总结问题与排查

在 Dockerfile 构建过程中,难免会遇到一些让人头疼的报错。下面整理了 4 个高频错误,并给出排查思路和解决方案。

5.1 COPY 路径错误

错误信息示例

代码语言:bash
复制
COPY failed: file not found in build context or excluded by .dockerignore

常见原因

  • 源路径是相对于构建上下文(build context)的,而不是 Dockerfile 所在目录。
  • 目标文件被 .dockerignore 排除。
  • 路径拼写错误或目录层级不对。

排查步骤

  1. 确认 docker build 命令末尾的上下文路径(.)指向了正确的目录。
  2. 检查目标文件是否存在于该目录下(可使用 lsdir 验证)。
  3. 查看 .dockerignore 文件,确认没有误排除该文件。

解决方案

  • 将源路径修改为相对于构建上下文的正确路径,例如:COPY ./src/app.js /app/./src/app.js 必须相对于构建上下文存在。
  • 如果文件确实不在当前上下文,可以调整构建上下文路径,例如 docker build -f docker/Dockerfile -t my-app . 将上下文设为父目录,然后 Dockerfile 中使用相对路径 COPY src/app.js /app/

5.2 RUN 命令执行失败

错误信息示例

代码语言:bash
复制
The command '/bin/sh -c apt-get install -y curl' returned a non-zero code: 100

常见原因

  • 网络不通,导致包管理器无法下载。
  • 依赖包版本冲突或仓库索引过期。
  • 命令本身语法错误(如多行命令未用 && 连接)。

排查步骤

  1. 查看构建日志中 RUN 命令输出的详细错误信息。
  2. 尝试在本地相同环境(如相同基础镜像的容器内)手动执行该命令,看是否复现。
  3. 检查网络连通性(特别是国内访问官方源)。

解决方案

  • 对于 apt-get 等包管理器,构建前先执行 apt-get update,并合并为一条 RUN 指令以减少层数:RUN apt-get update && apt-get install -y curl
  • 使用国内镜像源加速(如阿里云、清华源),例如:RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list && apt-get update && apt-get install -y curl
  • 强制不使用缓存重新构建:docker build --no-cache -t my-app .

5.3 缓存导致依赖未更新

错误现象:修改了 package.jsonrequirements.txt,但 npm install / pip install 没有重新执行,镜像中依然是旧依赖。

原因

Docker 按层缓存。如果 COPY package*.json ./ 这层没有变化(因为 Docker 认为文件内容未变),后续的 RUN npm install 就会直接使用缓存,不会重新运行。

排查步骤

  1. 确认 package.json 是否真的被修改(检查文件内容或时间戳)。
  2. 检查 Dockerfile 中 COPY 指令是否正确复制了依赖文件,且该指令在 RUN install 之前。
  3. 使用 docker history <image> 查看镜像构建历史,确认缓存命中情况。

解决方案

  • 确保 Dockerfile 中先复制依赖文件,再执行安装,且 COPY 指令中的文件列表与依赖文件完全一致。
  • 在需要强制更新时,使用 --no-cache 构建:docker build --no-cache -t my-app .
  • 更精细的做法:在 RUN 命令中加入版本号变量或构建参数,使其每次变化:ARG CACHEBUST=1 RUN npm install构建时传入 --build-arg CACHEBUST=$(date +%s) 可强制跳过该层缓存。

5.4 Docker 守护进程未运行或权限不足

错误信息示例

代码语言:bash
复制
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

代码语言:bash
复制
Got permission denied while trying to connect to the Docker daemon socket

常见原因

  • Docker 服务未启动。
  • 当前用户不在 docker 用户组,没有权限访问 Docker 守护进程。
  • 在 Windows/Mac 上 Docker Desktop 未运行。

排查步骤

  1. 检查 Docker 服务状态:
    • Linux:systemctl status dockerservice docker status
    • macOS/Windows:查看 Docker Desktop 是否在运行。
  2. 确认当前用户权限:
    • docker ps 能否正常执行?若报权限错误,说明用户不在 docker 组。
    • 使用 groups 查看当前用户所属组,是否包含 docker

解决方案

  • 启动 Docker 服务:
    • Linux:sudo systemctl start docker
    • macOS/Windows:启动 Docker Desktop 应用程序。
  • 将当前用户加入 docker 组(需重新登录生效):sudo usermod -aG docker $USER newgrp docker
  • 若仍无法连接,检查 DOCKER_HOST 环境变量是否设置正确,通常无需设置,保持默认即可。5. 总结

通过 Dockerfile 构建镜像,你可以将应用环境标准化、版本化,实现“一次构建,到处运行”。本文介绍了 Dockerfile 的核心编写流程、常用指令以及多阶段构建等实用技巧。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 1. 引言
  • 2. 核心流程
    • 2.1 编写 Dockerfile
    • 2.2 构建镜像
  • 3. 常用指令速览
  • 4. 实用技巧
    • 4.1 多阶段构建
    • 4.2 利用构建缓存
    • 4.3 .dockerignore 文件
  • 5. 总结问题与排查
    • 5.1 COPY 路径错误
    • 5.2 RUN 命令执行失败
    • 5.3 缓存导致依赖未更新
    • 5.4 Docker 守护进程未运行或权限不足
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档