Azure の SLES15 SP1(PAYG) で Docker イメージをビルドすると、コンテナ内の zypper が「There are no enabled repositories defined」となり更新できないことがあります。原因は plugin:/susecloud と container-suseconnect-zypp の前提条件不足であるケースが多く、確認ポイントと回避策をまとめます。
今回の症状:ホストでは見えるのに、コンテナ内だけ zypper が空になる
Azure の SLES15 SP1(従量課金 / PAYG)では、ホスト OS 上の zypper がクラウド登録(SUSEConnect)と連携し、クラウド固有の “プラグイン経由リポジトリ” を使って更新できる構成になっていることがあります。ところが Dockerfile でホスト同様に plugin:/susecloud?... を使って repo を追加しても、コンテナ内で次のように「リポジトリ 0」と判断され、追加パッケージのインストールや update が止まるケースがあります。
zypper ref -s && zypper update -y
Refreshing service 'container-suseconnect-zypp'...
Warning: Skipping service 'container-suseconnect-zypp' ...
Warning: There are no enabled repositories defined.
ここで重要なのは、あなたが追加した repo が無いのではなく、zypper が “サービス(service)” を更新できず、その結果として repo が 0 扱いになっている点です。表示上は「No repositories defined」「There are no enabled repositories defined」と出ますが、根っこは container-suseconnect-zypp の呼び出し失敗にあります。
結論:plugin:/ はコンテナ内でも使えるが、前提条件が欠けると必ず失敗する
質問ポイントへの回答を先にまとめます。
| 質問 | 結論 | 補足 |
|---|---|---|
| plugin:/ で始まる URI はコンテナ内で使っても問題ない? | 前提条件が揃っていれば利用可能 | plugin:/ は “実体の https URL を生成する仕組み” なので、プラグインと登録情報が必要です。 |
| Azure の PAYG SLES15 であることが原因? | 原因になり得る | PAYG は自動登録に依存するため、登録が壊れる/クローンで不整合が出ると repo が消えたように見えます。 |
| RMT の SSL 証明書を別途準備する必要がある? | 通常は不要 | 公式の更新先を使う限り、追加の証明書準備は不要。 ただし社内 RMT を自前証明書で運用している場合は、コンテナ側に CA 取り込みが必要です。 |
plugin:/susecloud と container-suseconnect-zypp を正しく理解する
SLES の zypper は、通常は https:// で始まるリポジトリ URL を参照します。一方で Azure の PAYG などクラウド連携が入る環境では、実際の更新先を動的に解決するために plugin:/ スキームが登場します。
plugin:/ の正体
plugin:/...は zypper が認識する “特殊な URI スキーム” で、プラグインを呼び出してリポジトリ情報を生成します。- 見た目は URI ですが、実体は「このプラグインを動かして、適切な repo 定義(URL、認証情報、リージョン別のエンドポイント等)を取ってきてね」という指示です。
- したがって、プラグインが動かない=repo が生成できない=repo 0 扱いになりやすい構造です。
container-suseconnect-zypp が担っていること
container-suseconnect-zypp は、zypper の “サービス(service)プラグイン” として動き、SUSEConnect(クラウド登録)と連携して、SLES の公式リポジトリを参照できる状態を整えます。つまり、次のような役割をまとめて引き受けています。
- ホスト(PAYG)の登録状態を前提に、コンテナが更新できるための repo 情報を供給する
- モジュールや拡張(例:Server Applications、Containers など)の有効化状況に応じた repo を提示する
- クラウド環境固有の認証や接続先の違いを吸収する
この仕組みが “クラウド自動登録” と密結合しているため、PAYG で登録が崩れた瞬間に、コンテナ内の zypper も一緒に崩れたように見える、というのが今回の落とし穴です。
zypper の「サービス」と「リポジトリ」を分けて考えると理解が早い
zypper には大きく分けて service と repo の2種類の入口があります。今回のように container-suseconnect-zypp が絡むケースでは、repo そのものより “service が repo を生成できるか” が核心になります。
| 要素 | 格納場所の例 | zypper コマンド | 今回のポイント |
|---|---|---|---|
| サービス(service) | /etc/zypp/services.d/ | zypper ls | container-suseconnect-zypp がここ。ここが壊れると repo を生成できず “repo 0” になりやすい |
| リポジトリ(repo) | /etc/zypp/repos.d/ | zypper lr -u | service の refresh 成功後に repo が見える/増えることがある |
まずホストとコンテナの両方で、次の2つを必ず取っておくと、どこで差が出ているかが一気に見えます。
# サービス一覧
zypper ls
# repo 一覧(URL 付き)
zypper lr -u
コンテナ内で repo が 0 扱いになる主な原因と、最短で切り分ける方法
「Skipping service ‘container-suseconnect-zypp’」が出た時点で、zypper はサービス更新に失敗し、結果として “有効な repo が無い” と判定しています。ここからは、原因を再現性高く切り分けるための観点を整理します。
| よくある原因 | 典型的なサイン | 確認コマンド(例) | 対処の方向性 |
|---|---|---|---|
| ホストの登録状態が壊れている/期限切れ | ホストでも repo が少ない、更新が不安定、SUSEConnect がエラー | SUSEConnect --status-text zypper lr -u | クラウド登録の再実行、登録情報のクリーンアップ、必要な拡張の再アタッチ |
| コンテナから SUSEConnect 連携先に到達できない | host network でないと失敗、プロキシ環境で失敗、NSG/Firewall で外に出られない | docker build --network=host . # あるいはコンテナ内で curl -I https://updates.suse.com/ | ビルド時のネットワーク設定、プロキシ環境変数の引き継ぎ、到達性の担保 |
| container-suseconnect-zypp のプラグイン/サービス定義が不整合 | サービス更新で即スキップ、ログに Python/権限/依存関係エラー | ls -l /usr/lib/zypp/plugins/services/ ls -l /etc/zypp/services.d/ zypper -vvv ref -s | 必要パッケージの導入、ファイル権限の修復、ログから依存関係を解消 |
| コンテナに必要な情報が引き継がれていない | ホストは OK だがコンテナだけ失敗、ビルド環境を変えると直る | cat /etc/zypp/services.d/*.service env | grep -i proxy | ビルド時の環境変数、必要な設定の受け渡し(ただし機密情報の扱いに注意) |
| 時刻ずれ・証明書検証で失敗 | TLS エラー、証明書期限エラー、curl も失敗 | timedatectl curl -v https://updates.suse.com/ | NTP 同期、CA 証明書の更新、プロキシでの TLS 中間証明書対応 |
推奨トラブルシュート手順
闇雲に Dockerfile をいじるより、ホスト登録 → プラグインの健全性 → コンテナの到達性の順で潰すと、最短で原因にたどり着けます。
ホスト側:登録と repo の状態を先に確定させる
- 登録状態の確認:
SUSEConnect --status-textで “有効な登録” になっているかを見る - リポジトリの可視化:
zypper lr -uで、想定モジュール(例:Containers、Server Applications など)が有効か確認 - ホスト単体で更新が通るか:
zypper ref -sとzypper updateが安定して成功する状態を作る
ここが不安定だと、コンテナ側は高確率で崩れます。PAYG の場合、VM を複製(OS ディスクのコピーやイメージ化)したタイミングで登録連携が崩れることがあるため、“新規に Marketplace から作った素の VM” と挙動比較するのが効果的です。
ホスト側:container-suseconnect-zypp と関連コンポーネントを点検する
サービスがスキップされる時は、たいていログにヒントがあります。まずは zypper を冗長ログで動かし、次に systemd / ログを確認します。
# まずは zypper を冗長ログで
zypper -vvv ref -s
# サービスとプラグインの所在
zypper ls
ls -l /usr/lib/zypp/plugins/services/
ls -l /etc/zypp/services.d/
# systemd / 全体ログ(環境によりユニット名は異なる場合があります)
journalctl -b | grep -i suseconnect
journalctl -b | grep -i container
特に、プラグイン本体が無い、実行権限が無い、依存パッケージが足りない、といった基本的な不整合は早めに潰しておくと後が楽です。
ビルド側:コンテナが “ホストと同じ前提” で動けるかを確認する
PAYG のクラウド連携系プラグインは、ホスト側の連携サービスにアクセスする前提になっていることがあります。Docker build の RUN ステップがデフォルトの NAT ネットワークのままだと、ホストの 127.0.0.1 にアクセスできず失敗することがあるため、まずは --network=host を試す価値があります。
DOCKER_BUILDKIT=1 docker build --network=host -t my-sap-sles-image:latest .
すでに --network=host を付けているのに失敗する場合は、次を重点的に疑います。
- プロキシ環境で、ホストは通るがビルドコンテキストでは環境変数が渡っていない
- ホスト側の “連携サービス” が起動していない/別ポートで待ち受けている
- ホスト側で登録が壊れていて、連携サービスが正常に repo を生成できない
ログの取り方:成功したホストと、失敗するコンテナの差分を取る
「Warning: Skipping service …」の背後には、ほぼ必ず具体的な失敗理由があります。zypper の冗長ログと標準ログをセットで取ると、サポート問い合わせ時も通りが良くなります。
- zypper 冗長ログ:
zypper -vvv ref -s(サービス更新の直前直後が出ます) - zypper ログファイル:
/var/log/zypper.log - 履歴:
/var/log/zypp/history - systemd ログ:
journalctl -bと、関連ユニットのjournalctl -u ...
コンテナはビルド中にログが流れて消えやすいので、再現性が低いときは一度 “デバッグ用の一時コンテナ” を起動し、手で zypper を叩いてログを残すのが確実です。
# 例:ホストネットワークで一時コンテナを起動して確認(イメージ名は環境に合わせて)
docker run --rm -it --network=host your-base-image:15sp1 /bin/bash
# コンテナ内で
zypper -vvv ref -s
zypper lr -u
cat /etc/zypp/services.d/*.service
tail -n 200 /var/log/zypper.log
containerbuild-regionsrv を使う構成での注意点
質問文にある通り、ホストで containerbuild-regionsrv を起動している場合でも、コンテナ側がそのサービスにアクセスできなければ意味がありません。典型的には次のどれかでつまずきます。
- Docker build が host network で実行されていない(ビルド時の RUN からホストの 127.0.0.1 に届かない)
- サービスは起動しているが、待ち受けが想定と違う(ポート/バインド先)
- 登録状態が壊れていて、regionsrv が “repo 生成に必要な情報” を返せない
まずホストで “本当に待ち受けているか” を確認します(ポート番号は環境差があるため、プロセス名で探すと確実です)。
systemctl status containerbuild-regionsrv
ss -lntp | grep -i regionsrv
Dockerfile の書き方でハマりやすいポイント
同じ SLES15 SP1 でも、ベースイメージが “何の前提を持っているか”で結果が変わります。次のポイントを押さえると、再現性の高い Dockerfile になります。
RUN の直前に “現状確認” ステップを入れて、壊れ方を見える化する
ビルドが通らない時は、いきなり zypper update を実行するより、repo/サービスの一覧と状態を出してから更新すると原因が絞れます。
RUN zypper -n --gpg-auto-import-keys lr -u && \
zypper -n -vvv ref -s || (echo "zypper refresh failed" && exit 1)
プラグイン依存の repo 追加は “サービスが成功している前提” でしか成立しない
zypper ar 'plugin:/susecloud?...' が書けたとしても、それは “登録情報やプラグインが動く” ことを保証しません。refresh でサービスが生成する repo が本体なので、まず refresh が成功する状態が必要です。
機密情報を Dockerfile に焼き込まない
回避策として SCC の登録コード(レジストレーションコード)をコンテナに入れて更新する方法もありますが、Dockerfile に平文で埋め込むのは避けるべきです。CI/CD で実施するなら、BuildKit の secret マウントなどを使い、イメージに残さない形にします。
どうしても急ぐときの回避策
本番運用では “クラウド連携の正攻法” で直すのが理想ですが、SAP 向けカスタムイメージのビルドが止まっている場合、現実的には回避策が必要になることもあります。代表的な選択肢をまとめます。
| 回避策 | メリット | デメリット/注意点 | 向いているケース |
|---|---|---|---|
| BYOS(自前サブスク)でコンテナを登録して更新 | クラウド連携に依存せず repo を確実に使える | 登録情報の取り扱いが難しい(秘密情報の混入、ライセンス管理) | CI 上で一時的にビルドだけ通したい |
| RMT で社内ミラーを立て、コンテナは https repo を参照 | 外部到達性に依存せず安定、帯域や監査にも強い | RMT 運用コスト。自前証明書の場合はコンテナへ CA 取り込みが必要 | 閉域・プロキシ必須・大規模環境 |
| SUSE のコンテナ向けベースイメージ(BCI 等)を採用 | コンテナ前提の整備が進んでおり、依存関係の罠が減る | ベースイメージのポリシーに合わせた設計が必要 | 新規のコンテナ設計、長期運用を見据える |
RMT の SSL 証明書は本当に不要なのか
公式リポジトリ(SUSE の公開更新サーバ)へ出ていく構成であれば、基本的に追加の証明書準備は不要です。一方で、次のような構成では “証明書が原因で zypper が落ちる” ことが起こり得ます。
- 社内 RMT を立て、社内 CA(自己署名またはプライベート PKI)で TLS 終端している
- 透過型プロキシが TLS を中間者として終端し、独自の中間証明書を挿入している
この場合は、コンテナ内に CA 証明書を入れて信頼ストアを更新する必要があります。つまり「RMT の証明書が不要」というのは、“公式をそのまま参照している限り”の話であり、ネットワーク設計によって前提が変わります。
Azure Marketplace 版 SLES15 SP1 で「No repositories defined」となる場合
2つ目の症状(/etc/zypp/repos.d/ が空、zypper pchk で「No repositories defined」)は、コンテナではなくホストそのものが repo を持っていない状態です。この場合はほぼ例外なく、自動登録(または登録の引き継ぎ)が失敗していることが原因です。
まず確認すること:PAYG か BYOS かで “正しい登録手順” が変わる
| 項目 | PAYG(従量課金) | BYOS(自前サブスク) |
|---|---|---|
| 登録の基本 | Azure 側の課金・連携情報を使った自動登録が前提 | SUSE Customer Center の登録コードで手動登録 |
| repo が空になる典型 | 自動登録が走っていない/失敗している/複製で崩れた | 登録未実施/登録コード間違い/期限切れ |
| よく効く対処 | クラウド登録ツールの再実行、VM 作り直しで比較 | SUSEConnect で再登録、拡張の付け直し |
| コンテナビルドへの影響 | ホスト登録が崩れると container-suseconnect-zypp も巻き込まれやすい | コンテナ内登録方式を設計しやすいが、秘密情報管理が必須 |
登録状態の確認と、再登録の大枠
まずはホストで登録状態を確認します。
SUSEConnect --status-text
zypper lr -u
ls -l /etc/zypp/repos.d/
ここで未登録・期限切れ・repo 0 の場合は、環境に合わせて再登録が必要です。操作はイメージ種別や運用(PAYG/BYOS)で異なりますが、次の流れで進めると安全です。
- クラウド登録ツールや SUSEConnect のヘルプを確認し、“今の VM が想定する登録方式”を特定する
- 必要に応じて登録情報をクリーンアップ(例:登録の解除や再初期化)
- 再登録を実行し、
/etc/zypp/repos.d/に repo ファイルが生成されることを確認 zypper refreshが通るまで、ネットワーク(プロキシ/NSG/DNS)と時刻を点検
特に Azure でありがちなのが、VM 作成後に OS ディスクをコピーして別 VM を作ったケースです。この場合、登録の一意性が崩れ、自動登録がスキップされて repo が生成されないことがあります。最短の切り分けは、同じ Marketplace イメージから新規 VM を作って比較し、差分をログで追うことです。
現場で使えるチェックリスト
最後に、現場で “やること” が一目で分かるようにチェックリスト化します。コンテナ問題でも Marketplace repo 0 問題でも、ここを順に潰せば原因が浮かびます。
| チェック項目 | 見る場所 | OK の目安 | NG のときの次アクション |
|---|---|---|---|
| SUSEConnect の登録状態 | ホスト | status が有効、製品/拡張が想定通り | 再登録(PAYG はクラウド登録、BYOS は登録コード) |
| repo の生成 | ホスト | /etc/zypp/repos.d に repo が作られている | 自動登録ログ確認、VM 複製の有無確認 |
| container-suseconnect-zypp の健全性 | ホスト/コンテナ | サービス更新がスキップされない | プラグイン実体・権限・依存関係・ログを確認 |
| ネットワーク到達性(更新先/プロキシ) | ホスト/コンテナ | curl で外部へ到達、DNS が解決 | HTTP(S)_PROXY の引き継ぎ、NSG/Firewall/DNS を見直す |
| 時刻と証明書 | ホスト/コンテナ | 時刻が正しい、TLS エラーが出ない | NTP 同期、CA 更新、社内 CA を信頼ストアへ追加 |
よくある質問
ホストでは zypper が動くのに、なぜコンテナだけダメなの?
ホストはクラウド登録の状態と連携サービス(プラグイン)が揃っている一方、コンテナはビルドの実行環境・ネットワーク・引き継がれる設定が異なります。plugin:/ は “動的生成” なので、わずかな前提差で repo が 0 扱いになりやすいのが理由です。
plugin:/ を https:// に置き換えれば解決する?
置き換えで直るケースもありますが、PAYG の恩恵(自動的な認証・課金連携)を捨てることになります。自前で SCC 認証や RMT を用意する必要が出るため、短期回避としては有効でも、運用設計としては慎重に判断してください。
最終的にどこへ問い合わせるのが早い?
ホストの登録が怪しい/Marketplace で repo が空、といった “クラウド連携そのもの” の問題は、SUSE 側と Azure 側の境界にまたがります。ログ(SUSEConnect の状態、zypper の冗長ログ、systemd ログ、ネットワーク到達性の結果)を揃えた上で、SUSE サポートまたは Azure のサポートに投げると解決が早いことが多いです。
まとめ
- plugin:/susecloud はコンテナ内でも使えるが、動的生成のため前提条件が欠けると repo 0 扱いになりやすい
- 「Skipping service ‘container-suseconnect-zypp’」が出たら、まずホストの登録状態とプラグインの健全性を確定させる
- Marketplace 版で
/etc/zypp/repos.d/が空なら、ほぼ確実に自動登録の失敗。PAYG/BYOS を見極めて再登録する - 急ぎなら BYOS 登録や RMT、BCI の採用など回避策もあるが、ライセンスと秘密情報の取り扱いを含めて設計する

コメント