Docker

Install Docker and Docker Compose on Void Linux

Most Docker installation guides assume systemd, which leaves Void Linux users translating commands on the fly. Void uses runit as its init system, so enabling and managing services works differently. The good news: Docker is available directly from the Void repositories, and the whole setup takes under five minutes.

Original content from computingforgeeks.com - post 165026

This guide covers installing Docker Engine and Docker Compose on Void Linux, verifying everything works, running a multi-container application with Compose, and managing the Docker service through runit. If you’ve only used systemd before, the runit comparison table near the end will save you some searching.

Tested March 2026 | Void Linux (glibc, x86_64), Docker 29.3.1, Docker Compose v5.1.0

Prerequisites

  • Void Linux (glibc variant, x86_64) with a working network connection
  • Root or sudo access
  • Tested with: Docker 29.3.1, Docker Compose v5.1.0, Containerd 2.2.0

Update the System

Start by updating the xbps package manager itself, then upgrade all installed packages. Void handles these as two separate steps.

sudo xbps-install -u xbps

Once xbps is current, pull in all available upgrades:

sudo xbps-install -Syu

Reboot if the kernel was updated. Otherwise, continue straight to the Docker installation.

Install Docker Engine

Docker ships in the official Void repositories, so no third-party repos are needed.

sudo xbps-install -y docker

This pulls in Docker Engine, containerd, and the CLI tools. Confirm the installed version:

docker --version

The output should show Docker 29.3.1 or newer:

Docker version 29.3.1, build 7e5decf

Enable and Start Docker

Void Linux uses runit instead of systemd. There is no systemctl enable here. To enable and start a service, you create a symlink from /etc/sv/ into /var/service/. Runit picks it up within five seconds and starts the daemon automatically.

sudo ln -s /etc/sv/docker /var/service/docker

Give runit a moment, then check the service status:

sudo sv status docker

You should see the service running with its PID and uptime:

run: docker: (pid 1842) 6s

If Docker fails to create containers later with errors about /run/user/0, create that directory manually. This catches most people off guard on a fresh Void install:

sudo mkdir -p /run/user/0

Verify Docker Installation

The docker info command confirms the engine is running and shows the storage and cgroup configuration:

sudo docker info

Key details from the output:

Client: Docker Engine - Community
 Version:    29.3.1
 Context:    default

Server:
 Server Version: 29.3.1
 Storage Driver: overlayfs
 Cgroup Driver: cgroupfs
 Cgroup Version: 2
 Operating System: Void
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 1.938GiB
 Docker Root Dir: /var/lib/docker

Note the cgroupfs driver. Void does not use systemd, so Docker defaults to cgroupfs v2, which is exactly what you want here.

Now test with the classic hello-world container:

sudo docker run --rm hello-world

The full output confirms Docker can pull images and run containers:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
e6590344b1a5: Pull complete
Digest: sha256:d715f14f9eca81473d9112df50457893aa7a0a5e35d427c9fa9b1fa26a8de2e1
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Install Docker Compose

Docker Compose is also available from the Void repositories. The packaged version is the Python-based Compose v2 plugin.

sudo xbps-install -y docker-compose

Verify the installed version:

docker compose version

The output confirms Compose v5.1.0:

Docker Compose version v5.1.0

Deploy a Multi-Container Application

To put Compose through a real test, create a project with Nginx and MariaDB running together. This is a typical pattern for web applications.

Create a project directory and the Compose file:

mkdir -p ~/compose-demo && cd ~/compose-demo

Open the Compose file for editing:

vi compose.yaml

Add the following configuration:

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    depends_on:
      - db
    restart: unless-stopped

  db:
    image: mariadb:11
    environment:
      MARIADB_ROOT_PASSWORD: S3cur3P@ssw0rd
      MARIADB_DATABASE: appdb
      MARIADB_USER: appuser
      MARIADB_PASSWORD: AppUs3rP@ss
    volumes:
      - dbdata:/var/lib/mysql
    restart: unless-stopped

volumes:
  dbdata:

Bring up both containers in detached mode:

