一、Docker 基础概念

1. 什么是 Docker

Docker 是基于 Linux 内核容器技术 的开源容器化平台; 容器:操作系统级虚拟化,共享宿主机内核,独立文件系统、网络、进程空间;

对比虚拟机:

  • 虚拟机:Hypervisor + 完整 OS,笨重、启动慢、资源开销大
  • Docker 容器:共享宿主机内核,只打包应用 + 依赖,轻量、秒级启动

2. 核心四大组件

  1. Docker Engine(引擎):C/S 架构,后台守护进程 dockerd
  2. Docker Client(客户端)docker 命令行,和 daemon 通信
  3. Docker Registry(仓库):存放镜像,官方:Docker Hub;私有仓库:Harbor
  4. Docker Objects 对象:镜像、容器、网络、数据卷

3. 镜像 (Image) vs 容器 (Container)

  • 镜像:只读模板,分层文件系统,静态模板(类程序安装包)
  • 容器:镜像运行实例,镜像启动后生成可读写层(类进程)

一句话:镜像创建容器,一个镜像可以启动 N 个容器

4. 分层存储原理

  • 镜像由多层只读层叠加;
  • 启动容器,自动在最上层新增可读写层
  • 容器删除,仅销毁读写层,底层镜像不变;
  • 相同镜像层复用,节省磁盘空间。

5. UnionFS 联合文件系统

Docker 底层存储驱动,实现多层文件叠加,AUFS/overlay2(主流默认 overlay2)。

(如果容器要修改一个只读层里的文件: 触发 写时复制(CoW Copy-on-Write) 把文件复制一份到顶层可写层,修改副本;底层原始文件纹丝不动。)

  1. 宿主机 Linux 内核 bootfs 打底
  2. 加载一堆只读镜像层(centos→jdk→tomcat)
  3. docker run 启动容器 → 新增一层可写容器层
  4. UnionFS 把所有层联合,合成完整 rootfs 给容器使用
  5. 容器内所有文件改动全部保存在顶层读写层
  6. 执行 docker commit:读写层改动固化为新只读镜像,生成新镜像
  7. docker rm 容器:仅仅销毁顶层可写层,底层所有只读镜像保留

三、安装与基础环境

1. 系统要求

Linux 内核 ≥3.10,推荐 CentOS7+/Ubuntu18.04+; Windows/Mac 使用 Docker Desktop(内置虚拟机)

2. 核心配置文件

  • /etc/docker/daemon.json(最重要!) 常用配置:镜像加速器、日志驱动、存储驱动、代理、私有仓库 http 支持
{
  // 配置国内镜像加速,拉镜像更快
  "registry-mirrors": \["阿里云镜像地址"\],
  // 日志使用默认json文件方式存储
  "log-driver": "json-file",
  // 日志文件单文件上限100M,最多保存3个,防止撑爆磁盘
  "log-opts": {"max-size":"100m","max-file":"3"},
  // 使用overlay2存储驱动,管理镜像分层、容器读写层
  "storage-driver": "overlay2"
}

生效命令

systemctl daemon-reload
systemctl restart docker

3. 服务管理

systemctl start docker
systemctl stop docker
systemctl enable docker
# 查看docker信息
docker info
# 查看版本
docker version

四、Docker 镜像操作命令

# 搜索镜像
docker search nginx
# 拉取镜像
docker pull nginx:1.25
# 列出本地镜像
docker images
# 删除镜像
docker rmi 镜像ID/镜像名
# 导出镜像(离线)
docker save -o nginx.tar nginx:1.25
# 导入镜像
docker load -i nginx.tar
# 镜像打标签
docker tag nginx:1.25 harbor.local/nginx:v1
# 推送镜像到私有仓库
docker push harbor.local/nginx:v1
# 查看镜像分层历史
docker history nginx
# 清理无用镜像
docker image prune -a

五、容器生命周期 & 容器命令

容器生命周期

创建 → 启动 → 运行 → 暂停 / 停止 → 删除

# 创建并启动容器
docker run [参数] 镜像名

# 常用run参数
-d          # 后台运行(守护进程)
-p 宿主机端口:容器端口  # 端口映射
--name      # 指定容器名称
-v 宿主机目录:容器目录  # 数据挂载
--network   # 指定网络
-e KEY=VAL  # 设置环境变量
--restart=always # 容器退出自动重启
#容器退出之后,Docker 是否自动重启这个容器
#参数  no             不重启
       on-failure     异常退出重启
       always         无论什么原因退出,一律自动重启
       unless-stopped 手动 stop 之后,重启宿主机不会拉起

-it         # 交互式终端
--rm        # 容器停止自动删除

# 示例
docker run -d --name nginx -p 80:80 nginx

# 查看运行中容器
docker ps
# 查看所有容器(含停止)
docker ps -a

