Armadilloフォーラム

コンテナ内でsystemctlコマンドを使う方法

m.yoshida

2023年12月8日 15時32分

お世話になっております。
systemctlを使用すると

System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

と表示されプロセスを確認すると確かにPID1でないので動作しません

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0    188    44 pts/0    Ss   06:23   0:00 /run/podman-ini
root         2  0.0  0.4   2772  2224 pts/0    S    06:23   0:00 /bin/bash
root         3  0.0  0.3   5092  1876 pts/0    R+   06:24   0:00 ps aux

変更する方法ありますでしょうか?

コメント

具体的にはsystemctlで何をしたいですか?
systemctlコマンドはinitであるsystemdに対して制御を行うためのコマンドですが、
そもそもコンテナの中にはinitは居ないので、実行したいサービスがあるなら、単に
コマンドとしてコンテナのrunで実行します。

もしくはコンテナの外のホストOS(ABOS)のinitを制御したいのであれば
(これはコンテナがアップデートサービスを破壊できる程度に権限を持つため
システムを停止させることが可能になるため推奨しません。)
ABOS側のinitはsystemdではなくopenrcなのでsystemcrlではなく
rc-status等のコマンドを使うことになります。

後者はできれば実施してほしくないので、用途をおしえてください。

アットマークテクノの古賀です。

m.yoshidaさん:
>systemctlを使用すると

System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

>と表示されプロセスを確認すると確かにPID1でないので動作しません

systemctl が存在しているということで、Debian コンテナに systemd パッケージをインストールしていらっしゃる状態なのでしょうね。

>変更する方法ありますでしょうか?

at_ohsawa:
>具体的にはsystemctlで何をしたいですか?

おそらくですが、以下の投稿で質問していらした、sshd や postgresql などのサービス/デーモンを、コンテナ起動時に自動起動するために systemd を利用しようと思い、systemctl を使ってみた、ということだろうかと想像しています。
 https://armadillo.atmark-techno.com/forum/armadillo/18059
m.yoshidaさん、この想像で違っていたら、ごめんなさい。

>systemctlコマンドはinitであるsystemdに対して制御を行うためのコマンドですが、
>そもそもコンテナの中にはinitは居ないので、実行したいサービスがあるなら、単に
>コマンドとしてコンテナのrunで実行します。

m.yoshida さんが作成されたコンテナには、たぶん、/lib/systemd/systemd は systemd パッケージのインストールにより存在しているものの、/sbin/init が存在していない状態だと思います。
その場合は、次のようにすれば、コンテナ起動時に systemd が init として実行され、systemctl で有効に設定したサービスを自動起動させることができます。ただし、「コンテナに入れて動かすものを必要最小限に保つべし」というセキュリティの観点からの推奨ポリシーで考えれば、コンテナ起動時に自動起動したいサービスを、個別に明示起動する設定をコンテナに加える方が良いと思います。
以下、systemd を init としてコンテナ起動時に実行させる方法です:

1.) コンテ内で、/sbin/init から /lib/systemd/systemd へのシンボリックリンクを作る

# ln -s /lib/systemd/systemd /sbin/init

2.) (1) で変更したコンテナ内容を podman commit で保存する。

3.) (3) で保存したコンテナイメージからコンテナを生成する際に、podman run の引数を次のようにする:
 3-1.) --systemd=true の指定を追加
 3-2.) 実行コマンドとして /sbin/init を指定
 3-3.) -it を指定しない(-d での起動にする)

これにより、(3) で生成したコンテナ内では、PID: 1 のプロセスとして init(: 実体は systemd)が起動しますので、systemctl を実行できるようになります。
podman exec -it <コンテナ名> /bin/bash でコンテナ内のシェルを起動して、systemctl を使い、コンテナ起動時に自動起動されるサービスを有効化すれば、その後、コンテナを podman stop & podman start で起動し直すと、有効化したサービスが起動するはずです。

なお、systemctl でサービスの有効化を設定した後、再度 podman commit でコンテナ変更内容をイメージに保存してください。そうしておけば、イメージからコンテナを生成し直しても、サービスの有効化設定が保持されます。
コンテナ内での systemd の実行については、以下の Blog が参考になると思います:

 How to run systemd in a container
 https://developers.redhat.com/blog/2019/04/24/how-to-run-systemd-in-a-c…

 Podman - systemd in containers
 https://blog.while-true-do.io/podman-systemd-in-containers/

また、コンテナの動作の仕組みや、コンテナ運用上でのセキュリティの考え方などについて、以下の本は参考書籍として良いと思います:

 Container Security: Fundamental Technology Concepts That Protect Containerized Applications
 https://www.amazon.co.jp/gp/product/1492056707

いかがでしょうか?もし参考になりましたら幸いです。

アットマークテクノ 古賀様

