diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-10-29 02:23:17 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-10-29 02:23:17 +0800 |
| commit | 808c626c612b238f6923c3ec2d6a05c5611d87db (patch) | |
| tree | 049edc6114487c2cecc8034c778c50ec0758aaeb | |
| parent | 298dd9150ec8bc92af1bc1685726e1cd98d16b49 (diff) | |
| download | rutils-808c626c612b238f6923c3ec2d6a05c5611d87db.tar.gz rutils-808c626c612b238f6923c3ec2d6a05c5611d87db.tar.xz | |
Add container profiles for persistent network and bind mount configuration.
Signed-off-by: Richard Qin <richard.qin.x@gmail.com>
| -rw-r--r-- | debian-container/README | 15 | ||||
| -rwxr-xr-x | debian-container/debian-container.sh | 1 | ||||
| -rw-r--r-- | debian-container/lib/common.sh | 5 | ||||
| -rw-r--r-- | debian-container/lib/container.sh | 39 | ||||
| -rw-r--r-- | debian-container/lib/profiles.sh | 50 |
5 files changed, 108 insertions, 2 deletions
diff --git a/debian-container/README b/debian-container/README index b0e11fe..25734f0 100644 --- a/debian-container/README +++ b/debian-container/README @@ -19,6 +19,17 @@ sudo ./debian-container.sh init test-1 --tarball ./debian-stable.tar.gz sudo ./debian-container.sh init test-2 --tarball ./debian-stable.tar.gz sudo ./debian-container.sh init test-3 --size 8G --tarball ./debian-stable.tar.gz +使用 profile 创建容器: + +profile 文件内容: + +network=none +mount=/home/richard/project:/workspace:rw +mount=/home/richard/data:/data:ro + +sudo ./debian-container.sh init lab --profile ./lab.profile --tarball ./debian-stable.tar.gz +sudo ./debian-container.sh enter lab + 扩容容器: sudo ./debian-container.sh resize test-3 --size 12G @@ -53,6 +64,7 @@ sudo ./debian-container.sh init test-3 instances/test-1/rootfs.ext4 instances/test-1/root/ +instances/lab/config 默认基础 tarball: @@ -83,4 +95,7 @@ HOST:CONTAINER[:ro|rw] 目前只支持目录挂载,默认模式为 rw。 +实例 profile 保存在 instances/NAME/config,支持 network 和 mount 配置项。 +enter 或 exec 的命令行选项会覆盖 profile 中的网络模式,并追加挂载项。 + 脚本实现按职责拆分在 lib/ 目录中,入口脚本只负责加载模块和分发命令。 diff --git a/debian-container/debian-container.sh b/debian-container/debian-container.sh index d6bfbaf..44bd55a 100755 --- a/debian-container/debian-container.sh +++ b/debian-container/debian-container.sh @@ -14,6 +14,7 @@ source "$DC_DIR/lib/network.sh" source "$DC_DIR/lib/storage.sh" source "$DC_DIR/lib/mount.sh" source "$DC_DIR/lib/binds.sh" +source "$DC_DIR/lib/profiles.sh" source "$DC_DIR/lib/container.sh" DC_ACTION=${1:-} diff --git a/debian-container/lib/common.sh b/debian-container/lib/common.sh index 4102188..96ed00b 100644 --- a/debian-container/lib/common.sh +++ b/debian-container/lib/common.sh @@ -61,6 +61,7 @@ dc_usage() { init 选项: --tarball PATH 从本地 tarball 初始化,跳过软件包下载 --size SIZE 镜像大小(默认:3G) + --profile PATH 复制实例 profile resize 选项: --size SIZE 新的镜像大小,只能扩大 @@ -79,6 +80,10 @@ base-create 选项: 挂载选项: --mount SPEC 目录挂载:HOST:CONTAINER[:ro|rw] +profile 配置项: + network=MODE + mount=HOST:CONTAINER[:ro|rw] + 环境变量: DEBIAN_INSTANCES 实例目录(默认:当前目录/instances) DEBIAN_SIZE 新实例镜像大小(默认:3G) diff --git a/debian-container/lib/container.sh b/debian-container/lib/container.sh index 5f040e3..2ae920e 100644 --- a/debian-container/lib/container.sh +++ b/debian-container/lib/container.sh @@ -5,6 +5,7 @@ dc_init() { local tarball= local size=$DC_SIZE + local profile= while (($# > 0)); do case "$1" in @@ -18,6 +19,11 @@ dc_init() { size=$2 shift 2 ;; + --profile) + (($# >= 2)) || dc_die '--profile 需要一个文件路径。' + profile=$2 + shift 2 + ;; --help|-h) dc_usage return 0 @@ -34,6 +40,10 @@ dc_init() { tarball=$(readlink -f -- "$tarball") [[ -f "$tarball" ]] || dc_die "找不到 tarball:$tarball" fi + if [[ -n "$profile" ]]; then + profile=$(readlink -f -- "$profile") + [[ -f "$profile" ]] || dc_die "找不到 profile:$profile" + fi if [[ -e "$DC_INSTANCE_DIR" ]]; then dc_die "实例已存在:$DC_INSTANCE。请使用 enter 进入,避免覆盖容器数据。" @@ -45,6 +55,12 @@ dc_init() { else unshare --mount --propagation private -- bash "$DC_SCRIPT" _init "$DC_INSTANCE" fi + DC_PROFILE_FILE="$DC_INSTANCE_DIR/config" + if [[ -n "$profile" ]]; then + cp -- "$profile" "$DC_PROFILE_FILE" + else + dc_profile_write_default "$DC_NETWORK_MODE" + fi echo "初始化完成。执行 sudo bash $DC_SCRIPT enter $DC_INSTANCE 进入容器。" } @@ -182,6 +198,10 @@ dc_base_create() { dc_enter() { local network_mode=$DC_NETWORK_MODE local -a bind_args=() + local spec + + dc_profile_load + network_mode=$DC_PROFILE_NETWORK while (($# > 0)); do case "$1" in @@ -193,7 +213,6 @@ dc_enter() { --mount) (($# >= 2)) || dc_die '--mount 需要一个挂载参数。' dc_bind_add "$2" - bind_args+=(--mount "${DC_BIND_SPECS[$((${#DC_BIND_SPECS[@]} - 1))]}") shift 2 ;; --help|-h) @@ -208,6 +227,9 @@ dc_enter() { [[ -f "$DC_IMAGE" ]] || dc_die '没有找到镜像,请先运行 init。' dc_network_prepare "$network_mode" + for spec in "${DC_BIND_SPECS[@]}"; do + bind_args+=(--mount "$spec") + done unshare --mount --uts --ipc --pid --fork --propagation private \ "${DC_NETWORK_UNSHARE_ARGS[@]}" -- bash "$DC_SCRIPT" _enter "$DC_INSTANCE" "${bind_args[@]}" @@ -230,6 +252,10 @@ dc_enter_rootfs() { dc_exec() { local network_mode=$DC_NETWORK_MODE local -a bind_args=() + local spec + + dc_profile_load + network_mode=$DC_PROFILE_NETWORK while (($# > 0)); do case "$1" in @@ -241,7 +267,6 @@ dc_exec() { --mount) (($# >= 2)) || dc_die '--mount 需要一个挂载参数。' dc_bind_add "$2" - bind_args+=(--mount "${DC_BIND_SPECS[$((${#DC_BIND_SPECS[@]} - 1))]}") shift 2 ;; --) @@ -261,6 +286,9 @@ dc_exec() { (($# > 0)) || dc_die 'exec 需要一个命令。' [[ -f "$DC_IMAGE" ]] || dc_die '没有找到镜像,请先运行 init。' dc_network_prepare "$network_mode" + for spec in "${DC_BIND_SPECS[@]}"; do + bind_args+=(--mount "$spec") + done unshare --mount --uts --ipc --pid --fork --propagation private \ "${DC_NETWORK_UNSHARE_ARGS[@]}" -- \ @@ -300,8 +328,15 @@ dc_exec_rootfs() { } dc_status() { + local spec + + dc_profile_load echo "实例:$DC_INSTANCE" echo "目录:$DC_INSTANCE_DIR" + echo "网络:$DC_PROFILE_NETWORK" + for spec in "${DC_BIND_SPECS[@]}"; do + echo "挂载:$spec" + done if [[ -f "$DC_IMAGE" ]]; then echo '镜像:存在' fi diff --git a/debian-container/lib/profiles.sh b/debian-container/lib/profiles.sh new file mode 100644 index 0000000..77deee7 --- /dev/null +++ b/debian-container/lib/profiles.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (C) 2026 by Richard Qin + +DC_PROFILE_FILE= +DC_PROFILE_NETWORK= + +dc_profile_parse() { + local file=$1 + local line + local key + local value + + while IFS= read -r line || [[ -n "$line" ]]; do + [[ -z "$line" || "$line" == \#* ]] && continue + [[ "$line" == *=* ]] || dc_die "profile 配置格式无效:$line" + key=${line%%=*} + value=${line#*=} + case "$key" in + network) + DC_PROFILE_NETWORK=$value + ;; + mount) + dc_bind_add "$value" + ;; + *) + dc_die "profile 配置项无效:$key" + ;; + esac + done < "$file" +} + +dc_profile_load() { + DC_BIND_SPECS=() + DC_BIND_SOURCES=() + DC_BIND_TARGETS=() + DC_BIND_MODES=() + DC_PROFILE_FILE="$DC_INSTANCE_DIR/config" + DC_PROFILE_NETWORK=$DC_NETWORK_MODE + + if [[ -f "$DC_PROFILE_FILE" ]]; then + dc_profile_parse "$DC_PROFILE_FILE" + fi +} + +dc_profile_write_default() { + local network_mode=$1 + + printf 'network=%s\n' "$network_mode" > "$DC_PROFILE_FILE" +} |