sudo docker compose up -d

Compose pulls the images and starts both services:

[+] Running 3/3
 ✔ Network compose-demo_default  Created
 ✔ Container compose-demo-db-1   Started
 ✔ Container compose-demo-web-1  Started

Check that both containers are running:

sudo docker ps

Both should show “Up” status:

CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                  NAMES
a3f1b2c4d5e6   nginx:alpine   "/docker-entrypoint.…"   12 seconds ago   Up 10 seconds   0.0.0.0:8080->80/tcp   compose-demo-web-1
b7e8f9a0c1d2   mariadb:11     "docker-entrypoint.s…"   12 seconds ago   Up 11 seconds   3306/tcp               compose-demo-db-1

Test the Nginx container with curl:

curl -s http://localhost:8080 | head -5

The default Nginx welcome page confirms the web container is serving traffic:

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

To tear down the stack when finished:

sudo docker compose down

Manage Docker as Non-Root User

Running every Docker command with sudo gets old fast. Add your user to the docker group to run containers without root privileges.

sudo usermod -aG docker $(whoami)

Apply the group membership without logging out:

newgrp docker

Confirm it works by running a container without sudo:

docker run --rm alpine echo "Docker works without sudo"

You should see:

Docker works without sudo

Be aware that anyone in the docker group effectively has root-level access to the host through container mounts. Only add trusted users.

Docker Service Management with Runit

If you’re coming from a systemd-based distro, runit’s approach to service management takes a bit of adjustment. The table below maps common operations between the two.

ActionRunit (Void Linux)systemd Equivalent
Start servicesudo sv start dockersudo systemctl start docker
Stop servicesudo sv stop dockersudo systemctl stop docker
Restart servicesudo sv restart dockersudo systemctl restart docker
Check statussudo sv status dockersudo systemctl status docker
Enable (start at boot)sudo ln -s /etc/sv/docker /var/service/dockersudo systemctl enable docker
Disable (remove from boot)sudo rm /var/service/dockersudo systemctl disable docker
View logssudo cat /var/log/docker/currentsudo journalctl -u docker

Runit Service Gotcha

Runit’s model is simpler than systemd, but there is one behavior that surprises newcomers: creating the symlink into /var/service/ both enables and starts the service immediately. There is no separate “enable” step that waits for the next reboot. Runit scans /var/service/ every five seconds and launches anything new it finds.

The reverse is also true. Removing the symlink with rm /var/service/docker stops the running service and prevents it from starting at boot. This is different from systemd, where systemctl disable only affects boot behavior and does not stop a currently running service.

Troubleshooting

Error: “failed to create temp dir: stat /run/user/0: no such file or directory”

This happens when Docker tries to create a container but the XDG runtime directory doesn’t exist. Void’s rootfs image doesn’t create it automatically. The fix:

sudo mkdir -p /run/user/0

To make it persistent across reboots, add the mkdir to a runit one-shot service or your shell profile.

Docker service shows “down” immediately after enabling

Runit takes a few seconds to pick up a new service symlink. If sv status docker shows down: docker: 0s, normally up, want up right after creating the link, wait 5-10 seconds and check again. The Docker daemon itself needs time to initialize containerd and set up networking. On first start, 10-15 seconds is typical before the socket appears at /var/run/docker.sock.

Docker containers can’t resolve DNS

If containers start but can’t reach the internet, check that /etc/resolv.conf on the host has valid nameservers. Docker inherits the host’s DNS configuration. On Void, if you’re using dhcpcd, the resolv.conf should be populated automatically. For static configurations, make sure you have at least one working nameserver entry.

For Docker setup on other distributions, see Docker on Rocky Linux 10 or Docker on Ubuntu / Debian. If you need a web management UI, Portainer works well with this setup.

Related Articles

Containers Install Docker and Compose on Linux Mint Containers Docker vs CRI-O vs Containerd: Container Runtimes Compared Containers Install Docker and Run Containers on Ubuntu 24.04|22.04 Containers How To Run ERPNext ERP System in Docker Containers

Leave a Comment

Press ESC to close