# syntax=docker/dockerfile:1
FROM ubuntu:22.04

# Base image is ubuntu, not alpine, because wal-g v3.x stopped publishing
# alpine-musl prebuilt binaries — only ubuntu glibc builds remain. We need
# wal-g v3+ for the current S3 + Postgres 16 wire protocol support.

ENV DEBIAN_FRONTEND=noninteractive

# Install PostgreSQL 16 client + utilities. PG 16 isn't in the default
# ubuntu 22.04 repos; pull it from the postgresql apt repo. AWS CLI is
# installed as the standalone v2 binary further down (the apt-shipped
# `awscli` is v1 and pulls ~500MB of Python deps; v2 is ~80MB self-
# contained and the only version AWS itself supports for new code).
#
# apt cache mount: keeps /var/cache/apt populated across rebuilds so
# `apt-get install` reuses .deb files. The cache lives outside the layer,
# so we don't need the historical `rm -rf /var/lib/apt/lists/*` to keep
# the final image small — that's still done below as a belt-and-braces
# measure for cases where the cache mount isn't honored (e.g. legacy
# `docker build` without BuildKit).
# `sharing=locked` serializes parallel builds against the same cache
# (apt's lock semantics expect exclusive access).
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
    --mount=type=cache,target=/var/lib/apt,sharing=locked \
    apt-get update && apt-get install -y --no-install-recommends \
        ca-certificates curl gnupg lsb-release \
        bash tar gzip unzip && \
    install -d /usr/share/postgresql-common/pgdg && \
    curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \
        -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc && \
    echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt jammy-pgdg main" \
        > /etc/apt/sources.list.d/pgdg.list && \
    apt-get update && apt-get install -y --no-install-recommends \
        postgresql-client-16

# Install AWS CLI v2 standalone binary (~80MB) instead of `apt-get install
# awscli` (v1 with ~500MB of Python/boto3 deps). Saves ~400MB on the
# final image, which matters because the backup image is sideloaded to
# every k3s node (~6 nodes in HA = ~2.4GB less network per deploy).
# --fail makes curl exit non-zero on HTTP 4xx/5xx instead of piping a
# 404 HTML body into unzip.
RUN curl -fL https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip \
        -o /tmp/awscli.zip && \
    unzip -q /tmp/awscli.zip -d /tmp && \
    /tmp/aws/install --bin-dir /usr/local/bin --install-dir /usr/local/aws-cli && \
    rm -rf /tmp/aws /tmp/awscli.zip

# Install WAL-G v3.0.5 (ubuntu 22.04 amd64 build).
# --fail makes curl exit non-zero on HTTP 4xx/5xx instead of piping a 404
# HTML body into tar (the previous v3.0.3-alpine URL 404'd, tar saw "<html>"
# and errored "not in gzip format" — observed 2026-04-26 matrix run #2).
RUN curl -fL https://github.com/wal-g/wal-g/releases/download/v3.0.5/wal-g-pg-ubuntu-22.04-amd64.tar.gz \
        | tar -xz && \
    mv wal-g-pg-ubuntu-22.04-amd64 /usr/local/bin/wal-g && \
    chmod +x /usr/local/bin/wal-g

# Security: non-root system user. We can't reuse the name `backup` —
# ubuntu pre-populates a `backup` system group (GID 34, used for system
# backup operations) and `groupadd backup` errors with exit 9 ("group
# 'backup' already exists"). The previous alpine version sidestepped
# this because alpine doesn't ship the same default. Use a unique name
# (`vbbackup`) and let --system pick a free system GID/UID.
# The k8s manifest doesn't pin runAsUser so any UID works.
RUN groupadd --system vbbackup && \
    useradd --system -g vbbackup -s /usr/sbin/nologin -M vbbackup

# Copy backup script
COPY backup.sh /usr/local/bin/backup.sh
RUN chmod +x /usr/local/bin/backup.sh

USER vbbackup

# CronJob handles scheduling — script runs once and exits
ENTRYPOINT ["/usr/local/bin/backup.sh"]
