Skip to content

容器与镜像

核心概念

容器(Container)

容器是镜像的运行实例,是一个轻量级、可移植的运行环境。

与虚拟机的区别:

┌─────────────────────────────────────────────────────────┐
│                      虚拟机                              │
│  ┌─────────────────────────────────────────────────┐   │
│  │ Guest OS + Hypervisor                           │   │
│  │   ┌─────────────────────────────────────────┐   │   │
│  │   │ App + Libs + Dependencies               │   │   │
│  │   └─────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────┘   │
│                        ▲                                │
│                        │                                │
│              ┌─────────┴─────────┐                      │
│              │   Host OS + Hypervisor                  │
│              └───────────────────┘                      │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│                      容器                                │
│  ┌─────────────────────────────────────────────────┐   │
│  │ App + Libs + Dependencies (隔离)                │   │
│  └─────────────────────────────────────────────────┘   │
│                        ▲                                │
│              ┌─────────┴─────────┐                      │
│              │   Docker Engine                         │
│              │   Host OS                                 │
│              └───────────────────┘                      │
└─────────────────────────────────────────────────────────┘

容器特点:

  • 启动快(秒级)
  • 资源占用少
  • 环境一致性
  • 隔离性好

镜像(Image)

镜像是一个只读的模板,包含运行应用所需的所有内容。

镜像分层结构:

┌─────────────┐
│  Layer 4    │  应用层(最上层,可写)
├─────────────┤
│  Layer 3    │  运行时依赖
├─────────────┤
│  Layer 2    │  系统工具
├─────────────┤
│  Layer 1    │  基础系统(Ubuntu、Alpine)
├─────────────┤
│  Layer 0    │  Bootfs(引导文件系统)
└─────────────┘

Dockerfile 详解

基础指令

dockerfile
# 基础镜像
FROM node:18-alpine

# 维护者信息
LABEL maintainer="developer@example.com"

# 工作目录
WORKDIR /app

# 复制文件
COPY package*.json ./
COPY . .

# 安装依赖
RUN npm ci --only=production

# 暴露端口
EXPOSE 3000

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

常用指令对比

指令作用注意点
COPY复制本地文件不能访问 URL
ADD复制 + 解压 + URL优先使用 COPY
RUN执行命令尽量合并减少层数
CMD默认命令只有一个生效
ENTRYPOINT入口点与 CMD 配合
ENV设置环境变量后续指令可用
ARG构建参数构建时使用

最佳实践

dockerfile
# 1. 使用特定版本而非 latest
FROM node:18-alpine

# 2. 优先使用多阶段构建减小体积
FROM node:18-alpine AS builder
WORKDIR /app
COPY . .
RUN npm ci

FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/server.js"]

# 3. 合理利用缓存层级(把变化少的放前面)
COPY package*.json ./
RUN npm ci --only=production
COPY . .

# 4. 使用 .dockerignore 排除不必要文件
# .dockerignore
node_modules
.git
*.log
.env
coverage

# 5. 非 root 用户运行
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nextjs -u 1001
USER nextjs

常用命令

bash
# 构建镜像
docker build -t myapp:v1.0 .
docker build -t myapp:v1.0 --no-cache .

# 运行容器
docker run -d -p 8080:3000 --name myapp myapp:v1.0
docker run -it --rm node:18 node  # 交互式运行

# 容器管理
docker ps                    # 运行中的容器
docker ps -a                 # 所有容器
docker logs myapp            # 查看日志
docker logs -f myapp         # 实时日志
docker exec -it myapp sh     # 进入容器
docker stop myapp            # 停止容器
docker start myapp           # 启动容器
docker restart myapp         # 重启容器
docker rm myapp              # 删除容器
docker rm -f myapp           # 强制删除

# 镜像管理
docker images
docker rmi myapp:v1.0
docker rmi $(docker images -q)  # 删除所有镜像

# 查看资源使用
docker stats
docker top myapp
docker inspect myapp

面试高频题

Q1: Docker 容器与虚拟机有什么区别?

答案:

  • 虚拟机:每个虚拟机有独立的 Guest OS,通过 Hypervisor 虚拟化硬件,启动慢(分钟级),资源占用大
  • 容器:共享 Host OS,通过 Docker Engine 实现进程级别隔离,启动快(秒级),资源占用小

核心区别:

特性虚拟机容器
启动时间分钟级秒级
资源占用
隔离级别硬件级进程级
操作系统每个 VM 独立共享 Host OS

Q2: COPY 和 ADD 指令的区别?

答案:

  • COPY:纯复制本地文件到容器,简单直接
  • ADD:具备复制 + 解压 tar 文件 + 访问 URL 功能

推荐: 优先使用 COPY,除非需要自动解压功能

Q3: CMD 和 ENTRYPOINT 的区别?

答案:

  • CMD:提供默认命令,可被 docker run 参数覆盖
  • ENTRYPOINT:固定入口,通常与 CMD 配合提供默认参数
dockerfile
# CMD 示例(可被覆盖)
CMD ["node", "server.js"]
# docker run myapp debug.js  → 执行 debug.js

# ENTRYPOINT 示例(固定入口)
ENTRYPOINT ["node"]
CMD ["server.js"]
# docker run myapp debug.js → node debug.js

Q4: 如何优化 Dockerfile 减小镜像体积?

答案:

  1. 使用合适的基础镜像(alpine)
  2. 多阶段构建
  3. 合理利用缓存层级
  4. 合并 RUN 指令减少层数
  5. 清理不必要的文件
  6. 使用非 root 用户

前端面试知识库