Skip to content

Commit

Permalink
rework the repo to enable more images
Browse files Browse the repository at this point in the history
  • Loading branch information
gbionescu committed Jul 28, 2021
1 parent b623bb6 commit 606862d
Show file tree
Hide file tree
Showing 16 changed files with 240 additions and 81 deletions.
47 changes: 33 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
# Alpine to image builder
# Rootfs image builder

This repo builds an `ext4` or an `initrd` based on an Alpine image.
This repo builds an `ext4` or an `initrd` using Docker containers.

Note: *some assembly required.*

## Building a rootfs

1. Customize `docker_rootfs_builder` to add custom list of packages.
Here you can install anything that you need in the final image.
2. Customize `alpine_boot` to run a startup script.
3. Run `./build_rootfs.sh`.
Simply run:

```bash
./build-rootfs.sh <rootfs-type>
```

Where `rootfs-type` is one of the root filesystem generators that starts with `type-`.

For example, to generate an `Ubuntu 21.04` rootfs, run:

```bash
./build-rootfs.sh ubuntu21.04
```

## Building an initrd

1. Customize `docker_rootfs_builder` to add custom list of packages.
Here you can install anything that you need in the final image.
2. Customize `alpine_boot` to run a startup script.
3. Run `./build_initrd.sh`.
The initrd is

## Customizing the build process

## Utils
Each rootfs generator consists of 3 files:

`ext4_to_initrd.sh rootfs.ext4` converts an ext4 rootfs to an initrd
- `init-rootfs.sh`: creates the root filesystem and formats it.
This is needed because a distribution may take a larger amount of space

- `inside-container.sh`: what is installed in a rootfs.
Here this script usually finishes with copying the rootfs contents to a mounted rootfs.ext4 file.

- `run-container.sh`: controls the container lifetime. For example the Ubuntu container is started
twice because systemd needs to be initialized.

### Adding a new image type

Just add a new folder with the 3 files described above

## Troubleshooting

- Need a larger image? Change `build_rootfs.sh`.
- Need to run something at startup? Change `alpine_boot`
- Need a larger image? Change `init-rootfs.sh`.

14 changes: 0 additions & 14 deletions alpine_boot

This file was deleted.

8 changes: 8 additions & 0 deletions build-initrd.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
# Build an initrd from alpine
set -e

SCRIPT_DIR="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"

"$SCRIPT_DIR"/build-rootfs.sh alpine
"$SCRIPT_DIR"/utils/ext4_to_initrd.sh rootfs.ext4
22 changes: 22 additions & 0 deletions build-rootfs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash
set -e
SCRIPT_DIR="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
RPATH="$SCRIPT_DIR/rootfs.ext4"

if [ $UID != 0 ]; then
echo "Needs root"
exit 1
fi

if [[ ! -d "$SCRIPT_DIR/type-$1" ]]; then
types=`ls -d1 ./type* | cut -d'-' -f2`
echo -e "$1 is not a rootfs type. Try one of:\n$types"
fi

# Clean up old files
if [[ -f "$RPATH" ]]; then
rm -rf "$RPATH"
fi

"type-$1/init-rootfs.sh" "$RPATH"
"type-$1/run-container.sh" "$RPATH"
13 changes: 0 additions & 13 deletions build_initrd.sh

This file was deleted.

28 changes: 0 additions & 28 deletions build_rootfs.sh

This file was deleted.

5 changes: 5 additions & 0 deletions type-alpine/init-rootfs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

# Create the rootfs and format it
dd if=/dev/zero of="$1" bs=1M count=50 > /dev/null
mkfs.ext4 "$1" > /dev/null
37 changes: 25 additions & 12 deletions docker_rootfs_builder → type-alpine/inside-container.sh
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
#!/bin/sh

set -e
# Based on:
# https://github.com/firecracker-microvm/firecracker/blob/master/docs/rootfs-and-kernel-setup.md

### Common
### Customize me!
apk add openrc
apk add util-linux

###

### Customize me!
# Build stuff
apk add vim iperf3 fio bash dropbear haveged
# Set up ssh access
apk add bash dropbear haveged
mkdir -p /etc/dropbear
rc-update add haveged
###

### Optional: Working dir
# mkdir -p /work

### Post install stuff
# Set up a login terminal on the serial console (ttyS0):
ln -s agetty /etc/init.d/agetty.ttyS0
Expand All @@ -39,12 +33,31 @@ rc-update add sysfs boot
# Enable local.d scripts
rc-update add local default

# Optional: copy startup script
cp /alpine_boot /etc/local.d/RunMe.start
# Create startup script
cat <<EOF > /etc/local.d/RunMe.start
# Mount ramfs in /tmp
mkdir /tmp
mount -t tmpfs tmpfs /tmp
# Create an overlayfs over /etc
# dropbear uses /etc to create keys
mkdir -p /tmp/etc/work
mkdir -p /tmp/etc/upper
mount -t overlay \
-o lowerdir=/etc,upperdir=/tmp/etc/upper,workdir=/tmp/etc/work \
overlay /etc
dropbear -RBE&
EOF

