Docker 容器明文密码问题解决之道
wptr33 2024-11-22 21:59 17 浏览
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”,拉入群内,备注公司+职位+姓名。
相关推荐
- Python自动化脚本应用与示例(python办公自动化脚本)
-
Python是编写自动化脚本的绝佳选择,因其语法简洁、库丰富且跨平台兼容性强。以下是Python自动化脚本的常见应用场景及示例,帮助你快速上手:一、常见自动化场景文件与目录操作...
- Python文件操作常用库高级应用教程
-
本文是在前面《Python文件操作常用库使用教程》的基础上,进一步学习Python文件操作库的高级应用。一、高级文件系统监控1.1watchdog库-实时文件系统监控安装与基本使用:...
- Python办公自动化系列篇之六:文件系统与操作系统任务
-
作为高效办公自动化领域的主流编程语言,Python凭借其优雅的语法结构、完善的技术生态及成熟的第三方工具库集合,已成为企业数字化转型过程中提升运营效率的理想选择。该语言在结构化数据处理、自动化文档生成...
- 14《Python 办公自动化教程》os 模块操作文件与文件夹
-
在日常工作中,我们经常会和文件、文件夹打交道,比如将服务器上指定目录下文件进行归档,或将爬虫爬取的数据根据时间创建对应的文件夹/文件,如果这些还依靠手动来进行操作,无疑是费时费力的,这时候Pyt...
- python中os模块详解(python os.path模块)
-
os模块是Python标准库中的一个模块,它提供了与操作系统交互的方法。使用os模块可以方便地执行许多常见的系统任务,如文件和目录操作、进程管理、环境变量管理等。下面是os模块中一些常用的函数和方法:...
- 21-Python-文件操作(python文件的操作步骤)
-
在Python中,文件操作是非常重要的一部分,它允许我们读取、写入和修改文件。下面将详细讲解Python文件操作的各个方面,并给出相应的示例。1-打开文件...
- 轻松玩转Python文件操作:移动、删除
-
哈喽,大家好,我是木头左!Python文件操作基础在处理计算机文件时,经常需要执行如移动和删除等基本操作。Python提供了一些内置的库来帮助完成这些任务,其中最常用的就是os模块和shutil模块。...
- Python 初学者练习:删除文件和文件夹
-
在本教程中,你将学习如何在Python中删除文件和文件夹。使用os.remove()函数删除文件...
- 引人遐想,用 Python 获取你想要的“某个人”摄像头照片
-
仅用来学习,希望给你们有提供到学习上的作用。1.安装库需要安装python3.5以上版本,在官网下载即可。然后安装库opencv-python,安装方式为打开终端输入命令行。...
- Python如何使用临时文件和目录(python目录下文件)
-
在某些项目中,有时候会有大量的临时数据,比如各种日志,这时候我们要做数据分析,并把最后的结果储存起来,这些大量的临时数据如果常驻内存,将消耗大量内存资源,我们可以使用临时文件,存储这些临时数据。使用标...
- Linux 下海量文件删除方法效率对比,最慢的竟然是 rm
-
Linux下海量文件删除方法效率对比,本次参赛选手一共6位,分别是:rm、find、findwithdelete、rsync、Python、Perl.首先建立50万个文件$testfor...
- Python 开发工程师必会的 5 个系统命令操作库
-
当我们需要编写自动化脚本、部署工具、监控程序时,熟练操作系统命令几乎是必备技能。今天就来聊聊我在实际项目中高频使用的5个系统命令操作库,这些可都是能让你效率翻倍的"瑞士军刀"。一...
- Python常用文件操作库使用详解(python文件操作选项)
-
Python生态系统提供了丰富的文件操作库,可以处理各种复杂的文件操作需求。本教程将介绍Python中最常用的文件操作库及其实际应用。一、标准库核心模块1.1os模块-操作系统接口主要功能...
- 11. 文件与IO操作(文件io和网络io)
-
本章深入探讨Go语言文件处理与IO操作的核心技术,结合高性能实践与安全规范,提供企业级解决方案。11.1文件读写11.1.1基础操作...
- Python os模块的20个应用实例(python中 import os模块用法)
-
在Python中,...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
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)