简介

LFS 项目不用太多介绍,前面已经有很多的内容描述了。我基于前面的内容考虑实现一个简化版本的支持 docker 的 LFS 环境。从前面实现的 LFS 项目来看需要解决以下几个问题

  1. 系统服务管理需要与时俱进采用 systemd 的管理方式而不是传统的 Sysvint 的模式
  2. 系统的内核需要支持容器环境
  3. 容器服务同时还依赖 git 和 iptables 组件

容器环境要求

官网上有专门的二进制安装方法,安装步骤很简洁,就是下载解压即可使用,但是对系统的依赖说法比较简洁

  • A 64-bit installation 64位操作系统(这个都满足)
  • Version 3.10 or higher of the Linux kernel. (3.1版本以上的内核,缺乏细致的内核配置要求说明)
  • iptables version 1.4 or higher (iptables 版本 1.4 以上,但是该组件相关的依赖非常多,官网没有更详细的说明)
  • git version 1.7 or higher (git 版本容易满足)
  • A ps executable, usually provided by procps or a similar package. (ps 工具)
  • XZ Utils 4.9 or higher (xz 压缩工具及对应的版本)
  • A properly mounted cgroupfs hierarchy; a single, all-encompassing cgroup mount point is not sufficient. (cggoup 相关的支持)

最麻烦的其实时内核编译所需的组件配置,因为内核编译相关的组件太多了,容器环境涉及存储、网络、cggroup、服务等多方面的内容。

LFS 相关

LFS 直接参照之前的步骤,除了在创建系统文件(passwd 和 group )及 systemd 组件及后续配置有不同外,其他的步骤可以沿用。

调整的部分主要包括

  • /etc/passwd
  • /etc/group
  • 网络配置文件
  • systemd 组件
  • 内核配置

详细的步骤 参照 LFS systemd 项目https://www.linuxfromscratch.org/lfs/view/stable-systemd/

构建基础环境

1、参照 4014-LFS 自定义 Linux(上)的描述直至完成【3. 交叉编译临时工具

2、在【4. 进入 Chroot 并构建其他临时工具】步骤中调整【4.4. 创建目录和相关文件】的配置如下

mkdir -pv /{boot,home,mnt,opt,srv}
mkdir -pv /etc/{opt,sysconfig}
mkdir -pv /lib/firmware
mkdir -pv /media/{floppy,cdrom}
mkdir -pv /usr/{,local/}{include,src}
mkdir -pv /usr/lib/locale
mkdir -pv /usr/local/{bin,lib,sbin}
mkdir -pv /usr/{,local/}share/{color,dict,doc,info,locale,man}
mkdir -pv /usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir -pv /usr/{,local/}share/man/man{1..8}
mkdir -pv /var/{cache,local,log,mail,opt,spool}
mkdir -pv /var/lib/{color,misc,locate}

ln -sfv /run /var/run
ln -sfv /run/lock /var/lock

install -dv -m 0750 /root
install -dv -m 1777 /tmp /var/tmp

ln -sv /proc/self/mounts /etc/mtab
cat > /etc/hosts << EOF
127.0.0.1  localhost $(hostname)
::1        localhost
EOF

cat > /etc/passwd << "EOF"
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/dev/null:/usr/bin/false
daemon:x:6:6:Daemon User:/dev/null:/usr/bin/false
messagebus:x:18:18:D-Bus Message Daemon User:/run/dbus:/usr/bin/false
uuidd:x:80:80:UUID Generation Daemon User:/dev/null:/usr/bin/false
nobody:x:65534:65534:Unprivileged User:/dev/null:/usr/bin/false
systemd-journal-gateway:x:73:73:systemd Journal Gateway:/:/usr/bin/false
systemd-journal-remote:x:74:74:systemd Journal Remote:/:/usr/bin/false
systemd-journal-upload:x:75:75:systemd Journal Upload:/:/usr/bin/false
systemd-network:x:76:76:systemd Network Management:/:/usr/bin/false
systemd-resolve:x:77:77:systemd Resolver:/:/usr/bin/false
systemd-timesync:x:78:78:systemd Time Synchronization:/:/usr/bin/false
systemd-coredump:x:79:79:systemd Core Dumper:/:/usr/bin/false
systemd-oom:x:81:81:systemd Out Of  Memory Daemon:/:/usr/bin/false
EOF

