diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-10-28 23:44:45 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-10-28 23:44:45 +0800 |
| commit | 4e6376cfc58e73fc14ddb691c0fac9da425efac9 (patch) | |
| tree | 7b4e06cdfe2b4f4fbf6fb1a10ba94b5ab8402809 | |
| parent | e7236907dfe3e9130d532d5e8a7f2b17af13df1c (diff) | |
| download | rutils-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/.gitignore | 1 | ||||
| -rw-r--r-- | debian-container/README | 27 | ||||
| -rwxr-xr-x | debian-container/debian-container.sh | 8 | ||||
| -rw-r--r-- | debian-container/lib/common.sh | 14 | ||||
| -rw-r--r-- | debian-container/lib/config.sh | 4 | ||||
| -rw-r--r-- | debian-container/lib/container.sh | 77 |
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。' |
