
一、Docker 基础概念
1. 什么是 Docker
Docker 是基于 Linux 内核容器技术 的开源容器化平台; 容器:操作系统级虚拟化,共享宿主机内核,独立文件系统、网络、进程空间;
对比虚拟机:
- 虚拟机:Hypervisor + 完整 OS,笨重、启动慢、资源开销大
- Docker 容器:共享宿主机内核,只打包应用 + 依赖,轻量、秒级启动
2. 核心四大组件
- Docker Engine(引擎) :C/S 架构,后台守护进程
dockerd - Docker Client(客户端) :
docker命令行,和 daemon 通信 - Docker Registry(仓库):存放镜像,官方:Docker Hub;私有仓库:Harbor
- Docker Objects 对象:镜像、容器、网络、数据卷
3. 镜像 (Image) vs 容器 (Container)
- 镜像:只读模板,分层文件系统,静态模板(类程序安装包)
- 容器:镜像运行实例,镜像启动后生成可读写层(类进程)
一句话:镜像创建容器,一个镜像可以启动 N 个容器
4. 分层存储原理
- 镜像由多层只读层叠加;
- 启动容器,自动在最上层新增可读写层;
- 容器删除,仅销毁读写层,底层镜像不变;
- 相同镜像层复用,节省磁盘空间。
5. UnionFS 联合文件系统
Docker 底层存储驱动,实现多层文件叠加,AUFS/overlay2(主流默认 overlay2)。
(如果容器要修改一个只读层里的文件: 触发 写时复制(CoW Copy-on-Write) 把文件复制一份到顶层可写层,修改副本;底层原始文件纹丝不动。)
- 宿主机 Linux 内核 bootfs 打底
- 加载一堆只读镜像层(centos→jdk→tomcat)
- docker run 启动容器 → 新增一层可写容器层
- UnionFS 把所有层联合,合成完整 rootfs 给容器使用
- 容器内所有文件改动全部保存在顶层读写层
- 执行
docker commit:读写层改动固化为新只读镜像,生成新镜像 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 区别
-
Dockerfile 中
ENTRYPOINT和CMD都是指定容器启动命令,核心区别: - ENTRYPOINT :定义容器主执行程序;
- CMD :作为默认参数传给 ENTRYPOINT;运行时传入指令可以覆盖 CMD,但不能直接覆盖 ENTRYPOINT。
另外语法分 shell 模式 和 exec 数组模式[] ,生产统一推荐exec 数组格式 ,shell 模式会产生 shell 子进程,无法接收信号,docker stop不能优雅关闭进程。
分两种组合模式:
只有 CMD :docker 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)
容器删除后读写层数据丢失,三种持久化方案:
-
Volume 数据卷(推荐) docker 管理,宿主机路径
/var/lib/docker/volumes/xxx/_data创建卷
docker volume create nginx-data
使用卷
docker run -v nginx-data:/usr/share/nginx/html nginx
-
Bind Mount 绑定挂载 手动指定宿主机任意目录和容器目录映射(开发常用)
-v /host/html:/usr/share/nginx/html -
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
新创建的容器不创建独立网络栈,直接共享另一个已有容器的:
- 两个容器 IP 完全一样!
- 端口不能冲突:A 容器占用 80 端口,复用网络的 B 容器不能再监听 80
- 容器之间通信:直接
127.0.0.1互通(像本机进程) - 经典场景: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 安全要点
-
尽量不以 root 用户运行容器
USER xxx--user test
-
禁用特权容器
--privileged(高危) -
只读文件系统
--read-only(整个容器都不可以写,:ro只是挂载的不可以写) -
资源限制:CPU、内存
--memory 512m --cpus 0.5
-
镜像扫描,不要使用未信任公共镜像
-
宿主机内核安全,定期更新
-
限制 capabilities 能力
--cap-drop=ALL -
不要把宿主机 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 默认公开项目
-
推送镜像
docker push harbor.local/library/nginx:1.24
-
其他机器拉取镜像
同样需要配置证书/insecure-registry
docker pull harbor.local/library/nginx:1.24