EN
Docker
A minimal, bootstrappable Slackware64-current container - with slacker as its package manager.
~54MB pull, 195MB on disk, 31 stock packages + slacker. It ships without
gnupg and without a system CA store, and grows itself to full GPG-verified
operation with its first install. Real glibc, real GNU coreutils, real
pkgtools - every official Slackware package installs and runs, resolved by
slacker's resolve-stock from a precomputed dependency database.
docker pull ghcr.io/rizitis/slackware64-current-ci:slacker-very_mini-testing
docker run --rm -it ghcr.io/rizitis/slackware64-current-ci:slacker-very_mini-testing
# or the same image from Docker Hub:
docker run --rm -it rizitis/slackware-slacker:slacker-very_mini-testing
Status: testing. The tag name says so. Built for CI and for exercising slacker on a bare system - not (yet?) a supported production base image.
Why it exists
A full Slackware installation has every stock library already, so official
packages never declare dependencies - they simply assume a complete system.
A container is the opposite: almost nothing is present, for example a naive
installpkg gnupg2-*.txz gives you a binary that cannot load.
This image is the reason slacker grew RESOLVE_STOCK: the container asks for a
package, and slacker pulls exactly what that package needs to run on a bare
system - from data, not guesses. See Dependencies for the .dep side of
resolution; stock deps are a separate, optional layer on top.
What is inside
The 31 stock packages, chosen from the real dependency graph (not guessed):
| group | packages |
|---|---|
| base | aaa_glibc-solibs aaa_libraries aaa_base etc bash |
| GNU tools (pkgtools need them) | coreutils findutils gawk grep sed gzip tar xz file |
| package handling | pkgtools util-linux |
| libraries the above load | ncurses readline zlib bzip2 acl attr libcap gmp mpfr pcre2 zstd lz4 lzlib |
| comfort | nano less |
plus the slacker package itself.
Worth knowing:
util-linuxis there forinstallpkg, which needsrevto detect the package compression (without it every install fails with "external compression utility missing"). Some other util-linux tools (su,login,mount) lack their libraries until you install them - irrelevant in a container, andresolve-stockbrings them if ever needed.lessis there forslacker show-changelog- without a pager the whole ChangeLog would dump to the terminal. (PAGERis respected, andmorefrom util-linux also works:PAGER=more slacker show-changelog.)- No gnupg, no ca-certificates, no openssl. slacker's TLS is rustls with
the Mozilla roots compiled into the binary -
lddon slacker shows only glibc. The mirror's certificate is verified without any system CA store, and gnupg2 arrives in the bootstrap below.
Preconfigured in /etc/slacker/slacker.conf, /etc/slacker/mirrors and
/etc/slacker/blacklist:
VERIFY=md5
RESOLVE_STOCK=yes
STOCK_DB_URL=https://raw.githubusercontent.com/rizitis/Slackware64-Current-sofiles/main
VERIFY=md5 is required at first boot: the default VERIFY=all refuses to
work without a gpg binary, and the image ships none - yet.
# --- UNITED KINGDOM (UK) ---------------------------------------------------
https://slackware.uk/slackware/slackware64-current/
This is the preconfigured default slackware64-current mirror - replace it with
your own at any time (slacker find-mirror lists the fastest ones).
The 31 base packages are also blacklisted by default - they are frozen: no
slacker operation (remove, remove-template, clean-system, upgrade replacing
them with another repo's build) will ever touch the image's foundation. The
only way to remove one is a manual removepkg - which you should not do, it
breaks the container. See Blacklist for how the mechanism works; edit
/etc/slacker/blacklist if you really know better.
The bootstrap
The image is born small and arms itself. In order - steps 2-4 are optional: they upgrade the default md5-only verification to full GPG:
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#161b22','primaryBorderColor':'#1f6feb','primaryTextColor':'#e6edf3','lineColor':'#6e7781','fontFamily':'monospace'}}}%%
flowchart LR
A["update<br/>(md5 + stock-db)"] --> B["install gnupg2<br/>(15 pkgs via closure)"]
B --> C["update gpg<br/>(TOFU key pin)"]
C --> D["VERIFY=all"]
D --> E["full GPG<br/>forever after"]
classDef blue fill:#0d1117,stroke:#1f6feb,color:#e6edf3;
classDef green fill:#0d1117,stroke:#2ea043,color:#e6edf3;
class A,B,C,D blue
class E green
# 0) OPTIONAL: pick a faster mirror and replace the stock one - exactly ONE
# line must be uncommented in /etc/slacker/mirrors
slacker find-mirror
nano /etc/slacker/mirrors
# 1) metadata + the stock dependency database, md5-verified over HTTPS
slacker update
# 2) OPTIONAL: gnupg2 + its whole crypto chain (15 packages, not 300 - see below)
slacker install gnupg2
# 3) OPTIONAL: pin the Slackware signing key (trust-on-first-use - see the Security wiki page)
slacker update gpg
# 4) OPTIONAL: full signature verification from now on
nano /etc/slacker/slacker.conf # VERIFY=md5 -> VERIFY=all
# 5) Doctor: Checking your setup.
slacker status
# 6) Update repository metadata
slacker update
After step 4 the container verifies every package's GPG signature exactly like a full installation. The md5 window exists only between first boot and step 3, and even inside it every transfer is HTTPS against rustls' pinned roots plus md5 integrity - the trust model is "the official mirror, over verified TLS", upgraded to "the Slackware signing key" as soon as gpg exists.
Non-interactive use (CI / workflows)
Every prompt slacker asks - the update repo selection, the install plan's
y/N, the multi-match picker - is auto-accepted with --yes. That is what CI
pipelines and Dockerfiles want:
slacker --yes update
slacker --yes install gnupg2
slacker --yes update gpg
One-shot example (a workflow step or a RUN line):
docker run --rm ghcr.io/rizitis/slackware64-current-ci:slacker-very_mini-testing \
bash -c "slacker --yes update && slacker --yes install gnupg2"
--dry-run still works with it if you only want the plan printed.
More options and all 39 actions: slacker --help - and see Commands for
the full reference.
Stock dependency resolution
slacker status shows the extra row when RESOLVE_STOCK=yes:
✓ Stock-db present, valid, in sync with -current
The database (depgraph.db, from
Slackware64-Current-sofiles)
ships a precomputed closure table: for every stock package, what it needs
to run on a bare system. It is computed from the real ELF files - level 1 is
the whole package's own NEEDED plus its runtime hints; deeper levels follow
only the NEEDED chains of libraries, i.e. exactly what the dynamic loader
would pull. Tool-only dependencies of other packages never cascade in:
glibc's memusagestat links libgd, gnupg2's dirmngr links openldap, and a
naive graph walk through such edges drags in half the distribution (~300
packages for gnupg2 - measured). The closure stops where the loader stops.
Real numbers from this image, all verified live:
slacker install ... |
packages pulled | result |
|---|---|---|
gnupg2 |
15 (gnutls, nettle, libgcrypt, sqlite, icu4c, ...) | runs, verifies |
ffmpeg |
66 (codecs, X/VA/VD, SDL2 - all genuine NEEDED) |
loads |
xsnow |
37 (the whole GTK3 stack) | loads, snows over X11 |
slacker itself stays dumb on purpose: one SELECT on the closure table, no
graph-walking, no guessing - the repository's data is the resolver. With
RESOLVE_STOCK=no (the default outside this image) nothing changes anywhere.
Templates: a build environment in one command
The slacker inside this image ships 36 curated templates - plain-text
package lists (one name per line, plus include <template> lines) that turn
the minimal container into a ready build environment with a single command.
Combined with resolve-stock, every package a template names arrives with its
full runtime closure - so install-template cargo really does leave you with a
working Rust toolchain, not a pile of unlinkable binaries. See Templates
for the general feature reference; this section is about how they are used (and
curated) in the container.
The four commands:
generate-template Snapshot installed packages into a template
install-template Install all packages listed in a template
remove-template Remove all packages listed in a template
delete-template Delete a template file (does not touch installed packages)
What ships, by family:
| family | templates |
|---|---|
| toolchain base | base (gcc, binutils, glibc, kernel-headers, make, pkgconf, patch, diffutils, which) |
| build systems | autotools cmake meson cargo |
| languages | ada cxx d fortran go lua nodejs objc perl php python ruby tcl vala |
| stacks | gtk qt5 qt6 llvm kernel |
| SlackBuilds.org build sets | sbo_autotools sbo_cargo sbo_cmake sbo_go sbo_haskell sbo_meson sbo_perl sbo_python sbo_rubygem |
| misc | docs extras vcs |
Typical CI usage - a Rust build job on this image is literally:
docker run --rm ghcr.io/rizitis/slackware64-current-ci:slacker-very_mini-testing \
bash -c "slacker --yes update && slacker --yes install-template cargo && cargo build --release"
Most language templates start with include base - installing go gives you
the Go compiler and the C toolchain underneath it, because that is what
building software needs. Includes resolve recursively; a template only lists
what is specific to it.
How the container templates are curated - and why it matters: no template
in this image references ANY of the 31 base packages. That is deliberate, and
it is a safety rule, not tidiness: remove-template removes everything a
template names, following its includes. An early version of base listed
file, tar, coreutils and friends - so remove-template go (which
includes base) stripped them out of the running container and broke it. The
fix lives in the data, where slacker's philosophy says it belongs: templates
describe what they ADD on top of the image, never the image itself. If you
write your own templates for this container, follow the same rule.
And there is a second, independent safety layer: the 31 base packages ship blacklisted (see above), so even a template that DOES name one of them cannot make slacker remove it - the blacklist wins. Belt and suspenders: the curation keeps templates honest, the blacklist keeps the foundation standing even against a dishonest one.
Two behaviours worth knowing before you script around them:
remove-templatefollows includes.remove-template goremoves google-go-lang AND the wholebasetoolchain (gcc, make, ...). In a CI container that is usually exactly what you want - "tear down the build environment" - but if you built several environments on top ofbase, removing one tears the shared foundation from under the others. Remove the leaf templates last, or just throw the container away (--rmdoes it for you).generate-templatesnapshots the container. After hand-installing a working set,slacker generate-template mystackwrites it as a reusable list - drop it in/etc/slacker/templates/of your own image build and your environment is reproducible.
All template commands honor --yes, so they are workflow-safe.
Running X11 programs (but, hey do you need X in a slackware docker image?)
The container has no display. To show windows on the host's desktop (X11 or Wayland via XWayland):
# on the host, once:
xhost +local:docker
docker run --rm -it \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
ghcr.io/rizitis/slackware64-current-ci:slacker-very_mini-testing bash
# inside:
slacker update
slacker install xsnow # pulls the GTK3 stack (37 packages)
xsnow # ❄
Add --device /dev/dri for GPU acceleration. Revoke access afterwards with
xhost -local:docker.
Building the image yourself
The build script lives in its own repository:
slackware64-current-ci.
It needs:
- a local Slackware64-current tree (rsync mirror) - set
SLACKWARE_TREEat the top of the script; - the slacker binary package (
slacker-*.txz) in aBINS/folder next to the script - build it from source first, see Installation; dockerand root (the script usesinstallpkg --rootinto a scratch rootfs).
sudo bash slacker-docker.sh
The script installs the 31 packages into a scratch rootfs with
installpkg --root, installs everything from BINS/, writes the bootstrap
config, strips docs/man/info and locales (~15MB), produces a single-layer
FROM scratch image, and (optionally - uncomment the push lines) publishes it
to GHCR / Docker Hub.
Two build details that cost real debugging time, recorded here so nobody repeats them:
- Use
installpkg --root, notupgradepkg --root, for a fresh rootfs.upgradepkg --install-new --reinstall --rootfails silently on an empty root - the log claims success, the rootfs stays empty. - The build host's tools are not the container's tools.
installpkgworks during the build (it runs on the host, which hasrev) and then fails inside the container ifutil-linuxis missing. Test installs in the container, not just the build.
FAQ
Why is the image 195MB when alpine is 8MB?
Alpine is musl + busybox - a different world, binary-incompatible with
Slackware packages. This image is genuine Slackware: real glibc (~35MB by
itself), real GNU userland, and aaa_libraries (~30MB), which is what lets the
closure table resolve libstdc++/zlib/readline needs to the always-present
base bundle instead of dragging in gcc-g++. For comparison: debian-slim ~75MB,
fedora ~180MB - and no other Slackware image is both this small and able to
install the whole distribution correctly.
slacker install fails with "external compression utility missing".
Your image predates util-linux in the package list (installpkg needs its
rev). Rebuild with the current script.
show-changelog dumps everything.
No pager found. slacker install less, or PAGER=more slacker show-changelog
(more ships in util-linux).
Can I skip the bootstrap and stay on md5? Yes - it keeps working. You are trusting HTTPS (rustls pinned roots) plus the official mirror's checksums instead of the Slackware signing key. For anything beyond throwaway CI, do the three extra commands.
Does RESOLVE_STOCK=yes change slacker's behaviour on my real machine?
On a full installation every stock dep is already installed, so the plan shows
nothing new - it is effectively a no-op there. The feature earns its keep
exactly here, on bare systems.
slacker is free software under the Apache License 2.0, by Ioannis Anagnostakis (rizitis). Sources: https://forge.slackware.nl/rizitis/slacker.
slacker
Getting started
Using slacker
- Commands
- Common Workflows
- Distribution Upgrade
- Repositories and Priority
- Package History
- Dependencies
- Docker
- Templates
- Blacklist
Trust & safety
Reference
For contributors
slacker - slackpkg + slackpkg+ in one - Apache-2.0 - by Ioannis Anagnostakis (rizitis) - beta / WIP, for Slackware -current (64-bit & 32-bit)