需要在无法访问 Internet 且无法写入随机文件系统位置的环境中运行安装在主机上的命令行程序。想用lxc。
- 尽可能共享宿主的文件系统
- 独立的网络堆栈和用户 ID
- 非特权容器
问题是因为使用像 ubuntu 这样的通用模板会安装很多单独的软件,我宁愿使用主机中的 lib 等
在未来,这可能会用于 Evince 或 LibreOffice,用于可能嵌入了脚本和跟踪器的文档,或用于不正当的闭源软件。
最佳答案
以下是特权容器案例,基于 sshd 模板,它将花费 152 KiB 的磁盘空间:
sudo lxc-create --template=$PWD/lxc-sshd-ubuntu --name=x
sudo lxc-start --name=x
sudo lxc-attach --name=x
# check disk space: du -hs /var/lib/lxc/x/rootfs
模板文件如下,它源自 /usr/share/lxc/templates/lxc-sshd
并修复了一些阻止分布式版本实际工作的错误。 lxc-sshd-ubuntu
#!/bin/bash -eu
# © 2017 Harald Rudell <harald.rudell@gmail.com> (http://haraldrudell.com) ISC License.
auth_key= # undefined
options=$(getopt -o hp:n:S: -l help,rootfs:,path:,name:,auth-key: -- "$@")
if [ $? -ne 0 ]; then echo >&2 "parameter FAIL"; exit 1; fi
eval set -- "$options"
while true; do
case "$1" in
-h|--help) usage $0 && exit 0;;
-p|--path) path=$2; shift 2;;
--rootfs) rootfs=$2; shift 2;;
-n|--name) name=$2; shift 2;;
-S|--auth-key) auth_key=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
if [ $0 = "/sbin/init" ]; then
check_for_cmd() {
cmd_path=`type $1`
if [ $? -ne 0 ]; then echo "The command '$1' $cmd_path is not accessible on the system"; exit 1; fi
cmd_path=`echo $cmd_path |cut -d ' ' -f 3`
}
PATH="$PATH:/bin:/sbin:/usr/sbin"
check_for_cmd /usr/sbin/init.lxc
check_for_cmd sshd
sshd_path=$cmd_path
if [ -f /run-dhcp ]; then
check_for_cmd dhclient
check_for_cmd ifconfig
touch /etc/fstab
rm -f /dhclient.conf
cat > /dhclient.conf << EOF
send host-name = gethostname();
EOF
ifconfig eth0 up
dhclient eth0 -cf /dhclient.conf
echo "Container IP address:"
ifconfig eth0 |grep inet
fi
exec /usr/sbin/init.lxc -- $sshd_path
exit 1
fi
if [ -z "$path" ]; then echo "'path' parameter is required"; exit 1; fi
config="$path/config"
if [ -z "$rootfs" ]; then
if grep -q '^lxc.rootfs' $config 2>/dev/null ; then
rootfs=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $config)
else
rootfs=$path/rootfs
fi
fi
tree="\
$rootfs/var/empty/sshd \
$rootfs/var/lib/empty/sshd \
$rootfs/etc/init.d \
$rootfs/etc/rc.d \
$rootfs/etc/ssh \
$rootfs/etc/sysconfig/network-scripts \
$rootfs/dev/shm \
$rootfs/run/sshd \
$rootfs/proc \
$rootfs/sys \
$rootfs/bin \
$rootfs/sbin \
$rootfs/usr \
$rootfs/tmp \
$rootfs/home \
$rootfs/root \
$rootfs/lib \
$rootfs/lib64"
mkdir -p $tree
ln -s /run $rootfs/var/run
cat <<EOF > $rootfs/etc/passwd
root:x:0:0:root:/root:/bin/bash
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
EOF
cat <<EOF > $rootfs/etc/group
root:x:0:root
sshd:x:74:
EOF
ssh-keygen -t rsa -N "" -f $rootfs/etc/ssh/ssh_host_rsa_key
ssh-keygen -t dsa -N "" -f $rootfs/etc/ssh/ssh_host_dsa_key
cat <<EOF > $rootfs/etc/ssh/sshd_config
Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
UsePrivilegeSeparation yes
SyslogFacility AUTH
LogLevel INFO
LoginGraceTime 120
PermitRootLogin yes
StrictModes yes
PubkeyAuthentication yes
IgnoreRhosts yes
HostbasedAuthentication no
PermitEmptyPasswords yes
ChallengeResponseAuthentication no
EOF
if [ -n "$auth_key" -a -f "$auth_key" ]; then
u_path="/root/.ssh"
root_u_path="$rootfs/$u_path"
mkdir -p $root_u_path
cp $auth_key "$root_u_path/authorized_keys"
chown -R 0:0 "$rootfs/$u_path"
chmod 700 "$rootfs/$u_path"
echo "Inserted SSH public key from $auth_key into $rootfs/$u_path"
fi
init_path=$(realpath --relative-to=/ $(readlink -f /sbin/init))
grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config
cat <<EOF >> $path/config
lxc.utsname = $name
lxc.pts = 1024
lxc.cap.drop = sys_module mac_admin mac_override sys_time
lxc.aa_profile = unconfined
lxc.mount.entry = /lib lib none ro,bind 0 0
lxc.mount.entry = /bin bin none ro,bind 0 0
lxc.mount.entry = /usr usr none ro,bind 0 0
lxc.mount.entry = /sbin sbin none ro,bind 0 0
lxc.mount.entry = tmpfs run/sshd tmpfs mode=0644 0 0
lxc.mount.entry = /usr/share/lxc/templates/lxc-sshd $init_path none ro,bind 0 0
lxc.mount.entry = /etc/init.d etc/init.d none ro,bind 0 0
lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
EOF
if [ -d /etc/sysconfig/network-scripts ]; then
cat <<EOF >> $path/config
lxc.mount.entry = /etc/sysconfig/network-scripts etc/sysconfig/network-scripts none ro,bind 0 0
EOF
fi
if [ -d /etc/rc.d ]; then
cat <<EOF >> $path/config
lxc.mount.entry = /etc/rc.d etc/rc.d none ro,bind 0 0
EOF
fi
grep -q "^lxc.network.ipv4" $path/config || touch $rootfs/run-dhcp
if [ "$(uname -m)" = "x86_64" ]; then
cat <<EOF >> $path/config
lxc.mount.entry = /lib64 lib64 none ro,bind 0 0
EOF
fi
关于linux - 如何在尽可能精简的 lxc 容器中运行实用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46020211/