# 启动/停止/重启容器
docker start 容器名
docker stop 容器名 # 优雅关闭(10s超时)
docker kill 容器名 # 强制杀死

# 删除容器
docker rm 容器名
# 批量删除停止容器
docker container prune

# 进入运行中容器
docker exec -it nginx /bin/bash

# 查看容器日志
docker logs nginx
# 实时跟踪日志
docker logs -f --tail 100 nginx

# 查看容器资源占用
docker stats

# 容器与宿主机拷贝文件
docker cp 宿主机文件 容器名:/路径
docker cp 容器名:/路径 宿主机路径

# 查看容器详细信息(IP、挂载、配置)
docker inspect 容器名

六、Dockerfile 镜像构建(核心重点)

1. Dockerfile 构建流程

docker build -t myapp:v1 . 读取 Dockerfile → 逐层执行指令 → 生成镜像;每一条指令生成一层缓存。

2. 常用指令大全

指令作用
FROM基础镜像,必须第一条
MAINTAINER维护者(废弃,推荐 LABEL)
LABEL镜像元数据标签
ENV设置环境变量
ARG构建阶段临时变量(容器运行不可见)
WORKDIR设置工作目录(自动创建)
COPY复制宿主机文件到镜像,支持文件保留权限
ADD复制 + 自动解压 tar 包,远程 URL 下载(不推荐优先用 COPY)
RUN构建时执行命令,生成镜像层
CMD容器默认启动命令,可被 run 传入参数覆盖
ENTRYPOINT入口程序,CMD 作为参数传给它
EXPOSE声明容器使用端口(仅文档,不会自动映射端口)
VOLUME声明匿名数据卷
USER指定运行用户,不要默认 root 运行
HEALTHCHECK容器健康检查

3. CMD vs ENTRYPOINT 区别

  1. Dockerfile 中 ENTRYPOINTCMD 都是指定容器启动命令,核心区别:

  2. ENTRYPOINT:定义容器主执行程序
  3. CMD:作为默认参数传给 ENTRYPOINT;运行时传入指令可以覆盖 CMD,但不能直接覆盖 ENTRYPOINT。

另外语法分 shell 模式exec 数组模式[],生产统一推荐exec 数组格式,shell 模式会产生 shell 子进程,无法接收信号,docker stop不能优雅关闭进程。

分两种组合模式:

只有 CMDdocker run 镜像 传入参数,参数直接完全替换 CMD; ENTRYPOINT + CMD 配合:传入参数覆盖 CMD,追加给 ENTRYPOINT 执行;

4. 多阶段构建 Multi-stage(减小镜像体积)

适用:Java、Go、前端编译,编译环境和运行环境分离

# 编译阶段
FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN go build -o app main.go


# 运行阶段(只拷贝二进制,无编译环境) --from=builder  起作用 只需要编译的结果 不需要环境
FROM alpine
COPY --from=builder /app/app /usr/local/bin/
CMD ["/usr/local/bin/app"]

5. 构建缓存优化

文件变更越少,越能命中缓存; 把频繁变动代码放 Dockerfile 靠后位置;不常变动依赖靠前。

七、Docker 数据持久化(Volume)

容器删除后读写层数据丢失,三种持久化方案:

  1. Volume 数据卷(推荐) docker 管理,宿主机路径 /var/lib/docker/volumes/xxx/_data
# 创建卷
docker volume create nginx-data
# 使用卷
docker run -v nginx-data:/usr/share/nginx/html nginx
  1. Bind Mount 绑定挂载 手动指定宿主机任意目录和容器目录映射(开发常用)-v /host/html:/usr/share/nginx/html
  2. Tmpfs Mount 内存挂载 数据存内存,重启丢失,用于临时机密数据

读写权限

:ro 容器内只读 -v /host:/container:ro

数据卷命令

docker volume ls
docker volume inspect xxx
docker volume rm xxx
# 删除未使用卷
docker volume prune

最佳实践:生产优先使用 Volume,不要直接宿主机目录挂载管理权限。

八、Docker 网络(重中之重)

Docker 内置 5 种网络驱动模式

# 查看网络
docker network ls
# 创建自定义网络
docker network create mynet

1. bridge(默认)

默认网桥 docker0;同一 bridge 内容器互通;跨 bridge 默认不通;容器通过宿主机 SNAT 访问外网。

注意:不要使用默认 docker0,推荐自定义 bridge 网络,支持 DNS 自动解析容器名!默认的docker0 容器之间无法通过容器名访问,以前没考虑到

2. host

容器直接共享宿主机网络栈,不再端口映射;容器 IP = 宿主机 IP;隔离最弱。

3. none

关闭所有网络,无网卡,完全隔离。

4. container 复用网络

--net container:其他容器ID,和另一个容器共享网卡(sidecar 常用)

docker run -it --name sidecar --network container:main-nginx1 alpine

