For setting up rootless Docker on Ubuntu under a new docker-rootless user account.

Setup

Install Docker:

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
 
# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
 
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Create account and set password:

sudo useradd -m -s $(which bash) docker-rootless

Install systemd-container and uidmap,then use machinectl to log in as the new user:

sudo apt update
sudo apt install systemd-container uidmap
sudo machinectl shell docker-rootless@

Enable rootless Docker (as docker-rootless user):

# setup script
dockerd-rootless-setuptool.sh install
 
# enable user service
systemctl --user enable --now docker

Exit the shell / switch back to an account with sudo privs and enable linger so the user’s Docker service will run at startup:

sudo loginctl enable-linger docker-rootless

Usage notes

Daemon

Remarks about directory paths:

  • The socket path is set to $XDG_RUNTIME_DIR/docker.sock by default. $XDG_RUNTIME_DIR is typically set to /run/user/$UID.
  • The data dir is set to ~/.local/share/docker by default. The data dir should not be on NFS.
  • The daemon config dir is set to ~/.config/docker by default. This directory is different from ~/.docker that is used by the client.

Client

You need to specify either the socket path or the CLI context explicitly.

To specify the socket path using $DOCKER_HOST:

export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
docker run -d -p 8080:80 nginx

To specify the CLI context using docker context:

docker context use rootless
> rootless
> Current context is now "rootless"
docker run -d -p 8080:80 nginx

See also: