📋

Podman Compose (Rootless) で自動起動

に公開

概要

ユーザでログインすることなくpodman composeを自動起動させる。
nvidiaのGPUを有効にしたコンテナではハマりポイントがあるので、そこの対応策も示す。

  • systemdを活用する。
  • nvidiaのドライバ初期化を待つために、nvidia-smiを実行する。

因みに、nvidiaのGPUを有効にしたコンテナの生成方法はこちらで記事にしている。

環境

項目 内容 Versionなど
ホストOS Ubuntu 24.04 Server
コンテナマネージャ Podman 4.9.3
podman compose のバックエンド podman-compose 1.3.0
グラフィックボード GTX 1650 Turing(第六世代)

systemdの設定

systemd に unit ファイルを登録

# コマンドを確認
podman compose systemd -h

# unitファイルを生成
# /etc/systemd/user/podman-compose@.service
sudo podman compose systemd -a create-unit

# systemd 再読み込み
sudo systemctl daemon-reload

生成されたunitファイルを編集

/etc/systemd/user/podman-compose@.service が生成されるが、このままでは上手く動作しないので手で修正する。ExecStopPostはお好みで。

/etc/systemd/user/podman-compose@.service
# /etc/systemd/user/podman-compose@.service

[Unit]
Description=%i rootless pod (podman-compose)

[Service]
Type=simple
EnvironmentFile=%h/.config/containers/compose/projects/%i.env

# これは nvidia の GPUを有効にしたコンテナのみ。
+ ExecStartPre=/usr/bin/nvidia-smi

# podman-composeでpodを生成するように修正
- ExecStartPre=-/usr/bin/podman-compose up --no-start
+ ExecStartPre=-/usr/bin/podman-compose --in-pod pod_%i up --no-start

ExecStartPre=/usr/bin/podman pod start pod_%i
ExecStart=/usr/bin/podman-compose wait
ExecStop=/usr/bin/podman pod stop pod_%i

# 停止するだけでなくpodを削除する。podman-compose down のイメージ。
+ ExecStopPost=/usr/bin/podman pod rm pod_%i

[Install]
WantedBy=default.target

個別のcomposeを登録

下記をコマンドでunitファイル内で利用するenvファイルを生成。
(一つのunitファイルから、複数のserviceを管理することが出来る)

podman compose systemd -a register

例えば、下記のようなファイルが生成され、先ほどのunitファイルから参照されることになる。

~/.config/containers/compose/projects/your-service.env
COMPOSE_PROJECT_DIR=/home/user/your-service
COMPOSE_FILE=compose.yml
COMPOSE_PATH_SEPARATOR=:
COMPOSE_PROJECT_NAME=your-service

Unitファイル有効化

register コマンドを実行した際に、指示が表示されるので、それ通りにコマンドを実行する。

# your-service の部分は対象のサービス名で置き換え
systemctl --user enable --now podman-compose@your-service

# 動作確認
systemctl --user status podman-compose@your-service
journalctl --user -xeu podman-compose@your-service

# podman側からも確認できる(pod化された以降のみ可)
podman pod stats pod_your-service

PC起動時(ログインしていない状態)でもユーザ空間のsystemd管理サービスを実行

# ログインしていない状態でもuser空間のsystemd管理サービスを動作させる。
# uservame の部分は、適切なユーザ名で置き換え。
sudo loginctl enable-linger username

以上でsystemdでpodman-composeで規定したコンテナ群を管理できるようになった。
以降は、podman compose ではなく、systemctlで管理する。

参考

podman-compose systemd のソース 該当部分

create-unit部分
script = os.path.realpath(sys.argv[0])
...

    elif args.action == "create-unit":
        fn = "/etc/systemd/user/podman-compose@.service"
        out = f"""\
# {fn}

[Unit]
Description=%i rootless pod (podman-compose)

[Service]
Type=simple
EnvironmentFile=%h/{stacks_dir}/%i.env
ExecStartPre=-{script} up --no-start
ExecStartPre=/usr/bin/podman pod start pod_%i
ExecStart={script} wait
ExecStop=/usr/bin/podman pod stop pod_%i

[Install]
WantedBy=default.target
"""
        if os.access(os.path.dirname(fn), os.W_OK):
            log.debug("writing [%s]: ...", fn)
            with open(fn, "w", encoding="utf-8") as f:
                f.write(out)
            log.debug("writing [%s]: done.", fn)
            print(
                """
while in your project type `podman-compose systemd -a register`
"""
            )
        else:
            print(out)
            log.warning("Could not write to [%s], use 'sudo'", fn)
register部分
if args.action == "register":
    proj_name = compose.project_name
    fn = os.path.expanduser(f"~/{stacks_dir}/{proj_name}.env")
    os.makedirs(os.path.dirname(fn), exist_ok=True)
    log.debug("writing [%s]: ...", fn)
    with open(fn, "w", encoding="utf-8") as f:
        for k, v in compose.environ.items():
            if k.startswith("COMPOSE_") or k.startswith("PODMAN_"):
                f.write(f"{k}={v}\n")
    log.debug("writing [%s]: done.", fn)
    log.info("\n\ncreating the pod without starting it: ...\n\n")
    username = getpass.getuser()
    print(
        f"""
you can use systemd commands like enable, start, stop, status, cat
all without `sudo` like this:

\t\tsystemctl --user enable --now 'podman-compose@{proj_name}'
\t\tsystemctl --user status 'podman-compose@{proj_name}'
\t\tjournalctl --user -xeu 'podman-compose@{proj_name}'

and for that to work outside a session
you might need to run the following command *once*

\t\tsudo loginctl enable-linger '{username}'

you can use podman commands like:

\t\tpodman pod ps
\t\tpodman pod stats 'pod_{proj_name}'
\t\tpodman pod logs --tail=10 -f 'pod_{proj_name}'
"""
    )

引用: Github - containers / Podman Compose

GitHubで編集を提案

Discussion