新创建的容器不创建独立网络栈,直接共享另一个已有容器的:

  1. 两个容器 IP 完全一样!
  2. 端口不能冲突:A 容器占用 80 端口,复用网络的 B 容器不能再监听 80
  3. 容器之间通信:直接 127.0.0.1 互通(像本机进程)
  4. 经典场景:Sidecar 边车模式(日志采集、监控代理)

5. overlay(Swarm 集群网络)

跨主机容器通信,Docker Swarm 集群使用。

网络关键特性

  • 自定义 bridge 网络:容器之间可以直接用容器名称 DNS 通信,默认 docker0 不支持!
  • 端口映射原理:iptables DNAT
  • 外部访问容器:宿主机防火墙放行端口
# 容器加入已有网络
docker run --network mynet
# 容器动态连接网络,相当于两块网卡,加入另外一个交换机
docker network connect mynet 容器名

九、Docker Compose(单机多容器编排)

作用

通过 yaml 文件定义一组容器,一键启动 / 停止依赖服务(开发、测试环境首选) 文件默认名称 docker-compose.yml

核心命令

# 创建并启动服务
docker-compose up -d
# 停止
docker-compose down
# 重启
docker-compose restart
# 查看日志
docker-compose logs -f
# 构建镜像
docker-compose build
# 扩缩容
docker-compose up -d --scale app=3

yaml 核心字段

version: "3.8"
services:
  nginx:
    image: nginx
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html
    networks:
      - webnet
    depends_on:
      - app
    restart: always
networks:
  webnet:
volumes:
  data:

注意:depends_on 只控制启动顺序,不等待服务就绪,需要程序内部重试。

十、Docker 安全要点

  1. 尽量不以 root 用户运行容器 USER xxx
--user test
  1. 禁用特权容器 --privileged(高危)
  2. 只读文件系统 --read-only(整个容器都不可以写,:ro只是挂载的不可以写)
  3. 资源限制:CPU、内存
--memory 512m --cpus 0.5
  1. 镜像扫描,不要使用未信任公共镜像
  2. 宿主机内核安全,定期更新
  3. 限制 capabilities 能力 --cap-drop=ALL
  4. 不要把宿主机 docker.sock 挂载进容器(权限逃逸)
# 一旦挂载,容器内可以操控宿主机docker,权限逃逸
docker run -v /var/run/docker.sock:/var/run/docker.sock xxx

十一、资源限制

run 参数限制容器资源,防止容器耗尽宿主机资源

# 内存限制
--memory 1g
# CPU核心
--cpus 1.5
# 内存+swap
--memory-swap 2g

十二、Docker 日志

默认驱动 json-file; 生产一定要配置日志滚动,防止磁盘打满 daemon.json 配置日志最大大小

"log-driver": "json-file",
"log-opts": {
  "max-size": "100m",
  "max-file": "3"
}

十三、harbor私有仓库

1、下载离线安装包

wget https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-offline-installer-v2.10.0.tgz
tar zxvf harbor-offline-installer-v2.10.0.tgz
cd harbor

2、复制配置模板

cp harbor.yml.tmpl harbor.yml

3、配置 harbor.yml

设置 hostname: harbor.local

记住密码  Harbor12345

# 修改1:主机名,不要用IP,尽量域名
hostname: harbor.local

# 修改2:https配置
#https:
 ## port: 443
 # certificate: /data/harbor/cert/harbor.crt
 # private_key: /data/harbor/cert/harbor.key

# http关闭(生产)
http:
  port: 80
  # 可选:关闭http
  # relative_url: false

# admin初始密码,务必修改
harbor_admin_password: Harbor12345

# 数据持久化目录
data_volume: /data/harbor/data

# 漏洞扫描器,启用trivy
trivy:
  enabled: true

4.测试环境 HTTP(不推荐生产)

修改 docker daemon 配置 `/etc/docker/daemon.json`

```
{
  "insecure-registries": ["harbor.local"]
}
```

重启 docker

风险:明文传输镜像,用户名密码泄露,仅测试使用!

4、执行安装

# 自动生成docker-compose.yml、配置文件
./install.sh

5、查看并且进入

docker compose ps

访问:https://harbor.local 账号:admin,密码配置文件内设置

6、登录 Harbor

docker login harbor.local
# 输入admin / 密码

7、 镜像标签规范

格式:harbor地址/项目名称/镜像名:版本

# 原始镜像
docker pull nginx:1.24

# 重新打标签
docker tag nginx:1.24 harbor.local/library/nginx:1.24

注意:必须指定项目名,library 是 Harbor 默认公开项目

8. 推送镜像

docker push harbor.local/library/nginx:1.24

9. 其他机器拉取镜像

# 同样需要配置证书/insecure-registry
docker pull harbor.local/library/nginx:1.24

更多推荐