aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-10-28 23:44:45 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-10-28 23:44:45 +0800
commit4e6376cfc58e73fc14ddb691c0fac9da425efac9 (patch)
tree7b4e06cdfe2b4f4fbf6fb1a10ba94b5ab8402809
parente7236907dfe3e9130d532d5e8a7f2b17af13df1c (diff)
downloadrutils-4e6376cfc58e73fc14ddb691c0fac9da425efac9.tar.gz
rutils-4e6376cfc58e73fc14ddb691c0fac9da425efac9.tar.xz
Add Debian base tarball creation and configurable initialization options.
Signed-off-by: Richard Qin <richard.qin.x@gmail.com>
-rw-r--r--debian-container/.gitignore1
-rw-r--r--debian-container/README27
-rwxr-xr-xdebian-container/debian-container.sh8
-rw-r--r--debian-container/lib/common.sh14
-rw-r--r--debian-container/lib/config.sh4
-rw-r--r--debian-container/lib/container.sh77
6 files changed, 119 insertions, 12 deletions
diff --git a/debian-container/.gitignore b/debian-container/.gitignore
index 842988b..f8dc340 100644
--- a/debian-container/.gitignore
+++ b/debian-container/.gitignore
@@ -1,2 +1,3 @@
rootfs.ext4
debian-root/
+*.tar.gz
diff --git a/debian-container/README b/debian-container/README
index 94a72e8..0749f14 100644
--- a/debian-container/README
+++ b/debian-container/README
@@ -5,6 +5,16 @@ Debian 容器
用法:
+第一次创建基础软件包 tarball:
+
+sudo ./debian-container.sh base-create ./debian-stable.tar.gz
+
+从 tarball 创建容器:
+
+sudo ./debian-container.sh init --tarball ./debian-stable.tar.gz
+
+直接联网初始化容器:
+
sudo ./debian-container.sh init
sudo ./debian-container.sh enter
sudo ./debian-container.sh delete
@@ -14,11 +24,24 @@ sudo ./debian-container.sh delete
rootfs.ext4
debian-root/
+默认基础 tarball:
+
+debian-base.tar.gz
+
可以通过环境变量修改路径:
sudo env \
- RUTILS_DEBIAN_IMAGE=/path/to/rootfs.ext4 \
- RUTILS_DEBIAN_ROOT=/path/to/debian-root \
+ DEBIAN_IMAGE=/path/to/rootfs.ext4 \
+ DEBIAN_ROOT=/path/to/debian-root \
./debian-container.sh enter
+可配置的环境变量:
+
+DEBIAN_IMAGE 镜像路径
+DEBIAN_ROOT 挂载目录
+DEBIAN_TARBALL 默认基础 tarball 路径
+DEBIAN_SUITE Debian 版本,默认 stable
+DEBIAN_MIRROR Debian 镜像地址
+DEBIAN_INCLUDE 额外软件包,使用逗号分隔
+
脚本实现按职责拆分在 lib/ 目录中,入口脚本只负责加载模块和分发命令。
diff --git a/debian-container/debian-container.sh b/debian-container/debian-container.sh
index 4a52da0..893d83b 100755
--- a/debian-container/debian-container.sh
+++ b/debian-container/debian-container.sh
@@ -14,6 +14,7 @@ source "$DC_DIR/lib/mount.sh"
source "$DC_DIR/lib/container.sh"
DC_ACTION=${1:-}
+shift || true
case "$DC_ACTION" in
help|-h|--help)
@@ -25,15 +26,16 @@ esac
dc_require_root
case "$DC_ACTION" in
- init|enter|delete)
+ base-create|init|enter|delete)
# 防止多个会话同时读写同一 ext4 镜像。
dc_acquire_lock
;;
esac
case "$DC_ACTION" in
- init) dc_init ;;
- _init) dc_init_rootfs ;;
+ base-create) dc_base_create "$@" ;;
+ init) dc_init "$@" ;;
+ _init) dc_init_rootfs "$@" ;;
enter) dc_enter ;;
_enter) dc_enter_rootfs ;;
delete) dc_delete ;;
diff --git a/debian-container/lib/common.sh b/debian-container/lib/common.sh
index 1fd08b0..19bbd78 100644
--- a/debian-container/lib/common.sh
+++ b/debian-container/lib/common.sh
@@ -29,14 +29,22 @@ dc_usage() {
用法:sudo bash $DC_SCRIPT <命令>
命令:
- init 创建 Debian 容器镜像
- enter 进入容器
- delete 删除容器镜像
+ base-create [路径] 下载一次并创建 debootstrap 软件包 tarball
+ init [选项] 创建 Debian 容器镜像
+ enter 进入容器
+ delete 删除容器镜像
+
+init 选项:
+ --tarball PATH 从本地 tarball 初始化,跳过软件包下载
环境变量:
DEBIAN_IMAGE 镜像路径(默认:当前目录/rootfs.ext4)
DEBIAN_ROOT 挂载目录(默认:当前目录/debian-root)
DEBIAN_LOCK_FILE 锁文件路径
+ DEBIAN_TARBALL 基础 tarball(默认:当前目录/debian-base.tar.gz)
+ DEBIAN_SUITE Debian 版本(默认:stable)
+ DEBIAN_MIRROR Debian 镜像地址
+ DEBIAN_INCLUDE 额外软件包,使用逗号分隔
EOF
}
diff --git a/debian-container/lib/config.sh b/debian-container/lib/config.sh
index 66b1bfe..cee5473 100644
--- a/debian-container/lib/config.sh
+++ b/debian-container/lib/config.sh
@@ -8,4 +8,8 @@
DC_IMAGE=${DEBIAN_IMAGE:-"$PWD/rootfs.ext4"}
DC_ROOT=${DEBIAN_ROOT:-"$PWD/debian-root"}
DC_LOCK_FILE=${DEBIAN_LOCK_FILE:-/run/lock/debian-container.lock}
+DC_TARBALL=${DEBIAN_TARBALL:-"$PWD/debian-base.tar.gz"}
+DC_SUITE=${DEBIAN_SUITE:-stable}
+DC_MIRROR=${DEBIAN_MIRROR:-http://deb.debian.org/debian}
+DC_INCLUDE=${DEBIAN_INCLUDE:-passwd,util-linux,vim-tiny,e2fsprogs}
diff --git a/debian-container/lib/container.sh b/debian-container/lib/container.sh
index 759d798..05c3944 100644
--- a/debian-container/lib/container.sh
+++ b/debian-container/lib/container.sh
@@ -3,8 +3,31 @@
# Copyright (C) 2026 by Richard Qin
dc_init() {
+ local tarball=
+
+ while (($# > 0)); do
+ case "$1" in
+ --tarball)
+ (($# >= 2)) || dc_die '--tarball 需要一个文件路径。'
+ tarball=$2
+ shift 2
+ ;;
+ --help|-h)
+ dc_usage
+ return 0
+ ;;
+ *)
+ dc_die "未知的 init 选项:$1"
+ ;;
+ esac
+ done
+
dc_require_commands debootstrap unshare mkfs.ext4 mount chroot setpriv flock
+ if [[ -n "$tarball" && ! -f "$tarball" ]]; then
+ dc_die "找不到 tarball:$tarball"
+ fi
+
if [[ -e "$DC_IMAGE" ]]; then
dc_die "镜像已存在:$DC_IMAGE。请使用 enter 进入,避免覆盖容器数据。"
fi
@@ -12,23 +35,69 @@ dc_init() {
mkdir -p "$(dirname -- "$DC_IMAGE")" "$DC_ROOT"
truncate -s 3G "$DC_IMAGE"
mkfs.ext4 -F -q -L DEBIAN_CONTAINER "$DC_IMAGE"
- unshare --mount --propagation private -- bash "$DC_SCRIPT" _init
+ if [[ -n "$tarball" ]]; then
+ unshare --mount --propagation private -- bash "$DC_SCRIPT" _init "$tarball"
+ else
+ unshare --mount --propagation private -- bash "$DC_SCRIPT" _init
+ fi
echo "初始化完成。执行 sudo bash $DC_SCRIPT enter 进入容器。"
}
dc_init_rootfs() {
+ local tarball=${1:-}
+ local -a include_packages=()
+
dc_mount_root
trap dc_cleanup_mounts EXIT
- debootstrap --variant=minbase stable "$DC_ROOT" http://deb.debian.org/debian
+ if [[ -n "$tarball" ]]; then
+ debootstrap \
+ --variant=minbase \
+ --unpack-tarball="$tarball" \
+ "$DC_SUITE" "$DC_ROOT" "$DC_MIRROR"
+ else
+ debootstrap \
+ --variant=minbase \
+ "$DC_SUITE" "$DC_ROOT" "$DC_MIRROR"
+ fi
+
rm -f "$DC_ROOT/etc/resolv.conf"
cp -L /etc/resolv.conf "$DC_ROOT/etc/resolv.conf"
dc_mount_virtual_filesystems
- chroot "$DC_ROOT" /usr/bin/env DEBIAN_FRONTEND=noninteractive /usr/bin/apt-get update
- chroot "$DC_ROOT" /usr/bin/env DEBIAN_FRONTEND=noninteractive /usr/bin/apt-get install -y passwd util-linux vim-tiny e2fsprogs
+
+ if [[ -z "$tarball" ]]; then
+ IFS=, read -r -a include_packages <<< "$DC_INCLUDE"
+ chroot "$DC_ROOT" /usr/bin/env DEBIAN_FRONTEND=noninteractive /usr/bin/apt-get update
+ chroot "$DC_ROOT" /usr/bin/env DEBIAN_FRONTEND=noninteractive /usr/bin/apt-get install -y "${include_packages[@]}"
+ fi
+
echo debian-container > "$DC_ROOT/etc/hostname"
}
+dc_base_create() {
+ local output=${1:-$DC_TARBALL}
+ local temporary_root
+
+ (($# <= 1)) || dc_die '用法:base-create [tarball 路径]'
+ output=$(readlink -m -- "$output")
+ [[ ! -e "$output" ]] || dc_die "tarball 已存在:$output"
+
+ dc_require_commands debootstrap mktemp readlink
+ mkdir -p "$(dirname -- "$output")"
+ temporary_root=$(mktemp -d)
+
+ (
+ trap 'rm -rf -- "$temporary_root"' EXIT
+ debootstrap \
+ --variant=minbase \
+ --include="$DC_INCLUDE" \
+ --make-tarball="$output" \
+ "$DC_SUITE" "$temporary_root" "$DC_MIRROR"
+ )
+
+ echo "基础 tarball 已创建:$output"
+}
+
dc_enter() {
[[ -f "$DC_IMAGE" ]] || dc_die '没有找到镜像,请先运行 init。'