本专栏文章持续更新,新增内容使用蓝色表示。

背景

早期开源项目采用 LAMP 架构(Linux + Apache + MySQL + PHP),随着应用复杂度提升,部署和运维挑战日益增加。2006年亚马逊推出 AWS 服务,开创了云计算商业化先河,也为容器技术的发展铺平了道路。

虚拟化技术作为云计算的基础设施,为微服务架构的兴起创造了条件。而容器技术则在虚拟化基础上,提供了更加轻量级的解决方案。

一、什么是容器?

容器本质上是一种特殊的进程,通过内核级隔离技术实现容器间运行环境的完全隔离。这种隔离机制确保了各个容器互不影响,为应用程序提供了一种轻量级的打包和部署解决方案。容器技术不仅简化了应用程序的依赖管理,还极大地提升了部署效率和环境一致性。

1.1 核心支撑技术

1.1.1 Control Groups (cgroups)

cgroups 是 Linux 内核特性,负责资源管理和分配。它主要控制:

  • CPU 资源分配和限制

  • 内存使用量和交换空间管理

  • 磁盘 I/O 带宽控制

  • 网络优先级设置

1.1.2 Namespace 隔离机制

Namespace 提供进程间的隔离环境,包括:

  • PID Namespace:进程 ID 隔离

  • Network Namespace:网络栈隔离

  • Mount Namespace:文件系统挂载点隔离

  • UTS Namespace:主机名和域名隔离

  • IPC Namespace:进程间通信资源隔离

  • User Namespace:用户和组 ID 隔离

1.1.3 安全增强型 Linux (SELinux)

SELinux 提供强制访问控制机制(MAC),为容器环境增加额外的安全层,防止权限提升和资源滥用。

1.2【重要】容器与虚拟机的区别

虽然虚拟机和容器在用户体验上相似,甚至容器启动速度更快,但两者的架构本质不同:

1.2.1 虚拟机架构特点

  • 通过 Hypervisor 虚拟化层抽象硬件资源

  • 每个虚拟机包含完整的操作系统

  • 资源开销较大,启动速度较慢

  • 提供完全隔离的运行环境

1.2.2 容器架构特点

  • 直接运行在主机操作系统上

  • 共享主机操作系统内核(通过docker引擎借助主机的操作系统)

  • 资源利用率高,启动速度快(秒级)

  • 容器内部只包含应用及其所有依赖(二进制文件、库、配置文件)

1.3 有根容器和无根容器

在容器主机上,用户可以选择以 root 用户或普通用户身份运行容器:

1)Rootful 容器:以 root 权限运行,具有系统级访问能力,但存在安全风险。

2)Rootless 容器(无根容器):以非特权用户运行,安全性更高但功能受限

  • 无法绑定特权端口(1024以下)

  • 部分系统操作受到限制

由于容器继承父进程的地址空间,在 root 用户下运行的容器需要特别关注安全配置。

1.4 Podman 与 Docker 的主要区别

1)无守护进程 (Daemon-less):不需要一个常驻后台进程来管理容器,更加轻量和安全。

2)Rootless 模式这是最重要的特性。普通用户无需 root 权限即可直接运行和管理容器,极大地提升了安全性。以上所有命令都可以在非 root 用户下执行。

3)Pod 原生支持:直接支持管理 Kubernetes 风格的 Pod(一组共享资源的容器)。

1.5 容器特点

1)环境一致性:解决"开发-测试-生产"环境差异问题,避免因环境配置导致的运行异常。

2)版本管理:支持容器镜像版本控制,方便回滚和版本追踪。

3)可移植性:轻松跨环境迁移,从开发到生产环境无缝过渡。

4)临时性:容器生成的数据通常为临时的,重要数据需通过卷(volume)持久化存储。

5)镜像复用:一个镜像可启动多个容器实例,可以类比面向对象中的对象关系。

1.6 容器镜像

容器镜像基于应用程序代码、运行时配置、系统库和依赖项构建而成,构建完成后为只读状态,不可修改,想要更新需要重新构建镜像版本。

