Docker容器技术
1 Docker介绍
1.1 Docker简介
1.1.1 什么是Docker
**定义:**Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
**核心价值:**Build Once, Run Anywhere:一次构建,到处运行。
**轻量级:**容器共享宿主机内核,无需像虚拟机那样模拟完整的操作系统。
Docker是管理容器的引擎,为应用打包、部署平台,就好比比传统的货运集装箱,而非单纯的虚拟化技术。
特点和优势:
- 轻量级虚拟化:启动一个Docker容器可能只需要几秒钟,而启动一个虚拟机则可能需要几分钟。
- 一致性:开发、测试、生产环境完全一样,告别“环境不一致”问题。
- 可移植性:本地打包好的容器,可以无缝部署到云服务器上。
- 高效的资源利用:一台机器能跑上百个容器,而虚拟机只能跑几十个。
- 易于部署和扩展:流量大了多开几个容器,小了关掉,非常灵活。
Docker极大地简化了应用程序的开发、部署和管理流程,提高了开发效率和运维的便利性。它在现代软件开发和云计算领域得到了广泛的应用。
1.1.2 Docker在企业中的应用场景
Docker把应用打包成一个 “标准小盒子”,走到哪都能直接跑,不用再配环境、不用再装依赖、也就不会出现 “环境不一致” 的问题。
场景
-
统一开发、测试、生产环境
开发打包好一个 Docker 镜像,测试直接用,上线也直接用;环境完全一致,不会出现 “版本不一样、依赖不一样” 导致的 bug。
-
快速部署、快速扩容
以前部署一个服务要装 Java、装数据库、配配置文件,可能半小时;用 Docker 一条命令启动,几秒钟搞定;当流量大了就多启动几个容器,流量小了关掉,非常灵活。
-
节省服务器资源
虚拟机要占一整个操作系统,很重;Docker 共享宿主机内核,非常轻量;一台机器能跑几十上百个容器,资源利用率高很多。
-
微服务架构的基石
现在企业都拆微服务:订单、用户、支付、商品…… 每个服务一个容器;Docker就是微服务的 “最小运行单元”。
-
CI/CD 自动化发布流水线
代码提交–>自动构建镜像–>自动测试–>自动上线;整个流程无人干预,Docker 是核心载体。
云计算的三层服务模式
- Docker:把应用打包成标准盒子,轻量、一致、随处可跑。
- IaaS:给你服务器,你自己搭环境。
- PaaS:给你运行平台,你只管代码。
- SaaS:给你现成软件,直接用。
-
IaaS(Infrastructure as a Service):基础设施即服务
买的是"服务器硬件"本身。
- 云厂商给:虚拟机、硬盘、网络、IP
- 自己装:操作系统、数据库、中间件、应用
- 例子:阿里云 ECS、华为云 ECS、AWS EC2
-
PaaS(Platform as a Service):平台即服务
买的是"运行平台",不用管服务器。
- 云厂商给:操作系统、运行环境、数据库、中间件
- 只需要:上传代码运行
- Docker + Kubernetes 本质就是企业自建的 PaaS 平台
-
SaaS(Software as a Service):软件即服务
买的是"直接能用的软件"
- 不用部署、不用维护,打开就用
- 例子:钉钉、企业微信、飞书、阿里云邮箱、各种在线 CRM
Docker跟这三层的关系
- 传统应用跑在:IaaS 虚拟机里
- Docker容器也可以跑在:IaaS 虚拟机上
- 一堆 Docker 用 K8s 管理—>就变成了企业自己的 PaaS 平台
- 企业把服务做成 Docker 镜像发布–>对外就是 SaaS
1.1.3 Docker与虚拟化的对比

| 对比维度 | 虚拟机 (VM) | Docker 容器 | 核心差异 |
|---|---|---|---|
| 操作系统 | 宿主机上运行独立的虚拟机 OS | 共享宿主机 OS 内核 | 容器无需完整 OS,仅打包应用 + 依赖 |
| 架构层级 | Hypervisor 虚拟化层 | Docker Engine 容器引擎层 | 容器直接运行在宿主机内核,无 Hypervisor overhead |
| 存储/镜像大小 | 镜像较大(GB 级别) | 镜像极小(MB 级别) | 容器镜像仅包含运行时必要组件,无冗余系统文件 |
| 性能/资源占用 | 有操作系统额外的 CPU、内存消耗,资源占用高 | 几乎无性能损耗,资源占用低 | 容器共享宿主机内核,无独立 OS 的资源开销 |
| 启动速度 | 慢,分钟级 | 快,秒级 | 容器无需启动完整操作系统,仅启动应用进程 |
| 隔离性 | 完全隔离(强隔离) | 进程级安全隔离(基于 Namespace/Cgroups) | 虚拟机隔离性更强,容器隔离性满足业务需求且更高效 |
| 移植性/迁移 | 笨重,与虚拟化技术耦合度高 | 轻量、灵活迁移 | 容器镜像标准化,可在任意 Docker 环境一致运行 |
| 部署效率 | 慢,分钟级部署 | 快速,秒级部署 | 容器支持 CI/CD 流水线,实现秒级发布 / 回滚 |
| 运行密度 | 单机一般仅能运行几十个 | 单机支持上千个容器 | 容器资源利用率极高,大幅提升服务器承载能力 |
选虚拟机:需要强安全隔离、运行不同 OS、对环境完全可控的场景(如多租户隔离、传统单体应用)
选 Docker 容器:追求高效、快速部署、微服务架构、CI/CD 自动化的场景(如云原生、弹性扩容)
| 核心特性 | 虚拟机 | Docker 容器 |
|---|---|---|
| 本质 | 硬件级虚拟化,模拟完整计算机 | 操作系统级虚拟化,隔离进程 |
| 资源 | 高(独立 OS) | 低(共享内核) |
| 启动 | 分钟级 | 秒级 |
| 隔离 | 强(完全隔离) | 中(进程级隔离) |
| 镜像 | GB 级 | MB 级 |
| 适用场景 | 强隔离、多 OS 需求 | 微服务、快速部署、CI/CD |
1.2 容器工作方法

