Alan的Docker容器学习笔记

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: (本文的内容主要来源于Google、百科和学过的一些专栏,目前没有实际的企业级应用容器化部署经验,写的比较浅薄见笑了)

(本文的内容主要来源于Google、百科和学过的一些专栏,目前没有实际的企业级应用容器化部署经验,写的比较浅薄见笑了)

为什么会接触到Docker

运维同学使用k8s将业务迁移上云时遇到一些问题解决不了,需要我去验证一下并帮助解决问题。了解到容器是k8s的基础,并且根据我对问题的推测认为主要原因是文件目录没有挂载,所以我决定学习一下Docker.

Docker容器

Docker这东西使用起来一点都不复杂,跟着Docker官网的说明,聪明的程序员十来分钟应该就能搞定,即使像我一样不太聪明的,结合Google上的部署教程1小时左右的时间也能搞定。

简单来说,它就是个小工具,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

遇到的是什么问题,这个问题的根本原因是什么,如何解决?

问题描述:容器无法获取到宿主机的设备信息,具体点说就是无法在容器上执行dmidecode命令。

想要解决这个问题,需要先了解一下执行dmidecode命令需要具备的条件以及容器的实现机制。

dmidecode命令

dmidecode命令可以让你在Linux系统下获取有关硬件方面的信息包括UUID、BIOS、系统、主板、处理器、内存、缓存等等。

常用用法如下(需要root权限):

[root@localhost ~]$ dmidecode                          # 打印所有硬件信息

[root@localhost ~]$ dmidecode -q                       # 打印所有硬件信息,比较简洁[root@localhost ~]$ dmidecode -h                       # 获取帮助

[root@localhost ~]$ dmidecode | grep 'Product Name'    # 以过滤的方式来查看指定的硬件信息

[root@localhost ~]$ dmidecode --type bios        # 查看BIOS相关的硬件信息

[root@localhost ~]$ dmidecode --type system      # 查看系统相关的硬件信息

[root@localhost ~]$ dmidecode --type baseboard   # 查看主板相关的硬件信息

[root@localhost ~]$ dmidecode --type chassis     # 查看机箱相关的硬件信息

[root@localhost ~]$ dmidecode --type processor   # 查看处理器相关的硬件信息

[root@localhost ~]$ dmidecode --type memory      # 查看内存相关的硬件信息

我们不可能每次都使用root权限执行命令,这时候我们可以提前使用chmod + s升级目录权限。chmod+s 就是给某个文件以suid权限,当一个具有执行权限的文件设置SUID权限后,用户执行这个文件时将以文件所有者的身份执行。

具体代码如下:

chmod +s /usr/sbin/dmidecode

或者

sudo chmod +s /usr/sbin/dmidecode

再来看看容器背后的实现机制

容器的两大关键技术Namespace和Cgroups。我看过的教程都说,理解了这两个概念,基本上就能彻底搞懂容器的核心原理了。我的感受是,虽然没有彻底搞懂容器的核心原理,但是对容器的实现机制有一个大概的了解,然后能搞清楚运维同学提到的问题为什么会出现了。

下面开始分享我学习两大关键技术的经验:

首先我是跟着教程用容器启动服务

具体的做法是先创建一个镜像,然后用这个镜像启动一个容器,也就是启动我们的jar包。(具体的操作可以看Docker官网教程)此时我们的项目就已经被Docker隔离在了一个跟宿主机完全不同的世界当中,这个世界可以称之为“沙盒”。“沙盒”的进程、网络还有文件系统都是独立的。

然后就是思考Docker容器实现“沙盒”的技术手段。

首先是学习实现“边界”的手段Namespace

也就是思考容器的独立运行环境到底是怎么创造的。

容器是一个“单进程”模型,是一种特殊的进程。容器对被隔离应用的进程空间做了手脚,使得这些进程之间”相互隔离“,不能访问彼此的资源,这种技术,就是Linux里面的Namespace机制。