容器镜像统一存储在镜像仓库中管理。这个仓库在 docker 叫做 repository ,在红帽的 podman 中为了区分叫做容器注册表 registry ,实际上是一个内容。

注:容器可以理解为是运行中的镜像。

1.7 容器运行时与编排

容器运行依赖底层运行时(如 runc、crun),这些运行时实现容器生命周期管理。在 Docker 中称为容器引擎,在 Podman 中采用无守护进程架构。

Kubernetes——容器编排工具,现版本可以称为云原生的操作系统

:这部分的具体内容会在【Kubernetes 学习与面试必知】专栏中具体介绍。

OpenShift——Kubernetes 的企业级发行版,拥有图形化界面,封装了k8s并增加了一些功能,如 Web 管理界面、监控、审计等,,简化容器编排复杂度。

二、Podman 使用

Podman 在设计时就有意保持了与 Docker CLI(命令行界面)的高度兼容性。 对于绝大多数日常命令,只需要将 podman 换成 docker 即可。命令的格式、选项和参数都完全相同,降低了用户从 Docker 迁移到 Podman 的学习成本和迁移门槛。

2.1 镜像管理

1)查看镜像:podman images (列出本地镜像)

2)搜索镜像:podman search <镜像名> (从仓库搜索,如 podman search nginx)

3)拉取镜像:podman pull <镜像名:标签> (下载镜像到本地,如 podman pull ubuntu:22.04)

4)构建镜像:podman build -t <镜像名:标签> <路径> (根据 Dockerfile 构建镜像,如 podman build -t myapp:1.0 .)

补充

-t 是 --tag 的缩写,目的是为了给镜像一个有意义的标识符,方便后续的使用、管理和分享。

标签(Tag)用于用于区分同一镜像的不同版本、不同变体或不同构建。

镜像名和标签的关系就像 “书名” 和 “版本号”。

5)推送镜像:podman push <镜像名> <仓库地址> (将镜像推送到远程仓库)

6)删除镜像:podman rmi <镜像名或ID> (删除本地镜像,如 podman rmi alpine)

2.2 容器生命周期管理

1)创建并运行容器:podman run [选项] <镜像名>

选项 助记 功能描述
-d detach 后台运行容器。容器启动后,终端会立即返回,并只显示容器ID。不会阻塞当前命令行窗口。
-it -i (--interactive) + -t (--tty) 交互式运行容器并分配一个伪终端。通常用于启动需要直接交互的容器(如进入Shell)。
--name name 为容器指定一个自定义名称,而不是使用系统生成的随机名称。便于后续管理(如启动、停止)。
-p port 端口映射。将主机的端口映射到容器的端口,使得外部可以通过主机IP访问容器内的服务。
-v volume 挂载数据卷。将主机上的一个目录或文件挂载到容器中,实现数据持久化宿主机与容器间共享文件
--rm remove 容器退出后自动删除。适用于临时测试任务,容器停止后会自动清理,避免积累大量停止的容器。
podman run -d --name my_web nginx:alpine (后台运行一个名为 my_web 的 Nginx 容器)

podman run -p 8080:80 nginx (运行Nginx并将容器80端口映射到主机8080端口)

podman run -it --rm ubuntu bash (交互式运行一个临时Ubuntu容器,退出即删除)

2)启动容器:podman start <容器名或ID>

3)停止容器:podman stop <容器名或ID>

4)重启容器:podman restart <容器名或ID>

5)暂停/恢复容器:podman pause / podman unpause <容器名或ID>

6)删除容器:podman rm <容器名或ID>,使用 -f 选项强制删除运行中的容器。

podman rm -f my_web

注:删除前,必须先停止容器。

2.3 查看与监控

1)列出容器:

podman ps            # 查看运行中的容器

podman ps -a         # 查看所有容器,包括已停止的

2)查看日志:podman logs <容器名或ID>,使用 -f 选项实时跟踪日志输出。

podman logs -f my_web

3)查看详情:podman inspect <容器名或ID> (以JSON格式显示容器或镜像的详细配置信息)

4)查看资源统计:podman stats (实时显示所有容器的CPU、内存等资源使用情况)