容器与宿主机共享操作系统内核,每个容器运行在独立的命名空间中,实现了资源隔离与轻量级虚拟化。
1.3 Docker 的三大核心组件
- **镜像 (Image):**只读模板,包含运行容器所需的代码、库、环境变量和配置文件。(类比:类的定义)
- **容器 (Container):**镜像的运行实例。可以被启动、停止、删除。(类比:类的实例)
- **仓库 (Registry):**集中存放镜像文件的场所。分为公有仓库(Docker Hub)和私有仓库(Harbor)。
1.4 容器底层技术原理
为什么这么轻量又隔离
- **Namespace (命名空间):**提供视图隔离(PID, NET, IPC, UTS, USER, MNT)。
- **Cgroups (控制组):**限制资源使用(CPU, 内存, 磁盘 I/O)。
- **UnionFS (联合文件系统):**支持分层镜像,实现Copy-on-Write (写时复制)。
2 Docker镜像管理
2.1 镜像基本操作
| 操作 | 命令示例 | 说明 |
|---|---|---|
| 搜索镜像 | docker search nginx | 在Docker Hub中搜索镜像 |
| 拉取镜像 | docker pull nginx:alpine | 从仓库下载镜像 |
| 查看镜像 | docker images | 列出本地所有镜像 |
| 导出镜像 | docker save -o nginx.tar nginx:alpine | -o指定导出路径,支持.tar.gz压缩 |
| 删除镜像 | docker rmi nginx:alpine | 删除本地镜像 |
# 1.搜索镜像
[root@Docker-node1 ~]# docker search nginx
NAME DESCRIPTION STARS OFFICIAL
nginx Official build of Nginx. 20094 [OK]
………………
# NAME-->镜像名称;DESCRIPTION-->镜像说明;STARS-->点赞数量;OFFICIAL-->是否是官方的
# 2.拉取镜像
# 从镜像仓库中拉取镜像
[root@Docker-node1 ~]# docker pull busybox
[root@Docker-node1 ~]# docker pull nginx:1.26-alpine
# 3.查看镜像
# 查看本地系统中的镜像列表
[root@Docker-node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 900dca2a61f5 7 weeks ago 188MB
nginx 1.26-alpine b32ed582bddb 7 weeks ago 43.2MB
ubuntu latest 35a88802559d 2 months ago 78.1MB
busybox latest 65ad0d468eb1 15 months ago 4.26MB
centos 7 eeb6ee3f44bd 2 years ago 204MB
centos latest 5d0da3dc9764 2 years ago 231MB
gcr.io/distroless/base-debian12 latest 7273f3276b21 N/A 20.7MB
gcr.io/distroless/base-debian11 latest 2a6de77407bf N/A 20.6MB
# alpine 版本:nginx镜像的最小安装发型版本
# 查看镜像的详细信息
[root@Docker-node1 ~]# docker image inspect nginx:1.26-alpine
# 查看对镜像的更改记录
[root@docker-node1 ~]# docker history nginx:latest
# 4.导出镜像
# 保存镜像
[root@Docker-node1 ~]# docker image save nginx:latest -o nginx-latest.tar.gz
[root@Docker-node1 ~]# docker image save nginx:latest nginx:1.26-alpine -o nginx.tag.gz
# 保持所有镜像
[root@Docker-node1 ~]# docker save `docker images | awk 'NR>1{print $1":"$2}'` -o images.tar.gz
# 5.删除镜像
[root@Docker-node1 ~]# docker rmi nginx:latest
[root@Docker-node1 ~]# docker rmi `docker images | awk 'NR>1{print $1":"$2}'`
2.2 镜像获取方式
| 方式 | 命令示例 | 说明 |
|---|---|---|
| 从仓库拉取 | docker pull nginx:alpine | 从Docker Hub等公共仓库下载 |
| 从本地文件加载 | docker load -i nginx.tar | 导入之前导出的镜像包 |
| 从Dockerfile构建 | docker build -t mynginx:v1 . | 使用当前目录的Dockerfile构建 |
| 从容器提交 | docker commit container myimage | 不推荐,企业应用请用Dockerfile |
2.3 Docker镜像结构

- 共享宿主机的内核
- Base镜像提供最小的Linux发行版
- 同一Docker主机支持运行多种Linux发行版
- 分层结构的最大好处是:共享资源
- 一个镜像最多127层
写时复制(Copy-on-Write):容器层以下所有镜像层都是只读的。当容器需要修改某个文件时,Docker会将该文件从只读层复制到容器可写层,然后修改可写层的副本。原镜像保持不变,因此同一个镜像可以启动无数个容器而互不干扰。
2.4 镜像构建(Dockerfile)
2.4.1 常用指令
| 指令 | 说明 |
|---|---|
FROM | 指定base镜像,eg:FROM busybox:version |
COPY | 复制文件,eg:COPY file /file 或 COPY ["file","/"] |
LABEL | 添加元数据,eg:LABEL maintainer="user@example.com" |
ADD | 类似COPY,支持压缩文件自动解压或URL,eg:ADD test.tar /mnt |
ENV | 指定环境变量,eg:ENV FILENAME test |
EXPOSE | 暴露容器端口,eg:EXPOSE 80 |
VOLUME | 声明数据卷挂载点,eg:VOLUME ["/var/www/html"] |
WORKDIR | 切换工作目录,eg:WORKDIR /mnt |
RUN | 在构建时执行的指令,eg:RUN touch file |
CMD | 容器启动时执行的命令,可被docker run覆盖 |
ENTRYPOINT | 容器启动时执行的命令,不可被覆盖,与CMD可组合使用 |
2.4.2 构建命令
docker build -t [镜像名]:[标签] [构建上下文路径]
2.4.3 镜像优化策略
| 方法 | 实现方式 | 效果 |
|---|---|---|
| 缩减镜像层 | 使用&&连接多个RUN命令,合并为单层 | 减少层数 |
| 多阶段构建 | 在Dockerfile中使用多个FROM,只复制最终产物 | 减小最终镜像 |
| 使用精简镜像 | 选用alpine、distroless等基础镜像 | 大幅减小体积 |
方法1 缩减镜像层
[root@docker-node1 docker]# vim Dockerfile
FROM centos:7 AS build
ADD nginx-1.23.3.tar.gz /mnt
WORKDIR /mnt/nginx-1.23.3
RUN yum install -y gcc make pcre-devel openssl-devel && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module --with-http_stub_status_module && make && make install && cd .. && rm -fr nginx-1.23.3 && yum clean all
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@docker-node1 docker]# docker build -t webserver:v2 .
[root@docker-node1 docker]# docker images webserver
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v2 caf0f80f2332 4 seconds ago 317MB
webserver v1 bfd6774cc216 About an hour ago 494MB
方法2 多阶段构建
[root@ docker-node1 docker]# vim Dockerfile
FROM centos:7 AS build
ADD nginx-1.23.3.tar.gz /mnt
WORKDIR /mnt/nginx-1.23.3
RUN yum install -y gcc make pcre-devel openssl-devel && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module --with-http_stub_status_module && make && make install && cd .. && rm -fr nginx-1.23.3 && yum clean all
# 第二阶段:运行阶段(只有二进制文件)
FROM centos:7
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@server1 docker-node1 docker]# docker build -t webserver:v3 .
[root@server1 docker-node1 docker]# docker images webserver
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v3 1ac964f2cefe 29 seconds ago 205MB
webserver v2 caf0f80f2332 3 minutes ago 317MB
webserver v1 bfd6774cc216 About an hour ago 494MB
方法3 使用最精简镜像
使用google提供的最精简镜像,下载地址:
https://github.com/GoogleContainerTools/distroless
# 下载镜像
[root@docker-node1 ~]# docker pull gcr.io/distroless/base
# 利用最精简镜像构建
[root@docker-node1 ~]# mkdir new
[root@docker-node1 ~]# cd new/
[root@docker-node1 new]# vim Dockerfile
FROM nginx:1.23 AS base
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
ARG TIME_ZONE
RUN mkdir -p /opt/var/cache/nginx && \
cp -a --parents /usr/lib/nginx /opt && \
cp -a --parents /usr/share/nginx /opt && \
cp -a --parents /var/log/nginx /opt && \
cp -aL --parents /var/run /opt && \
cp -a --parents /etc/nginx /opt && \
cp -a --parents /etc/passwd /opt && \
cp -a --parents /etc/group /opt && \
cp -a --parents /usr/sbin/nginx /opt && \
cp -a --parents /usr/sbin/nginx-debug /opt && \
cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libpcre* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime
FROM gcr.io/distroless/base-debian11
COPY --from=base /opt /
EXPOSE 80 443
ENTRYPOINT ["nginx", "-g", "daemon off;"]
[root@docker-node1 new]# docker build -t webserver:v4 .
[root@docker-node1 new]# docker images webserver
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v4 c0c4e1d49f3d 4 seconds ago 34MB
webserver v3 1ac964f2cefe 12 minutes ago 205MB
webserver v2 caf0f80f2332 15 minutes ago 317MB
webserver v1 bfd6774cc216 About an hour ago 494MB
2.5 镜像仓库管理
2.5.1 什么是Docker仓库
Docker 仓库(Docker Registry) 是用于存储和分发 Docker 镜像的集中式存储库。
它就像是一个大型的镜像仓库,开发者可以将自己创建的 Docker 镜像推送到仓库中,也可以从仓库中拉取所需的镜像。
类型:
- 公共仓库:如Docker Hub,任何人都可以访问和使用其中的镜像。许多常用软件(nginx、redis、mysql)都有官方镜像。
- 私有仓库:由组织或个人自己搭建和管理,用于存储内部使用的、不希望公开的镜像。

