使用 podman 将容器作为 systemd 服务运行

前置环境要求:需要以 CRI-O 作为容器运行时。安装 CRI-O 及配置国内容器镜像加速器请参考:

使用 CRI-O 容器引擎

本文介绍了如何使用 podman 初始化 systemd 服务,以两种不同的方式使用容器:

使用 systemd 启动容器:通过在宿主机上生成并使用 systemd 单元文件,你可以让宿主机对容器进行自动启动、停止、检查状态,以及以其他方式将容器作为 systemd 服务进行管理。

使用 systemd 启动容器中的服务:许多 Linux 服务(Web 服务器、文件服务器、数据库服务器等)已经被打包为 RHEL 的 systemd 服务。如果你使用的是基于 RHEL 构建的容器镜像,以及任何兼容 RHEL / CentOS 的其他 Linux 发行版构建的容器镜像,你都可以将此类容器镜像设置为启动 systemd 服务,然后在容器启动时自动启动容器内选定的服务。下面以 AnolisOS 8.4 构建的容器镜像为例。

一、使用 systemd 启动容器

为了使用 AnolisOS systemd,你需要创建一份类似下面文本的 Dockerfile 文件。执行 vi Dockerfile 命令,按 i 进入编辑,然后复制粘贴下面的文本,再按 Esc 输入 :wq 保存并返回。

FROM openanolis/anolisos:8.4-x86_64
ENV container docker
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]

此 Dockerfile 删除了许多可能导致问题的单元文件。 从此处开始,执行如下命令以构建 systemd 基础镜像。

podman build --format=docker --rm -t anolisos-systemd:8.4 .

列出刚创建的镜像,执行如下命令。

podman images
# 显示如下内容
localhost/anolisos-systemd     8.4         b4c0566418b0  3 hours ago   231 MB
docker.io/openanolis/anolisos  8.4-x86_64  92b8136491cc  2 months ago  231 MB

删除构建的依赖镜像,执行如下命令。

podman rmi -f 92b8136491cc

创建并启动容器,执行如下命令。 

podman run --privileged -ti --name=master1 localhost/anolisos-systemd:8.4 /usr/sbin/init

使用容器名称或 ID 生成 systemd 单元文件,并将其定向到 /usr/lib/systemd/system/container-master1.service 文件中:

podman generate systemd --name master1 > /usr/lib/systemd/system/container-master1.service

查看生成的 systemd 单元文件的内容:

cat /usr/lib/systemd/system/container-master1.service
# 显示如下内容
# container-master1.service
# autogenerated by Podman 4.0.2
# Sun Apr 17 14:54:21 CST 2022

[Unit]
Description=Podman container-master1.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/run/containers/storage

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStart=/usr/bin/podman start master1
ExecStop=/usr/bin/podman stop -t 10 master1
ExecStopPost=/usr/bin/podman stop -t 10 master1
PIDFile=/run/containers/storage/overlay-containers/1e31f66d7d83977d0860345ad7be3ae25461a314257fd58db0dfd75caa6c6cc8/userdata/conmon.pid
Type=forking

[Install]
WantedBy=default.target

Restart=on-failure 行,设置重启策略,并指示 systemd 在无法完全启动或停止服务时或者进程退出非零时重新启动。
ExecStart 行,描述了如何启动容器。
ExecStop 行,描述了如何停止和移除容器。

重新载入 systemd Manager 配置:

systemctl daemon-reload

启用并启动 container-master1.service : 

systemctl enable --now container-master1.service

以上服务无论用户是否登录,都会随系统启动而自动启动。更多服务启动方式请参阅:启用 systemd 服务

二、使用 systemd 在容器中启动服务

为了使用上面创建的支持 systemd 的基础容器,你需要创建类似于下面的 Dockerfile。 

FROM localhost/anolisos-systemd:8.4
RUN dnf -y install httpd; dnf clean all; systemctl enable httpd.service
EXPOSE 80
CMD ["/usr/sbin/init"]

构建此镜像,执行如下命令:

podman build --format=docker --rm -t systemd-httpd .

为了使用 systemd 运行一个容器,你需要从主机上挂载 cgroups 卷,执行如下命令:

podman run --privileged -ti --name=systemd-httpd -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 80:80 localhost/systemd-httpd

验证容器是否正在运行,并且服务是否正在工作,键入以下命令:

curl 127.0.0.1
# 显示如下内容
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
......

注:由于 podman 创建的容器是独立于 CRI-O 而存在的,因此,此类容器并不会受 crio.service 的状态(如启动、停止、崩溃等)影响。同时,必须得按第一种方式为该类容器单独生成一份 systemd 单元文件后,才能使其随宿主机开机自启动。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值