Important: All container images will be migrated to the tar+zstd format.
Older versions of docker do not support tar+zstd!
docker.io installed with apt is still stuck at v20.10, you may need to install docker-ce manually.
| version | release |
|---|---|
| 0.01 ~ 0.90 | 1993-08 ~ 1993-12 |
| 0.91 | 1994-01 |
| 0.93R5 | 1995-03 |
| 0.93R6 | 1995年10月26日 |
| version | codename | created | release | eol |
|---|---|---|---|---|
| 1.1 | Buzz | 1993年08月16日 | 1996年06月17日 | 1997年06月05日 |
| 1.2 | Rex | 1996年06月17日 | 1996年12月12日 | 1998年06月05日 |
| 1.3 | Bo | 1996年12月12日 | 1997年06月05日 | 1999年03月09日 |
| 2.0 | Hamm | 1997年06月05日 | 1998年07月24日 | 2000年03月09日 |
| 2.1 | Slink | 1998年07月24日 | 1999年03月09日 | 2000年10月30日 |
| 2.2 | Potato | 1999年03月09日 | 2000年08月15日 | 2003年06月30日 |
| 3.0 | Woody | 2000年08月15日 | 2002年07月19日 | 2006年06月30日 |
| 3.1 | Sarge | 2002年07月19日 | 2005年06月06日 | 2008年03月31日 |
| 4.0 | Etch | 2005年06月06日 | 2007年04月08日 | 2010年02月15日 |
| 5.0 | Lenny | 2007年04月08日 | 2009年02月14日 | 2012年02月06日 |
| version | codename | created | release | eol | eol-lts | eol-elts |
|---|---|---|---|---|---|---|
| 6.0 | Squeeze | 2009年02月14日 | 2011年02月06日 | 2014年05月31日 | 2016年02月29日 | |
| 7 | Wheezy | 2011年02月06日 | 2013年05月04日 | 2016年04月25日 | 2018年05月31日 | 2020年06月30日 |
| 8 | Jessie | 2013年05月04日 | 2015年04月26日 | 2018年06月17日 | 2020年06月30日 | 2025年06月30日 |
| 9 | Stretch | 2015年04月26日 | 2017年06月17日 | 2020年07月18日 | 2022年06月30日 | 2027年06月30日 |
| 10 | Buster | 2017年06月17日 | 2019年07月06日 | 2022年09月10日 | 2024年06月30日 | 2029年06月30日 |
| 11 | Bullseye | 2019年07月06日 | 2021年08月14日 | 2024年08月14日 | 2026年08月31日 | 2031年06月30日 |
| 12 | Bookworm | 2021年08月14日 | 2023年06月10日 | 2026年06月10日 | 2028年06月30日 | 2033年06月30日 |
| version | codename | created | release |
|---|---|---|---|
| 13 | Trixie | 2023年06月10日 | 2025? |
| 14 | Forky | 2025-08? | 2027? |
| version | codename |
|---|---|
| unstable | Sid |
| experimental | RC-Buggy |
Unlike the Debian Releases unstable and testing, experimental isn't a complete distribution, it can work only as an extension of unstable.
To enable experimental source, run a sid container and then edit the /etc/apt/sources.list.d/mirror.sources file in the container.
See also:
Unlike containers, virtual machine images only support a few newer versions such as jessie, stretch, buster, bullseye, bookworm, and sid.
The primary reason for this is that testing different architectures and versions of virtual machine images is quite exhausting!
Container images even support versions from the last century.
Please feel free to send an issue to tell us which version you are using and which architecture.
DO NOT use PROFANITY or DISCRIMINATORY language in issues!
We're going to probably increase support for the version and the architecture.
Although this isn't the best virtual machine project, nor the most comprehensive, for me, it's the best nogui virtual machine project!
Why not give it a try? You can experience virtual machines for riscv64gc, loongarch64, mipsle, s390x, and other architectures in just a few minutes.
These VM images are built automatically by github actions.
Go to the Releases page and download file that start with vm-.
Files starting with version numbers are container images (e.g., 8_jessie_), not virtual machine images.
Now let's take bookworm x64 (x86_64) as an example.
mkdir -p vm/12/x64 cd vm/12 url='https://github.com/2cd/debian-museum/releases/download/12/vm-minimal_bookworm_x64.tar.zst' # If you don't have aria2 installed, then curl will be used. aria2c -s5 -x5 "$url" || curl -LO "$url" cd x64 tar -xvf ../vm-minimal_bookworm_x64.tar.zst
Unlike other software, where older versions are installed to maintain stability, for qemu, it is recommended to install a newer version (such as 8.2+) instead of the old one.
Alpine
# If the VM is x64 arch: apk add qemu-system-x86_64 # If the VM is arm64 arch: apk add qemu-system-aarch64 # If the VM is rv64 arch: apk add qemu-system-riscv64 # If the VM is loong64 arch: apk add qemu-system-loongarch64
Android Termux
# If the VM is x64 arch: pkg i qemu-system-x86-64-headless # If the VM is arm64 arch: pkg i qemu-system-aarch64-headless
ArchLinux
# If the VM is x64 arch: paru -Sy qemu-system-x86 # If the VM is arm64 arch: paru -S qemu-system-aarch64
Debian, Ubuntu, Kali, Mint, ...
# run apt as root (e.g., sudo-rs apt update)
apt update
apt install qemu-systemThere are other distributions that we haven’t listed one by one. For example, on Fedora, the package name for x64 QEMU is qemu-system-x86. You can use the package manager that comes with your distribution to search for qemu-system and then install the corresponding architecture’s QEMU.
Feel free to explore and set up QEMU based on your distribution!
Please note: Linux Kernel 5.7+ no longer supports arm32 KVM. If you’re using an armv7l device, you can skip this part.
Unfortunately, if your system kernel and CPU don’t support KVM or other acceleration schemes (e.g., xen), virtual machine performance will be quite slow. Some people humorously say that QEMU isn’t Quick at all; it’s more like Slow EMU. However, this is a misconception.
For instance:
On devices that support x64 KVM, using a Debian Sid x64 minimal virtual machine, the boot time is only around 4 seconds. But the same image on Android arm64 takes over a minute to boot. Nevertheless, this is already quite fast and comparable to Alpine Linux.
I’ve experienced running Windows arm64 on a device without arm64 KVM support, and it is not an exaggeration to say that you need to wait for hours.
Add the current user to the kvm user group.
# run it as root (i.e., +sudo/+sudo-rs/+doas) usermod -aG kvm "$(id -un)"
If it does not work, change he permissions manually.
# run it as root
chmod 666 -v /dev/kvmOn most distributions, the package name for zsh is zsh, and you can install it using your system's package manager.
e.g., apt install zsh
For Linux systems other than Android and embedded distributions, you can also download it from the 2moe/zsh-static-docker repository. (Extract tar.zst and get opt/bin/zsh, finally move it to ${XDG_BIN_HOME:~/.local/bin})
It can also be another "PATH", not necessarily
XDG_BIN_HOME.
Install qemu-utils, then run qemu-img.
If you have enough disk space then
+2Gcan be changed to+10G
qemu-img resize disk.img +2G
If unsafe-resize-disk.service (systemd) works correctly, it will automatically resize the partitions to utilize the unallocated space.
The disk partition table is automatically backed up to /var/lib/tmm/bak/sfdisk/ before resizing.
This is a Zsh script that doesn’t require root permissions and won’t automatically create files outside of $PWD or ${0:a:h} (i.e., current_exe()?.parent()) directories.
It’s a bit complex, and in the future, it might be combined with WASI (WebAssembly System Interface) to handle the core logic.
./run || zsh runlocalhost login: root
install OpenSSH client
The ssh package name for debian/ubuntu is
ssh, oropensshin some distributions.
If you don't need sshd, install the ssh client separately.
Open a new terminal session/window, then run:
# run apt as root (i.e., +sudo/+sudo-rs/+doas)
apt install openssh-clientRun it on your host, not VM.
Then check the ./connect-to-ssh script.
SSH is a very important thing. Before running related scripts, you have to make sure there is no malicious code inside!
No matter what, you need to be cautious about this.
cat connect-to-ssh
Finally, connect to SSH.
./connect-to-ssh || zsh connect-to-sshThe following content is prepared for Docker users.
If you want to experience Docker on devices that do not support the Docker kernel, you can use vm-dev_bookworm_x64.tar.zst or vm-dev_bookworm_arm64.tar.zst.
The Dev VM comes pre-installed with Docker, qemu-user-static, and systemd-nspawn.
- RUN IT ON zsh.
- bash is NOT SUPPORTED, NOR is dash
- Just change the values of
ver&arch - What follows may seem complicated, but it's actually quite simple to follow step-by-step.
- Depends:
docker-ce|docker-eezsh(>= 5)
- Recommends:
setopt interactive_comments # On modern Linux distro, running very very old debian containers can be problematic! (e.g., host: 12(bookworm, kernel: 6.x), container: 3.1(sarge), host-arch: amd64, container-arch: amd64) # # versions: 8, 9, 10, 11, 12, 13, sid ver=sid # architectures: "", "riscv64", "rv64", "amd64", "x86_64", "x64", "arm64", "aarch64", "i386", "loong64", "armhf" # The architectures supported by different versions are not exactly the same. # For example, trixie(13) no longer supports mipsle (a.k.a., MIPS 32-bit Little Endian), # sid(unstable) supports more architectures than stable. arch="" # -------------------------- dbg() { print >&2 -Pr "%F{blue}[DEBUG]%f $*" } # if ver.is_empty() if ((! $#ver)) { ver=sid } # Debian sid supports a very large number of architectures, not all of which are listed here. rv64=riscv64 x86=386 x64=amd64 aa64=arm64 local -A oci_arch_map=( # riscv64imafdc rv64gc $rv64 riscv64 $rv64 rv64 $rv64 # x64 $x64 amd64 $x64 x86_64 $x64 # aarch64 $aa64 arm64 $aa64 # loong64 loong64 loongarch64 loong64 # i386 ~ i686 x86 $x86 i386 $x86 i486 $x86 i586 $x86 i686 $x86 # armhf armv7 # In fact, just relying on `uname -m` cannot determine `feature = "+vfp3"` (armhf). # armv7l $armv7 # # armv8m is arm32, not arm64 armv8m armv7 ) # On alpine, if dpkg is installed, it will output musl-linux-[xxx] (e.g., musl-linux-riscv64), not [xxx] (e.g., riscv64). # For busybox, the dpkg it contains is a lite version. Therefore, the value of `deb_arch` may be empty. # If `deb_arch.is_empty()`, use `uname`, not `dpkg`. get_dpkg_architecture() { local dpkg_arch=$(dpkg --print-architecture) # dpkg_arch.split('-').last() local deb_arch=$dpkg_arch[(ws^-^)-1] case $deb_arch { ("") uname -m ;; (*) print $deb_arch ;; } } # if arch.is_empty() if ((! $#arch)) { # arch = if "dpkg".cmd_exists() { dpkg --print-architecture } else { uname -m } arch=$( if (($+commands[dpkg])) { get_dpkg_architecture } else { uname -m } ) } args=( # Run a new container run # Pull image before running ("always"|"missing"|"never") (default "missing") # --pull always # Automatically remove the container when it exits --rm # ( -i ) Keep STDIN open even if not attached --interactive # ( -t ) Allocate a pseudo-TTY --tty # Set environment variables --env # LANG=?, e.g., C.UTF-8, en_US.UTF-8 LANG=$LANG ) # Set timezone env. # # if "timedatectl".cmd_exists() if (($+commands[timedatectl])) { # args.push(docker_tz_env) args+=( --env # TZ=?, e.g., UTC, Asia/[CITY], Europe/[CITY] TZ=$(timedatectl show --property=Timezone --value) ) } # map: oci_arch_map # key: arch # value => platform platform=$oci_arch_map[$arch] # if platform.is_not_empty() if (($#platform)) { args+=( # If you want to run containers from other architectures # (e.g., host: arm64, container: riscv64), # you need to install `qemu-user-static`. --platform linux/$platform ) } case $ver { (sid|unstable) is_sid=true ;; (*) is_sid=false ;; } is_loongarch=false case $platform { # Due to the fact that older versions of Debian (such as Buster) # do not support RISC-V 64-bit architecture, it is defined as "sid" here. # However, this is not accurate. # A more reasonable approach would be to create a `HashMap<version_name, arch_set>` # that corresponds to different versions and architectures, and then # make the determination based on that. (*/riscv64) is_sid=true ;; (*/loong64) is_sid=true is_loongarch=true ;; } repo="ghcr.io/2cd/debian" if {$is_sid} { repo+=-sid } if {$is_loongarch} { repo+=:loong64 } dbg repo: $repo args+=$repo dbg args: $args docker $args
-
+Debian GNU/Hurd VM (a.k.a., Virtual Machine) image
-
+Debian kFreeBSD VM image
-
+ia64 (a.k.a., Intel Itanium architecture) stage1 container image
- Since modern qemu does not support emulation of the ia64, there is only stage1 and no full rootfs.