Docker 核心知识速查笔记 (从入门到实战)

一、核心概念速记

概念 类比 关键特性 备注
镜像 (Image) Java 的 只读模板、分层存储 (UnionFS) 包含运行所需一切,是容器的源代码
容器 (Container) Java 的 对象 可读写、进程隔离、秒级启动 镜像的运行实例,拥有独立网络/进程空间
仓库 (Repo) Maven/GitHub 集中存放镜像 Docker Hub (公), Harbor/Registry (私)
Docker vs VM - 共享内核、轻量 (MB)、秒启 VM 是硬件虚拟化 (重),Docker 是操作系统级虚拟化

底层三大基石

  1. Namespace:资源隔离 (PID, Net, IPC, Mnt, UTS)。
  2. Cgroups:资源限制 (CPU, 内存)。
  3. UnionFS:镜像分层 (写时复制 CoW)。

二、环境搭建

1. CentOS 7 一键安装脚本

# 1. 卸载旧版
yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine

# 2. 安装依赖 & 配置阿里云源
yum install -y yum-utils
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 3. 安装 Docker CE
yum install -y docker-ce docker-ce-cli containerd.io

# 4. 启动 & 开机自启
systemctl start docker && systemctl enable docker

# 5. 验证
docker version && docker run hello-world

2. Ubuntu 安装脚本

# 1. 卸载旧版
apt-get remove docker docker-engine docker.io containerd runc

# 2. 安装依赖
apt-get update
apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common

# 3. 添加 Docker GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -

# 4. 添加 Docker 仓库
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

# 5. 安装 Docker CE
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io

# 6. 启动 & 开机自启
systemctl start docker && systemctl enable docker

# 7. 验证
docker version && docker run hello-world

3. 镜像加速 (必配)

编辑 /etc/docker/daemon.json

{
  "registry-mirrors": ["https://<你的ID>.mirror.aliyuncs.com", "https://hub-mirror.c.163.com", "https://docker.mirrors.ustc.edu.cn"]
}

生效:systemctl daemon-reload && systemctl restart docker


三、高频命令速查表

1. 镜像管理 (Image)

操作 命令 备注
查找 docker search <name> --limit 5 限制返回数量
拉取 docker pull <name>:<tag> 不写 tag 默认为 latest
列表 docker images -q 仅显示 ID, -a 显示中间层
删除 docker rmi -f <id> -f 强制删除
清理 docker image prune 删除悬空镜像
构建 docker build -t <name>:<tag> . 基于 Dockerfile
导入/导出 docker save -o <file> <image> / docker load -i <file> 备份/恢复镜像

2. 容器管理 (Container)

操作 命令 关键参数/备注
运行 docker run [opts] <image> 见下方详解
列表 docker ps -a 所有, -q 仅 ID
启动/停止 docker start/stop/restart <id> kill 强制停止
删除 docker rm -f $(docker ps -aq) 强制删除所有容器
日志 docker logs -f --tail 100 <id> -f 跟踪, --tail 行数
进入 docker exec -it <id> bash 推荐,新开终端
拷贝 docker cp <id>:<path> <host_path> 双向拷贝
详情 docker inspect <id> 查看 IP、挂载点等 JSON 信息
统计 docker stats 查看容器资源使用情况

3. docker run 核心参数

docker run -d \
--name my-app \
-p 8080:80 \
-v /host/data:/app/data \
--privileged=true \
--restart=always \
--network my-net \
--memory 512m \
--cpus 1 \
<image_name>
  • -d: 后台运行
  • -p: 端口映射 (宿:容)
  • -v: 数据卷挂载 (宿:容)
  • --privileged=true: 赋予 root 权限 (解决 CentOS 挂载报错)
  • --restart=always: 崩溃自动重启
  • --network: 指定自定义网络
  • --memory: 内存限制
  • --cpus: CPU 限制

四、镜像制作 (Dockerfile)

1. 核心指令

  • FROM: 基础镜像 (必须第一行)
  • RUN: 构建时执行 (安装软件),每行一层
  • COPY/ADD: 复制文件 (ADD 支持解压/URL)
  • EXPOSE: 声明端口 (不自动映射)
  • ENV: 设置环境变量
  • WORKDIR: 设置工作目录
  • CMD/ENTRYPOINT: 启动命令 (CMD 可被覆盖,ENTRYPOINT 不易被覆盖)
  • VOLUME: 声明挂载点
  • ARG: 构建时参数
  • LABEL: 添加元数据

2. 最佳实践模板

FROM openjdk:8-jdk-alpine # 1. 使用小体积基础镜像
MAINTAINER yourname

WORKDIR /app
COPY target/my-app.jar app.jar # 2. 仅复制必要文件

ENV JAVA_OPTS="-Xms256m -Xmx256m"
EXPOSE 8080