5)查看进程:podman top <容器名或ID> (查看容器内运行的进程)

6)执行命令:podman exec [选项] <容器名或ID> <命令>,常用 -it 选项进入容器交互界面。

podman exec -it my_web /bin/sh

2.4 数据管理

1)创建卷:podman volume create <卷名> (创建命名的持久化数据卷)

2)列出卷:podman volume ls

3)使用卷:在 podman run 命令中使用 -v 选项

podman run -v <卷名>:<容器内路径>  ... (使用命名卷)

podman run -v <主机路径>:<容器内路径> ... (挂载主机目录)

2.5 系统与信息

查看信息:podman info (显示系统、存储、运行时等全面信息)

查看版本:podman version

2.6 登录镜像仓库

登录到镜像仓库之后,可以进行拉取、上传等操作

podman login -u <用户名> --password <服务器地址>  
# 输入密码,回车

# 或者
echo "<密码>" | podman login -u <用户名> --password-stdin <服务器地址>        # 推荐

注:不指定 <服务器地址>时,Podman 会默认尝试登录 Docker Hub (docker.io)。

不要使用以下方式登录,因为密码会明文保存在 shell 历史记录中。

podman login -u <用户名> --password <密码> <服务器地址>  

2.7 退出镜像仓库

podman logout                     # 默认 Docker Hub (docker.io)
podman logout <服务器地址>  

三、把容器做成服务的形式

普通用户可以使用 systemctl 命令来启动、停止、重启服务等,通过创建 systemd 单元配置 rootless 容器,可将容器作为常规的系统服务进行管理。

1)在主机上创建数据目录并更改权限

创建要映射到容器内的主机目录,并确保运行容器的用户有权访问它。

# 示例
mkdir /host/data

# 改权限为将要运行容器的用户
chown testuser:testuser /opt/cloud

2)登录管理容器的用户账户

如果尚未创建用户,可先创建:sudo useradd testuser。然后必须通过SSH登录该用户:

ssh testuser@localhost

注意:Podman 在 rootless(非root)模式下,依赖每个用户独立的后台进程和通信套接字,这些都由用户级的 systemd --user 管理。

SSH 登录会自动创建完整的用户会话并启动 systemd --user,所以我们通过此方式登录后操作。而 sudo 或 su 只是切换了权限,没有创建完整的用户会话,导致找不到后台进程和套接字,因此不能使用。

3)创建并运行测试容器,验证配置

这一步的目的是作为一个配置模板,验证所有参数是否正确后再生成服务文件。完成后停止测试容器,为其生成服务文件做准备。

podman run -d \
  --name myapp \                         # 容器名
  -v /host/data:/container/data:Z \      # 卷映射路径
  <仓库位置>/<镜像名称>:<标签>             # 使用实际镜像名

# 完成后停止测试容器,锁定其配置
podman stop myapp

其它参数可以根据需要添加。

注:Z 选项是为了自动设置目录的 SELinux 上下文,当然也可以自己手动设置为container_file_t。

更多有关 SELinux 的内容请查看以下文章:
【Linux】权限管理详解(三):SELinux安全性管理 | Redhat_selinux权限-CSDN博客

4)生成Systemd服务文件

基于已停止的测试容器生成服务文件。--new参数确保服务每次启动时都创建新容器,而不是重启旧容器。

# Rootless (用户级):
mkdir -p ~/.config/systemd/user/
cd ~/.config/systemd/user/
podman generate systemd --name myapp --new --files

# 删除测试容器
podman rm -f myapp

补充:

# Rootful:
cd /etc/systemd/system/
sudo podman generate systemd --name myapp --new --files

5)重新加载并启动Systemd服务

systemctl --user daemon-reload
systemctl --user enable --now container-myapp.service

6)配置为系统引导时启动 

启用 linger 使用户服务在系统启动时自动运行。

loginctl enable-linger

# 恢复
loginctl disable-linger

除了上述介绍的方式外,还可以手动创建 Systemd 服务文件完成,此处不多介绍。


有关容器的更多内容将在【Docker】专栏进行介绍。

如有问题或建议,欢迎在评论区中留言~

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