☰
90DaysOfDevOps 第 47 天:Docker 网络与容器安全实战指南
2026/10/5 2:20:36 网站建设 项目流程
  • 文档/教程

【免费下载链接】90DaysOfDevOps

This repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.

项目地址:https://gitcode.com/gh_mirrors/90/90DaysOfDevOps
点击查看免费下载

本篇文章来自 90DaysOfDevOps 学习项目 2022 年路线图的 Day 47,聚焦两个此前未系统展开的核心主题:容器网络(Container Networking)与容器安全(Container Security)。你将学会使用docker network命令族管理网络、理解 bridge 网络的本质、通过端口映射(NAT)让容器服务对外可达,并掌握非 root 用户运行、私有镜像仓库、精简镜像等降低攻击面的实战手段。文中所有命令均可在 Docker Desktop(含 WSL 2 环境)上直接复现。

<输出文章> <输出文章>

90DaysOfDevOps 第 47 天:Docker 网络与容器安全实战指南

本篇文章来自 90DaysOfDevOps 学习项目 2022 年路线图的 Day 47,聚焦两个此前未系统展开的核心主题:容器网络(Container Networking)与容器安全(Container Security)。你将学会使用docker network命令族管理网络、理解 bridge 网络的本质、通过端口映射(NAT)让容器服务对外可达,并掌握非 root 用户运行、私有镜像仓库、精简镜像等降低攻击面的实战手段。文中所有命令均可在 Docker Desktop(含 WSL 2 环境)上直接复现。

Docker 网络基础:认识 docker network 命令族

在前面的容器专题练习中,我们已经让很多容器"跑起来"了,但始终没有从网络视角审视它们如何在后台工作,也尚未涉及安全话题。本小节先建立容器网络的操作基础。

打开终端,输入主命令:

docker network

这是配置和管理容器网络的核心命令。其帮助输出会展示该命令的用法(Usage: docker network COMMAND)以及全部可用的子命令:

子命令功能
connect将容器连接至网络
create创建新网络
disconnect将容器从网络断开
inspect查看一个或多个网络的详细信息
ls列出网络
prune移除所有未使用的网络
rm移除一个或多个网络

也就是说,借助这一个命令族,我们就能完成"创建网络、列出已有网络、检查网络细节、删除网络"的完整闭环。对任意子命令,还可以通过docker network <子命令> --help获取更详细的参数说明。

查看默认网络:docker network list

安装 Docker 后,系统会预置一批网络。执行:

docker network list

可以看到开箱即用的 Docker 网络视图。输出表格包含四列:NETWORK ID、NAME、DRIVER、SCOPE。每张网络都有唯一的 ID 与名称,并且与且仅与一个驱动(driver)关联。

值得注意的细节:名为bridge的网络其 DRIVER 也是bridge,名为host的网络其 DRIVER 也是host——网络名与驱动同名,不代表它们是同一个东西,只是"相关联"而已。同时可以看到这些网络的 SCOPE 都是local,即仅存在于当前 Docker 主机上。

深入网络细节:docker network inspect

list只给了概览,若要查看某个网络的完整配置,使用:

docker network inspect bridge

该命令会返回指定网络名称的全部配置细节,包括:

  • 网络的名称(Name)与唯一 ID;
  • 使用的驱动(Driver);
  • 作用域(Scope);
  • 已连接的容器列表(Containers),包含每个容器的名称、端点 ID、IPv4/IPv6 地址等;
  • 以及子网、网关、内嵌 DNS、IPAM 配置等更多信息。

正是通过inspect,我们才能看到"哪些容器接入了哪个网络、分到了什么 IP"这类运行时事实。

Bridge 网络:单主机的虚拟交换机

标准安装的 Docker Desktop 会预建一张名为bridge的网络,如上文docker network list所示,它关联的是bridge驱动。虽然名字相同,但网络与驱动是两个层面的概念。

从输出可以看到,bridge 网络的作用域是local,这意味着该网络只存在于当前这台 Docker 主机上。所有使用 bridge 驱动创建的网络都是如此——bridge 驱动提供的是单主机(single-host)网络能力。

从底层实现看,所有由 bridge 驱动创建的网络,都基于Linux bridge构建,Linux bridge 也就是常说的虚拟交换机(virtual switch)。它负责在同一主机内的容器之间、以及容器与主机网络之间转发数据帧。

连接容器:默认接入 bridge 网络

bridge 网络是新容器的默认归属——只要你在运行时没有通过--network显式指定网络,所有容器都会被连接到 bridge 网络。

创建并保持一个后台运行的测试容器:

docker run -dt ubuntu sleep infinity

这里的sleep infinity会让容器进程在后台持续运行,从而让我们有充足的时间"把玩"这个容器。此时再用docker network inspect bridge检查 bridge 网络,就能在Containers一节看到一条与我们刚部署的容器完全匹配的记录——这正是"未指定网络则默认接入 bridge"的直接证据。

接着进入容器内部查看:

docker ps # 获取容器 ID,例如 3a99af449ca2 docker exec -it 3a99af449ca2 bash

进入容器后,Ubuntu 基础镜像默认没有可用的 ping 工具,需要先安装:

apt-get update && apt-get install -y iputils-ping ping -c5 www.90daysofdevops.com

成功返回 5 个回显包,说明容器通过 bridge 网络的默认配置能够访问外部网络。练习完毕后,用docker stop 3a99af449ca2停止该容器(注意:随后执行docker ps就看不到它了)。

配置 NAT 实现外部访问:端口映射实战

容器默认网络地址是主机私有的,外部流量无法直接抵达。本小节演示通过**端口映射(NAT)**把 Docker 主机的 8080 端口映射到容器内部的 80 端口,让流量"主机 8080 → 容器 80"。

基于官方 NGINX 镜像启动一个具名容器:

docker run --name web1 -d -p 8080:80 nginx

参数说明:

  • --name web1:为容器指定名称,便于后续管理;
  • -d:后台运行(detached);
  • -p 8080:80:端口映射,左侧为 Docker 主机端口,右侧为容器内部端口;
  • nginx:官方 NGINX 镜像。

执行docker ps查看容器状态与端口映射。输出顶部即为运行 NGINX 的 web1 容器,注意其 PORTS 列显示:

0.0.0.0:8080->80/tcp

这表示所有主机接口上的 8080 端口都被映射到 web1 容器内部的 80 端口。正是这条映射,使容器内的 Web 服务可以经"Docker 主机 IP + 8080 端口"从外部被访问。

接下来获取主机 IP。在 WSL 终端中执行:

ip addr

记下主机接口的 IP 地址(示例中为172.25.218.154,你的环境可能不同),然后打开浏览器访问:

http://172.25.218.154:8080/

看到 NGINX 默认欢迎页面,即证明端口映射链路(主机 8080 → 容器 80)完全打通,容器服务已对外可达。这套 NAT 思路源自 2017 年 DockerCon 的官方演示,至今仍然适用;原演示后半部分涉及 Docker Swarm,不在本专题范围内。

容器安全:从 root 权限迁移到非 root 用户

与整机服务器配置相比,容器为工作负载提供了更安全的环境:它把应用拆分为更小、更松耦合且彼此隔离的组件,从而从整体上缩小攻击面(attack surface)。

但这并不意味着容器对攻击者免疫。只要系统存在可被利用的漏洞,我们仍需要理解这项技术的安全陷阱并坚持最佳实践。第一个最典型的隐患就是权限过大。

问题:容器内的 root 进程

到目前为止,我们部署的所有容器,其内部进程都是以 root 权限运行的。这意味着进程对容器乃至宿主机环境拥有完整的管理员访问权。练习环境里这些容器不会长期存活,但"以 root 起容器如此容易"恰恰是危险所在。

方案一:在 Dockerfile 中创建非 root 用户

更规范的做法是在构建镜像时就指定非 root 用户。90DaysOfDevOps 仓库的 Containers 目录 中就保存着这份示例 Dockerfile,原文如下:

# 使用官方 Ubuntu 18.04 作为基础镜像 FROM ubuntu:18.04 # 安装 nginx 和 curl RUN apt-get update && apt-get upgrade -y #RUN apt-get install -y nginx curl #RUN rm -rf /var/lib/apt/lists/* RUN groupadd -g 1000 basicuser && useradd -r -u 1000 -g basicuser basicuser USER basicuser

