🐳 Docker 核心实战与进阶笔记

一、 Dockerfile 指令全参数详解

Dockerfile 是定义镜像“静态环境”的说明书。

指令 参数与功能说明 代码示例 关键避坑
FROM 指定基础镜像。开启一个构建阶段。 FROM node:20-slim AS builder AS 用于起别名,方便后续多阶段引用。
WORKDIR 设定工作目录。后续指令的相对路径基准。 WORKDIR /app 目录不存在会自动递归创建(类似 mkdir -p)。
COPY 复制文件。从宿主机或其它阶段拷贝。 COPY --from=builder /app/dist ./dist --from 是跨阶段搬运产物的唯一通道。
ADD 高级复制。支持 URL 下载和自动解压缩。 ADD source.tar.gz /data 原则:除非需要自动解压,否则一律用 COPY
RUN 构建时执行。用于安装软件、编译代码。 RUN pnpm install && pnpm build 层缓存:每一个 RUN 都会产生一层,尽量合并命令。
ENV 运行时环境变量。容器启动后程序可见。 ENV NODE_ENV=production 常用于切换生产/开发环境逻辑。
VOLUME 声明数据卷。定义持久化挂载点。 VOLUME ["/opt/admin"] 标记该目录为“数据出入口”,防止数据随容器消失。
HEALTHCHECK 健康检查。监控业务逻辑是否正常。 HEALTHCHECK --interval=30s CMD curl -f... 不仅看进程,更看服务是否真正可用。
CMD 默认启动命令。容器运行时的第一个进程。 CMD ["node", "server.js"] 限制:只能有一个,多个只有最后一个生效。

二、 核心进阶逻辑:多阶段构建 (Multi-stage)

在企业级 Node.js 开发中,为了解决“镜像臃肿”问题,通常采用双阶段设计:

1. 逻辑结构图

  • 阶段一:Builder(施工房):安装编译器、源代码、缓存。任务是把代码编译成 dist

  • 阶段二:Runner(精装房):重新开一个干净的镜像,只通过 COPY --from=builder 把 dist 拿过来。

2. 代码演练:利用“层缓存”优化速度

codeDockerfile
 
# --- 第一阶段:编译 ---
FROM node:20-slim AS builder
WORKDIR /app

# 【关键】将 package.json 拷贝放在前面。
# 只要这个文件没变,Docker 就不会重新跑耗时的 install,直接复用缓存层。
COPY package.json pnpm-lock.yaml ./
RUN pnpm install

COPY . .
RUN pnpm build

# --- 第二阶段:运行 ---
FROM node:20-slim AS runner
WORKDIR /app

# 只搬运成品,丢弃源码和构建垃圾,镜像体积缩减 80%
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules

# 构建自检逻辑:确保关键程序安装成功
RUN test -f ./dist/index.js || (echo "Build failed" && exit 1)

CMD ["node", "dist/index.js"]

三、 Dockerfile vs. Docker Compose:元件与组装

1. 深度解读:两者的关联性

  • 关联性:在 docker-compose.yml 中使用 build: . 即可直接触发 Dockerfile 的构建流程,实现“一键代码到系统”。

  • 网络互通(服务发现):Compose 会自动创建内部局域网。容器连接数据库时,主机名直接填 服务名(Service Name)(如 db),Compose 的内置 DNS 会自动解析 IP。

  • 动静结合:Dockerfile 负责固化环境(),Compose 负责动态挂载目录、配置网络、管理端口()。

2. 代码联动示例

codeYaml
 
# docker-compose.yml
version: '3'
services:
  web-app:
    build: .             # 关联 Dockerfile
    container_name: web_service
    ports:
      - "8080:3000"      # 外部映射
    environment:
      - DB_URL=mysql_db  # 直接使用下面定义的服务名
    volumes:
      - ./logs:/app/logs # 动态挂载日志:活数据进卷

  mysql_db:
    image: mysql:8.0     # 官方镜像直接用,不需 Dockerfile
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:               # 具名卷:确保数据库删了数据还在

四、 避坑指南与最佳实践(金句总结)

  1.  陷阱

    • 如果 Dockerfile 需要 COPY dist/绝对不能在 .dockerignore 里忽略 dist/。否则 Docker 引擎会因找不到文件而报错。

  2. 镜像即光盘

    • Dockerfile 做出来的镜像是“死”的只读光盘(ROM);启动后的容器才是“活”的运行环境。

  3. 动静分离的思想

    • 死的东西(入镜像):代码逻辑、Node 库、编译成品。

    • 活的东西(入卷):数据库文件、用户上传图片、日志、配置文件。不要把活数据存在镜像里!

  4. 变量管理

    • GitLab CI 自带的 $CI_... 变量是系统自动注入的(如仓库地址、分支名);而 $SONAR_TOKEN 类变量需在 Settings 界面手动录入。

  5. 命令顺序

    • 顺序决定速度:修改代码频繁,修改依赖不频繁。因此先 COPY package.json 再 COPY 源码,能极大加速构建。

  6. 安全原则

    • 默认容器是 root 权限。生产环境建议在 Dockerfile 最后使用 USER node 切换用户,降低被攻破后的风险。


💡 总结:Dockerfile 保证了环境的确定性,Docker Compose 保证了系统的协作性。掌握了卷(Volume)的挂载和多阶段构建的隔离,你就掌握了 Docker 生产级应用的核心。

posted @ 2025-12-19 14:37  洛晨随风  阅读(8)  评论(0)    收藏  举报