Robert Važan

Cache pre apt-get v kontajneroch

Kompilujem veľa kontajnerov, tak som sa rozhodol spraviť si cache pre inštalačné súbory, ktoré sťahuje apt v Ubuntu. Chvíľu trvalo, kým som to vyladil. Pre budúcnosť tu opíšem finálne nastavenie.

Prečo mať cache pre apt-get v kontajneroch?

Ak kompilujete štandardný kontajner alebo len zopár súkromných kontajnerov, cache kontajnerových vrstiev pokryje všetky vaše potreby. Ak ste ale ako ja a kompilujete desiatky až stovky súkromných kontajnerov, mať v cache inštalačné súbory z distribúcie sa z viacerých dôvodov stáva veľmi žiaduce. V prípade kontajnerových imidžov postavených na populárnej distribúcii Ubuntu to znamená mať cache pre apt.

Aké sú teda tie dôvody... Po prvé, je očividne neslušné zneužívať servery Ubuntu na opakované sťahovanie tých istých inštalačných súborov niekoľkokrát za deň. Po druhé, sťahovanie môže byť pomalé a nespoľahlivé. Po tretie, lokálna cache poskytuje odolnosť voči (možno aj nepriateľským) výpadkom internetového pripojenia alebo serverov Ubuntu.

Pripravte si svoj Containerfile

Chceme mať v cache stiahnuté súbory z apt tak počas kompilácie imidžu, ako aj neskôr počas behu kontajnera. Chceme, aby bola táto cache z veľkej časti transparentná a nepovinná, aby Containerfile mohol byť vo verejnom projekte bez toho, aby sme nútili ostatných implementovať náš cache systém. Cache služba nakonfigurovaná cez argument pri kompilácii kontajnera je na tento účel ideálna.

Tu je príklad kontajnera, ktorý sa dá voliteľne nakonfigurovať, aby používal cache pre apt:

FROM docker.io/library/ubuntu:24.04

# Voliteľný APT proxy. Ovplyvní kompiláciu aj následný beh kontajnera.
ARG APT_PROXY=""

# Nastavenie neinteraktívneho rozhrania pre apt.
ENV DEBIAN_FRONTEND=noninteractive

# Konfigurácia APT proxy, ak bol proxy špecifikovaný.
RUN if [ -n "$APT_PROXY" ]; then \
        echo "Acquire::http::Proxy \"$APT_PROXY\";" > /etc/apt/apt.conf.d/99proxy; \
    fi

# Na ukážku niečo nainštalujeme, napríklad curl.
RUN apt-get -y update && \
    apt-get -y install curl && \
    apt-get -y clean && \
    rm -rf /var/lib/apt/lists/*

# ...

Všimnite si, že argument APT_PROXY má predvolenú hodnotu, aj keď je to len prázdny reťazec. Tým sa predíde varovaniam o nenastavených argumentoch počas kompilácie. Všimnite si tiež, že pridaním nastavenia proxy do /etc/apt/apt.conf.d/ sa toto nastavenie stane trvalým. Proxy sa bude používať aj počas následného behu kontajnera. Ak chcete cache len počas kompilácie, môžete súbor odstrániť.

Začnime základným scenárom, keď nie je zapnutá žiadna cache. Imidž môžete skompilovať a spustiť ako zvyčajne:

podman build -t localhost/apt-cache-test
podman run -it --rm localhost/apt-cache-test

Containerfile pre cache službu

Použijeme apt-cacher-ng, čo je cache špeciálne navrhnutá pre apt.

FROM docker.io/library/ubuntu:24.04

# Nezabudnite na ca-certificates pre prístup k HTTPS mirrorom.
RUN export DEBIAN_FRONTEND=noninteractive && \
    apt-get -y update && \
    apt-get -y install --no-install-recommends ca-certificates apt-cacher-ng && \
    rm -rf /var/lib/apt/lists/*

# Kontajnerová verzia apt-cacher-ng potrebuje trochu pomôcť s adresárom /run a konfiguráciou.
RUN mkdir -p /run/apt-cacher-ng && \
    chown apt-cacher-ng:apt-cacher-ng /run/apt-cacher-ng && \
    chmod 0755 /run/apt-cacher-ng && \
    sed -i 's/^# *ForeGround: 0/ForeGround: 1/' /etc/apt-cacher-ng/acng.conf && \
    sed -i 's/^# *PassThroughPattern:.*this would allow.*/PassThroughPattern: .* #/' /etc/apt-cacher-ng/acng.conf

EXPOSE 3142

USER apt-cacher-ng

CMD ["/usr/sbin/apt-cacher-ng", "-c", "/etc/apt-cacher-ng"]

Pred použitím musíme imidž skompilovať:

podman build -t localhost/apt-cache

Konfigurácia systemd

Teraz môžeme použiť integráciu podmana so systemd na spustenie imidžu ako služby systemd:

[Unit]
Description=APT caching proxy (apt-cacher-ng)
After=network-online.target
Wants=network-online.target

[Container]
Image=localhost/apt-cache
ContainerName=apt-cache
RunInit=true
Volume=apt-cache-data:/var/cache/apt-cacher-ng:z
PublishPort=127.0.0.1:3142:3142

[Service]
Restart=always

[Install]
WantedBy=default.target

Uložte tento súbor ako ~/.config/containers/systemd/apt-cache.container, dajte o ňom vedieť systemd a reštartujte ho pre prípad, že beží predchádzajúca verzia:

systemctl --user daemon-reload
systemctl --user restart apt-cache

Dáta sa uložia do pomenovaného zväzku (volume) apt-cache-data. Všimnite si, že používame rootless verziu podmana na spustenie služby pod neprivilegovaným účtom. Snažím sa čo najviac vyhýbať kontajnerom, ktoré bežia pod rootom. Zjednodušuje to veci, keď z akéhokoľvek dôvodu chcete použiť bind mount. Aby sa kontajner spustil aj bez prihlásenia používateľa, povoľte pre používateľa lingering:

sudo loginctl enable-linger $USER

Ak všetko funguje, po otvorení http://127.0.0.1:3142/ by ste mali vidieť stránku s nápovedou pre apt-cacher-ng.

Konfigurácia kontajnera, aby používal cache

Na spustenie príkladu, ktorý sme vytvorili na začiatku tohto článku, stačí špecifikovať jeden argument a presmerovať jeden port. Port musí byť presmerovaný počas kompilácie aj počas behu:

podman build \
    -t localhost/apt-cache-test \
    --build-arg APT_PROXY=http://127.0.0.1:3142 \
    --network=pasta:-T,3142
podman run -it --rm \
    --network=pasta:-T,3142 \
    localhost/apt-cache-test

To, že sa cache používa, by ste mali vidieť na stránke http://127.0.0.1:3142/acng-report.html.