# 3. 合并 RUN 减少层数,清理缓存
RUN apk add --no-cache curl && rm -rf /var/cache/apk/*

ENTRYPOINT ["java", "-jar", "app.jar"] # 4. 前台运行,避免容器退出

3. 多阶段构建 (Multi-stage)

# 编译阶段
FROM maven:3.8.4-openjdk-11 AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests

# 运行阶段
FROM openjdk:11-jre-slim
WORKDIR /app
COPY --from=builder /app/target/my-app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

五、数据持久化 (Volume)

痛点:容器删除,数据丢失。
方案:挂载宿主机目录或命名卷。

1. 常用挂载模式

# 直接挂载 (宿主机路径:容器路径)
-v /mydata/mysql/data:/var/lib/mysql

# 只读挂载
-v /config:/app/config:ro

# 继承其他容器的卷
--volumes-from <parent_container>

# 使用命名卷
docker volume create my-volume
-v my-volume:/app/data

2. 常见软件挂载清单

软件 关键挂载点 配置文件示例
MySQL /var/lib/mysql (数据), /etc/mysql/conf.d (配置) my.cnf (字符集, log-bin)
Redis /data (数据), /etc/redis/redis.conf (配置) appendonly yes (持久化)
Nginx /usr/share/nginx/html (网页), /etc/nginx (配置) nginx.conf
GitLab /etc/gitlab, /var/log/gitlab, /var/opt/gitlab -
Elasticsearch /usr/share/elasticsearch/data, /usr/share/elasticsearch/config elasticsearch.yml
MongoDB /data/db, /data/configdb mongod.conf

六、网络管理

1. 网络类型

网络类型 特点 适用场景
bridge 默认,容器间通过 IP 通信 单主机容器通信
host 移除网络隔离,直接使用宿主机网络 性能要求高的场景
overlay 跨主机通信 Swarm/K8s 集群
macvlan 给容器分配物理 MAC 地址 需要物理网络环境的场景
none 无网络 不需要网络的场景

2. 网络操作命令

# 创建网络
docker network create --driver bridge my-net

# 查看网络
docker network ls

# 查看网络详情
docker network inspect my-net

# 将容器加入网络
docker network connect my-net my-container

# 将容器从网络移除
docker network disconnect my-net my-container

# 删除网络
docker network rm my-net

七、实战部署案例

1. MySQL (主从复制)

Master 配置 (my.cnf):

[mysqld]
server_id=101
log-bin=mysql-bin
binlog_format=mixed
binlog-ignore-db=mysql
binlog-ignore-db=information_schema

Slave 配置 (my.cnf):

[mysqld]
server_id=102
relay_log=mysql-relay-bin
read_only=1

启动容器:

# Master
docker run -d --name mysql-master \
-p 3306:3306 \
-v /mydata/mysql/master/data:/var/lib/mysql \
-v /mydata/mysql/master/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.7

# Slave
docker run -d --name mysql-slave \
-p 3307:3306 \
-v /mydata/mysql/slave/data:/var/lib/mysql \
-v /mydata/mysql/slave/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.7

连接命令 (在 Slave 执行):

CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=107;
START SLAVE;
SHOW SLAVE STATUS\G; -- 检查 Seconds_Behind_Master 是否为 0

2. Redis Cluster (3 主 3 从)

# 1. 创建网络
docker network create redis-net

# 2. 启动 6 个节点
for port in $(seq 6381 6386); do
  mkdir -p /data/redis/node-$port
  docker run -d --name redis-node-$port --net redis-net -p $port:6379 \
  -v /data/redis/node-$port:/data \
  redis:6.0.8 redis-server --cluster-enabled yes --appendonly yes --cluster-config-file nodes.conf
  done

# 3. 组建集群 (在任意节点执行)
docker exec -it redis-node-6381 redis-cli --cluster create \
172.18.0.2:6379 172.18.0.3:6379 172.18.0.4:6379 \
172.18.0.5:6379 172.18.0.6:6379 172.18.0.7:6379 \
--cluster-replicas 1

3. Nginx 反向代理

配置文件 (nginx.conf):

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log /var/log/nginx/access.log main;
    sendfile on;
    keepalive_timeout 65;

    server {
        listen 80;
        server_name localhost;

        location / {
            root /usr/share/nginx/html;
            index index.html index.htm;
        }

        location /api {
            proxy_pass http://backend:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

启动容器:

docker run -d -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
--network my-net \
nginx:1.20

4. Spring Boot 应用

Dockerfile:

FROM openjdk:8-jdk-alpine
WORKDIR /app
COPY target/spring-boot-app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

构建并运行:

# 构建镜像
docker build -t spring-boot-app:1.0 .

# 运行容器
docker run -d --name spring-boot-app \
-p 8080:8080 \
-v /mydata/app/logs:/app/logs \
--network my-net \
spring-boot-app:1.0

八、Docker Compose (编排神器)

1. 核心结构

version: '3'
services:
  web:
    image: nginx
    ports: ["80:80"]
    volumes:
      - ./html:/usr/share/nginx/html
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on: [db]
    networks: [my-net]
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: example
      MYSQL_DATABASE: mydb
    volumes:
      - db-data:/var/lib/mysql
    networks: [my-net]
volumes:
  db-data:
networks:
  my-net:
    driver: bridge

2. 常用命令

命令 作用
docker-compose up -d 后台启动所有服务
docker-compose down 停止并删除容器、网络
docker-compose ps 查看状态
docker-compose logs -f 查看实时日志
docker-compose restart 重启服务
docker-compose build 构建服务镜像
docker-compose pull 拉取服务镜像
docker-compose exec <service> bash 进入容器

3. 实战案例:完整的 Web 应用栈

docker-compose.yml:

version: '3'
services:
  nginx:
    image: nginx:1.20
    ports: ["80:80"]
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./html:/usr/share/nginx/html
    depends_on: [app]
    networks: [app-net]

  app:
    build: ./spring-boot-app
    ports: ["8080:8080"]
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/mydb
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: 123456
    depends_on: [db]
    networks: [app-net]

  db:
    image: mysql:5.7
    ports: ["3306:3306"]
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: mydb
    volumes:
      - db-data:/var/lib/mysql
    networks: [app-net]

volumes:
  db-data:

networks:
  app-net:
    driver: bridge

九、Docker Swarm (集群管理)

1. 核心概念

  • 节点 (Node):集群中的主机,分为 Manager 和 Worker
  • 服务 (Service):运行在集群上的容器集合
  • 任务 (Task):服务的最小运行单位,一个容器实例
  • 堆栈 (Stack):由多个服务组成的应用

2. 基本操作

# 初始化集群 (在 Manager 节点执行)
docker swarm init --advertise-addr <manager-ip>

# 加入集群 (在 Worker 节点执行)
docker swarm join --token <token> <manager-ip>:2377

# 查看节点
docker node ls

# 创建服务
docker service create --name web --replicas 3 -p 80:80 nginx

# 查看服务
docker service ls

# 扩展服务
docker service scale web=5

# 删除服务
docker service rm web

# 部署堆栈
docker stack deploy -c docker-compose.yml my-stack

# 查看堆栈
docker stack ls

# 删除堆栈
docker stack rm my-stack

十、故障排查与最佳实践

1. 常见问题

  • 容器启动后立即退出

    • 原因:没有前台进程。
    • 解决:确保 CMD/ENTRYPOINT 运行的是前台程序 (如 nginx -g 'daemon off;')。
  • 挂载卷权限 denied

    • 原因:SELinux 或宿主目录权限。
    • 解决:加 --privileged=truechown -R 1000:1000 /host/path
  • 网络不通

    • 原因:防火墙或未加入同一网络。
    • 解决:firewall-cmd --zone=public --add-masquerade --permanent 或使用自定义网络。
  • 镜像拉取失败

    • 原因:网络问题或镜像不存在。
    • 解决:配置镜像加速或检查镜像名称和标签。

2. 最佳实践

  • 镜像优化:使用 Alpine 基础镜像,多阶段构建,清理缓存。
  • 数据安全:敏感信息用环境变量或 Secret,不要硬编码。
  • 日志管理:配置 logging-driver 限制日志大小,避免占满磁盘。
  • 资源限制:生产环境务必加 --memory--cpus 防止资源耗尽。
  • 版本锁定:镜像 Tag 不要用 latest,指定具体版本号。
  • 健康检查:为容器添加健康检查,确保服务正常运行。
  • 定期清理:定期清理悬空镜像、停止的容器和未使用的卷。
  • 监控告警:配置 Prometheus + Grafana 监控容器运行状态。

3. 监控与日志

Docker 自带监控

# 查看容器资源使用情况
docker stats

# 查看容器日志
docker logs -f <container-id>

ELK 日志收集

version: '3'
services:
  elasticsearch:
    image: elasticsearch:7.14.0
    environment:
      - discovery.type=single-node
    ports: ["9200:9200"]
    volumes: ["es-data:/usr/share/elasticsearch/data"]

  logstash:
    image: logstash:7.14.0
    volumes:
      - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
    depends_on: [elasticsearch]

  kibana:
    image: kibana:7.14.0
    ports: ["5601:5601"]
    depends_on: [elasticsearch]

volumes:
  es-data:

十一、Docker 安全

1. 安全最佳实践

  • 使用官方镜像:从 Docker Hub 官方仓库拉取镜像。
  • 最小化镜像:只安装必要的软件包,减少攻击面。
  • 非 root 用户:在 Dockerfile 中创建非 root 用户并切换。
  • 定期更新:定期更新镜像和基础系统。
  • 网络隔离:使用自定义网络,限制容器间通信。
  • 资源限制:设置 CPU、内存和磁盘限制。
  • 只读文件系统:对不需要写入的容器使用 --read-only
  • Secret 管理:使用 Docker Secret 或外部密钥管理服务。

2. 安全扫描

使用 Trivy 扫描镜像

# 安装 Trivy
docker pull aquasec/trivy

# 扫描镜像
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image <image-name>
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