Skip to content
第 211 / 250 章运维⏱ 12 分钟阅读

第 211 章:Docker 入门与容器化

学习目标

  • 理解 Docker 核心概念
  • 掌握镜像与容器操作
  • 学会 Dockerfile 编写
  • 实现多阶段构建

一、Docker 简介

Docker 是容器化平台,把应用 + 依赖打包成镜像,实现"一处构建,处处运行"。

vs 虚拟机:

维度容器虚拟机
启动秒级分钟
性能接近原生10-20% 损耗
资源MBGB
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    # alpine

5.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 nginx

7.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
.vscode

9.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:v1

10.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:v1

10.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: secret
bash
docker compose up -d
docker compose logs -f

十三、本章小结

命令用途
docker pull拉镜像
docker run启容器
docker ps查容器
docker exec进容器
docker build构建镜像
docker push推镜像

动手练习

  1. 拉 nginx 镜像,启动并访问
  2. 写 Dockerfile 构建自己的应用
  3. 用多阶段构建,镜像 < 200MB
  4. 用数据卷持久化 MySQL 数据

推荐阅读


下一章:第 212 章:Docker Compose 多容器编排

本站基于 VitePress 构建 · 由 Codebook 团队维护