cat > /etc/group << "EOF"
root:x:0:
bin:x:1:daemon
sys:x:2:
kmem:x:3:
tape:x:4:
tty:x:5:
daemon:x:6:
floppy:x:7:
disk:x:8:
lp:x:9:
dialout:x:10:
audio:x:11:
video:x:12:
utmp:x:13:
cdrom:x:15:
adm:x:16:
messagebus:x:18:
input:x:24:
mail:x:34:
kvm:x:61:
uuidd:x:80:
wheel:x:97:
users:x:999:
nogroup:x:65534:
systemd-journal-gateway:x:73:
systemd-journal-remote:x:74:
systemd-journal-upload:x:75:
systemd-network:x:76:
systemd-resolve:x:77:
systemd-timesync:x:78:
systemd-coredump:x:79:
systemd-oom:x:81:
EOF

echo "tester:x:101:101::/home/tester:/bin/bash" >> /etc/passwd
echo "tester:x:101:" >> /etc/group
install -o tester -d /home/tester
exec /usr/bin/bash --login
touch /var/log/{btmp,lastlog,faillog,wtmp}
chgrp -v utmp /var/log/lastlog
chmod -v 664  /var/log/lastlog
chmod -v 600  /var/log/btmp

可以看到和之前的版本相比主要是增加了【systemd-journal-gateway、systemd-journal-remote、systemd-journal-upload、systemd-network、systemd-resolve、systemd-timesync、systemd-coredump、
systemd-oom】这些用户和组的信息

如果没有这些用户和组,后面操作系统在启动时相关的服务都将无法正常启动。例如 “systemd-oomd failed to determine user credentials”类似的错误

3、参照【4. 进入 Chroot 并构建其他临时工具】完成该部分的其它步骤

构建 LFS 系统