ご回答ありがとうございます。
(製品をA6EではなくA6で登録してしまったため、気が付くのおくれました。)
回答遅れてすいません。

> おそらくですが、以下の投稿で質問していらした、sshd や postgresql などのサービス/デーモンを、コンテナ起動時に自動起動するために systemd を利用しようと思い、systemctl を使ってみた、ということだろうかと想像しています。
>  https://armadillo.atmark-techno.com/forum/armadillo/18059
> m.yoshidaさん、この想像で違っていたら、ごめんなさい。

ご認識の通りです。systemdでサービスの自動起動できないか検討していました。
上記のURLで紹介していただきましたが、他にも動作させたいサービスもあるので、systemdを使用したいとおてます。

> 1.) コンテ内で、/sbin/init から /lib/systemd/systemd へのシンボリックリンクを作る
>

> # ln -s /lib/systemd/systemd /sbin/init
> 

>
> 2.) (1) で変更したコンテナ内容を podman commit で保存する。
>
> 3.) (3) で保存したコンテナイメージからコンテナを生成する際に、podman run の引数を次のようにする:
>  3-1.) --systemd=true の指定を追加
>  3-2.) 実行コマンドとして /sbin/init を指定
>  3-3.) -it を指定しない(-d での起動にする)
>
> これにより、(3) で生成したコンテナ内では、PID: 1 のプロセスとして init(: 実体は systemd)が起動しますので、systemctl を実行できるようになります。
> podman exec -it <コンテナ名> /bin/bash でコンテナ内のシェルを起動して、systemctl を使い、コンテナ起動時に自動起動されるサービスを有効化すれば、その後、コンテナを podman stop & podman start で起動し直すと、有効化したサービスが起動するはずです。

→(3)コンテナコミットしてイメージ化後コンテナ作成時下記のエラーがでました。
コンテナは作成してるみたいです。修正点ありますでしょうか?

podman run  --name=コンテナ名 --systemd=true  -d  イメージ名  /sbin/init
Error: crun: open executable: Operation not permitted: OCI permission denied

> なお、systemctl でサービスの有効化を設定した後、再度 podman commit でコンテナ変更内容をイメージに保存してください。そうしておけば、イメージからコンテナを生成し直しても、サービスの有効化設定が保持されます。
> コンテナ内での systemd の実行については、以下の Blog が参考になると思います:
>
>  How to run systemd in a container
>  https://developers.redhat.com/blog/2019/04/24/how-to-run-systemd-in-a-c…
>
>  Podman - systemd in containers
>  https://blog.while-true-do.io/podman-systemd-in-containers/
>
> また、コンテナの動作の仕組みや、コンテナ運用上でのセキュリティの考え方などについて、以下の本は参考書籍として良いと思います:
>
>  Container Security: Fundamental Technology Concepts That Protect Containerized Applications
>  https://www.amazon.co.jp/gp/product/1492056707
>
> いかがでしょうか?もし参考になりましたら幸いです。

上記も確認してみます。情報共有していただいてありがとうございます。

アットマークテクノの古賀です。

m.yoshidaさん:
>ご回答ありがとうございます。
>(製品をA6EではなくA6で登録してしまったため、気が付くのおくれました。)
>回答遅れてすいません。

あ、いえいえ。

>>おそらくですが、以下の投稿で質問していらした、sshd や postgresql などの
>>サービス/デーモンを、コンテナ起動時に自動起動するために systemd を利用
>>しようと思い、systemctl を使ってみた、ということだろうかと想像しています。
>> https://armadillo.atmark-techno.com/forum/armadillo/18059
>>m.yoshidaさん、この想像で違っていたら、ごめんなさい。
>
>
>ご認識の通りです。systemdでサービスの自動起動できないか検討していました。

了解しました。

>上記のURLで紹介していただきましたが、他にも動作させたいサービスもあるので、systemdを使用したいとおてます。

これについても、了解です。

>>1.) コンテ内で、/sbin/init から /lib/systemd/systemd へのシンボリックリンクを作る

# ln -s /lib/systemd/systemd /sbin/init

>>
>>2.) (1) で変更したコンテナ内容を podman commit で保存する。
>>
>>3.) (3) で保存したコンテナイメージからコンテナを生成する際に、podman run の
>>引数を次のようにする:
>> 3-1.) --systemd=true の指定を追加
>> 3-2.) 実行コマンドとして /sbin/init を指定
>> 3-3.) -it を指定しない(-d での起動にする)
>>
>>これにより、(3) で生成したコンテナ内では、PID: 1 のプロセスとして
>>init(: 実体は systemd)が起動しますので、systemctl を実行できるようになります。

>→(3)コンテナコミットしてイメージ化後コンテナ作成時下記のエラーがでました。
>コンテナは作成してるみたいです。修正点ありますでしょうか?
>

podman run  --name=コンテナ名 --systemd=true  -d  イメージ名  /sbin/init
Error: crun: open executable: Operation not permitted: OCI permission denied

