Omkar Konaraddi

How to run Anki in a container on Ubuntu 26.04

Published on 2026-06-07.

tl;dr — Here's how I run Anki in a locked-down, network-isolated Podman container on Ubuntu 26.04.

Why bother

First, my threat model consists of supply-chain attacks. Anki pulls in a tree of dependencies that I don't audit. I run it in a locked down container without network access. A container isn't a virtual machine and shares the host kernel so it ain't fully isolated but it still raises the bar for an attacker; a compromised dependency can't phone home or read my home directory but a kernel exploit could still break out. If your threat model demands stronger separation, use a VM.

Second, I don't want to pollute my host system with Anki's dependencies.

1. The Containerfile

You'll need Podman installed (sudo apt install podman). Make a directory for the build — I use ~/anki-container/ — and save the Containerfile below into it.

I'm using the Anki launcher (anki-launcher-25.09-linux.tar.zst), downloaded from apps.ankiweb.net. Download it into that same directory, next to the Containerfile.

FROM ubuntu:26.04

RUN apt-get update && apt-get install -y --no-install-recommends \
    libxcb-xinerama0 libxcb-cursor0 libnss3 libxcb-icccm4 libxcb-keysyms1 \
    libglib2.0-0 libgl1 libegl1 \
    libwayland-client0 libwayland-cursor0 libwayland-egl1 \
    libxkbcommon0 libxkbcommon-x11-0 libxkbfile1 \
    libdbus-1-3 libfontconfig1 libfreetype6 \
    libxcb-shape0 libxcb-xkb1 \
    libxfixes3 libxrender1 libxrandr2 libxi6 libxcomposite1 libxdamage1 libxtst6 \
    libasound2t64 libpulse0 libpango-1.0-0 libgssapi-krb5-2 \
    zstd python3 \
    && rm -rf /var/lib/apt/lists/*

COPY anki-launcher-25.09-linux.tar.zst /tmp/
RUN tar -xaf /tmp/anki-launcher-25.09-linux.tar.zst -C /opt/ && \
    rm /tmp/anki-launcher-25.09-linux.tar.zst

# Trigger the launcher's dependency download during the build so everything is
# baked into the image and no network is needed at runtime
RUN cd /opt/anki-launcher-25.09-linux && ./anki --help || true

ENV PATH="/opt/anki-launcher-25.09-linux:$PATH"
ENV QTWEBENGINE_CHROMIUM_FLAGS="--no-sandbox"

ENTRYPOINT ["anki"]

I found that lib* list by launching Anki, reading each cannot open shared object file error, and adding the package that provides it until it ran. (I had Claude Code run the loop.)

The ./anki --help line runs the launcher at build time. The launcher downloads Anki's Python virtual environment, and because it runs during the build, that environment gets baked into the image. The build needs network but the container doesn't.

The QTWEBENGINE_CHROMIUM_FLAGS="--no-sandbox" is needed because Anki runs as root inside the container and its embedded Chromium refuses to start as root with its sandbox on (likely to discourage running as root, which would render the sandbox largely useless anyway). This removes an inner layer of defense, but the outer boundary is strong: I run Podman rootless (so in-container root is just my unprivileged host user) and the container is locked down (--network=none, --read-only, --cap-drop ALL). You could go a step further and run Anki as a non-root user so Chromium keeps its sandbox, but I think this is plenty good enough.

Next, build the container:

$ podman build -t anki-local ~/anki-container/

2. The run script

The security properties live here, not in the image. I keep this as ~/.local/bin/anki-container:

#!/bin/bash

args=(
  --rm

  # Fixed name keeps it to a single running instance
  --name anki

  --network=none
  --security-opt no-new-privileges
  --cap-drop ALL
  --read-only

  # Anki extracts .colpkg/.apkg here on import/export
  --tmpfs /tmp:rw,noexec,nosuid,size=100m

  # Qt/Mesa shader cache — without it, shaders recompile every launch
  --tmpfs /root/.cache:rw,noexec,nosuid,size=50m

  # Wayland instead of X11, for display isolation
  -e ANKI_WAYLAND=1
  -e WAYLAND_DISPLAY="$WAYLAND_DISPLAY"
  -e XDG_RUNTIME_DIR="/run/user/$(id -u)"

  # Mount the host's Wayland socket read-only so Anki can draw windows
  -v "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY:/run/user/$(id -u)/$WAYLAND_DISPLAY:ro"

  # My Anki collection (cards, media, backups) — persistent
  -v "$HOME/.local/share/anki-container:/root/.local/share/Anki2:rw,noexec,nosuid"

  # A folder to move .colpkg/.apkg files in and out of the sealed container
  -v "$HOME/anki-transfer:/root/transfer:rw,noexec,nosuid"
)

exec podman run "${args[@]}" anki-local "$@"

Make it executable with chmod +x ~/.local/bin/anki-container and create the two host directories it mounts: mkdir -p ~/.local/share/anki-container ~/anki-transfer.

Now anki-container launches Anki. You'll see some harmless warnings on the way up — Mesa complaining there's no GPU, and Anki's update check failing because there's no network. Both are expected. The Mesa warning just means Anki renders on the CPU instead of the GPU — this setup doesn't give the container GPU access. It's fine for an app like Anki.

3. Importing and exporting decks

The container is sealed, so the transfer folder is the only way files cross in or out. To import, drop the .colpkg (or .apkg) into ~/anki-transfer on the host, then in Anki go to File → Import and pick it from /root/transfer. To export, save the file into /root/transfer from Anki's export dialog and grab it from ~/anki-transfer on the host.

4. Making it feel like an app

Running a command is fine, but I wanted Anki in my app list with the right icon. Create ~/.local/share/applications/anki-container.desktop:

[Desktop Entry]
Name=Anki (Container)
Exec=/home/YOUR_USERNAME/.local/bin/anki-container
Icon=anki-container
Type=Application
Categories=Education;
Comment=Anki in a network-isolated Podman container
StartupWMClass=anki

Replace YOUR_USERNAME with your actual username — .desktop files don't expand ~ or $HOME, so the Exec= path has to be absolute.

The icon is bundled inside the image, so pull it out and install it where the icon theme expects it:

$ mkdir -p ~/.local/share/icons/hicolor/256x256/apps/
$ podman create --name anki-tmp anki-local
$ podman cp anki-tmp:/opt/anki-launcher-25.09-linux/anki.png \
    ~/.local/share/icons/hicolor/256x256/apps/anki-container.png
$ podman rm anki-tmp
$ update-desktop-database ~/.local/share/applications/

That's it. Now you can search and launch Anki like it's a regular desktop app.