参照【5. 构建 LFS 系统】完成直到【5.73. Systemd-257.3 中的 Udev】,该步骤对应 LFS 官网项目中的 (8.76. Systemd-257.3 https://www.linuxfromscratch.org/lfs/view/stable-systemd/chapter08/systemd.html)这节

Systemd-257.3

tar xvf systemd-257.3.tar.gz
cd systemd-257.3
sed -e 's/GROUP="render"/GROUP="video"/' \
    -e 's/GROUP="sgx", //'               \
    -i rules.d/50-udev-default.rules.in
mkdir -p build
cd       build
meson setup ..                \
      --prefix=/usr           \
      --buildtype=release     \
      -D default-dnssec=no    \
      -D firstboot=false      \
      -D install-tests=false  \
      -D ldconfig=false       \
      -D sysusers=false       \
      -D rpmmacrosdir=no      \
      -D homed=disabled       \
      -D userdb=false         \
      -D man=disabled         \
      -D mode=release         \
      -D pamconfdir=no        \
      -D dev-kvm-mode=0660    \
      -D nobody-group=nogroup \
      -D sysupdate=disabled   \
      -D ukify=disabled       \
      -D docdir=/usr/share/doc/systemd-257.3
ninja
ninja install
systemd-machine-id-setup
systemctl preset-all

 D-Bus-1.16.0

tar xvf dbus-1.16.0.tar.xz 
cd dbus-1.16.0
mkdir build
cd    build
meson setup --prefix=/usr --buildtype=release --wrap-mode=nofallback ..
ninja
ninja install
ln -sfv /etc/machine-id /var/lib/dbus

Man-DB-2.13.0

tar xvf man-db-2.13.0.tar.xz 
cd man-db-2.13.0 
./configure --prefix=/usr \ 
			--docdir=/usr/share/doc/man-db-2.13.0 \ 
			--sysconfdir=/etc \ 
			--disable-setuid \ 
			--enable-cache-owner=bin \ 
			--with-browser=/usr/bin/lynx \ 
			--with-vgrind=/usr/bin/vgrind \ 
			--with-grap=/usr/bin/grap 
make 
make install

Procps-ng-4.0.5

tar xvf procps-ng-4.0.5.tar.xz 
cd procps-ng-4.0.5 
./configure --prefix=/usr \ 
			--docdir=/usr/share/doc/procps-ng-4.0.5 \ 
			--disable-static \ 
			--disable-kill \ 
			--enable-watch8bit \
			--with-systemd
make 
make install

Util-linux-2.40.4

tar xvf util-linux-2.40.4.tar.xz 
cd util-linux-2.40.4 
./configure --bindir=/usr/bin \ 
			--libdir=/usr/lib \ 
			--runstatedir=/run \ 
			--sbindir=/usr/sbin \ 
			--disable-chfn-chsh \ 
			--disable-login \ 
			--disable-nologin \ 
			--disable-su \ 
			--disable-setpriv \ 
			--disable-runuser \ 
			--disable-pylibmount \ 
			--disable-liblastlog2 \ 
			--disable-static \ 
			--without-python \ 
			--without-systemd \ 
			--without-systemdsystemunitdir \ 
			ADJTIME_PATH=/var/lib/hwclock/adjtime \ 
			--docdir=/usr/share/doc/util-linux-2.40.4 
make 
make install

E2fsprogs-1.47.2

tar xvf e2fsprogs-1.47.2.tar.gz 
cd e2fsprogs-1.47.2 
mkdir -v build 
cd build 
../configure --prefix=/usr \ 
			--sysconfdir=/etc \ 
			--enable-elf-shlibs \ 
			--disable-libblkid \ 
			--disable-libuuid \ 
			--disable-uuidd \ 
			--disable-fsck 
make 
make install 
rm -fv /usr/lib/{libcom_err,libe2p,libext2fs,libss}.a 
gunzip -v /usr/share/info/libext2fs.info.gz 
install-info --dir-file=/usr/share/info/dir /usr/share/info/libext2fs.info 
sed 's/metadata_csum_seed,//' -i /etc/mke2fs.conf

移除调试符号(可选)

如果系统不是为程序员设计的,也没有调试系统软件的计划,可以通过从二进制程序和库移除调试符号和不必要的符号表项,将系统的体积减小约 2 GB。对于一般的 Linux 用户,这不会造成任何不便。
save_usrlib="$(cd /usr/lib; ls ld-linux*[^g])
             libc.so.6
             libthread_db.so.1
             libquadmath.so.0.0.0
             libstdc++.so.6.0.33
             libitm.so.1.0.0
             libatomic.so.1.2.0"

cd /usr/lib

for LIB in $save_usrlib; do
    objcopy --only-keep-debug --compress-debug-sections=zlib $LIB $LIB.dbg
    cp $LIB /tmp/$LIB
    strip --strip-unneeded /tmp/$LIB
    objcopy --add-gnu-debuglink=$LIB.dbg /tmp/$LIB
    install -vm755 /tmp/$LIB /usr/lib
    rm /tmp/$LIB
done

online_usrbin="bash find strip"
online_usrlib="libbfd-2.44.so
               libsframe.so.1.0.0
               libhistory.so.8.2
               libncursesw.so.6.5
               libm.so.6
               libreadline.so.8.2
               libz.so.1.3.1
               libzstd.so.1.5.7
               $(cd /usr/lib; find libnss*.so* -type f)"

for BIN in $online_usrbin; do
    cp /usr/bin/$BIN /tmp/$BIN
    strip --strip-unneeded /tmp/$BIN
    install -vm755 /tmp/$BIN /usr/bin
    rm /tmp/$BIN
done

for LIB in $online_usrlib; do
    cp /usr/lib/$LIB /tmp/$LIB
    strip --strip-unneeded /tmp/$LIB
    install -vm755 /tmp/$LIB /usr/lib
    rm /tmp/$LIB
done

for i in $(find /usr/lib -type f -name \*.so* ! -name \*dbg) \
         $(find /usr/lib -type f -name \*.a)                 \
         $(find /usr/{bin,sbin,libexec} -type f); do
    case "$online_usrbin $online_usrlib $save_usrlib" in
        *$(basename $i)* )
            ;;
        * ) strip --strip-unneeded $i
            ;;
    esac
done

unset BIN LIB save_usrlib online_usrbin online_usrlib

rm -rf /tmp/{*,.*}
find /usr/lib /usr/libexec -name \*.la -delete
find /usr -depth -name $(uname -m)-lfs-linux-gnu\* | xargs rm -rf

系统配置

系统配置的步骤也可以对照【1. 系统配置】的步骤。但是 systemd 版本和之前的存在差异,特别时启动脚本和网络配置。

通用网络配置

默认情况下网络的接口名称由 udev 进程自动管理和生成,udev 进程包含在 


  • 无标签