Docker 容器明文密码问题解决之道
wptr33 2024-11-22 21:59 20 浏览
Docker 带着 “Dockerize Everything” 的口号,以“软件标准”的姿态展现于世人面前,不断影响大家对于软件的理解。然而现实是否就如想象中的那么饱满,新的科技诞生之际,是摧枯拉朽之势,还是循序渐进,皆有个过程,面对异军突起的 Docker,软件传统的精髓又是何去何从?这些无一不是值得深思的话题。
在《存储类 Docker 容器的明文密码问题》一文中,我们初步领略了存储类软件与 Docker 结合时,存在的些许安全隐患,比如明文密码问题。
过去数十年间,MySQL 数据库的创建都在人机交互过程中完成,流程大致可以分为以下三个步骤:
运维人员创建机器,安装并配置 MySQL 服务器;
DBA 负责管理 MySQL 数据库,如 MySQL 数据库的创建、删除与权限更改等;
开发人员使用 DBA 交付的数据库,对数据库进行增删改查等操作。
MySQL 历经了许多年,形成了以上这种交付方式,在 Docker 诞生之前,没有任何风吹草动。然而,在 Docker 诞生之后,MySQL 的 Docker 化路程似乎并不平坦。
常言道,Docker 横空出世,极大地推动了DevOps
的发展。虽然看似 MySQL 与 Docker 的结合并没有对开发造成直接的影响,但是 Docker 化的 MySQL 的确加速了运维进度,原本冗长的人机交互,以及多方协调,如今一条简易的docker run
命令即可全部完成。无可否认,自动化的程度有了质的飞跃,然而当我们审视自动化流程时,我们也可以从中找到一些隐患——MySQL容器的明文密码问题
。
MySQL 容器的明文密码问题,指的是:Docker 创建 MySQL 容器时,通过环境变量的方式传递 MySQL 存储引擎的密码,纵使 MySQL 会对密码进行加密,然而环境变量的存在却会泄漏密码信息,因此存在安全隐患。
明文密码解决方案
Docker 容器的明文密码问题,在于控制流程的过于自动化,并且环境变量的方式又无可避免地使用明文记录了密码。在一个完整的 MySQL 容器创建过程中,环境变量和 MySQL 引擎密码始终保持一致,假设我们可以做到用户为 MySQL 设定的密码最终可以落实到 MySQL 引擎处,而不存在于任何环境变量中
,那就可以说明明文密码可以解决。换言之,用户为 MySQL 容器设定的密码时,可以绕过环境变量。众所周知,环境变量在 Docker 的世界中是配置环境最常用的方式,连完成容器间通信的docker link
命令最终也是通过环境变量来完成。
绕过环境变量又是从何说起,首先让我们分析下图。
上图中,我们通过 Docker Daemon 创建了两个 MySQL 容器,容器名分别为 MySQL1 和 MySQL2,并且两个容器中的 MySQL 引擎的密码分别为 mysql1 和 mysql2。创建容器时使用的命令分别为:
docker run -d -e MYSQL_ROOT_PASSWORD=daocloud --name MySQL1 mysql docker run -d -e MYSQL_ROOT_PASSWORD=docker --name MySQL2 mysql
假设一位用户希望创建一个密码不会泄漏的 MySQL 容器,密码为 daocloud。为了弥合明文密码问题,绕过环境变量,我们可以按照以下三个步骤来完成。
1.创建两个 MySQL 容器 MySQL1 与 MySQL2,MySQL 的 root 密码分别为 daocloud 与 docker;
2.待 MySQL1 启动完毕,使用docker stop
命令停止 MySQL1 容器,并将 MySQL1 容器的 volume1 全部拷贝出来,最终使用docker rm
命令删除 MySQL1 容器;
3.待 MySQL2 启动完毕,使用docker stop
命令停止 MySQL2 容器,并将 MySQL2 容器 volume2 内的文件全部删除,接着将 volume1 的内容拷贝至 volume2 下,最终启动 MySQL2。
通过以上三个步骤,我们直接交付 MySQL2 容器,此时 MySQL2 容器中 MySQL 的 root 密码为 daocloud,即目标达成。虽然 MySQL2 容器的环境变量 MYSQLROOTPASSWORD 依旧是 docker,但是 MySQL 引擎使用的密文密码已经转变为 daocloud,交付完毕的 MySQL2 容器中不存在任何有关字符串 daocloud 的明文
信息,同时无需再使用的 MySQL1 容器也被我们删除。
上述流程的执行,可以很巧妙的通过替换volume
的方式,完成密文的转移,同时使得明文环境变量的失效。
Docker层与应用层
通过实践,可以验证解决方案的可行性。不过很多读者看到这里,不禁会对上述方案产生一些质疑,是否替换 volume 就是一个合理的解决方案。
以下的观点,相信很多人会认为同样是合理的解决方案。
明文密码固然是一个大问题,然而当 MySQL 容器创建完毕之后,用户完全有权限通过 mysql-client 等工具登陆 MySQL 引擎,实现 MySQL 引擎 root 密码的修改,最终的结果是:密码修改同样会作用到 volume 中的密文,使得充当明文密码的 Docker 容器环境变量失效。
不可否认,上述观点同样具有可行性。仔细分析和对比两种解决方案,可以看到两者之间存在一些明显的差异。
最大的差异性,当属通用性。替换 volume
的方式,虽然在容器创建流程中加入了部分额外的操作(比如创建两个容器、启动容器、替换 volume等),但是在通用性方面,优势十分明显。通用性的体现何在?本文举例的是 MySQL 容器,其实其他存储类 Docker 容器如 MongoDB、Redis 等,均可以采用这种方式。
换言之,对于存储类 Docker 容器而言,Docker Daemon 的管理员无需获知容器内部运行的是何种服务,机械化操作替换volume
即可导致明文密码失效。通过 mysql-client 修改密码的方式,只能由容器的用户来完成,而现实情况中, Docker Daemon 管理员与容器用户很有可能并非同一个人,尤其是在公有云服务上。因此,Docker Daemon 交付出的容器,必须由用户进行二次加工,才能真正满足用户需求,无疑在便捷性方面,无法尽如人意。
更为细致的比较,我们就能发现:其实两者的实现的立足点不同。替换 volume
则是从 Docker 层出发;而修改密码
则是站在应用层出发。
何为Docker层?Docker 是一款软件,Docker 的世界中 Docker 镜像、Docker 容器等,对于容器的管理(比如启动停止、环境变量的设置等),笔者都认为是 Docker 层的概念。
何为应用层?此处的应用层,指的是与用户镜像内或者容器内与应用直接相关的内容。
依然以 MySQL 为例,通过 MySQL 镜像启动 MySQL 容器时,会使用MYSQL_ROOT_PASSWORD
这个环境变量。环境变量是一个 Docker 层的概念,原因很简单,Docker Daemon 会机械化地将所有用户设置的环境变量作用到容器进程,而不会去关心具体哪个环境变量在容器中充当什么样的角色。同样的道理,名为MYSQL_ROOT_PASSWORD
的环境变量就是一个应用层的概念,这个具体的环境变量,有可能会被容器内部的应用进程来使用,最终影响容器内部的应用。
同样的道理,volume 是一个 Docker 层的概念,volume 内部的具体内容则是应用层的概念。因此,通过 volume 来操作容器,属于 Docker 层的操作,不会涉及任何应用层的内容。而通过事先获知容器内部应用的详细情况,再针对应用进程做出相应的行为,则属于应用层的操作。
总结
存储类 Docker 容器的明文密码问题,实则是:为应用层准备的密码,必须通过 Docker 层的环境变量来传递,而最终 Docker 层的环境变量将一直以明文的形式遗留于多处。通过替换 volume
的方式可以很好地从 Docker 层解决存储类 Docker 容器的明文密码问题。(责编/魏伟)作者简介:孙宏亮@DaoCloud 是《 Docker 源码分析》的专栏作者,已出版《Docker 源码分析》一书。Allen 接触 Docker 近两年,爱钻研系统实现原理,及 Linux 操作系统。本文未经作者允许,不得转载。
欢迎加入CSDN Container技术微信讨论群,和大牛面对面讨论技术和实践,加微信“k15751091376”,拉入群内,备注公司+职位+姓名。
相关推荐
- Windows10 编译OpenCV4.5源码
-
在OpenCV4.5+VisualStudio2017开发环境配置...
- 什么是OpenCV?有哪些基础图像处理操作?
-
一、OpenCV简介OpenCV是一款由Intel公司俄罗斯团队发起并参与和维护的一个计算机视觉处理开源软件库,支持与计算机视觉和机器学习相关的众多算法,并且正在日益扩展。...
- 学习Opencv-第9节-读写图像
-
1、读图像---imread()Matimread(conststring&filename,ingflags=1)定义中包含两个参数,一个图像文件名,一个flag标志位,返回的是一个Ma...
- 基于opencv的视觉巡线实现
-
前言这段时间在和学弟打软件杯的比赛,有项任务就是机器人的视觉巡线,这虽然不是什么稀奇的事情,但是对于一开始不了解视觉的我来说可以说是很懵了,所以现在就想着和大家分享一下,来看看是如何基于opencv来...
- OpenCV学习之图像读取与显示
-
1、OpenCV的特点(1)总体描述...
- OpenCV+Python裁剪图像
-
最近使用OpenCV+Python做了一个程序,功能是自动将照片中的文本部分找出来并裁剪/旋转保存为新的图片。这个功能用专业些的说法就是选择并提取感兴趣区域(ROI(RegionofInteres...
- OpenCV-Python速查表:从导入图像到人脸检测
-
——本文对图像裁剪、调整大小、旋转、阈值、模糊、在图像上绘图和书写、人脸检测和使用轮廓图像检测对象都进行了解释。什么是OpenCV-Python?OpenCV是一个开源的计算机视觉(computer...
- Python图像处理:OpenCV基础教程
-
OpenCV(OpenSourceComputerVisionLibrary)是一个开源计算机视觉和机器学习软件库。它提供了大量的图像和视频处理功能,可以用于各种应用场景,比如人脸识别、物体检...
- OpenCV学堂深度学习系统化学习路线图专题(2023版)
-
参考资料:aixuetang.xyz/15842...
- OpenCV4系统化学习路线图与教程
-
获课:bcwit.top/15489...
- 使用OpenCV库操作摄像头拍照、调节参数和视频录制
-
需求使用OpenCV做功能,播放摄像头(usb和网络),对摄像头设备进行参数调整(亮度、对比度、饱和度、色调、增益、曝光度)调节,拍照和录像。原理使用OpenCV打开摄像头(可打开USB和网路哦摄像...
- Python图像处理:用OpenCV实现照片的趣味特效与编辑!
-
在当今数字化时代,图像处理已经成为了我们生活中不可或缺的一部分,无论是社交媒体上的照片美化,还是专业领域的图像分析,都离不开图像处理技术。Python作为一门强大的编程语言,搭配OpenCV库,为我们...
- OpenCV-1: 读取图片,显示图片,保存图片
-
目标1在这里,将学习如何读取图像,如何显示图像以及如何将其保存回去将学习以下功能:...
- JAVA学习笔记——fileUpload文件上传
-
一、什么是fileUpload?fileUpload是apache的commons组件提供的上传组件,它最主要的工作就是帮我们解析request.getInpustream()。可以参考在线API文档...
- 如何在Windows10中配置java的JDK环境
-
今天给大家分享一下如何配置java的JDK环境。操作步骤如下:1.下载好jdk的安装文件,我下载的是jdk-10.0.1_windows-x64_bin.exe这个版本的安装文件;2.使用鼠标...
- 一周热门
-
-
因果推断Matching方式实现代码 因果推断模型
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
git pull命令使用实例 git pull--rebase
-
git 执行pull错误如何撤销 git pull fail
-
面试官:git pull是哪两个指令的组合?
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)