百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Docker 容器明文密码问题解决之道

itomcoil 2025-03-18 23:11 10 浏览

Docker 带着 “Dockerize Everything” 的口号,以“软件标准”的姿态展现于世人面前,不断影响大家对于软件的理解。然而现实是否就如想象中的那么饱满,新的科技诞生之际,是摧枯拉朽之势,还是循序渐进,皆有个过程,面对异军突起的 Docker,软件传统的精髓又是何去何从?这些无一不是值得深思的话题。

在《存储类 Docker 容器的明文密码问题》一文中,我们初步领略了存储类软件与 Docker 结合时,存在的些许安全隐患,比如明文密码问题。

过去数十年间,MySQL 数据库的创建都在人机交互过程中完成,流程大致可以分为以下三个步骤:

  1. 运维人员创建机器,安装并配置 MySQL 服务器;

  2. DBA 负责管理 MySQL 数据库,如 MySQL 数据库的创建、删除与权限更改等;

  3. 开发人员使用 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”,拉入群内,备注公司+职位+姓名。

相关推荐

selenium(WEB自动化工具)

定义解释Selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7,8,9,10,11),MozillaF...

开发利器丨如何使用ELK设计微服务中的日志收集方案?

【摘要】微服务各个组件的相关实践会涉及到工具,本文将会介绍微服务日常开发的一些利器,这些工具帮助我们构建更加健壮的微服务系统,并帮助排查解决微服务系统中的问题与性能瓶颈等。我们将重点介绍微服务架构中...

高并发系统设计:应对每秒数万QPS的架构策略

当面试官问及"如何应对每秒几万QPS(QueriesPerSecond)"时,大概率是想知道你对高并发系统设计的理解有多少。本文将深入探讨从基础设施到应用层面的解决方案。01、理解...

2025 年每个 JavaScript 开发者都应该了解的功能

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发。1.Iteratorhelpers开发者...

JavaScript Array 对象

Array对象Array对象用于在变量中存储多个值:varcars=["Saab","Volvo","BMW"];第一个数组元素的索引值为0,第二个索引值为1,以此类推。更多有...

Gemini 2.5编程全球霸榜,谷歌重回AI王座,神秘模型曝光,奥特曼迎战

刚刚,Gemini2.5Pro编程登顶,6美元性价比碾压Claude3.7Sonnet。不仅如此,谷歌还暗藏着更强的编程模型Dragontail,这次是要彻底翻盘了。谷歌,彻底打了一场漂亮的翻...

动力节点最新JavaScript教程(高级篇),深入学习JavaScript

JavaScript是一种运行在浏览器中的解释型编程语言,它的解释器被称为JavaScript引擎,是浏览器的一部分,JavaScript广泛用于浏览器客户端编程,通常JavaScript脚本是通过嵌...

一文看懂Kiro,其 Spec工作流秒杀Cursor,可移植至Claude Code

当Cursor的“即兴编程”开始拖累项目质量,AWS新晋IDEKiro以Spec工作流打出“先规范后编码”的系统工程思维:需求-设计-任务三件套一次生成,文档与代码同步落地,复杂项目不...

「晚安·好梦」努力只能及格,拼命才能优秀

欢迎光临,浏览之前点击上面的音乐放松一下心情吧!喜欢的话给小编一个关注呀!Effortscanonlypass,anddesperatelycanbeexcellent.努力只能及格...

JavaScript 中 some 与 every 方法的区别是什么?

大家好,很高兴又见面了,我是姜茶的编程笔记,我们一起学习前端相关领域技术,共同进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力在JavaScript中,Array.protot...

10个高效的Python爬虫框架,你用过几个?

小型爬虫需求,requests库+bs4库就能解决;大型爬虫数据,尤其涉及异步抓取、内容管理及后续扩展等功能时,就需要用到爬虫框架了。下面介绍了10个爬虫框架,大家可以学习使用!1.Scrapysc...

12个高效的Python爬虫框架,你用过几个?

实现爬虫技术的编程环境有很多种,Java、Python、C++等都可以用来爬虫。但很多人选择Python来写爬虫,为什么呢?因为Python确实很适合做爬虫,丰富的第三方库十分强大,简单几行代码便可实...

pip3 install pyspider报错问题解决

运行如下命令报错:>>>pip3installpyspider观察上面的报错问题,需要安装pycurl。是到这个网址:http://www.lfd.uci.edu/~gohlke...

PySpider框架的使用

PysiderPysider是一个国人用Python编写的、带有强大的WebUI的网络爬虫系统,它支持多种数据库、任务监控、项目管理、结果查看、URL去重等强大的功能。安装pip3inst...

「机器学习」神经网络的激活函数、并通过python实现激活函数

神经网络的激活函数、并通过python实现whatis激活函数感知机的网络结构如下:左图中,偏置b没有被画出来,如果要表示出b,可以像右图那样做。用数学式来表示感知机:上面这个数学式子可以被改写:...