Skip to content

Instantly share code, notes, and snippets.

@ScottJWalter
Last active April 20, 2025 22:06
Show Gist options
  • Save ScottJWalter/9ec839590f20fd4ac36d3432347a4548 to your computer and use it in GitHub Desktop.
Save ScottJWalter/9ec839590f20fd4ac36d3432347a4548 to your computer and use it in GitHub Desktop.
Install 32-bit docker on rpi (3, etc.)
#!/bin/bash
set -e
########################################
# 🧭 Configuration #
########################################
ARCH="$(dpkg --print-architecture)"
VERSION_CODENAME="$(grep -oP '(?<=\bVERSION_CODENAME=)[^;]+' /etc/os-release)"
URL="https://download.docker.com/linux/raspbian/dists/${VERSION_CODENAME}/pool/stable/${ARCH}/"
DOWNLOAD_DIR="${HOME}/.downloads/docker"
PATTERNS="^(containerd\.io|docker\-ce|docker\-ce\-cli|docker\-buildx\-plugin|docker\-compose\-plugin)_.*_${ARCH}\.deb$"
########################################
# 🧾 Functions #
########################################
print_help() {
cat <<EOF
Usage: $0 [options]
Options:
--dry-run Show which files would be downloaded
--no-log Skip logging to a file
--clean Remove existing Docker packages before installing
--quiet Suppress non-essential output
--debug Enable debug messages
--help Show this help message and exit
EOF
}
parse_flags() {
DRY_RUN=false
NO_LOG=false
CLEAN_FIRST=false
QUIET=false
DEBUG=false
for arg in "$@"; do
case "$arg" in
--dry-run) DRY_RUN=true ;;
--no-log) NO_LOG=true ;;
--clean) CLEAN_FIRST=true ;;
--quiet) QUIET=true ;;
--debug) DEBUG=true ;;
--help) print_help; exit 0 ;;
esac
done
}
log() {
if ! $QUIET; then
echo "$@"
fi
}
log_debug() { if $DEBUG; then echo "🐞 DEBUG: $1"; fi }
log_info() { log "ℹ️ $1"; }
log_warn() { log "⚠️ $1"; }
log_error() { echo "❌ $1" >&2; }
log_success() { log "βœ… $1"; }
run_test_stub() {
log_info "Running test stub: $1"
return 0
}
run_all_tests() {
run_test_stub "parse_flags"
run_test_stub "enable_logging"
run_test_stub "clean_existing_docker"
run_test_stub "prepare_download_dir"
run_test_stub "fetch_file_list"
run_test_stub "download_and_verify"
run_test_stub "install_packages"
run_test_stub "final_steps"
}
enable_logging() {
if ! $NO_LOG; then
mkdir -p "$DOWNLOAD_DIR"
LOGFILE="${DOWNLOAD_DIR}/install.log"
exec > >(tee -a "$LOGFILE") 2>&1
fi
}
clean_existing_docker() {
if $CLEAN_FIRST; then
log "🧹 Cleaning existing Docker packages..."
if $DRY_RUN; then
log " DRY-RUN: apt cleaned of docker packages here ..."
else
sudo apt remove -y docker docker-engine docker.io containerd runc docker-ce docker-ce-cli docker-compose-plugin docker-buildx-plugin containerd.io || true
sudo apt autoremove -y
fi
fi
}
prepare_download_dir() {
mkdir -p "$DOWNLOAD_DIR"
find "$DOWNLOAD_DIR" -type f -name '*.deb' -delete
find "$DOWNLOAD_DIR" -type f -name '*.sha256' -delete
}
fetch_file_list() {
log "πŸ“¦ Fetching latest files from: $URL"
log "πŸ“ Download directory: $DOWNLOAD_DIR"
mapfile -t DPKG_FILES < <(
curl -s "$URL" | \
grep -oP '(?<=href=")[^"]+' | \
grep -v '/$' | \
grep -E "$PATTERNS" | \
sort | \
awk -F'_' '
{
base = $1;
files[base] = $0;
}
END {
for (f in files) {
print files[f]
}
}')
if [[ ${#DPKG_FILES[@]} -eq 0 ]]; then
log_warn "No matching files found."
exit 0
fi
}
download_and_verify() {
for file in "${DPKG_FILES[@]}"; do
if $DRY_RUN; then
log "DRY-RUN: $file downloaded here..."
else
log "⬇️ Downloading $file..."
wget -q --show-progress --tries=3 --timeout=15 -O "${DOWNLOAD_DIR}/${file}" "${URL}${file}"
SHA_FILE="${file}.sha256"
log -n "πŸ” Checking for checksum: $SHA_FILE... "
if curl --silent --fail --head "${URL}${SHA_FILE}" > /dev/null; then
log "found."
curl -s "${URL}${SHA_FILE}" -o "${DOWNLOAD_DIR}/${SHA_FILE}"
pushd "$DOWNLOAD_DIR" > /dev/null
if ! sha256sum -c "$SHA_FILE"; then
log_error "Checksum failed for $file!"
exit 1
fi
popd > /dev/null
else
log "not found. Skipping validation."
fi
fi
done
log_success "All downloads complete."
}
install_packages() {
log "πŸ› οΈ Installing..."
pushd "$DOWNLOAD_DIR" > /dev/null
if $DRY_RUN; then
log "DRY-RUN: dpkg -i ${DPKG_FILES[@]/#/./}"
else
if sudo dpkg -i "${DPKG_FILES[@]/#/./}"; then
sudo rm -- "${DPKG_FILES[@]/#/./}"
else
log_error "dpkg install failed. Keeping downloaded files for inspection."
exit 1
fi
fi
popd > /dev/null
}
final_steps() {
log_success "Installation complete."
if ! $DRY_RUN; then
sudo systemctl status docker
if ! id -nG "$USER" | grep -qw docker; then
log "πŸ”§ Adding user '$USER' to docker group..."
sudo groupadd -f docker
sudo usermod -aG docker "$USER"
log_warn "You must log out and log back in for group changes to take effect."
else
log_info "User '$USER' is already in the docker group."
fi
log "πŸš€ All done! Try: 'docker run hello-world' after logging back in."
fi
}
report_summary() {
log_success "Docker components downloaded and installed successfully:"
for f in "${DPKG_FILES[@]}"; do
log_success " - $f"
done
}
########################################
# 🚦 Main Execution #
########################################
parse_flags "$@"
run_all_tests
enable_logging
clean_existing_docker
prepare_download_dir
fetch_file_list
download_and_verify
install_packages
final_steps
report_summary
@ScottJWalter
Copy link
Author

Assembled from various sources, I was looking for a convenient way to get 32-bit docker on a raspberry pi 3. With gpg key updates/expirations/depracations/etc., it's almost impossible to link "older" tech into the auto management system. So, here's a script that pulls the .deb files directly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment