working image without ml

This commit is contained in:
bwees
2025-08-13 21:18:20 +00:00
parent 0598aa7610
commit 887673a875
35 changed files with 112 additions and 401 deletions
+25 -1
View File
@@ -2,10 +2,33 @@
## How to build
Launch a Docker in Docker container
```bash
docker run --rm -d --privileged \
--name dind-test \
-v "$(pwd)":/home \
-v "$(pwd)/overlay/var/lib/docker":/var/lib/docker \
-e DOCKER_TLS_CERTDIR= \
docker:dind
```
Download images (you may have to wait a few moments for the dind container to start dockerd)
```bash
docker exec -it dind-test sh ./home/docker-gen.sh
```
You can now kill the dind-test container
```bash
docker container stop dind-test
```
Run the following from the root of this repository
```bash
docker run --rm -it -v "$(pwd)":/home --privileged alpine sh ./home/build.sh
docker run --rm -it -v "$(pwd)":/home --privileged --name iso-build alpine sh ./home/build.sh
```
The built image will be placed in `out/`
@@ -19,3 +42,4 @@ The built image will be placed in `out/`
- 2 core x86 processor
- 8GB of RAM, 16GB recommended
- No storage drive needed!
+1 -3
View File
@@ -1,12 +1,10 @@
#!/bin/sh
apk add alpine-sdk alpine-conf xorriso squashfs-tools grub grub-efi doas docker openrc fuse-overlayfs mtools dosfstools grub-efi
apk add alpine-sdk alpine-conf xorriso squashfs-tools grub grub-efi mtools dosfstools grub-efi pigz doas
echo "permit persist root" > /etc/doas.d/doas.conf
echo "permit nopass root" >> /etc/doas.d/doas.conf
addgroup build docker
# su - build -c "
abuild-keygen -i -a -n
apk update
+17 -6
View File
@@ -1,6 +1,17 @@
docker run -d --privileged \
--name dind-test \
-v "$(pwd)":/home \
-v "$(pwd)/overlay/var/lib/docker":/var/lib/docker \
-e DOCKER_TLS_CERTDIR= \
docker:dind
#!/bin/sh
# List of Docker image tags (space-separated)
# ML is excluded since it requires internet to download models
images="
ghcr.io/immich-app/immich-server:v1.137.3
docker.io/valkey/valkey:8-bookworm
ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
"
# Pull each image sequentially
for img in $images; do
echo "Pulling $img..."
docker pull "$img"
done
echo "All images pulled successfully."
+3
View File
@@ -0,0 +1,3 @@
alpine-base
docker
docker-compose
+1
View File
@@ -0,0 +1 @@
alpine
+17
View File
@@ -2,3 +2,20 @@
rc-update add docker boot
service docker start
# Wait until Docker is up
tries=0
until docker info >/dev/null 2>&1; do
tries=$((tries + 1))
if [ "$tries" -ge 20 ]; then
echo "Docker did not start in time" >&2
exit 1
fi
sleep 1
done
# Navigate to the compose directory
cd /usr/app/ || exit 1
# Start your stack
docker compose up -d
+5
View File
@@ -0,0 +1,5 @@
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
+1
View File
@@ -0,0 +1 @@
/etc/init.d/bootmisc
+1
View File
@@ -0,0 +1 @@
/etc/init.d/docker
+1
View File
@@ -0,0 +1 @@
/etc/init.d/hostname
+1
View File
@@ -0,0 +1 @@
/etc/init.d/hwclock
+1
View File
@@ -0,0 +1 @@
/etc/init.d/local
+1
View File
@@ -0,0 +1 @@
/etc/init.d/modules
+1
View File
@@ -0,0 +1 @@
/etc/init.d/sysctl
+1
View File
@@ -0,0 +1 @@
/etc/init.d/syslog
+1
View File
@@ -0,0 +1 @@
/etc/init.d/killprocs
+1
View File
@@ -0,0 +1 @@
/etc/init.d/mount-ro
+1
View File
@@ -0,0 +1 @@
/etc/init.d/savecache
+1
View File
@@ -0,0 +1 @@
/etc/init.d/devfs
+1
View File
@@ -0,0 +1 @@
/etc/init.d/dmesg
+1
View File
@@ -0,0 +1 @@
/etc/init.d/hwdrivers
+1
View File
@@ -0,0 +1 @@
/etc/init.d/mdev
+1
View File
@@ -0,0 +1 @@
/etc/init.d/modloop
+2 -2
View File
@@ -1,10 +1,10 @@
# You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables
# The location where your uploaded files are stored
UPLOAD_LOCATION=./library
UPLOAD_LOCATION=/usr/app/library
# The location where your database files are stored. Network shares are not supported for the database
DB_DATA_LOCATION=./postgres
DB_DATA_LOCATION=/usr/app/postgres
# To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
# TZ=Etc/UTC
+19 -19
View File
@@ -19,7 +19,7 @@ services:
volumes:
# Do not edit the next line. If you want to change the media storage location on your system, edit the value of UPLOAD_LOCATION in the .env file
- ${UPLOAD_LOCATION}:/data
- /etc/localtime:/etc/localtime:ro
# - /etc/localtime:/etc/localtime:ro
env_file:
- .env
ports:
@@ -31,32 +31,33 @@ services:
healthcheck:
disable: false
immich-machine-learning:
container_name: immich_machine_learning
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
# Example tag: ${IMMICH_VERSION:-release}-cuda
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
# extends: # uncomment this section for hardware acceleration - see https://immich.app/docs/features/ml-hardware-acceleration
# file: hwaccel.ml.yml
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference - use the `-wsl` version for WSL2 where applicable
volumes:
- model-cache:/cache
env_file:
- .env
restart: always
healthcheck:
disable: false
# if you are insane enough to uncomment this, you will need an active internet connection to download the image and models
# immich-machine-learning:
# container_name: immich_machine_learning
# # For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
# # Example tag: ${IMMICH_VERSION:-release}-cuda
# image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
# # extends: # uncomment this section for hardware acceleration - see https://immich.app/docs/features/ml-hardware-acceleration
# # file: hwaccel.ml.yml
# # service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference - use the `-wsl` version for WSL2 where applicable
# volumes:
# - model-cache:/cache
# env_file:
# - .env
# restart: always
# healthcheck:
# disable: false
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:8-bookworm@sha256:facc1d2c3462975c34e10fccb167bfa92b0e0dbd992fc282c29a61c3243afb11
image: docker.io/valkey/valkey:8-bookworm
healthcheck:
test: redis-cli ping || exit 1
restart: always
database:
container_name: immich_postgres
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:32324a2f41df5de9efe1af166b7008c3f55646f8d0e00d9550c16c9822366b4a
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
@@ -67,7 +68,6 @@ services:
volumes:
# Do not edit the next line. If you want to change the database storage location on your system, edit the value of DB_DATA_LOCATION in the .env file
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
shm_size: 128mb
restart: always
volumes:
-66
View File
@@ -1,66 +0,0 @@
#!/bin/sh -e
HOSTNAME="$1"
if [ -z "$HOSTNAME" ]; then
echo "usage: $0 hostname"
exit 1
fi
cleanup() {
rm -rf "$tmp"
}
makefile() {
OWNER="$1"
PERMS="$2"
FILENAME="$3"
cat > "$FILENAME"
chown "$OWNER" "$FILENAME"
chmod "$PERMS" "$FILENAME"
}
rc_add() {
mkdir -p "$tmp"/etc/runlevels/"$2"
ln -sf /etc/init.d/"$1" "$tmp"/etc/runlevels/"$2"/"$1"
}
tmp="$(mktemp -d)"
trap cleanup EXIT
mkdir -p "$tmp"/etc
makefile root:root 0644 "$tmp"/etc/hostname <<EOF
$HOSTNAME
EOF
mkdir -p "$tmp"/etc/network
makefile root:root 0644 "$tmp"/etc/network/interfaces <<EOF
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
EOF
mkdir -p "$tmp"/etc/apk
makefile root:root 0644 "$tmp"/etc/apk/world <<EOF
alpine-base
EOF
rc_add devfs sysinit
rc_add dmesg sysinit
rc_add mdev sysinit
rc_add hwdrivers sysinit
rc_add modloop sysinit
rc_add hwclock boot
rc_add modules boot
rc_add sysctl boot
rc_add hostname boot
rc_add bootmisc boot
rc_add syslog boot
rc_add mount-ro shutdown
rc_add killprocs shutdown
rc_add savecache shutdown
tar -c -C "$tmp" etc | gzip -9n > $HOSTNAME.apkovl.tar.gz
-75
View File
@@ -1,75 +0,0 @@
#!/bin/sh -e
HOSTNAME="$1"
if [ -z "$HOSTNAME" ]; then
echo "usage: $0 hostname"
exit 1
fi
cleanup() {
rm -rf "$tmp"
}
makefile() {
OWNER="$1"
PERMS="$2"
FILENAME="$3"
cat > "$FILENAME"
chown "$OWNER" "$FILENAME"
chmod "$PERMS" "$FILENAME"
}
rc_add() {
mkdir -p "$tmp"/etc/runlevels/"$2"
ln -sf /etc/init.d/"$1" "$tmp"/etc/runlevels/"$2"/"$1"
}
tmp="$(mktemp -d)"
trap cleanup EXIT
mkdir -p "$tmp"/etc
makefile root:root 0644 "$tmp"/etc/hostname <<EOF
$HOSTNAME
EOF
makefile root:root 0644 "$tmp"/etc/modules <<EOF
xen_netback
xen_blkback
xenfs
xen-platform-pci
xen_wdt
tun
EOF
mkdir -p "$tmp"/etc/network
makefile root:root 0644 "$tmp"/etc/network/interfaces <<EOF
auto lo
iface lo inet loopback
EOF
mkdir -p "$tmp"/etc/apk
makefile root:root 0644 "$tmp"/etc/apk/world <<EOF
xen
EOF
rc_add devfs sysinit
rc_add dmesg sysinit
rc_add udev sysinit
rc_add hwclock boot
rc_add modules boot
rc_add sysctl boot
rc_add hostname boot
rc_add bootmisc boot
rc_add syslog boot
rc_add udev-postmount default
rc_add xenstored default
rc_add xenconsoled default
rc_add mount-ro shutdown
rc_add killprocs shutdown
rc_add savecache shutdown
tar -c -C "$tmp" etc | gzip -9n > $HOSTNAME.apkovl.tar.gz
-71
View File
@@ -1,71 +0,0 @@
build_rpi_blobs() {
for i in raspberrypi-bootloader-common raspberrypi-bootloader; do
apk fetch --root "$APKROOT" --quiet --stdout "$i" | tar -C "${DESTDIR}" -zx --strip=1 boot/ || return 1
done
}
rpi_gen_cmdline() {
echo "modules=loop,squashfs,sd-mod,usb-storage quiet ${kernel_cmdline}"
}
rpi_gen_config() {
local arm_64bit=0
case "$ARCH" in
aarch64) arm_64bit=1;;
esac
cat <<-EOF
# do not modify this file as it will be overwritten on upgrade.
# create and/or modify usercfg.txt instead.
# https://www.raspberrypi.com/documentation/computers/config_txt.html
kernel=boot/vmlinuz-rpi
initramfs boot/initramfs-rpi
arm_64bit=$arm_64bit
include usercfg.txt
EOF
}
build_rpi_config() {
rpi_gen_cmdline > "${DESTDIR}"/cmdline.txt
rpi_gen_config > "${DESTDIR}"/config.txt
}
section_rpi_config() {
[ "$hostname" = "rpi" ] || return 0
build_section rpi_config $( (rpi_gen_cmdline ; rpi_gen_config) | checksum )
build_section rpi_blobs
}
profile_rpi() {
profile_base
title="Raspberry Pi"
desc="First generation Pis including Zero/W (armhf).
Pi 2 to Pi 3+ generations (armv7).
Pi 3 to Pi 5 generations (aarch64)."
image_ext="tar.gz"
arch="aarch64 armhf armv7"
kernel_flavors="rpi"
kernel_cmdline="console=tty1"
initfs_features="base squashfs mmc usb kms dhcp https"
hostname="rpi"
grub_mod=
}
create_image_imggz() {
sync "$DESTDIR"
local image_size=$(du -L -k -s "$DESTDIR" | awk '{print $1 + 8192}' )
local imgfile="${OUTDIR}/${output_filename%.gz}"
dd if=/dev/zero of="$imgfile" bs=1M count=$(( image_size / 1024 ))
mformat -i "$imgfile" -N 0 ::
mcopy -s -i "$imgfile" "$DESTDIR"/* "$DESTDIR"/.alpine-release ::
echo "Compressing $imgfile..."
pigz -v -f -9 "$imgfile" || gzip -f -9 "$imgfile"
}
profile_rpiimg() {
profile_rpi
title="Raspberry Pi Disk Image"
image_name="alpine-rpi"
image_ext="img.gz"
}
+1 -1
View File
@@ -1,5 +1,5 @@
profile_immich() {
profile_standard
apks="$apks docker docker-compose"
apkovl="scripts/genapkovl-dhcp.sh"
apkovl="utils/gen-overlay.sh"
}
-25
View File
@@ -1,25 +0,0 @@
section_minirootfs() {
return 0
}
create_image_rootfs() {
local _script=$(readlink -f "$scriptdir/genrootfs.sh")
local output_file="$(readlink -f ${OUTDIR:-.})/$output_filename"
(cd "$OUTDIR"; fakeroot "$_script" -k "$APKROOT"/etc/apk/keys \
-r "$APKROOT"/etc/apk/repositories \
-o "$output_file" \
-a $ARCH \
$rootfs_apks)
}
profile_minirootfs() {
title="Mini root filesystem"
desc="Minimal root filesystem.
For use in containers
and minimal chroots."
image_ext=tar.gz
output_format=rootfs
arch="$ARCH" # allow any arch
rootfs_apks="busybox alpine-baselayout alpine-keys alpine-release apk-tools libc-utils"
}
-32
View File
@@ -1,32 +0,0 @@
create_image_netboot() {
rm -rf "${OUTDIR}"/netboot-$RELEASE "${OUTDIR}"/netboot
cp -aL "${DESTDIR}"/boot "${OUTDIR}"/netboot-$RELEASE
ln -s netboot-$RELEASE "${OUTDIR}"/netboot
# let webserver read initramfs
chmod a+r "${OUTDIR}"/netboot-$RELEASE/*
tar -C "${DESTDIR}" -chzf ${OUTDIR}/${output_filename} boot/
}
profile_netboot() {
title="Netboot"
desc="Kernel, initramfs and modloop for
netboot.
"
arch="aarch64 armhf armv7 ppc64le x86 x86_64 s390x"
case "$ARCH" in
armhf) kernel_flavors="rpi";;
armv7) kernel_flavors="lts rpi";;
aarch64) kernel_flavors="lts virt rpi";;
x86_64) kernel_flavors="lts virt";;
*) kernel_flavors="lts";;
esac
case "$ARCH" in
s390x) initfs_features="base network squashfs usb dasd_mod qeth zfcp";;
*) initfs_features="base network squashfs usb virtio"
esac
modloop_sign=yes
apks=""
output_format="netboot"
image_ext="tar.gz"
}
-32
View File
@@ -1,32 +0,0 @@
build_uboot() {
# FIXME: Fix apk-tools to extract packages directly
local pkg pkgs="$(apk fetch --simulate --root "$APKROOT" --recursive u-boot-all | sed -ne "s/^Downloading \(.*\)\-[0-9].*$/\1/p")"
for pkg in $pkgs; do
[ "$pkg" = "u-boot-all" ] || apk fetch --root "$APKROOT" --stdout $pkg | tar -C "$DESTDIR" -xz usr
done
mkdir -p "$DESTDIR"/u-boot
mv "$DESTDIR"/usr/sbin/update-u-boot "$DESTDIR"/usr/share/u-boot/* "$DESTDIR"/u-boot
rm -rf "$DESTDIR"/usr
}
section_uboot() {
[ -n "$uboot_install" ] || return 0
build_section uboot $ARCH $(apk fetch --root "$APKROOT" --simulate --recursive u-boot-all | sort | checksum)
}
profile_uboot() {
profile_base
title="Generic U-Boot"
desc="Has default LTS kernel.
Includes the U-Boot bootloader.
Tarball.
"
image_ext="tar.gz"
arch="aarch64 armv7 riscv64"
kernel_flavors="lts"
case "$ARCH" in
aarch64|armv7) kernel_addons="xtables-addons";;
esac
initfs_features="base ext4 kms mmc nvme phy raid scsi squashfs usb"
uboot_install="yes"
}
-29
View File
@@ -1,29 +0,0 @@
build_xen() {
apk fetch --root "$APKROOT" --stdout xen-hypervisor | tar -C "$DESTDIR" -xz boot
}
section_xen() {
[ -n "${xen_params+set}" ] || return 0
build_section xen $ARCH $(apk fetch --root "$APKROOT" --simulate xen-hypervisor | checksum)
}
profile_xen() {
profile_standard
profile_abbrev="xen"
title="Xen"
desc="Built-in support for Xen Hypervisor.
Includes packages targetted at Xen usage.
Use for Xen Dom0."
arch="x86_64"
kernel_addons="zfs"
xen_params=""
apks="$apks ethtool lvm2 mdadm multipath-tools rng-tools sfdisk xen xen-bridge xen-qemu syslinux zfs"
local _k _a
for _k in $kernel_flavors; do
apks="$apks linux-$_k"
for _a in $kernel_addons; do
apks="$apks $_a-$_k"
done
done
}
+3 -19
View File
@@ -27,8 +27,7 @@ rc_add() {
}
tmp="$(mktemp -d)"
trap cleanup EXIT
tmp="/home/overlay"
mkdir -p "$tmp"/etc
makefile root:root 0644 "$tmp"/etc/hostname <<EOF
@@ -64,25 +63,10 @@ rc_add hostname boot
rc_add bootmisc boot
rc_add syslog boot
rc_add docker boot
rc_add local boot
rc_add mount-ro shutdown
rc_add killprocs shutdown
rc_add savecache shutdown
# copy all directories from overlay/ into $tmp and merge
cp -a /home/overlay/. "$tmp"/
# run docker and docker pull the images
mkdir -p "$tmp"/var/lib/docker
dockerd --data-root "$tmp"/var/lib/docker/ &
sleep 5
docker pull ghcr.io/immich-app/immich-server:release
docker pull ghcr.io/immich-app/immich-machine-learning:release
docker pull docker.io/valkey/valkey:8-bookworm
docker pull ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
pkill docker || true
tar -c -C "$tmp" etc usr var | gzip -9n > $HOSTNAME.apkovl.tar.gz
tar -c -C "$tmp" etc usr var | pigz -9n > "$HOSTNAME.apkovl.tar.gz"
-18
View File
@@ -1,18 +0,0 @@
#!/bin/bash
# Array of Docker image tags
images=(
"ghcr.io/immich-app/immich-server:v1.137.3"
"ghcr.io/immich-app/immich-machine-learning:v1.137.3"
"docker.io/valkey/valkey:8-bookworm"
"ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0"
)
# Pull each image sequentially
for img in "${images[@]}"; do
echo "Pulling $img..."
docker pull "$img"
docker save "$img" -o "overlay/usr/app/images/${img//[:\/]/_}.tar"
done
echo "All images pulled successfully."