2.5.2 Docker Hub与镜像加速
Docker Hub是Docker官方提供的公共镜像仓库,拥有大量官方和社区镜像。
国内访问Docker Hub较慢时,可配置镜像加速器:
# 编辑/etc/docker/daemon.json(如果不存在则创建)
{
"registry-mirrors": ["https://docker.m.daocloud.io"]
}
# 重启Docker服务
systemctl restart docker
# 配置完成后,docker pull会自动从镜像加速器下载。
2.5.3 Docker仓库的工作原理
三个角色
仓库涉及三个角色:
- Index:索引服务,负责用户认证、镜像校验、命名空间管理。
- Registry:镜像存储仓库,不提供用户认证,依赖Index进行Token验证。
- Registry Client:Docker客户端,执行push/pull。
Pull流程(下载镜像)

# 镜像拉取分为以下几步:
1.docker客户端向index发送镜像拉去请求并完成与index的认证
2.index发送认证token和镜像位置给dockerclient
3.dockerclient携带token和根据index指引的镜像位置取连接registry
4.Registry会根据client持有的token跟index核实身份合法性
5.index确认此token合法性
6.Registry会根据client的请求传递镜像到客户端
Push流程(上传镜像)

# 镜像上传的步骤:
1.client向index发送上传请求并完成用户认证
2.index会发方token给client来证明client的合法性
3.client携带index提供的token连接Registry
4.Registry向index合适token的合法性
5.index证实token的合法性
6.Registry开始接收客户端上传过来的镜像
2.5.4 私有仓库方案
为什么需要私有仓库?
- Docker Hub需要互联网连接,内网环境无法访问
- 公开仓库所有人可访问,企业镜像需要保密
- 企业安全策略要求镜像存储在内网
| 方案 | 特点 | 适用场景 |
|---|---|---|
| 简单Registry | 无认证、无UI、无高可用,一个容器搞定 | 测试环境、开发环境 |
| Registry + TLS | 增加HTTPS传输加密,防止中间人攻击 | 有一定安全要求 |
| Registry + 认证 | 增加登录认证(HTTP Basic Auth或Token),需要搭配nginx等 | 内部团队使用 |
| Harbor | 企业级:RBAC权限控制、图形化UI、镜像复制、漏洞扫描、审计日志、垃圾回收 | 生产环境推荐 |
Harbor简介:由VMware开源的企业级Docker Registry项目,是目前最流行的私有仓库解决方案。它提供的功能如下:
- 基于角色的访问控制(RBAC):可以为不同用户分配项目级别的权限
- 镜像复制:支持在多个Harbor实例之间同步镜像(主备、异地)
- 图形化用户界面:方便管理项目、镜像、用户
- 审计日志:记录所有操作,满足合规要求
- 漏洞扫描:自动扫描镜像中的已知漏洞
- 垃圾回收:清理无用的镜像层,释放存储空间
2.5.4 仓库相关命令
| 操作 | 命令 |
|---|---|
| 登录仓库 | docker login [仓库地址] |
| 给镜像打标签 | docker tag nginx:latest myrepo/nginx:v1 |
| 推送镜像 | docker push myrepo/nginx:v1 |
| 拉取镜像 | docker pull myrepo/nginx:v1 |
| 登出仓库 | docker logout |
3 Docker容器操作
3.1 容器生命周期管理
| 操作 | 命令示例 | 说明 |
|---|---|---|
| 启动容器 | docker run [选项] [镜像] [命令] | 常用选项:-d后台运行、-it交互式终端、--name指定名称、-p端口映射、--rm停止后自动删除、--network指定网络 |
| 查看运行容器 | docker ps | 加-a查看所有容器(包括已停止) |
| 停止/启动/重启 | docker stop/start/restart [容器名或ID] | 容器内的第一个进程必须保持运行,否则容器会退出 |
| 删除容器 | docker rm [容器名或ID] | 加-f强制删除运行中的容器 |
| 进入运行中的容器 | docker exec -it [容器名] /bin/bash | 推荐使用,避免docker attach |
# 1.启动容器
[root@Docker-node1 ~]# docker run -d --name mario -p 80:8080 timinglee/mario
[root@Docker-node1 ~]# docker run -it --name centos7 centos:7
[root@3ba22e59734f /]# #进入到容器中,按<ctrl>+<d>退出并停止容器,#按<ctrl>+<pq>退出但不停止容器
#重新进入容器
[root@docker ~]# docker attach centos7
[root@3ba22e59734f /]#
# 2.查看运行容器
[root@Docker-node1 ~]# docker ps # 查看当前运行容器
[root@Docker-node1 ~]# docker ps -a # 查看所有容器
[root@Docker-node1 ~]# docker inspect busybox # 查看容器运行的详细信息
# 3.停止/启动/重启
[root@Docker-node1 ~]# docker stop busybox # 停止容器
[root@Docker-node1 ~]# docker kill busybox # 杀死容器,可以使用信号
[root@Docker-node1 ~]# docker start busybox # 开启停止的容器
# 容器内的第一个进程必须一直处于运行的状态,否则这个容器,就会处于退出状态!
# 4.删除容器
[root@Docker-node1 ~]# docker rm centos7 #删除停止的容器
[root@Docker-node1 ~]# docker rm -f busybox #删除运行的容器
[root@Docker-node1 ~]# docker container prune -f #删除所有停止的容器
# 5.进入运行中的容器
#在容器中执行命令
[root@docker ~]# docker exec -it test ifconfig
lo Link encap:Local Loopback
………………
3.2 容器信息与日志
| 操作 | 命令 | 说明 |
|---|---|---|
| 查看容器日志 | docker logs [容器名] | 加-f实时跟踪日志 |
| 查看容器详情 | docker inspect [容器名或ID] | 显示容器的详细配置信息 |
| 查看容器进程 | docker top [容器名] | 查看容器内运行的进程 |
| 查看容器统计 | docker stats | 实时查看容器资源使用情况 |
[root@Docker-node1 ~]# docker logs web
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
……………………
3.3 文件传输与提交
| 操作 | 命令 | 说明 |
|---|---|---|
| 文件传输 | docker cp [宿主机路径] [容器名]:[容器路径] docker cp [容器名]:[容器路径] [宿主机路径] | 支持宿主机与容器之间双向复制 |
| 提交容器镜像 | docker commit [容器名] [新镜像名] | 不推荐,企业应用请用Dockerfile |
[root@Docker-node1 ~]# docker cp test2:/leefile /mnt # 把容器中的文件复制到本机
Successfully copied 1.54kB to /mnt
[root@Docker-node1 ~]# docker cp /etc/fstab test2:/fstab # 把本机文件复制到容器中
3.4 容器资源限制与安全优化
Docker 安全依赖 Linux 内核:命名空间隔离、Cgroups 资源控制、Capability 权限控制、Docker 服务端安全。
Docker容器的安全性高度依赖Linux系统自身(Linux内核),主要的安全维度如下:
- Linux命名空间提供的容器隔离安全
- Linux Cgroups对资源控制的安全
- Linux Capability带来的细粒度权限安全
- Docker服务端本身的抗攻击能力
- 其他安全增强机制(如 LXCFS)
容器本质是宿主机上的特殊进程,多个容器共享同一个内核,所以隔离不是绝对彻底,部分资源(如磁盘)无法完全 Namespace 化。
-
命名空间隔离的安全:
Docker启动容器时会自动创建独立Namespace(pid、net、mnt、ipc、uts、user),提供最基础隔离。
- 作用:提供最基础的隔离,使容器看起来像是一个独立的系统。
- 局限性:容器本质是宿主机上的特殊进程,共享同一个内核。与虚拟机相比,隔离不彻底,部分资源(如磁盘、内核参数)无法被 Namespace 完全隔离。
-
控制组(Cgroups)资源控制的安全:
当使用
docker run启动容器时,Docker会在后台为容器创建一个独立的控制组(Cgroups)策略集合。- **资源公平分配:**确保各容器可以公平地分享主机的内存、CPU、磁盘 IO 等资源,避免 “邻里纠纷”。
- **防DDoS攻击:**确保容器内发生的资源压力(如死循环占满 CPU)不会影响到本地主机系统及其他容器,防止单个容器拖垮整个宿主机。
- 防止资源争抢导致整体雪崩
rhel9 cgroup说明:rhel9默认使用 cgroup-v2,但不利于观察 Docker 资源限制,可以切换为cgroup-v1
grubby --update-kernel=/boot/vmlinuz-$(uname -r) \ --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"默认情况下,容器内并未被强制隔离资源,容器内看到的资源信息与宿主机无异。
# 1. 启动一个 busybox 容器 [root@docker ~]# docker run -it --name test busybox # 2. 查看容器内内存情况(显示的是宿主机总量) / # free -m total used free shared buff/cache available Mem: 3627 648 516 16 2463 2678 Swap: 2063 1 2062 # 3. 退出容器,查看宿主机内存 / # exit [root@docker ~]# free -m # 结果与容器内基本一致,说明默认未做资源隔离。为了实现安全的资源控制,需要通过 docker run 的参数手动限制,否则容器可以无限制消耗主机资源。
-
内核能力机制:
**能力机制(Capability)**是Linux内核的一个强大特性,为容器权限控制提供了细粒度的支持。
- 核心逻辑:大部分情况下,容器并不需要"真正的"root 权限(UID=0)。root 权限过大,风险过高;Capability将权限拆分成多个小块,容器只需要申请必要的能力即可。
- Docker策略:默认情况下,Docker采用 "白名单"机制,严格禁用"必需功能"之外的其他权限,最小化攻击面。
这就是为什么即使在容器内执行 ip a 等网络操作也不会被完全限制,但无法修改系统关键内核参数的原因。
-
Docker服务端防护:
Docker的核心是服务端(daemon),其安全性直接决定了整个平台的安危。
- 访问控制:必须确保只有可信的用户才能访问Docker服务接口(避免未授权接管主机)。
- 权限映射:将容器内的 root 用户映射到本地主机上的非root用户,减轻容器与主机之间因权限提升引起的安全隐患。
- **非root运行:**允许Docker服务端在非root权限下运行,并利用安全可靠的子进程来代理执行需要特权的操作。这些子进程被严格限制在特定范围内,降低了整体风险。
3.4.1 资源控制(Linux Cgroups)
Linux Cgroups(Linux Control Group)用于限制容器(一个进程组能够使用)CPU、内存、磁盘 IO等资源上限,对进程进行优先级设置、审计,以及将进程挂起和恢复等操作,防止单个容器耗尽主机资源(防 DDoS、保证稳定性)。
基于上述Cgroups机制,通过命令行限制容器资源示例如下:
限制CPU资源
# 限制容器最多使用 20% 的 CPU 时间
docker run -it --rm --cpu-period 100000 --cpu-quota 20000 ubuntu
# 设置 CPU 权重(优先级)
docker run -it --rm --cpu-shares 512 ubuntu
限制内存资源
# 限制内存 200M,且内存+Swap 等于 200M(禁用额外Swap)
docker run -d --name test --memory 200M --memory-swap 200M nginx
限制磁盘 IO
# 限制写入速度为 30MB/s
docker run -it --rm --device-write-bps /dev/sda:30M ubuntu
总结
| 资源类型 | 限制参数 | 示例命令 |
|---|---|---|
| CPU使用量 | --cpus | docker run --cpus=2 ... |
| CPU优先级 | --cpu-shares | docker run --cpu-shares=512 ... |
| 内存限制 | -m / --memory | docker run -m 512m ... |
| 磁盘IO | --device-read-bps / --device-write-bps | docker run --device-write-bps /dev/sda:1mb |
3.4.2 容器隔离增强与权限管理
Docker容器默认不是完全隔离的,容器内的root用户只是宿主机上的一个普通用户(通过命名空间映射)。但某些操作(如修改网络配置、挂载文件系统)默认被禁止。
-
容器隔离增强:
-
**隔离缺陷:**容器内free命令看到的是宿主机的资源信息,容易导致应用误判。
-
**LXCFS修复:**LXCFS是解决此问题的利器,可挂载到容器中,让容器内进程看到准确的自身资源限制。
# 1. 运行 LXCFS 服务 lxcfs /var/lib/lxcfs & # 2. 启动容器并挂载 LXCFS docker run -it -m 256m \ -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \ -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \ ubuntu效果:容器内
free -m将显示 256M,而非宿主机的大容量。
-
-
容器权限配置:
-
特权模式(高危):
-
docker run -it --privileged busybox -
拥有近乎宿主机root的权限。
-
注意:生产环境严禁随意使用,风险极高。
-
-
白名单机制(推荐):
-
docker run -it --cap-add NET_ADMIN busybox -
NET_ADMIN仅开放网络管理能力,无法操作磁盘,安全性远高于--privileged。
-
-
| 方式 | 说明 | 风险 |
|---|---|---|
| 默认 | 容器内root受限,无法修改系统配置(如iptables、modprobe) | 较低 |
--privileged=true | 获得宿主机几乎全部权限(接近宿主机root) | 高,仅调试用 |
--cap-add / --cap-drop | 精确添加或删除特定Linux Capability,遵循最小权限原则 | 推荐生产使用 |
capabilities手册地址:http://man7.org/linux/man-pages/man7/capabilities.7.html
常用Capability示例:
NET_ADMIN:允许网络管理(如配置iptables)SYS_TIME:允许修改系统时间CAP_SYS_ADMIN:允许挂载文件系统、执行特权系统调用(权限很大,慎用)DAC_OVERRIDE:绕过文件读/写/执行权限检查
4 Docker数据卷与持久化
4.1 为什么需要数据卷
Docker容器默认的文件系统是临时的:容器删除后,所有在容器内写入的数据都会丢失。数据卷(Volume)就是为了解决这个问题。
| 特性 | 容器分层文件系统 | 数据卷 |
|---|---|---|
| 性能 | 较差 | 与主机磁盘相同 |
| 生命周期 | 随容器删除而消失 | 独立于容器,持久保存 |
| 跨容器共享 | 困难 | 支持多容器挂载 |
| 迁移能力 | 无 | 仅限本地(需额外工具) |
4.2 三种数据卷对比
选 bind mount:需要直接在宿主机编辑容器内文件、共享宿主机配置 / 日志,不考虑跨主机迁移
选 管理卷:标准的容器数据持久化方案,适合数据库、微服务等生产环境,可移植性强
选 tmpfs:仅需临时存储、对性能要求极高、数据无需持久化(如临时缓存、敏感凭证)
| 对比项 | bind mount(绑定挂载) | docker managed volume(Docker 管理卷) | tmpfs mount(临时内存挂载) |
|---|---|---|---|
| 定义方式 | -v 宿主机路径:容器路径 --mount type=bind,src=宿主机路径,dst=容器路径 | -v 容器路径 / -v 卷名:容器路径 --mount type=volume,src=卷名,dst=容器路径 | --tmpfs 容器路径 --mount type=tmpfs,dst=容器路径 |
| 宿主机位置 | 任意指定宿主机文件系统路径 | /var/lib/docker/volumes/卷名/_data | 宿主机内存(RAM),不落地磁盘 |
| 可移植性 | 差(强依赖宿主机路径结构,跨主机需手动同步) | 好(Docker 统一管理,支持 docker volume 命令备份 / 迁移) | 无(容器销毁即数据丢失,不可移植) |
| 数据初始化 | 无(宿主机目录内容直接覆盖容器内对应路径) | 若容器路径已有数据,会自动复制到新创建的卷中 | 无(内存挂载,容器启动时初始化空目录) |
| 数据持久性 | 持久化(容器销毁后数据仍保留在宿主机) | 持久化(容器销毁后卷数据独立保留) | 临时(仅容器运行时存在,容器停止 / 销毁即数据丢失) |
| 性能 | 受宿主机磁盘 IO 性能影响 | 受宿主机磁盘 IO 性能影响 | 极高(直接读写内存,无磁盘 IO 开销) |
| 适用场景 | 宿主机与容器共享配置文件、日志文件;需要直接编辑容器内文件 | 数据库数据持久化、容器间数据共享、无宿主机路径依赖的持久化存储 | 敏感临时数据(如密码、密钥)、高 IO 临时缓存、无需持久化的中间数据 |
| 权限控制 | 完全由宿主机文件权限控制,需手动配置 | Docker 统一管理,支持卷级权限配置 | 可通过 --tmpfs-size/--tmpfs-mode 限制大小、设置权限 |
| 跨容器共享 | 支持(多个容器挂载同一宿主机路径) | 支持(多个容器挂载同一命名卷) | 支持(多个容器挂载同一内存路径,容器销毁即失效) |
4.3 数据卷常用命令
| 操作 | 命令 | 说明 |
|---|---|---|
| 创建数据卷 | docker volume create [卷名] | 创建命名卷,方便管理 |
| 查看数据卷列表 | docker volume ls | 列出所有数据卷 |
| 查看数据卷详情 | docker volume inspect [卷名] | 显示卷的挂载点、驱动等信息 |
| 挂载数据卷 | docker run -v [卷名]:[容器路径] ... | 使用命名卷启动容器 |
| 清理未使用卷 | docker volume prune | 危险操作,删除所有未被任何容器使用的卷 |
| 删除数据卷 | docker volume rm [卷名] | 删除指定卷(必须未被使用) |
4.4 数据卷容器
数据卷容器是一个专门用于共享数据卷的容器,本身不运行业务进程(通常使用
busybox或alpine作为基础镜像)。其他容器通过--volumes-from挂载同一个数据卷,实现数据共享。
操作步骤:
- 创建数据卷容器:
docker create -v /data --name data_vol busybox - 其他容器使用:
docker run --volumes-from data_vol ...
4.5 备份与迁移数据卷
由于数据卷的物理位置在宿主机上,可以通过启动一个临时容器来备份卷内容。
备份:
# 运行一个临时容器,挂载要备份的数据卷和宿主机的备份目录
docker run --rm --volumes-from data_vol -v $(pwd):/backup alpine \
tar czf /backup/backup.tar.gz /data
# --rm:备份完成后自动删除容器;--volumes-from data_vol:继承数据卷容器的挂载点;-v $(pwd):/backup:将当前目录挂载到容器的/backup;tar czf /backup/backup.tar.gz /data:压缩/data目录
恢复:
# 先创建一个新的数据卷容器(或直接挂载到目标容器)
docker run --rm --volumes-from data_vol -v $(pwd):/backup alpine \
tar xzf /backup/backup.tar.gz -C /
5 Docker网络模型
5.1 默认网络
Docker安装后自动创建3种默认网络:
NETWORK ID NAME DRIVER SCOPE
2a93d6859680 bridge bridge local
4d81ddd9ed10 host host local
8c8c95f16b68 none null local
5.1.1 原生bridge网络
docker安装时会创建一个名为 docker0 的Linux bridge,新建的容器会自动桥接到这个接口。
[root@docker-note1 mnt]# ip link show type bridge
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:5f:e2:34:6c brd ff:ff:ff:ff:ff:ff
- bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的。
- 容器通过宿主机的NAT规则后可以访问外网