# Then, copy the newly configured system to the rootfs image:
mkdir /my-rootfs
mount /rootfs.ext4 /my-rootfs

for d in bin etc lib root sbin usr; do tar c "/$d" | tar x -C /my-rootfs; done
for dir in dev proc run sys var tmp; do mkdir /my-rootfs/${dir}; done
umount /my-rootfs

# All done, exit docker shell
exit
21 changes: 21 additions & 0 deletions type-alpine/run-container.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash
set -e
SCRIPT_DIR="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"

# Launch the container
cont_id=$(docker run -td --rm --privileged -v $1:/rootfs.ext4 alpine)

# Run the payload
set +e
docker exec -it "$cont_id" /bin/sh -c "`cat $SCRIPT_DIR/inside-container.sh`"

rval=$?
set -e

# Stop the container
docker stop "$cont_id"

if [[ "$rval" != 0 ]]; then
echo "Error running the payload"
exit 1
fi
5 changes: 5 additions & 0 deletions type-amazonlinux2/init-rootfs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

# Create the rootfs and format it
dd if=/dev/zero of="$1" bs=1M count=800 > /dev/null
mkfs.ext4 "$1" > /dev/null
27 changes: 27 additions & 0 deletions type-amazonlinux2/inside-container.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/sh
set -e
### Customize me!
yum install -y \
openssh-server \
openssh-clients \
iproute2 \
net-tools \
tar \
procps

# Set password
echo "root:root" | chpasswd

# Start the ssh server to generate keys
systemctl start sshd

# Then, copy the newly configured system to the rootfs image:
mkdir /my-rootfs
mount /rootfs.ext4 /my-rootfs

for d in bin etc lib lib64 root run sbin usr var; do tar c "/$d" | tar x -C /my-rootfs; done
for dir in dev proc run sys var tmp; do mkdir -p /my-rootfs/${dir}; done
umount /my-rootfs

# All done, exit docker shell
exit
30 changes: 30 additions & 0 deletions type-amazonlinux2/run-container.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash
set -e
SCRIPT_DIR="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"

# Launch the container
cont_id=$(docker run -td --rm --privileged -v $1:/rootfs.ext4 amazonlinux:2)

# Install systemd
docker exec -it "$cont_id" /bin/bash -c "yum install -y systemd"

# Restart the container
docker commit "$cont_id" "temp-build-amazonlinux"
docker stop "$cont_id"
new_cont_id=$(docker run -td --rm --privileged -v $1:/rootfs.ext4 temp-build-amazonlinux /sbin/init)

# Run the payload
set +e
docker exec -it "$new_cont_id" /bin/sh -c "`cat $SCRIPT_DIR/inside-container.sh`"

rval=$?
set -e

# Stop the container
docker stop "$new_cont_id"
docker rmi -f "temp-build-amazonlinux"

if [[ "$rval" != 0 ]]; then
echo "Error running the payload"
exit 1
fi
5 changes: 5 additions & 0 deletions type-ubuntu21.04/init-rootfs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

# Create the rootfs and format it
dd if=/dev/zero of="$1" bs=1M count=800 > /dev/null
mkfs.ext4 "$1" > /dev/null
29 changes: 29 additions & 0 deletions type-ubuntu21.04/inside-container.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/sh
set -e
### Customize me!
DEBIAN_FRONTEND="noninteractive" apt-get install -y \
openssh-server \
openssh-client \
iproute2 \
net-tools strace

# Enable SSH
echo "PermitRootLogin yes" >> /etc/ssh/sshd_config

# Set password
echo "root:root" | chpasswd

# Set up serial
systemctl enable getty@ttyS0
systemctl start getty@ttyS0

# Then, copy the newly configured system to the rootfs image:
mkdir /my-rootfs
mount /rootfs.ext4 /my-rootfs

for d in bin etc lib lib64 root run sbin usr var; do tar c "/$d" | tar x -C /my-rootfs; done
for dir in dev proc run sys var tmp; do mkdir -p /my-rootfs/${dir}; done
umount /my-rootfs

# All done, exit docker shell
exit
30 changes: 30 additions & 0 deletions type-ubuntu21.04/run-container.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash
set -e
SCRIPT_DIR="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"

# Launch the container
cont_id=$(docker run -td --rm --privileged -v $1:/rootfs.ext4 ubuntu:21.04)

# Install systemd
docker exec -it "$cont_id" /bin/bash -c "apt-get update && DEBIAN_FRONTEND='noninteractive' apt-get install -y systemd"

# Restart the container
docker commit "$cont_id" "temp-build-ubuntu"
docker stop "$cont_id"
new_cont_id=$(docker run -td --rm --privileged -v $1:/rootfs.ext4 temp-build-ubuntu /usr/bin/systemd)

# Run the payload
set +e
docker exec -it "$new_cont_id" /bin/sh -c "`cat $SCRIPT_DIR/inside-container.sh`"

rval=$?
set -e

# Stop the container
docker stop "$new_cont_id"
docker rmi -f "temp-build-ubuntu"

if [[ "$rval" != 0 ]]; then
echo "Error running the payload"
exit 1
fi
File renamed without changes.

0 comments on commit 606862d

Please sign in to comment.