こちらで試していた環境では問題ありませんが、もしかすると、systemd パッケージをインストールした際。パーミッションを追加する必要があったかも知れません。
そちらの状況を再現できるか試そうと思い、コンテナ内の /sbin/init のシンボリックリンク先である /lib/systemd/systemd の実行パーミッションを 'chmod -x' で削ってコンテナイメージを保存して、保存したコンテナイメージから podman run でコンテナを生成・起動しようとしたところ、同じエラーになりました。

状況確認のため、以下のことを行ってみてください:

(1) 上記エラーが出た後、作成されたコンテナは、"Created" 状態になっていると思います(podman ps -a で見てみてください)。そのコンテナは不要なので、podman rm で削除してください。

(2) 以下のコマンドを実行して、/bin/bash を対話実行するコンテナを新たに生成してください:

# podman run --name=コンテナ名 --systemd=true -it イメージ名 /bin/bash

(3) コンテナの /bin/bash が起動したら、次のコマンドを実行し、/sbin/init と、シンボリックリンク先を見てみてください:

ls -l /sbin/init
 
ls -l /lib/systemd/systemd

/lib/systemd/sytemd の実行パーミッションが欠けている場合は、chmod +x で追加した後、変更したコンテナ内容をイメージに保存し直して、
再度以下のコマンドを実行してみてくださいませ:

podman run  --name=コンテナ名 --systemd=true  -d  イメージ名  /sbin/init

解決遅れて申し訳ありません。
> (1) 上記エラーが出た後、作成されたコンテナは、"Created" 状態になっていると思います(podman ps -a で見てみてください)。そのコンテナは不要なので、podman rm で削除してください。
>
> (2) 以下のコマンドを実行して、/bin/bash を対話実行するコンテナを新たに生成してください:
>

> # podman run --name=コンテナ名 --systemd=true -it イメージ名 /bin/bash
> 

>
> (3) コンテナの /bin/bash が起動したら、次のコマンドを実行し、/sbin/init と、シンボリックリンク先を見てみてください:
>

> ls -l /sbin/init
> 
> ls -l /lib/systemd/systemd
> 

>

上記対応して

$ls -l /sbin/init
lrwxrwxrwx 1 root root /sbin/init -> /lib/systemd/system
$ ls -l /lib/systemd/system
total 884

上記コマンドの結果total 884と表示して実行権限をどれに付与していいか不明でしたので、改めて新規でイメージ作成して
(3)で作成することができました。
自動起動させる場合は、 /etc/atmark/containers/のconfigファイルの設定はどのようにすればよろしでしょうか?

set_image イメージ名
set_commnd /sbin/init

上記でよろしいでしょうか?
よろしくお願いいたします。

アットマークテクノの古賀です。

m.yoshidaさん:
>解決遅れて申し訳ありません。
>>(1) 上記エラーが出た後、作成されたコンテナは、"Created" 状態になっていると思います(
>>podman ps -a で見てみてください)。そのコンテナは不要なので、podman rm で削除してください。
>>
>>(2) 以下のコマンドを実行して、/bin/bash を対話実行するコンテナを新たに生成してください:

# podman run --name=コンテナ名 --systemd=true -it イメージ名 /bin/bash

>>
>>(3) コンテナの /bin/bash が起動したら、次のコマンドを実行し、/sbin/init と、シンボリックリンク先を見てみてください:

ls -l /sbin/init
 
ls -l /lib/systemd/systemd

>
>上記対応して

$ls -l /sbin/init
lrwxrwxrwx 1 root root /sbin/init ->/lib/systemd/system
$ ls -l /lib/systemd/system
total 884

>上記コマンドの結果total 884と表示して実行権限をどれに付与していいか不明でしたので、

ということですが、

$ls -l /sbin/init
lrwxrwxrwx 1 root root /sbin/init ->/lib/systemd/system

となっていて、/sbin/init のシンボリックリンク先が、/lib/systemd/systemd ではなく、/lib/systemd/system ディレクトリになっていたようですね。

>改めて新規でイメージ作成して
>(3)で作成することができました。

イメージを作成し直してやり直された際には、パスが正しかったのだろうと思います。

>自動起動させる場合は、 /etc/atmark/containers/のconfigファイルの設定はどのようにすればよろしでしょうか?
>

set_image イメージ名
set_commnd /sbin/init

>
>上記でよろしいでしょうか?

はい。これでよいです。
シンボリックリンクの /sbin/init を作成せず、set_command で /lib/systemd/systemd を直接指定しても大丈夫だと思います。

アットマークテクノの古賀です。
>シンボリックリンクの /sbin/init を作成せず、set_command で /lib/systemd/systemd を直接指定しても大丈夫だと思います。
回答ありがとうございます。
助かります。
以上よろしくお願いいたします。