[root@docker-node1 mnt]# docker run -d --name web -p 80:80 nginx:1.23
defeba839af1b95bac2a200fd1e06a45e55416be19c7e9ce7e0c8daafa7dd470
[root@docker-node1 mnt]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:5fff:fee2:346c prefixlen 64 scopeid 0x20<link>
ether 02:42:5f:e2:34:6c txqueuelen 0 (Ethernet)
RX packets 21264 bytes 1497364 (1.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 27358 bytes 215202237 (205.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
……………………
veth022a7c9: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::a013:5fff:fefc:c9e4 prefixlen 64 scopeid 0x20<link>
ether a2:13:5f:fc:c9:e4 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 15 bytes 2007 (1.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
# 其中veth022a7c9为容器使用的网卡
[root@docker-node1 mnt]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02425fe2346c no veth022a7c9
5.1.2 原生网络host
host网络模式需要在容器创建时指定 --network=host;host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。

[root@docker-node1 ~]# docker run -it --name test --network host busybox
/ # ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:5F:E2:34:6C
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
inet6 addr: fe80::42:5fff:fee2:346c/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:21264 errors:0 dropped:0 overruns:0 frame:0
TX packets:27359 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1497364 (1.4 MiB) TX bytes:215202367 (205.2 MiB)
eth0 Link encap:Ethernet HWaddr 00:0C:29:EC:FC:D3
inet addr:172.25.254.100 Bcast:172.25.254.255 Mask:255.255.255.0
inet6 addr: fe80::30b2:327e:b13a:31cf/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1902507 errors:0 dropped:0 overruns:0 frame:0
TX packets:831640 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2202443300 (2.0 GiB) TX bytes:849412124 (810.0 MiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:11819 errors:0 dropped:0 overruns:0 frame:0
TX packets:11819 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1279944 (1.2 MiB) TX bytes:1279944 (1.2 MiB)
/ #
# 如果公用一个网络,那么所有的网络资源都是公用的,比如启动了nginx容器那么真实主机的80端口被占用,在启动第二个nginx容器就会失败
5.1.3 原生网络none
none模式是指禁用网络功能,只有lo接口,在容器创建时使用–network=none指定。
[root@docker-node1 ~]# docker run -it --name test --rm --network none busybox
/ # ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
5.2 自定义网络
自定义网络模式,docker提供了三种自定义网络驱动:bridge、overlay、macvlan。
bridge驱动类似默认的bridge网络模式,但增加了一些新的功能,overlay和macvlan是用于创建跨主机网络。
5.3.1 为什么需要自定义网络
使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。
- DNS自动解析:自定义网络内置DNS服务,容器之间可以通过容器名直接通信,而不需要依赖可能变化的IP地址。默认bridge网络不支持这个功能。
- 网络隔离:不同的自定义网络默认是隔离的,可以精细控制哪些容器可以相互通信。
- 可配置性:可以指定子网、IP范围、网关等,方便与现有网络规划整合。
5.3.2 核心类型:自定义桥接网络
- 在所有自定义网络类型中,自定义桥接网络最贴合日常部署需求的类型,核心是在宿主机上创建虚拟网桥,将容器连接到该网桥上,实现容器与宿主机、容器与容器之间的通信。
- 相较于默认bridge网络,自定义桥接网络不仅保留了基础通信功能,还新增了DNS自动解析、更灵活的网络配置等特性,有效解决了默认bridge网络中IP动态变更、无法通过容器名通信的痛点。
自定义桥接网络支持两种创建方式,适配不同使用场景:
- 默认创建:系统自动分配子网和网关,IP地址按单调递增规则分配,无需额外配置,适合快速部署。
- 自定义配置创建:可手动指定子网、网关等参数,精准适配现有网络规划,满足复杂场景需求。
5.3.3 自定义网络命令
| 操作 | 命令示例 |
|---|---|
| 创建桥接网络 | docker network create [网络名] |
| 指定子网创建 | docker network create --subnet=172.20.0.0/16 mynet |
| 查看网络列表 | docker network ls |
| 查看网络详情 | docker network inspect [网络名] |
| 连接网络 | docker network connect [网络名] [容器名] |
| 断开网络 | docker network disconnect [网络名] [容器名] |
| 删除网络 | docker network rm [网络名] |
5.3.4 不同自定义网络互通

不同自定义网络之间的容器默认无法通信。如果需要互通,有两种方式:
-
将容器同时连接到两个网络:通过连接网络命令,将需要互通的容器加入两个目标网络,使其具备两个网络的通信权限。(容器连接多个网络后,会自动获取每个网络对应的IP地址,可正常与各个网络内的其他容器通信)
# 需要手动将容器连接到另一个网络 docker network connect net1 containerA docker network connect net2 containerA -
通过宿主机或外部路由器进行路由:借助宿主机的路由功能或外部路由器,实现不同自定义网络之间的通信。(日常场景中优先使用容器多网络连接的方式。需注意,仅当有明确互通需求时才进行配置,避免破坏网络隔离的安全性。)
5.3.5 Joined容器网络
Joined容器是一种特殊的网络模式,核心特点是容器创建时通过
--network=container:容器名参数,指定与另一个已运行的容器共享一个网络栈,无需额外配置即可通过localhost实现容器间的高效通信。

**核心说明:**Joined模式下,两个容器共享IP、端口等网络资源,一方容器的网络配置变更会同步影响另一方,适用于需要高效通信、共享网络环境的场景(如应用与依赖服务的紧密联动)。
**应用场景:**适用于需紧密联动的服务部署(如phpmyadmin与mysql),通过共享网络栈,让应用容器可直接通过localhost访问依赖服务,无需配置额外网络连接。
[!caution]
注意:Joined模式下的容器共享网络栈,需确保两个容器的服务端口不冲突,避免端口占用导致服务异常。
5.3.6 网络模式对比
| 网络模式 | 创建方式 | 特点 | 适用场景 |
|---|---|---|---|
| bridge(默认) | 不需要指定 | 容器通过NAT访问外网,外部主机不能直接访问容器(需端口映射)。容器之间通过IP通信,不支持自动DNS解析 | 单机默认模式 |
| host | --network=host | 容器共享宿主机网络栈,没有网络隔离。性能最好,但端口冲突风险高 | 性能要求极高,且不需要网络隔离的场景 |
| none | --network=none | 仅有lo回环接口,完全无网络 | 安全要求极高,不需要网络的服务 |
| container | --network=container:vm1 | 新容器与指定容器共享网络栈,两者可以通过localhost通信 | 多容器紧密协作,如sidecar模式 |
| 自定义 | docker network create | 内置DNS,支持通过容器名自动解析IP;网络隔离 | 生产环境推荐 |
5.3 容器内外网访问
5.3.1 容器访问外网
- 在rhel7中,docker访问外网是通过iptables添加地址伪装策略来完成容器网文外网
- 在rhel7之后的版本中通过nftables添加地址伪装来访问外网
Docker在宿主机上通过iptables/nftables添加地址伪装(MASQUERADE)规则,将容器的源IP转换为宿主机IP。

[root@docker-node1 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE 6 -- 172.17.0.2 172.17.0.2 tcp dpt:80 # 内网访问外网策略
Chain DOCKER (0 references)
target prot opt source destination
DNAT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80
5.3.2 外网访问容器
使用
-p 主机端口:容器端口做端口映射,通过端口映射来暴漏端口从而达到访问效果。
docker-proxy和dnat在容器建立端口映射后都会开启,那个传输速录高走那个。

# 通过docker-proxy对数据包进行内转
[root@docker-node1 ~]# docker run -d --name webserver -p 80:80 nginx
[root@docker ~]# ps ax
133986 ? Sl 0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.17.0.2 -container-port 80
133995 ? Sl 0:00 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 80 -container-ip 172.17.0.2 -container-port 80
134031 ? Sl 0:00 /usr/bin/containerd-shim-runc-v2 -namespace moby -id cae79497a01c0b8c488c7597b43de4a43f361f21a398ff423b4504c0905db143 -address /run/containerd/containerd.sock
134059 ? Ss 0:00 nginx: master process nginx -g daemon off;
134099 ? S 0:00 nginx: worker process
134100 ? S 0:00 nginx: worker process
# 通过dnat策略来完成浏览内转
[root@docker-node1 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE 6 -- 172.17.0.2 172.17.0.2 tcp dpt:80
Chain DOCKER (0 references)
target prot opt source destination
DNAT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80
5.4 跨主机网络
在生产环境中,容器往往分布在多台物理机上,所以需要具备跨主机通信能力。
- 跨主机网络解决方案
- docker原生的overlay和macvlan
- 第三方的flannel、weave、calico
- 众多网络方案是如何与docker集成在一起的
- libnetwork docker容器网络库。
- CNM(Container Network Model)这个模型对容器网络进行了抽象。
5.4.1 CNM模型

CNM分三类组件:
- Sandbox:容器网络栈,包含容器接口、dns、路由表。(namespace)
- Endpoint:作用是将sandbox接入network(veth pair)
- Network:包含一组endpoint,同一network的endpoint可以通信
5.4.2 Macvlan网络
Macvlan是Linux内核提供的网卡虚拟化技术,允许为物理网卡创建多个虚拟子接口,每个子接口有自己的MAC地址和IP地址。容器直接使用这些虚拟接口,无需NAT。
核心特点:
-
无需Linux bridge,直接使用物理接口,性能接近物理网卡,通信效率极高。
-
容器获得与宿主机同网段IP(其接口直接与主机网卡连接),外部主机可直接访问,无需NAT转换或端口映射,外部主机可直接访问容器。
-
Macvlan会独占主机网卡,但可通过vlan子接口实现多Macvlan网络部署。
-
使用前需在主机网卡上开启混杂模式,确保虚拟子接口正常通信。
-
# 在docker主机上添加一块网卡,打开网卡混杂模式: [root@docker-node1 ~]# ip link set eth1 promisc on [root@docker-node1 ~]# ip link set up eth1 [root@docker-node1 ~]# ifconfig eth1 eth1: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500 ether 00:0c:29:ec:fc:dd txqueuelen 1000 (Ethernet) RX packets 83 bytes 8696 (8.4 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
-
-
vlan技术可将物理二层网络划分为4094个逻辑网络(vlan id取值1~4094),各逻辑网络彼此隔离,适配多场景部署需求。
Macvlan网络的隔离与连通规则:
- 隔离性:Macvlan网络在二层上默认相互隔离,不同Macvlan网络中的容器无法直接通信;
- 连通性:可在三层上通过网关将不同Macvlan网络连通,Docker本身不做额外限制,按照传统vlan网络的管理方式操作即可。
Macvlan跨主机通信实现要点:
-
**准备工作:**在参与跨主机通信的所有Docker主机上,各添加一块专用网卡,并开启该网卡的混杂模式。
-
**创建网络:**在各主机上创建Macvlan网络,指定网络驱动为macvlan,同时配置子网、网关,并指定父接口(即开启混杂模式的网卡)。
docker network create -d macvlan --subnet=子网段 --gateway=网关地址 -o parent=网卡名 网络名 # 如 docker network create -d macvlan --subnet=192.168.100.0/24 --gateway=192.168.100.1 -o parent=eth1 macnet -
实现连通:不同主机上的容器若处于同一个子网内,可通过网关实现三层互通,无需额外配置Docker层面的连通规则。
5.4.3 跨主机网络方案对比
| 方案 | 特点 | 适用场景 |
|---|---|---|
| Overlay | Docker原生,基于VXLAN隧道封装,对底层网络无要求 | 跨主机,网络环境不可控 |
| Macvlan | 直接使用物理网卡,容器获得独立IP,性能最好 | 性能要求高,网络可控(如数据中心) |
| Flannel/Weave/Calico | 第三方CNI插件,功能丰富,常用于Kubernetes | K8s集群网络 |
6 Docker Compose编排
6.1 概述
Docker Compose是用于定义和运行多容器Docker应用程序的工具,通过一个YAML文件来配置所有服务、网络和存储卷,然后用一条命令启动整个应用。
是官方的一个开源项目,托管到github上:
https://github.com/docker/compose
6.1.1 核心概念(管理层)
- 服务(Service):一个应用的容器,可以包含多个容器实例(通过scale扩展)
- 项目(Project):一组关联服务组成的完整业务单元,由
docker-compose.yml定义 - 容器(Container):服务的具体运行实例
6.1.2 主要功能
- 定义服务:
- 使用 YAML 格式的配置文件来定义一组相关的容器服务。每个服务可以指定镜像、端口映射、环境变量、存储卷等参数。
- 例如,可以在配置文件中定义一个 Web 服务和一个数据库服务,以及它们之间的连接关系。
- 一键启动和停止:
- 通过一个简单的命令,可以启动或停止整个应用程序所包含的所有容器。这大大简化了多容器应用的部署和管理过程。
- 例如,使用
docker-compose up命令可以启动配置文件中定义的所有服务,使用docker-compose down命令可以停止并删除这些服务。
- 服务编排:
- 可以定义容器之间的依赖关系,确保服务按照正确的顺序启动和停止。例如,可以指定数据库服务必须在 Web 服务之前启动。
- 支持网络配置,使不同服务的容器可以相互通信。可以定义一个自定义的网络,将所有相关的容器连接到这个网络上。
- 环境变量管理:
- 可以在配置文件中定义环境变量,并在容器启动时传递给容器。这使得在不同环境(如开发、测试和生产环境)中使用不同的配置变得更加容易。
- 例如,可以定义一个数据库连接字符串的环境变量,在不同环境中可以设置不同的值。
6.1.3 工作原理
Compose会将项目名(默认为当前目录名)作为前缀,创建的资源名类似
项目名_服务名_序号,避免与其他项目冲突。
- 读取配置文件:Docker Compose 读取 YAML 配置文件,解析其中定义的服务和参数。
- 创建容器:根据配置文件中的定义,Docker Compose 调用 Docker 引擎创建相应的容器。它会下载所需的镜像(如果本地没有),并设置容器的各种参数。
- 管理容器生命周期:Docker Compose 监控容器的状态,并在需要时启动、停止、重启容器;它还可以处理容器的故障恢复,例如自动重启失败的容器。
6.2 常用命令
| 命令 | 说明 |
|---|---|
docker-compose up -d | 启动所有服务(后台运行) |
docker-compose down | 停止并删除所有服务、网络、卷 |
docker-compose start | 启动已存在的服务 |
docker-compose stop | 停止运行中的服务 |
docker-compose restart | 重启服务 |
docker-compose ps | 查看服务状态 |
docker-compose logs [服务名] | 查看日志 |
docker-compose build | 构建镜像 |
docker-compose up --build | 启动前重新构建 |
docker-compose exec [服务名] [命令] | 在容器中执行命令 |
docker-compose pull | 拉取服务所需镜像 |
docker-compose config | 验证并查看解析后的配置 |
docker-compose -f [文件] up | 指定配置文件 |
6.3 YAML文件结构
version: '3.8' # Compose文件格式版本,3.x是最新版
services:
web: # 服务名
image: nginx:latest # 直接使用现有镜像
# build: ./web # 或者使用Dockerfile构建(二选一)
ports:
- "80:80" # 端口映射 "宿主机:容器"
environment:
- ENV_VAR=value # 环境变量
volumes:
- ./html:/usr/share/nginx/html # bind mount挂载
networks:
- appnet # 连接到appnet网络
depends_on:
- db # 依赖db服务,会先启动db
command: nginx -g 'daemon off;' # 覆盖默认CMD
restart: always # 重启策略
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
volumes:
- db_data:/var/lib/mysql # 使用命名卷(docker managed volume)
networks:
- appnet
restart: always
networks:
appnet: # 自定义网络
driver: bridge # 网络驱动,默认bridge
volumes:
db_data: # 命名卷声明(否则会报错)
更多推荐

所有评论(0)