summaryrefslogtreecommitdiffstats
path: root/recipes-containers/vcontainer/files
diff options
context:
space:
mode:
authorBruce Ashfield <bruce.ashfield@gmail.com>2026-01-06 20:42:46 +0000
committerBruce Ashfield <bruce.ashfield@gmail.com>2026-02-09 03:32:52 +0000
commit18074e0efe255a43ab9155171d08aa6e0d736b5f (patch)
tree25411491f3a6c3ed7b3460a0bd9f3d4d1c561bc6 /recipes-containers/vcontainer/files
parentc32db56912b06a89490fda5d554468dbc12a39a2 (diff)
downloadmeta-virtualization-18074e0efe255a43ab9155171d08aa6e0d736b5f.tar.gz
vcontainer: add vdkr Docker support
Add vdkr - Docker CLI wrapper for cross-architecture container operations: Scripts: - vdkr.sh: Docker CLI entry point (vdkr-x86_64, vdkr-aarch64) - vdkr-init.sh: Docker init script for QEMU guest Recipes: - vdkr-native: Installs vdkr CLI wrappers - vdkr-rootfs-image: Builds Docker rootfs with containerd, runc, skopeo - vdkr-initramfs-create: Creates bootable initramfs blob The vdkr CLI provides Docker-compatible commands executed inside a QEMU-emulated environment, enabling cross-architecture container operations during Yocto builds. Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'recipes-containers/vcontainer/files')
-rw-r--r--recipes-containers/vcontainer/files/blobs/vdkr/aarch64/README26
-rw-r--r--recipes-containers/vcontainer/files/blobs/vdkr/x86_64/README26
-rwxr-xr-xrecipes-containers/vcontainer/files/vdkr-init.sh238
-rwxr-xr-xrecipes-containers/vcontainer/files/vdkr.sh25
4 files changed, 315 insertions, 0 deletions
diff --git a/recipes-containers/vcontainer/files/blobs/vdkr/aarch64/README b/recipes-containers/vcontainer/files/blobs/vdkr/aarch64/README
new file mode 100644
index 00000000..cabb5100
--- /dev/null
+++ b/recipes-containers/vcontainer/files/blobs/vdkr/aarch64/README
@@ -0,0 +1,26 @@
1vdkr aarch64 Blobs
2====================
3
4This directory should contain the boot blobs for vdkr aarch64:
5
6Required files:
7 - Image : Linux kernel for aarch64
8 - initramfs.cpio.gz : Tiny initramfs for switch_root
9 - rootfs.img : Ext4 root filesystem with Docker tools
10
11Build instructions:
12 1. Set MACHINE for aarch64:
13 MACHINE=qemuarm64
14
15 2. Build the blobs:
16 bitbake vdkr-initramfs-create
17
18 3. Copy from deploy directory:
19 cp tmp/deploy/images/qemuarm64/vdkr/aarch64/Image .
20 cp tmp/deploy/images/qemuarm64/vdkr/aarch64/initramfs.cpio.gz .
21 cp tmp/deploy/images/qemuarm64/vdkr/aarch64/rootfs.img .
22
23Once these files are present, vdkr-native will automatically include them.
24
25Alternatively, set VDKR_USE_DEPLOY = "1" in local.conf to use blobs
26directly from DEPLOY_DIR without copying to the layer.
diff --git a/recipes-containers/vcontainer/files/blobs/vdkr/x86_64/README b/recipes-containers/vcontainer/files/blobs/vdkr/x86_64/README
new file mode 100644
index 00000000..6902f729
--- /dev/null
+++ b/recipes-containers/vcontainer/files/blobs/vdkr/x86_64/README
@@ -0,0 +1,26 @@
1vdkr x86_64 Blobs
2===================
3
4This directory should contain the boot blobs for vdkr x86_64:
5
6Required files:
7 - bzImage : Linux kernel for x86_64
8 - initramfs.cpio.gz : Tiny initramfs for switch_root
9 - rootfs.img : Ext4 root filesystem with Docker tools
10
11Build instructions:
12 1. Set MACHINE for x86_64:
13 MACHINE=qemux86-64
14
15 2. Build the blobs:
16 bitbake vdkr-initramfs-create
17
18 3. Copy from deploy directory:
19 cp tmp/deploy/images/qemux86-64/vdkr/x86_64/bzImage .
20 cp tmp/deploy/images/qemux86-64/vdkr/x86_64/initramfs.cpio.gz .
21 cp tmp/deploy/images/qemux86-64/vdkr/x86_64/rootfs.img .
22
23Once these files are present, vdkr-native will automatically include them.
24
25Alternatively, set VDKR_USE_DEPLOY = "1" in local.conf to use blobs
26directly from DEPLOY_DIR without copying to the layer.
diff --git a/recipes-containers/vcontainer/files/vdkr-init.sh b/recipes-containers/vcontainer/files/vdkr-init.sh
new file mode 100755
index 00000000..7cfe12af
--- /dev/null
+++ b/recipes-containers/vcontainer/files/vdkr-init.sh
@@ -0,0 +1,238 @@
1#!/bin/sh
2# SPDX-FileCopyrightText: Copyright (C) 2025 Bruce Ashfield
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6# vdkr-init.sh
7# Init script for vdkr: execute arbitrary docker commands in QEMU
8#
9# This script runs on a real ext4 filesystem after switch_root from initramfs.
10# The preinit script mounted /dev/vda (rootfs.img) and did switch_root to us.
11#
12# Drive layout (rootfs.img is always /dev/vda, mounted as /):
13# /dev/vda = rootfs.img (this script runs from here, mounted as /)
14# /dev/vdb = input disk (optional, OCI/tar/dir data)
15# /dev/vdc = state disk (optional, persistent Docker storage)
16#
17# Kernel parameters:
18# docker_cmd=<base64> Base64-encoded docker command + args
19# docker_input=<type> Input type: none, oci, tar, dir (default: none)
20# docker_output=<type> Output type: text, tar, storage (default: text)
21# docker_state=<type> State type: none, disk (default: none)
22# docker_network=1 Enable networking (configure eth0, DNS)
23#
24# Version: 2.3.0
25
26# Set runtime-specific parameters before sourcing common code
27VCONTAINER_RUNTIME_NAME="vdkr"
28VCONTAINER_RUNTIME_CMD="docker"
29VCONTAINER_RUNTIME_PREFIX="docker"
30VCONTAINER_STATE_DIR="/var/lib/docker"
31VCONTAINER_SHARE_NAME="vdkr_share"
32VCONTAINER_VERSION="2.3.0"
33
34# Source common init functions
35# When installed as /init, common file is at /vcontainer-init-common.sh
36. /vcontainer-init-common.sh
37
38# ============================================================================
39# Docker-Specific Functions
40# ============================================================================
41
42setup_docker_storage() {
43 mkdir -p /run/containerd /run/lock
44 mkdir -p /var/lib/docker
45 mkdir -p /var/lib/containerd
46
47 # Handle Docker storage
48 if [ -n "$STATE_DISK" ] && [ -b "$STATE_DISK" ]; then
49 log "Mounting state disk $STATE_DISK as /var/lib/docker..."
50 if mount -t ext4 "$STATE_DISK" /var/lib/docker 2>&1; then
51 log "SUCCESS: Mounted $STATE_DISK as Docker storage"
52 log "Docker storage contents:"
53 [ "$QUIET_BOOT" = "0" ] && ls -la /var/lib/docker/ 2>/dev/null || log "(empty)"
54 else
55 log "WARNING: Failed to mount state disk, using tmpfs"
56 RUNTIME_STATE="none"
57 fi
58 fi
59
60 # If no state disk, use tmpfs for Docker storage
61 if [ "$RUNTIME_STATE" != "disk" ]; then
62 log "Using tmpfs for Docker storage (ephemeral)..."
63 mount -t tmpfs -o size=1G tmpfs /var/lib/docker
64 fi
65}
66
67start_containerd() {
68 CONTAINERD_READY=false
69 if [ -x "/usr/bin/containerd" ]; then
70 log "Starting containerd..."
71 mkdir -p /var/lib/containerd
72 mkdir -p /run/containerd
73 /usr/bin/containerd --log-level info --root /var/lib/containerd --state /run/containerd >/tmp/containerd.log 2>&1 &
74 CONTAINERD_PID=$!
75 # Wait for containerd socket
76 for i in 1 2 3 4 5 6 7 8 9 10; do
77 if [ -S /run/containerd/containerd.sock ]; then
78 log "Containerd running (PID: $CONTAINERD_PID)"
79 CONTAINERD_READY=true
80 break
81 fi
82 sleep 1
83 done
84 if [ "$CONTAINERD_READY" != "true" ]; then
85 log "WARNING: Containerd failed to start, check /tmp/containerd.log"
86 [ -f /tmp/containerd.log ] && cat /tmp/containerd.log >&2
87 fi
88 fi
89}
90
91start_dockerd() {
92 log "Starting Docker daemon..."
93 DOCKER_OPTS="--data-root=/var/lib/docker"
94 DOCKER_OPTS="$DOCKER_OPTS --storage-driver=overlay2"
95 DOCKER_OPTS="$DOCKER_OPTS --iptables=false"
96 DOCKER_OPTS="$DOCKER_OPTS --userland-proxy=false"
97 DOCKER_OPTS="$DOCKER_OPTS --bridge=none"
98 DOCKER_OPTS="$DOCKER_OPTS --host=unix:///var/run/docker.sock"
99 DOCKER_OPTS="$DOCKER_OPTS --exec-opt native.cgroupdriver=cgroupfs"
100 DOCKER_OPTS="$DOCKER_OPTS --log-level=info"
101
102 if [ "$CONTAINERD_READY" = "true" ]; then
103 DOCKER_OPTS="$DOCKER_OPTS --containerd=/run/containerd/containerd.sock"
104 fi
105
106 /usr/bin/dockerd $DOCKER_OPTS >/dev/null 2>&1 &
107 DOCKER_PID=$!
108 log "Docker daemon started (PID: $DOCKER_PID)"
109
110 # Wait for Docker to be ready
111 log "Waiting for Docker daemon..."
112 DOCKER_READY=false
113
114 sleep 5
115
116 for i in $(seq 1 60); do
117 if ! kill -0 $DOCKER_PID 2>/dev/null; then
118 echo "===ERROR==="
119 echo "Docker daemon died after $i iterations"
120 cat /var/log/docker.log 2>/dev/null || true
121 dmesg | tail -20 2>/dev/null || true
122 sleep 2
123 reboot -f
124 fi
125
126 if /usr/bin/docker info >/dev/null 2>&1; then
127 log "Docker daemon is ready!"
128 DOCKER_READY=true
129 break
130 fi
131
132 log "Waiting... ($i/60)"
133 sleep 2
134 done
135
136 if [ "$DOCKER_READY" != "true" ]; then
137 echo "===ERROR==="
138 echo "Docker failed to start"
139 sleep 2
140 reboot -f
141 fi
142}
143
144stop_runtime_daemons() {
145 # Stop Docker daemon
146 if [ -n "$DOCKER_PID" ]; then
147 log "Stopping Docker daemon..."
148 kill $DOCKER_PID 2>/dev/null || true
149 for i in $(seq 1 10); do
150 if ! kill -0 $DOCKER_PID 2>/dev/null; then
151 log "Docker daemon stopped"
152 break
153 fi
154 sleep 1
155 done
156 fi
157
158 # Stop containerd
159 if [ -n "$CONTAINERD_PID" ]; then
160 log "Stopping containerd..."
161 kill $CONTAINERD_PID 2>/dev/null || true
162 sleep 2
163 fi
164}
165
166handle_storage_output() {
167 echo "Stopping Docker gracefully..."
168 /usr/bin/docker system prune -f >/dev/null 2>&1 || true
169 kill $DOCKER_PID 2>/dev/null || true
170 [ -n "$CONTAINERD_PID" ] && kill $CONTAINERD_PID 2>/dev/null || true
171 sleep 3
172
173 echo "Packaging Docker storage..."
174 cd /var/lib
175 tar -cf /tmp/storage.tar docker/
176
177 STORAGE_SIZE=$(stat -c%s /tmp/storage.tar 2>/dev/null || echo "0")
178 echo "Storage size: $STORAGE_SIZE bytes"
179
180 if [ "$STORAGE_SIZE" -gt 1000 ]; then
181 dmesg -n 1
182 echo "===STORAGE_START==="
183 base64 /tmp/storage.tar
184 echo "===STORAGE_END==="
185 echo "===EXIT_CODE=$EXEC_EXIT_CODE==="
186 else
187 echo "===ERROR==="
188 echo "Storage too small"
189 fi
190}
191
192# ============================================================================
193# Main
194# ============================================================================
195
196# Initialize base environment
197setup_base_environment
198mount_base_filesystems
199
200# Check for quiet boot mode
201check_quiet_boot
202
203log "=== vdkr Init ==="
204log "Version: $VCONTAINER_VERSION"
205
206# Mount tmpfs directories and cgroups
207mount_tmpfs_dirs
208setup_cgroups
209
210# Parse kernel command line
211parse_cmdline
212
213# Detect and configure disks
214detect_disks
215
216# Set up Docker storage (Docker-specific)
217setup_docker_storage
218
219# Mount input disk
220mount_input_disk
221
222# Configure networking
223configure_networking
224
225# Start containerd and dockerd (Docker-specific)
226start_containerd
227start_dockerd
228
229# Handle daemon mode or single command execution
230if [ "$RUNTIME_DAEMON" = "1" ]; then
231 run_daemon_mode
232else
233 prepare_input_path
234 execute_command
235fi
236
237# Graceful shutdown
238graceful_shutdown
diff --git a/recipes-containers/vcontainer/files/vdkr.sh b/recipes-containers/vcontainer/files/vdkr.sh
new file mode 100755
index 00000000..818c831e
--- /dev/null
+++ b/recipes-containers/vcontainer/files/vdkr.sh
@@ -0,0 +1,25 @@
1#!/bin/bash
2# SPDX-FileCopyrightText: Copyright (C) 2025 Bruce Ashfield
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6# vdkr: Docker-like interface for cross-architecture container operations
7#
8# This provides a familiar docker-like CLI that executes commands inside
9# a QEMU-emulated environment with the target architecture's Docker.
10#
11# Command naming convention:
12# - Commands matching Docker's syntax/semantics use Docker's name (import, load, save, etc.)
13# - Extended commands with non-Docker behavior use 'v' prefix (vimport)
14
15# Set runtime-specific parameters before sourcing common code
16VCONTAINER_RUNTIME_NAME="vdkr"
17VCONTAINER_RUNTIME_CMD="docker"
18VCONTAINER_RUNTIME_PREFIX="VDKR"
19VCONTAINER_IMPORT_TARGET="docker-daemon:"
20VCONTAINER_STATE_FILE="docker-state.img"
21VCONTAINER_OTHER_PREFIX="VPDMN"
22VCONTAINER_VERSION="3.4.0"
23
24# Source common implementation
25source "$(dirname "${BASH_SOURCE[0]}")/vcontainer-common.sh" "$@"