其它(4):Docker 知识体系

0 阅读5分钟

Docker 知识体系

一、Docker 和虚拟机的区别

image.png Docker 不是虚拟机。容器共享宿主机内核,虚拟机则有完整 Guest OS 和独立内核。

维度Docker 容器虚拟机
隔离层级进程级隔离,共享宿主机内核硬件级虚拟化,独立操作系统
启动速度秒级甚至更快通常更慢
资源开销较小较大
隔离强度相对弱,依赖内核能力更强
典型场景应用交付、微服务部署、CI多系统运行、强隔离环境

二、核心原理:Namespace、UnionFS

Docker 本质上不是“发明了一种新进程”,而是把 Linux 已有能力组合起来。

1. Namespace:让进程“看不见别人”

Namespace 负责隔离视图,让容器里的进程以为自己拥有独立的系统环境。

Namespace隔离内容例子
PID进程号空间容器内进程可以看到自己是 PID 1
NET网络设备、IP、端口、路由表每个容器有自己的网卡和端口空间
MNT挂载点容器看到自己的根文件系统
UTS主机名和域名容器可以有独立 hostname
IPC进程间通信资源隔离共享内存、信号量等
USER用户和用户组 ID容器内 root 可映射为宿主机普通用户

一句话:Namespace 管“看见什么”。

2. UnionFS:镜像为什么能分层

镜像由多层只读 Layer 叠加而成,容器启动后会在最上面加一个可写层。

好处:

  1. 复用:多个镜像可以共享相同基础层,例如 ubuntualpine
  2. 缓存:Dockerfile 每一条指令通常会生成一层,未变化的层可以复用。
  3. 回滚:镜像天然有版本和层级结构,便于分发。

容器删除后,默认可写层也会删除;需要持久化的数据应该放到数据卷里。


三、镜像、容器、仓库

image.png

1. 三个概念

概念含义
镜像 Image只读模板,包含应用和依赖
容器 Container镜像运行后的实例,有自己的可写层
仓库 Registry存放和分发镜像的地方,如 Docker Hub、Harbor

关系可以理解为:

Dockerfile -> build -> Image -> run -> Container

四、Dockerfile 怎么写

Dockerfile 是镜像构建说明书,核心目标是:可复现、体积小、缓存友好、安全。

1. CMD 和 ENTRYPOINT 区别

  • CMD 更像默认参数,运行时容易被覆盖。
  • ENTRYPOINT 更像固定入口,适合封装一个可执行程序。
ENTRYPOINT ["java", "-jar", "app.jar"]
CMD ["--server.port=8080"]

运行时:

docker run app --server.port=9090

会把 CMD 替换成新的参数,但入口仍是 java -jar app.jar

2. Go 项目示例:多阶段构建

FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o server ./cmd/server

FROM alpine:3.19
WORKDIR /app
COPY --from=builder /app/server /app/server
EXPOSE 8080
ENTRYPOINT ["/app/server"]

多阶段构建的意义:

  1. 编译环境留在 builder 阶段,最终镜像只放运行产物。
  2. 减少镜像体积。
  3. 降低攻击面。

五、Docker 网络

image.png Docker 常见网络模式:

模式特点使用场景
bridge默认模式,容器接入 docker0 网桥单机容器互通
host共享宿主机网络命名空间追求性能、端口直接暴露
none无网络极端隔离场景
overlay跨主机容器网络Swarm、K8s 类场景

1. bridge 模式

默认情况下,Docker 会创建一个 docker0 网桥。容器连接到这个网桥上,容器访问外部网络时通常通过 NAT 出去。

docker network ls
docker network inspect bridge

端口映射:

docker run -p 8080:80 nginx

含义是:宿主机 8080 端口转发到容器内 80 端口。

2. 自定义网络

推荐使用自定义 bridge 网络,因为容器名可以自动 DNS 解析。

docker network create app-net
docker run -d --name mysql --network app-net mysql:8
docker run -d --name app --network app-net myapp:v1

此时 app 容器可以通过 mysql:3306 访问数据库。

3. host 模式

docker run --network host nginx

容器直接使用宿主机网络,不再有独立端口空间。

优点:少一层 NAT,性能和排查更直接。 缺点:隔离性下降,端口冲突风险更高。


六、数据卷

image.png 容器的可写层不适合保存长期数据,删除容器后数据可能一起丢失。持久化应该使用 Volume 或 Bind Mount。

1. Volume

由 Docker 管理,默认存放在 Docker 的数据目录下。

docker volume create mysql-data
docker run -d \
  --name mysql \
  -v mysql-data:/var/lib/mysql \
  mysql:8

适合数据库、上传文件、需要由 Docker 管理生命周期的数据。

2. Bind Mount

把宿主机目录挂载进容器。

docker run -d \
  --name nginx \
  -v /host/html:/usr/share/nginx/html \
  nginx

适合本地开发、配置文件挂载、日志目录挂载。

3. Volume 和 Bind Mount 对比

维度VolumeBind Mount
管理方式Docker 管理用户指定宿主机路径
可移植性更好依赖宿主机目录结构
适合场景生产数据持久化开发调试、配置挂载
风险需要理解 volume 生命周期容易误改宿主机文件

七、Docker Compose

Compose 适合描述一组服务,比如应用、MySQL、Redis、NSQ 一起启动。

services:
  app:
    image: myapp:v1
    ports:
      - "8080:8080"
    environment:
      MYSQL_ADDR: mysql:3306
    depends_on:
      - mysql

  mysql:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: app
    volumes:
      - mysql-data:/var/lib/mysql

volumes:
  mysql-data:

注意:depends_on 只能保证启动顺序,不保证 MySQL 已经准备好接受连接。应用侧仍要有重试机制。