第 211 章:Docker 入门与容器化
学习目标
- 理解 Docker 核心概念
- 掌握镜像与容器操作
- 学会 Dockerfile 编写
- 实现多阶段构建
一、Docker 简介
Docker 是容器化平台,把应用 + 依赖打包成镜像,实现"一处构建,处处运行"。
vs 虚拟机:
| 维度 | 容器 | 虚拟机 |
|---|---|---|
| 启动 | 秒级 | 分钟 |
| 性能 | 接近原生 | 10-20% 损耗 |
| 资源 | MB | GB |
| OS | 共享内核 | 独立内核 |
二、核心概念
| 概念 | 说明 |
|---|---|
| 镜像 (Image) | 只读模板 |
| 容器 (Container) | 镜像的运行实例 |
| Dockerfile | 镜像构建脚本 |
| Registry | 镜像仓库(Docker Hub) |
| Volume | 持久化卷 |
| Network | 容器网络 |
三、安装
bash
# macOS / Windows: Docker Desktop
# Linux:
curl -fsSL https://get.docker.com | sh
# 验证
docker --version
docker run hello-world四、镜像命令
bash
# 拉取
docker pull nginx:latest
docker pull nginx:1.25-alpine
# 列出
docker images
# 删除
docker rmi nginx:latest
# 搜索
docker search mysql
# 打标签
docker tag myapp:latest username/myapp:v1
# 推送
docker login
docker push username/myapp:v1
# 镜像历史
docker history nginx
# 详细信息
docker inspect nginx五、容器命令
5.1 基础
bash
# 运行
docker run -d -p 80:80 --name mynginx nginx:latest
# 选项
# -d 后台
# -p 80:80 端口映射(主机:容器)
# -v 挂载卷
# -e 环境变量
# --name 命名
# --rm 退出自动删
# 交互
docker run -it --rm ubuntu bash
# 列出
docker ps # 运行中
docker ps -a # 全部
# 启停
docker start mynginx
docker stop mynginx
docker restart mynginx
# 删除
docker rm mynginx
docker rm -f mynginx # 强制(含运行中)5.2 进入容器
bash
docker exec -it mynginx bash
docker exec -it mynginx sh # alpine5.3 日志 / 信息
bash
docker logs mynginx
docker logs -f mynginx # 实时跟踪
docker logs --tail 100 mynginx
docker stats # 资源占用
docker top mynginx # 进程六、Dockerfile
6.1 基本语法
dockerfile
FROM ubuntu:22.04 # 基础镜像
LABEL maintainer="tom@x.com" # 元数据
ENV NODE_ENV=production # 环境变量
ENV PORT=3000
WORKDIR /app # 工作目录
COPY package*.json ./ # 复制
COPY . .
RUN apt-get update && \ # 构建时执行
apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
RUN npm install
EXPOSE 3000 # 声明端口
CMD ["node", "server.js"] # 启动命令
ENTRYPOINT ["node"] # 入口6.2 关键指令
| 指令 | 说明 |
|---|---|
FROM | 基础镜像 |
WORKDIR | 工作目录 |
COPY / ADD | 复制 |
RUN | 构建命令 |
ENV | 环境变量 |
ARG | 构建参数 |
EXPOSE | 暴露端口 |
CMD | 默认启动命令 |
ENTRYPOINT | 入口 |
VOLUME | 数据卷 |
USER | 运行用户 |
HEALTHCHECK | 健康检查 |
6.3 多阶段构建(优化大小)
dockerfile
# 第一阶段:构建
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 第二阶段:运行
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/main.js"]构建:
bash
docker build -t myapp:1.0 .6.4 完整示例
dockerfile
# syntax=docker/dockerfile:1.6
# ===== 构建阶段 =====
FROM node:20-alpine AS builder
LABEL maintainer="tom@example.com"
WORKDIR /app
# 先复制依赖文件(利用缓存)
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile
COPY . .
RUN pnpm run build
# ===== 运行阶段 =====
FROM node:20-alpine
ENV NODE_ENV=production
ENV PORT=3000
# 用非 root
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --prod --frozen-lockfile && pnpm store prune
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
USER nodejs
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "dist/main.js"]七、数据卷
7.1 三种方式
bash
# 1. bind mount(双向)
docker run -v /host/path:/container/path nginx
# 2. 命名卷(推荐,Docker 管理)
docker volume create mydata
docker run -v mydata:/container/path nginx
# 3. tmpfs(内存)
docker run --tmpfs /tmp nginx7.2 管理
bash
docker volume ls
docker volume inspect mydata
docker volume rm mydata八、网络
8.1 模式
| 模式 | 说明 |
|---|---|
bridge | 默认,容器间可互联 |
host | 共享主机网络 |
none | 无网络 |
container | 共享其他容器网络 |
自定义 | 用户自定义网络 |
8.2 自定义网络
bash
docker network create mynet
docker network ls
# 容器加入
docker run --network mynet --name db mysql
docker run --network mynet --name app -e DB_HOST=db myapp容器间可通过容器名互相访问。
九、构建优化
9.1 层缓存
dockerfile
# ❌ 改一行代码全重装依赖
COPY . .
RUN npm install
# ✅ 先装依赖,代码改动不重装
COPY package*.json ./
RUN npm install
COPY . .9.2 减小镜像
dockerfile
# alpine 基础镜像(几 MB)
FROM node:20-alpine
# 多阶段构建
# .dockerignore 排除 node_modules 等.dockerignore:
node_modules
.git
*.log
.env
coverage
.vscode9.3 扫描镜像
bash
docker scan myapp:1.0
trivy image myapp:1.0十、镜像仓库
10.1 Docker Hub
bash
docker login
docker tag myapp:latest user/myapp:v1
docker push user/myapp:v110.2 私有仓库
bash
# 启动 registry
docker run -d -p 5000:5000 --restart=always --name registry \
-v /data/registry:/var/lib/registry \
registry:2
# 推送
docker tag myapp localhost:5000/myapp:v1
docker push localhost:5000/myapp:v110.3 阿里云镜像服务
bash
docker login registry.cn-hangzhou.aliyuncs.com
docker tag myapp registry.cn-hangzhou.aliyuncs.com/namespace/myapp:v1
docker push registry.cn-hangzhou.aliyuncs.com/namespace/myapp:v1十一、容器调试
bash
# 进入
docker exec -it myapp bash
# 查看进程
docker top myapp
# 查看文件变化
docker diff myapp
# 拷贝
docker cp myapp:/app/log.txt ./十二、Docker Compose
(下章详述)
yaml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
depends_on:
- db
db:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: secretbash
docker compose up -d
docker compose logs -f十三、本章小结
| 命令 | 用途 |
|---|---|
docker pull | 拉镜像 |
docker run | 启容器 |
docker ps | 查容器 |
docker exec | 进容器 |
docker build | 构建镜像 |
docker push | 推镜像 |
动手练习
- 拉 nginx 镜像,启动并访问
- 写 Dockerfile 构建自己的应用
- 用多阶段构建,镜像 < 200MB
- 用数据卷持久化 MySQL 数据