这种隔离有两个作用:第一是可以充分地利用系统的资源,也就是说在一台宿主机上可以运行多个容器;第二是保证了安全性,因为不同容器之间不能访问对方的资源

容器的网络和文件系统不一样,如何做到的呢?

其实这里依靠的是Network Namespace和Mount Namespace:

Mount Namespace,用于让被隔离进程只看到当前Namespace里的挂载点信息;

Network Namespace,用于让被隔离进程看到当前Namespace里的网络设备和配置。

当然除了上面这些, Linux操作系统还提供了Mount、UTS、IPC、Network和User这些Namespace,用来对各种不同的进程上下文进行“障眼法”操作。

这些Namespace尽管类型不同,但都是为了隔离容器资源,正是通过在创建容器进程时,指定了这个进程所需要启用的一组Namespace参数。所以,容器就只能“看”到当前Namespace所限定的资源、文件、设备、状态,或者配置。而对于宿主机以及其他不相关的内容,它就完全看不到了。

再就是学习约束“边界”的手段Cgroups

上面我们学习了,容器,是一种特殊的进程,它使用Namespace实现“障眼法”,即它的“视线”被操作系统做了限制,只能“看到”某些指定的内容。但对于宿主机来说在宿主机真实的进程空间里,这些被“隔离”了的进程跟其他进程并没有太大区别。也就是说这种做法有个问题就是:隔离得不彻底

虽然容器之间在Namespace“障眼法”的干扰下相互之间看不到对方容器内的情况。但是宿主机上,它与其他所有进程之间依然是平等的竞争关系。这就意味着,容器表面上被隔离了起来,但是它所能够使用到的资源(比如CPU、内存、磁盘、网络带宽),却是可以随时被宿主机上的其他进程(或者其他容器)占用的。

所以我们要对容器做一些限制,实现限制的技术手段就是Linux Cgroups,全称是Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带宽等等。

在今天的分享中,我就不和大家去深入学习Cgroups了。感兴趣的同学可以自行Google学习一下。

问题的答案

dmidecode命令和容器背后的实现机制讲完了,但运维同学提出的问题好像还没有解决,我直接把答案放出来吧。

如果要在docker容器中运行dmidecode命令,那么要将宿主机的如下两个目录挂载到容器中。
1. /sbin/dmidecode --这个目录是dmidecode程序的目录,如果不挂载那么容器中识别不了dmidecode命令。
2. /dev/mem --dmidecode调用时会使用到mem这个文件,如果不挂载会找不到文件。
3. 在启动时增加 --privileged 这个参数,让容器获得近似于宿主机root的权限。
完整的运行命令如下:

docker run -d --privileged -v /sbin/dmidecode:/sbin/dmidecode -v /dev/mem:/dev/mem --name my-demo -p 9090:8080 demo

(以近似于root的权限用后台模式启动demo这个镜像,取别名为my-demo,并挂载两个宿主机目录到容器中,将容器的8080端口映射到宿主机9090端口)

总结一下,其实容器中想要用的任何东西,无论是文件还是程序还是什么别的,都可以通过挂载的形式从宿主机中挂载到容器中,让容器中可以访问到。

安全性问题

Docker容器确实非常火热也很好用,但是在生产环境下当Docker运行在云提供商平台上时,安全性变得更加复杂,所以企业生产环境需要特别注意容器安全问题。

比如说,上文使用Privileged参数,让容器获得近似于宿主机root的权限,这个配置就是不安全的。

为什么这个Privileged配置不安全?

如果配置了privileged参数,容器就可以获取所有的capabilities,那什么是capabilities呢?

Linux capabilities:对于任意一个进程,在做任意一个特权操作的时候,都需要有这个特权操作对应的capability。

privileged 由于包含了所有的capabilities, 这样容器就可以轻易获取宿主机上的所有资源,这会对宿主机的安全产生威胁。类似于root权限的概念。

所以,我们要根据容器中进程需要的最少特权来赋予capabilities。添加权限的参数是 --cap-add ,具体要授权什么 capabilities 可以Google搜索“linux capabilities手册”了解。

