As a starting point I used the mkimage-arch.sh script on the Docker github contrib area.
Script must be run as root
if [ “$(id -u)” != “0” ]; then
printf "This script must be run as root\n"
exit 1
fi
There are two required packages : expect + pacstrap which can be installed with :$ pacman -S arch-install-scripts expect
The script checks for this as follows :hash pacstrap &>/dev/null || {
printf "Could not find pacstrap. Run pacman -S arch-install-scripts"
exit 1
}
hash expect &>/dev/null || {
printf "Could not find expect. Run pacman -S expect"
exit 1
}
The || is similar to && except it tells the shell only to evaluate the expression after it when the first expression fails.The hash command affects the way the current shell environment remembers the locations of utilities found. If run without any parameters it shows the path of all commands run since the hash was last reset (hash -r) e.g.
$ hash
hits command
1 /usr/bin/git
1 /usr/bin/vim
3 /usr/bin/cat
1 /usr/bin/touch
1 /usr/bin/mv
1 /usr/bin/mkdir
3 /usr/bin/man
13 /usr/bin/ls
The hash table is a feature of bash that prevents it from having to search $PATH every time you type a command by caching the results in memory. For this use case we use it as a way to test if the command is available.Next we set the language as UTF-8 :
export LANG="C.UTF-8"
Create a temporary root file system with mktemp :ROOTFS=$(mktemp -d /tmp/rootfs-archlinux-XXXXXXXXXX)
mktemp creates a temporary directory (or file) based on the template provided to randomize the name. Each X value is replaced with a random string.Set permissions
chmod 755 "$ROOTFS"
Define the packages to not install for minimal imagePKGIGNORE=(
cryptsetup
device-mapper
dhcpcd
iproute2
jfsutils
linux
lvm2
man-db
man-pages
mdadm
nano
netctl
openresolv
pciutils
pcmciautils
reiserfsprogs
s-nail
systemd-sysvcompat
usbutils
vi
xfsprogs
)
Expanding an array without an index only gives the first element. The $IFS is a special shell variable which stands for Internal Field Separator. IFS=','
PKGIGNORE="${PKGIGNORE[*]}"
unset IFS
printf "%s""\nPackages not to be installed : $PKGIGNORE\n"
Set pacman.conf to provided conf filePACMAN_CONF='./arch-docker-pacman.conf'
Define the mirror for pacman :PACMAN_MIRRORLIST='Server = https://mirrors.kernel.org/archlinux/\$repo/os/\$arch'
Set basic variables to create imagePACMAN_EXTRA_PKGS=''
EXPECT_TIMEOUT=60
ARCH_KEYRING=archlinux
DOCKER_IMAGE_NAME=archlinux
Export pacman mirror export PACMAN_MIRRORLIST
Use expect to auto reply to pacstrapexpect <<EOF
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- \$arg
}
set timeout $EXPECT_TIMEOUT
spawn pacstrap -C $PACMAN_CONF -c -d -G -i $ROOTFS base haveged $PACMAN_EXTRA_PKGS --ignore $PKGIGNORE
expect {
-exact "anyway? \[Y/n\] " { send -- "n\r"; exp_continue }
-exact "(default=all): " { send -- "\r"; exp_continue }
-exact "installation? \[Y/n\]" { send -- "y\r"; exp_continue }
}
EOF
Remove manual files to save spacearch-chroot "$ROOTFS" /bin/sh -c 'rm -r /usr/share/man/*'
Use haveged to generate random numbers and feed linux random device. You must run pacman-key –init before first using pacman; the local keyring can then be populated with the keys of all official Arch Linux packagers with pacman-key –populate archlinux.arch-chroot "$ROOTFS" /bin/sh -c "haveged -w 1024; pacman-key --init; pkill haveged; pacman -Rs --noconfirm haveged; pacman-key --populate $ARCH_KEYRING; pkill gpg-agent"
Set local timezone to UTCarch-chroot "$ROOTFS" /bin/sh -c "ln -s /usr/share/zoneinfo/UTC /etc/localtime"
Set locale to ‘en_US.UTF-8 UTF-8’echo 'en_US.UTF-8 UTF-8' > "$ROOTFS"/etc/locale.gen
arch-chroot "$ROOTFS" locale-gen
Set pacman mirrorlistarch-chroot "$ROOTFS" /bin/sh -c "echo $PACMAN_MIRRORLIST > /etc/pacman.d/mirrorlist"
udev is a device manager for the Linux kernel. Udev primarily manages device nodes in the /dev directory and also handles all user space events raised while hardware devices are added into the system or removed from it, including firmware loading as required by certain devices.udev doesn’t work in containers, rebuild /dev
DEV=$ROOTFS/dev
rm -rf "$DEV"
mkdir -p "$DEV"
mknod -m 666 "$DEV"/null c 1 3
mknod -m 666 "$DEV"/zero c 1 5
mknod -m 666 "$DEV"/random c 1 8
mknod -m 666 "$DEV"/urandom c 1 9
mkdir -m 755 "$DEV"/pts
mkdir -m 1777 "$DEV"/shm
mknod -m 666 "$DEV"/tty c 5 0
mknod -m 600 "$DEV"/console c 5 1
mknod -m 666 "$DEV"/tty0 c 4 0
mknod -m 666 "$DEV"/full c 1 7
mknod -m 600 "$DEV"/initctl p
mknod -m 666 "$DEV"/ptmx c 5 2
ln -sf /proc/self/fd "$DEV"/fd
tar root file system and import image to Docker. tar --numeric-owner --xattrs --acls -C "$ROOTFS" -c . | docker import - "$DOCKER_IMAGE_NAME"
Options for tar used : --numeric-owner Always use numbers for user/group names.
--xattrs Enable extended attributes support
--acls Enable the POSIX ACLs support
-C Change to directory
-c Create new archive
Test new imagedocker run --rm -t $DOCKER_IMAGE_NAME echo Success
Delete temp root file systemrm -rf "$ROOTFS"
Running the script should finish with tar: ./etc/pacman.d/gnupg/S.gpg-agent: socket ignored
sha256:82b0356924efb95e5483417dd4f0cef85fce7afbacb75c18632de7bc45edd796
Success
Script available on my docker repository on github.
No comments:
Post a Comment