We will see how to generate a rootfs tarball for redhat based system. Since we are targetting redhat based system, I am going to use debian based system (Ubuntu 17.10 64-bit - latest at the time of writing this post) as my host. We will generate rootfs tarball for CentOS 7 64-bit.
The below mentioned steps are validated on Ubuntu 17.10 desktop installation.
Lets get started
As usual the first step, install the required dependecy packages which in our
case is yum
.
sudo apt install yum
Second, will prepare the required directory structure. In our example ~/work
will be our working directory and we will install the CentOS 7 roofs in inside
of work
in a directory named centos7
.
export CENTOS\_BASE\_DIR=~/work
export CENTOS\_ROOT\_DIR=${CENTOS\_BASE\_DIR}/centos7
mkdir -p ${CENTOS\_ROOT\_DIR}
cd ${CENTOS\_BASE\_DIR}
Now we need to generate the repo
metadata file for CentOS 7 installation.
Below code does the same.
cat > ${CHROOT_BASE_DIR}/chroot-centos7.repo << EOF
[centos7-chroot-base]
name=CentOS-7-Base
baseurl=http://mirror.centos.org/centos/7/os/x86_64
gpgcheck=0
[centos7-chroot-epel]
name=Extra Packages for Enterprise Linux 7
baseurl=http://dl.fedoraproject.org/pub/epel/7/x86_64
gpgcheck=0
EOF
Once we have our directory structure and the repo
file prepared as mentioned
above, we can bootstrap the CentOS 7 root by executing the below mentioned
command. This creates a base rootfs with networking utilities and sudo command.
sudo yum -y -c chroot-centos7.repo --disablerepo=* \
--enablerepo=centos7-chroot-base \
--enablerepo=centos7-chroot-epel \
--disableplugin=* \
--installroot=${CHROOT_CENTOS7_BASE_DIR} install \
bash \
bash-completion \
vim-minimal \
yum \
iproute \
iputils \
rootfiles \
sudo
After the yum
installation is complete we need to prepare our rootfs for
customization. We will start by mounting the required mount points to use
chroot
.
sudo mount --bind /dev ${CHROOT_CENTOS7_BASE_DIR}/dev
sudo mount --bind /dev/pts ${CHROOT_CENTOS7_BASE_DIR}/dev/pts
sudo mount --bind /sys ${CHROOT_CENTOS7_BASE_DIR}/sys
sudo mount --bind /proc ${CHROOT_CENTOS7_BASE_DIR}/proc
sudo mount --bind /home ${CHROOT_CENTOS7_BASE_DIR}/home
sudo cp /etc/resolv.conf ${CHROOT_CENTOS7_BASE_DIR}/etc/
Now we can start using the rootfs using chroot
command. We will do the
following customizations
- Setup
releasever
andbasearch
yum variables. Unfortunately this is required because of thecaveat
mentioned in Appendix I. - Remove unncessary files like yum cache, locale definitions, temporary files, etc.
- Generate proper yum.conf, locale definition, build timestamp file and machine-id file - these are pretty standard stuff required for storage optimization in case we decide to use this rootfs for docker images
sudo chroot ${CHROOT_CENTOS7_BASE_DIR}
# Step no 1
echo "7" > /etc/yum/vars/releasever
echo "x86_64" > /etc/yum/vars/basearch
# Step no 2
yum clean all
rm -rf /boot /var/cache/yum/* \
/tmp/ks-script* \
/var/log/* \
/tmp/* \
/etc/sysconfig/network-scripts/ifcfg-*
###Optional for making the rootfs lean to be used as base container
umount /run
systemd-tmpfiles --create --boot
rm -f /var/run/nologin
# Step no 3
echo 'container' > /etc/yum/vars/infra
awk '(NF==0&&!done){print "override_install_langs='$LANG'\ntsflags=nodocs";done=1}{print}' \
< /etc/yum.conf > /etc/yum.conf.new
mv /etc/yum.conf.new /etc/yum.conf
rm -f /usr/lib/locale/locale-archive
#Setup locale properly
localedef -v -c -i en_US -f UTF-8 en_US.UTF-8
/bin/date +%Y%m%d_%H%M > /etc/BUILDTIME
:> /etc/machine-id
###End container
After the rootfs configuration we need to umount all the mount points we mounted earlier. The unmount order is important here.
sudo umount ${CHROOT_CENTOS7_BASE_DIR}/home
sudo umount ${CHROOT_CENTOS7_BASE_DIR}/proc
sudo umount ${CHROOT_CENTOS7_BASE_DIR}/sys
sudo umount ${CHROOT_CENTOS7_BASE_DIR}/dev/pts
sudo umount ${CHROOT_CENTOS7_BASE_DIR}/dev
sudo rm ${CHROOT_CENTOS7_BASE_DIR}/etc/resolv.conf
We do one last cleanup before we package the rootfs as a tarball.
sudo rm -rf ${CHROOT_CENTOS7_BASE_DIR}/boot
sudo rm -rf ${CHROOT_CENTOS7_BASE_DIR}/var/cache/yum/*
sudo rm -f ${CHROOT_CENTOS7_BASE_DIR}/tmp/ks-script*
sudo rm -rf ${CHROOT_CENTOS7_BASE_DIR}/var/log/*
sudo rm -rf ${CHROOT_CENTOS7_BASE_DIR}/tmp/*
sudo rm -rf ${CHROOT_CENTOS7_BASE_DIR}/etc/sysconfig/network-scripts/ifcfg-*
And the final piece, run the below command to generate the CentOS 7 rootfs tarball.
sudo tar --exclude=centos7/home \
--exclude=centos7/var/cache/yum/* \
-Jcvf centos7.tar.xz centos7
References
Appendix I
While running yum
command inside of the CentOS 7 chroot I ran into below error
message. Strangely this happens on Ubuntu host but not on CentOS host. As a fix
I have created yum
variables releasever
and basearch
inside the CentOS
rootfs. Please check Reference section for the
manual describing how to customize yum
variables.
$ yum search yum
Failed to set locale, defaulting to C
Loaded plugins: fastestmirror
One of the configured repositories failed (Unknown),
and yum doesn't have enough cached data to continue. At this point the only
safe thing yum can do is fail. There are a few ways to work "fix" this:
1. Contact the upstream for the repository and get them to fix the problem.
2. Reconfigure the baseurl/etc. for the repository, to point to a working
upstream. This is most often useful if you are using a newer
distribution release than is supported by the repository (and the
packages for the previous distribution release still work).
3. Run the command with the repository temporarily disabled
yum --disablerepo=<repoid> ...
4. Disable the repository permanently, so yum won't use it by default. Yum
will then just ignore the repository until you permanently enable it
again or use --enablerepo for temporary usage:
yum-config-manager --disable <repoid>
or
subscription-manager repos --disable=<repoid>
5. Configure the failing repository to be skipped, if it is unavailable.
Note that yum will try to contact the repo. when it runs most commands,
so will have to try and fail each time (and thus. yum will be be much
slower). If it is a very temporary problem though, this is often a nice
compromise:
yum-config-manager --save --setopt=<repoid>.skip_if_unavailable=true
Cannot find a valid baseurl for repo: base/$releasever/x86_64
$