一些思考

写了这么多其实只是学习了一些表面的东西。可能有同学会问我为什么不深入地去学习,比如说探究Cgroups、Namespace原理,深入学习容器进程、网络、安全、存储、内存模块,甚至是自己去实现Docker。

对此我的回答是,在深入学习容器之前我需要先去学习linux和一点C,这不是我现阶段想做的事情。

最后

我把上面的答案告诉运维同学后,他们反馈说,用K8s挂载不了上面提到的目录。限于我目前对K8s不了解,这个问题他们也不着急,所以只能暂时搁置一下,等我学完k8s再去解决。学习完k8s之后我会和今天一样把学习经验分享出来。我在微信公众号发表了本文的英文版(借助了翻译软件),如果您感兴趣可以关注一下我: ProgrammerAlan。

作者简介

鑫茂,深圳,Java开发工程师,2022年3月参加工作。

喜读思维方法、哲学心理学以及历史等方面的书,偶尔写些文字。

希望通过文章,结识更多同道中人。如果你对我感兴趣欢迎添加我的联系方式,可以一起讨论如何赚钱,实现共同富裕。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
6天前
|
弹性计算 运维 持续交付
探索Docker容器化技术及其在生产环境中的应用
探索Docker容器化技术及其在生产环境中的应用
36 5
|
1天前
|
负载均衡 网络协议 开发者
掌握 Docker 网络:构建复杂的容器通信
在 Docker 容器化环境中,容器间的通信至关重要。本文详细介绍了 Docker 网络的基本概念和类型,包括桥接网络、宿主网络、覆盖网络和 Macvlan 网络等,并提供了创建、管理和配置自定义网络的实用命令。通过掌握这些知识,开发者可以构建更健壮和灵活的容器化应用,提高应用的可扩展性和安全性。
|
1天前
|
运维 Ubuntu Linux
深入理解并实践Docker容器化技术
深入理解并实践Docker容器化技术
21 6
|
7天前
|
运维 Docker 微服务
掌握 Docker Compose:简化你的多容器应用部署
在微服务架构和容器化技术普及的今天,管理多容器部署变得颇具挑战。Docker Compose 通过一个 YAML 文件定义和运行多容器应用,简化了部署和运维。本文介绍其基本概念、使用方法及优势,包括服务、项目、卷和网络等核心概念,并提供从安装到管理服务的详细步骤,助你轻松掌握 Docker Compose,提高开发效率和应用运维质量。
|
7天前
|
Cloud Native 持续交付 Docker
探索Docker容器化技术及其在软件开发中的应用
探索Docker容器化技术及其在软件开发中的应用
17 7
|
7天前
|
存储 虚拟化 开发者
深入理解Docker容器化技术
深入理解Docker容器化技术
36 6
|
4天前
|
Prometheus 监控 Cloud Native
docker安装prometheus+Granfan并监控容器
【9月更文挑战第14天】本文介绍了在Docker中安装Prometheus与Grafana并监控容器的步骤,包括创建配置文件、运行Prometheus与Grafana容器,以及在Grafana中配置数据源和创建监控仪表盘,展示了如何通过Prometheus抓取数据并利用Grafana展示容器的CPU使用率等关键指标。
|
6天前
|
Cloud Native 持续交付 Docker
探索容器化技术Docker的奥秘
探索容器化技术Docker的奥秘
23 3
|
22天前
|
Cloud Native 持续交付 Docker
云原生之旅:Docker容器化实战指南
【8月更文挑战第29天】本文将引领你进入云原生技术的世界,以Docker容器化为切入点,深入浅出地介绍如何利用Docker进行应用的打包、部署及管理。我们将通过实际代码示例,一步步展示Docker镜像的构建过程,以及如何运行和管理这些容器。无论你是初学者还是有一定经验的开发者,都能从中获得宝贵的知识和实操经验。
|
17天前
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo