[docker] docker 安全知识 - docker 系统性简介
今年的 security training 选的 topic 就是 docker 了,为了过这个 training 于是先把 docker 过了一遍(笑死
之前干啃的时候确实觉得不太能看下去,不过走了一遍实践之后发现就比较好理解
运作流程
docker 本身的作用还是可以更快地部署项目,不管是传统的全体打包、使用 VM,或者是使用 docker,开发流程依然是:
开发 打包 传送 部署
但是三者对比起来还是比较明显的,这张图可以比较好的说明三者的区别:

传统模式下,所有的项目都会打包在一台服务器上------大多数情况下公司会拥有这台服务器
虚拟化模式下,每一个项目会单独在一台虚拟机上,随后服务器上会安装不同的虚拟机,最终实现部署。VM 本身就有一个完整的操作系统,服务器上需要安装 hypervisor 进行 VM 的管理,所以这个实现相对而言也是比较吃资源的实现
docker 容器化实现则是使用容器取代了 VM,docker engine 取代了 hypervisor,最主要的是,docker 会使用服务器的 kernel 去运行容器,因此并不需要像 VM 一样重新安装虚拟机
当然,这是理论上的实现,实际上更为复杂一些:
-
Linux
Linux 情况下 docker 会使用服务器的 kernel
-
MacOS
docker 还是会使用一个 Linux 的 VM 去运行 docker
-
Windows
docker 会使用 WSL 或者 Hyper-V。前者是 windows 自己支持的 linux kernel,后者则还是要开一个 VM,然后在 VM 上运行 docker
表格的对比如下:
优点 | 缺点 | |
---|---|---|
传统 | 完全控制 有些情况下性能更好,尤其是小型公司,项目更新的不是很勤快的情况下 | 扩展很困难也很麻烦 维护困难 依赖管理困难 |
虚拟化 | 环境一致性 高孤立性 有可移植性 | 资源过载 配置较慢 |
docker | 环境一致性 相对孤立性 高移植性 资源有效利用 启动快 管理方便 | 学习曲线陡峭 安全性 数据持久化管理复杂 |
关于 kernel 的补充如下:

OS 是一个 software,所以 kernel 介于 OS 和硬件之间
镜像容器管理
镜像是一个 轻量 的,独立 的,包含一切需要运行一个应用的 软件 、可执行 、库 、环境 和 配置,它可以被视为是容器的 蓝图
容器是镜像的实例,因此它自然也包含了所有镜像有的特征
docker hub
docker hub 是 docker images 的一个公共 registry,目前主流的工具都会在 docker hub 上提供官方的镜像,包括 mysql,node,java,tomcat 等。注意下载镜像的时候一定要看,docker hub 有没有认证对应的镜像,如:

说到 docker registry,其实也可以用私有的......或者说大型公司都会用私有 registry
另外还有一个比较有趣的 term,叫 golden image,一般商用的都是 golden image,这种镜像一般指的是遵从最佳时间,只运行所需的功能的镜像
docker engine
docker engine 是整个 docker 的核心组件,它负责管理、创建、运行 docker 容器,其主要组成部件为:
-
Docker Daemon (
dockerd
)这是整个 docker 最核心也是最底层的组件,他会根据从 Docker API 发来的请求进行对应的操作
具体这部分不会有太多的涉及,只需要知道有这个组件即可
-
Docker API
这个直接使用的场景很少,但是通过 CLI 使用的情况很多,不过本质上还是通过 restful api 的方式实现的,比如说我可以 curl 一下 docker 的 socket,查询一下 docker 所有使用的 socket:
这里输出的结果就是没有 pretty print 的 json 文件
-
Docker CLI (
docker
)这里也就是跑
docker start
,docker pull
,docker build
等指令的地方注意 CLI 和 Daemon 是通过 restful 请求实现的,可以理解成每一个指令都向 Docker Daemon 发出了一个 request,随后 Docker Daemon 完成了对应的指令后,会发出 response
这也是为什么运行
docker inspect
运行的结果是 JSON 的原因

⚠️:其实这里细想能够发现一个问题,那就是 docker engine 是可以创建 unix socket,并且与 host machine 进行交流。同样,通过 restful 的请求可以获取所有的信息,这是因为 Docker Daemon 在默认情况下是以 root 权限去运行的,而这可能会带来一系列的风险
👀 这在后面也会再次提到
dockerfile
这个就不细说了,这个在基础知识 [docker] 核心知识 - 概念和运行 里已经说得很细了
持久化数据
这个之前的笔记写得也很详细了:
包括怎么使用怎么 mount 都有提及,这里多提一个 tmpfs mount,是持久化里没有提到的。没提到的主要原因是 tmpfs 是写入 host machine 的 memory 里,其实并没有做持久化,它的 mount 大致实现如下:
bash
❯ docker run -d \
--tmpfs /mytmp:rw,noexec,nosuid,size=100m \
my_image
networking
之前的笔记也有写:[docker] 网络连接,不过之前的笔记写的是怎么用,这里提一下原理,首先看一下实现的具体结构:

-
network sandbox
每个容器内部都有独立的 network sandbox,有容器自己的 network namespace、network 接口(虚拟接口)、路由表、防火墙规则、DNS 设置等,所以容器内部使用的端口------在实现正确的情况下,即一个容器只安装一个组件------是不会产生毒冲突的
endpoints 指的是容器在 docker network 的连接点,这里会配置管理 IP 地址等,和 network 进行沟通交流的配置
-
newtork
通过图可以看到,docker 会生成多个 network,每个 network 只会与 network 中的容器进行沟通交流
-
network driver
总共有下面 6 种:
-
bridge
默认选项,也是最常见的选项
这个选项适用于所有的容器都在一个 host machine 上运行,容器可以通过 docker 内部的 IP 地址进行沟通,不需要对外暴露 IP 地址
这个使用在 [docker] 多容器项目 - PHP+MySQL+Nginx+utility containers 和 [docker] 多容器项目 都有实践过
-
host
这个选项会跳过 docker 内部的管理,直接使用 host machine 的 network namespace
不使用 virtual network,性能会有一部分的提升,也会失去 docker network 的孤立性
-
overlay
这个应该是针对分布式的选项,支持多 host 的 networking
看了下是支持 Swarm service 的,目前用不到
-
macvian
这个设置可以让容器看起来像是一个物理设备,而不是虚拟设备
-
ipvlan
貌似是共享 MAC 地址版本的 macvian
-
none
完全孤立,不与任何 network 有交流
-
-
IPAM driver
IP Address Management,负责管理容器与 network 之间的 IP 分配
-
docker engine
容器管理
容器优化
简单的说就是 1 个容器上只运行 1 个组件
比如说 mysql 容器运行 mysql,node 容器运行 node,这样可以实现容器的孤立性
docker compose
[docker] docker compose 部分说的比较多了,这里不多细究
容器编排
容器编排(container orchestration)指的是将容器联网和自动化管理的过程,一般用的是 kubernetes,在看资料的时候也看到有用 docker swarm
后面还是会就 k8s 进行学习
docker 的常见威胁
-
使用不安全的镜像
这种事情挺多的,后面也会提到就算是私有镜像可能也会有问题的情况
说起来今年 1 月份 npm 上出现了一个还蛮有趣(但是有问题)的包,叫
everything
,现在还在:https://www.npmjs.com/package/everything?activeTab=readme这个包就真的什么都不干,然后把 npm 上的所有 package 都下载一遍,然后有可能触发 DoS(Denial of Service)
所以还是要注意下载的 images/dependencies 啊
-
获取未授权的 docker api 的权限
比如说有黑客获取了 docker api 的权限,ta 可以:
-
使用
docker stop
去停止一个叫app-validator
的容器,这个容器负责 app 的验证,那么关掉这个容器就会导致部分应用 API 的验证失败,从而进行一些违规操作 -
使用
docker exec
去运行一些不应当被包含在容器内的脚本/软件 -
...
毕竟,docker 默认情况下是有 root 权限
-
-
利用程序代码中本身存在的问题,或利用 docker 错误配置去危害容器
-
从有问题的容器,获取更高权限去访问 docker host machine
这里尤其要注意 bind mounts