逐行拆解:

  • FROM ubuntu:18.04:以官方 Ubuntu 18.04 为基础镜像;
  • RUN apt-get update && apt-get upgrade -y:更新软件源并升级系统包;
  • RUN groupadd -g 1000 basicuser && useradd -r -u 1000 -g basicuser basicuser:创建 GID/UID 均为 1000 的系统用户basicuser(-r表示系统账户,-u 1000指定 UID,-g basicuser指定所属组);
  • USER basicuser:声明镜像默认以basicuser身份运行,这是最关键的一行——此后所有以该镜像启动的容器,进程都不再以 root 执行。

被注释掉的apt-get install -y nginx curl与rm -rf /var/lib/apt/lists/*也值得留意:前者是安装服务软件的可选步骤,后者是清理 apt 缓存以减小镜像体积的常用手段(与后文"精简镜像"呼应)。

方案二:docker run --user 运行时覆盖

除了在 Dockerfile 中固化用户,还可以在运行时临时指定:

docker run --user 1009 ubuntu

docker run --user会覆盖 Dockerfile 中通过USER指令指定的任何用户。例如上面的命令会让容器始终以 UID 1009 运行。但这里有一个前提:只有当 1009 本身具有最低权限级别时,容器才真正以最小权限运行。

更重要的是,--user这种方式并不能修复镜像自身潜在的安全缺陷(例如镜像里遗留的 root 属主敏感文件)。因此更稳妥的做法仍然是:在 Dockerfile 中显式指定非 root 用户,让容器从设计上就始终安全运行。

私有镜像仓库:掌控镜像供应链

镜像来源也是安全的重要一环。我们在前面的练习中大量使用了 DockerHub 这类公共仓库,而如果由组织搭建私有容器镜像仓库,既可以自主选择托管位置,也可以使用市面上的托管服务,本质收益是:对团队可用镜像拥有完全控制权。

相比之下,DockerHub 适合作为获取基线的起点,但它只提供基础服务,使用公共镜像意味着你要把大量信任托付给镜像发布者——镜像是否包含恶意内容、是否被篡改,都需要自行甄别。私有仓库(可自建,也可用托管服务)则把这份信任风险收回组织内部。

精简镜像:减小攻击面

镜像体积虽然不直接等同于安全,却与安全密切相关:如果应用运行根本用不到某些资源,就不该把它们装进容器。容器体积越大,潜藏的无用组件越多,攻击面也就越大。

作者特别提醒了对latest标签的担忧——拉取latest镜像常常会带入大量冗余(bloat)。DockerHub 上每个仓库中的镜像都会显示压缩后的体积,可作为选型参考。查看本地已有镜像及其大小,最直接的命令是:

docker image

(等价于docker images。)该命令会列出本地的镜像仓库、标签、镜像 ID、创建时间与大小,是体检镜像体积的第一入口。结合构建层面的实践(如使用精简基础镜像、清理apt缓存、移除无用层),可以把攻击面和存储开销同时压下来。

小结

Day 47 完成了容器专题中"网络"与"安全"两块拼图:

  • 网络侧:docker network命令族(list / inspect / create / connect / rm 等)是管理容器网络的入口;bridge 网络基于 Linux 虚拟交换机,提供单主机网络能力且是新容器的默认网络;-p端口映射通过 NAT 打通"主机端口 → 容器端口",配合ip addr获取主机 IP,即可在浏览器验证容器服务对外可达。
  • 安全侧:非 root 用户运行(Dockerfile 中USER指令,或docker run --user临时覆盖)、私有镜像仓库掌控镜像供应链、精简镜像缩小攻击面,三者共同构成了日常容器安全的基本盘。

仓库中与本节配套的素材包括 示例 Dockerfile 以及 Containers 目录下的 docker-compose 示例(如 my_wordpress 与 ELK 栈的编排文件),可作为下一步深入练习的起点。下一篇 Day 48 将继续容器主题的进阶内容。

  • 文档/教程

【免费下载链接】90DaysOfDevOps

This repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.

项目地址:https://gitcode.com/gh_mirrors/90/90DaysOfDevOps
点击查看免费下载
上一篇:XDM下载管理器终极指南:6个技巧解锁5倍提速与视频一键下载
下一篇:QQ聊天记录解密终极指南:从打不开的数据库到跨设备迁移,一份保姆级抢救手册

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询