summaryrefslogtreecommitdiffstats
path: root/recipes-containers/container-registry/docker-registry-config.bb
diff options
context:
space:
mode:
authorBruce Ashfield <bruce.ashfield@gmail.com>2026-02-09 03:17:24 +0000
committerBruce Ashfield <bruce.ashfield@gmail.com>2026-02-09 03:34:12 +0000
commit52fc4ca7c75594fe8b3c92a9f88df19f8f4d0944 (patch)
treef003083cf14ecb0543303ab0023d39fd3457eb78 /recipes-containers/container-registry/docker-registry-config.bb
parent092aa81983335b2346a725eebd2a75fc785bb42b (diff)
downloadmeta-virtualization-52fc4ca7c75594fe8b3c92a9f88df19f8f4d0944.tar.gz
container-registry: add target image TLS integration
Install CA certificates and registry configuration into target images so they can pull from the secure registry at runtime. docker-registry-config.bb: When CONTAINER_REGISTRY_SECURE=1, install the CA cert to /etc/docker/certs.d/{host}/ca.crt instead of adding insecure-registries to daemon.json. Translates localhost/127.0.0.1 to 10.0.2.2 for QEMU targets where the host registry is accessed via slirp networking. container-oci-registry-config.bb: Same secure mode support for podman/CRI-O with insecure=false in registries.conf. container-registry-ca.bb: New recipe that installs the CA certificate to Docker, podman/CRI-O, and system trust store paths on the target. container-cross-install.bbclass: Auto-add docker-registry-config or container-oci-registry-config to IMAGE_INSTALL when CONTAINER_REGISTRY_SECURE=1, based on the configured container engine. Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'recipes-containers/container-registry/docker-registry-config.bb')
-rw-r--r--recipes-containers/container-registry/docker-registry-config.bb120
1 files changed, 94 insertions, 26 deletions
diff --git a/recipes-containers/container-registry/docker-registry-config.bb b/recipes-containers/container-registry/docker-registry-config.bb
index e03cd3eb..0e8d66ad 100644
--- a/recipes-containers/container-registry/docker-registry-config.bb
+++ b/recipes-containers/container-registry/docker-registry-config.bb
@@ -10,46 +10,55 @@
10# FOR DOCKER ONLY - creates /etc/docker/daemon.json 10# FOR DOCKER ONLY - creates /etc/docker/daemon.json
11# 11#
12# NOT for Podman/Skopeo/Buildah - they use /etc/containers/registries.conf.d/ 12# NOT for Podman/Skopeo/Buildah - they use /etc/containers/registries.conf.d/
13# See: container-registry-config.bb for Podman/Skopeo/Buildah 13# See: container-oci-registry-config.bb for Podman/Skopeo/Buildah
14# 14#
15# This recipe creates daemon.json for Docker to access insecure registries. 15# This recipe creates daemon.json for Docker to access registries.
16# It is completely OPT-IN and requires explicit configuration. 16# It supports both insecure (HTTP) and secure (HTTPS with TLS) modes.
17# 17#
18# NOTE: Docker does not support "default registry" like our vdkr transform. 18# NOTE: Docker does not support "default registry" like our vdkr transform.
19# Users must still use fully qualified image names unless using Docker Hub. 19# Users must still use fully qualified image names unless using Docker Hub.
20# This config only handles insecure registry trust.
21# 20#
22# IMPORTANT: This recipe: 21# IMPORTANT: This recipe:
23# - Skips entirely if DOCKER_REGISTRY_INSECURE is not set 22# - Skips entirely if neither insecure nor secure registry is configured
24# - Creates /etc/docker/daemon.json (will be merged if docker recipe 23# - Creates /etc/docker/daemon.json
25# also creates one, or may need RCONFLICTS handling) 24# - In secure mode: installs CA cert to /etc/docker/certs.d/{registry}/
25# - In insecure mode: adds registry to insecure-registries list
26# 26#
27# Usage: 27# Usage:
28# # In local.conf or image recipe: 28# # Insecure mode (HTTP):
29# DOCKER_REGISTRY_INSECURE = "10.0.2.2:5000 myregistry.local:5000" 29# DOCKER_REGISTRY_INSECURE = "10.0.2.2:5000 myregistry.local:5000"
30# IMAGE_FEATURES += "container-registry" 30# IMAGE_FEATURES += "container-registry"
31# 31#
32# # Secure mode (HTTPS with TLS):
33# CONTAINER_REGISTRY_SECURE = "1"
34# CONTAINER_REGISTRY_URL = "localhost:5000"
35# IMAGE_FEATURES += "container-registry"
36#
32# The IMAGE_FEATURES mechanism auto-selects this recipe for Docker 37# The IMAGE_FEATURES mechanism auto-selects this recipe for Docker
33# or container-oci-registry-config for Podman/CRI-O based on 38# or container-oci-registry-config for Podman/CRI-O based on
34# VIRTUAL-RUNTIME_container_engine. 39# VIRTUAL-RUNTIME_container_engine.
35# 40#
36# =========================================================================== 41# ===========================================================================
37 42
38SUMMARY = "Configure insecure container registries for Docker daemon (opt-in)" 43SUMMARY = "Configure container registry for Docker daemon (opt-in)"
39DESCRIPTION = "Creates /etc/docker/daemon.json with insecure-registries config. \ 44DESCRIPTION = "Creates /etc/docker/daemon.json with registry config. \
40FOR DOCKER ONLY - not for Podman/Skopeo (use container-oci-registry-config for those). \ 45FOR DOCKER ONLY - not for Podman/Skopeo (use container-oci-registry-config for those). \
41This recipe is opt-in: requires DOCKER_REGISTRY_INSECURE to be set. \ 46Supports both insecure (HTTP) and secure (HTTPS with TLS) modes. \
42Use IMAGE_FEATURES container-registry to auto-select based on container engine." 47Use IMAGE_FEATURES container-registry to auto-select based on container engine."
43 48
44LICENSE = "MIT" 49LICENSE = "MIT"
45LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" 50LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
46 51
52inherit allarch container-registry
53
47# Space-separated list of insecure registries 54# Space-separated list of insecure registries
48# Example: "10.0.2.2:5000 myregistry.local:5000" 55# Example: "10.0.2.2:5000 myregistry.local:5000"
49# Can also use runtime-agnostic CONTAINER_REGISTRY_URL + CONTAINER_REGISTRY_INSECURE 56# Can also use runtime-agnostic CONTAINER_REGISTRY_URL + CONTAINER_REGISTRY_INSECURE
50DOCKER_REGISTRY_INSECURE ?= "" 57DOCKER_REGISTRY_INSECURE ?= ""
51CONTAINER_REGISTRY_URL ?= "" 58
52CONTAINER_REGISTRY_INSECURE ?= "" 59# Path to Docker auth config (for baked credentials)
60# NOT stored in bitbake - should point to external file
61CONTAINER_REGISTRY_AUTHFILE ?= ""
53 62
54def get_insecure_registries(d): 63def get_insecure_registries(d):
55 """Get insecure registries from either Docker-specific or generic config""" 64 """Get insecure registries from either Docker-specific or generic config"""
@@ -64,40 +73,99 @@ def get_insecure_registries(d):
64 return registry_url.strip() 73 return registry_url.strip()
65 return "" 74 return ""
66 75
67inherit allarch 76def is_secure_mode(d):
77 """Check if secure registry mode is enabled"""
78 return d.getVar('CONTAINER_REGISTRY_SECURE') == '1'
68 79
69# Skip recipe entirely if not configured 80# Skip recipe entirely if not configured
70python() { 81python() {
82 secure = is_secure_mode(d)
71 registries = get_insecure_registries(d) 83 registries = get_insecure_registries(d)
72 if not registries: 84
73 raise bb.parse.SkipRecipe("No insecure registry configured - recipe is opt-in only") 85 # Check for conflicting settings
86 if secure and registries:
87 bb.fatal("CONTAINER_REGISTRY_SECURE='1' conflicts with insecure registry settings. "
88 "Use secure mode (TLS+auth) OR insecure mode (HTTP), not both.")
89
90 if not secure and not registries:
91 raise bb.parse.SkipRecipe("No registry configured - recipe is opt-in only")
92
93 # In secure mode, depend on PKI generation
94 if secure:
95 d.appendVarFlag('do_install', 'depends', ' container-registry-index:do_generate_registry_script')
74} 96}
75 97
76python do_install() { 98python do_install() {
77 import os 99 import os
78 import json 100 import json
79 101 import shutil
80 registries = get_insecure_registries(d).split()
81 102
82 dest = d.getVar('D') 103 dest = d.getVar('D')
83 confdir = os.path.join(dest, d.getVar('sysconfdir').lstrip('/'), 'docker') 104 confdir = os.path.join(dest, d.getVar('sysconfdir').lstrip('/'), 'docker')
84 os.makedirs(confdir, exist_ok=True) 105 os.makedirs(confdir, exist_ok=True)
85 106
86 config_path = os.path.join(confdir, 'daemon.json') 107 secure = is_secure_mode(d)
108 registries = get_insecure_registries(d).split()
109 ca_cert = d.getVar('CONTAINER_REGISTRY_CA_CERT')
110 registry_url = d.getVar('CONTAINER_REGISTRY_URL') or ''
111 authfile = d.getVar('CONTAINER_REGISTRY_AUTHFILE') or ''
112
113 config = {}
114
115 if secure:
116 # Secure mode: install CA cert, no insecure-registries
117 # Translate localhost/127.0.0.1 to 10.0.2.2 for QEMU slirp networking
118 qemu_url = registry_url.replace('localhost', '10.0.2.2').replace('127.0.0.1', '10.0.2.2')
119 registry_host = qemu_url.split('/')[0] if '/' in qemu_url else qemu_url
120
121 if os.path.exists(ca_cert):
122 # Install CA cert to /etc/docker/certs.d/{registry}/ca.crt
123 cert_dir = os.path.join(dest, 'etc/docker/certs.d', registry_host)
124 os.makedirs(cert_dir, exist_ok=True)
125 shutil.copy(ca_cert, os.path.join(cert_dir, 'ca.crt'))
126 bb.note(f"Installed CA certificate for registry: {registry_host}")
127 else:
128 bb.warn(f"Secure mode enabled but CA certificate not found at {ca_cert}")
129 bb.warn("Run 'container-registry.sh start' to generate PKI, then rebuild this package")
130
131 # daemon.json can be empty or minimal in secure mode
132 # (no insecure-registries needed when using TLS)
133 bb.note("Secure mode: Docker will use TLS verification with installed CA cert")
134 else:
135 # Insecure mode: add to insecure-registries
136 if registries:
137 config["insecure-registries"] = registries
138 bb.note(f"Created Docker config with insecure registries: {registries}")
87 139
88 # Create daemon.json 140 # Install authfile if provided (for baked credentials)
89 config = { 141 if authfile and os.path.exists(authfile):
90 "insecure-registries": registries 142 docker_dir = os.path.join(dest, 'root/.docker')
91 } 143 os.makedirs(docker_dir, mode=0o700, exist_ok=True)
144 config_json = os.path.join(docker_dir, 'config.json')
145 shutil.copy(authfile, config_json)
146 os.chmod(config_json, 0o600)
147 bb.note(f"Installed Docker auth config from {authfile}")
92 148
149 # Write daemon.json (may be empty in secure mode)
150 config_path = os.path.join(confdir, 'daemon.json')
93 with open(config_path, 'w') as f: 151 with open(config_path, 'w') as f:
94 json.dump(config, f, indent=2) 152 json.dump(config, f, indent=2)
95 f.write("\n") 153 f.write("\n")
96
97 bb.note(f"Created Docker config with insecure registries: {registries}")
98} 154}
99 155
100FILES:${PN} = "${sysconfdir}/docker/daemon.json" 156FILES:${PN} = " \
157 ${sysconfdir}/docker/daemon.json \
158 ${sysconfdir}/docker/certs.d/*/ca.crt \
159 /root/.docker/config.json \
160"
161
162# Ensure proper permissions on auth file
163pkg_postinst:${PN}() {
164#!/bin/sh
165if [ -f $D/root/.docker/config.json ]; then
166 chmod 600 $D/root/.docker/config.json
167fi
168}
101 169
102# Docker must be installed for this to be useful 170# Docker must be installed for this to be useful
103RDEPENDS:${PN} = "docker" 171RDEPENDS:${PN} = "docker"