Run the command:

sudo apt install docker.io

Once installed we check the version:

docker --version

Which in my example returns:

operatorvm@vmrp01ubuntu2004web:~$ docker --version
Docker version 20.10.2, build 20.10.2-0ubuntu1~20.04.2
operatorvm@vmrp01ubuntu2004web:~$

With this we have docker installed, and now we check that the docker service that the installation created is up with:

operatorvm@vmrp01ubuntu2004web:~$ sudo systemctl status docker
[sudo] password for operatorvm:
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2021-06-18 16:27:32 UTC; 9min ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 2894 (dockerd)
      Tasks: 12
     CGroup: /system.slice/docker.service
             └─2894 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Jun 18 16:27:29 vmrp01ubuntu2004web dockerd[2894]: time="2021-06-18T16:27:29.923036084Z" level=warning msg="Your kernel does not support CPU realtime scheduler"
Jun 18 16:27:29 vmrp01ubuntu2004web dockerd[2894]: time="2021-06-18T16:27:29.923142334Z" level=warning msg="Your kernel does not support cgroup blkio weight"
Jun 18 16:27:29 vmrp01ubuntu2004web dockerd[2894]: time="2021-06-18T16:27:29.923240719Z" level=warning msg="Your kernel does not support cgroup blkio weight_device"
Jun 18 16:27:29 vmrp01ubuntu2004web dockerd[2894]: time="2021-06-18T16:27:29.924934723Z" level=info msg="Loading containers: start."
Jun 18 16:27:31 vmrp01ubuntu2004web dockerd[2894]: time="2021-06-18T16:27:31.516281956Z" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address"
Jun 18 16:27:32 vmrp01ubuntu2004web dockerd[2894]: time="2021-06-18T16:27:32.273558433Z" level=info msg="Loading containers: done."
Jun 18 16:27:32 vmrp01ubuntu2004web dockerd[2894]: time="2021-06-18T16:27:32.579292116Z" level=info msg="Docker daemon" commit="20.10.2-0ubuntu1~20.04.2" graphdriver(s)=overlay2 version=20.10.2
Jun 18 16:27:32 vmrp01ubuntu2004web dockerd[2894]: time="2021-06-18T16:27:32.580324456Z" level=info msg="Daemon has completed initialization"
Jun 18 16:27:32 vmrp01ubuntu2004web systemd[1]: Started Docker Application Container Engine.
Jun 18 16:27:32 vmrp01ubuntu2004web dockerd[2894]: time="2021-06-18T16:27:32.918908999Z" level=info msg="API listen on /run/docker.sock"
operatorvm@vmrp01ubuntu2004web:~$

We check the groups assigned to the user with whom we will manage docker in this VM, which is the user operatorvm:

sudo usermod -aG docker operatorvm

And we see that it has assigned the groups 'operatorvm' and 'sudo':

operatorfeitam@vmrp01toolbarcloudweb:~$ groups
operatorfeitam sudo
operatorfeitam@vmrp01toolbarcloudweb:~$

We assign this user the group 'docker' with:

sudo usermod -aG docker operatorvm


and we verify that now the user 'operatorvm' also belongs to the group 'docker':

operatorvm@vmrp01ubuntu2004web:~$ groups
operatorvm sudo docker
operatorvm@vmrp01ubuntu2004web:~$

And it only remains to configure that the docker service is configured to start at startup with the command:

sudo systemctl enable docker

We can now check the operation by executing:

docker run hello-world

which in my case generates the typical (why does it always happen to me) error:

operatorvm@vmrp01ubuntu2004web:~$ docker run hello-world
docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/create: dial unix /var/run/docker.sock: connect: permission denied.
See 'docker run --help'.
operatorvm@vmrp01ubuntu2004web:~$

which is due to the user 'operatorvm' now having the group 'docker', assigned but not having logged in again. Once we are logged in again we check our first hello-world container:

operatorvm@vmrp01ubuntu2004web:~$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
4ee5c797bcd7: Pull complete
Digest: sha256:9f6ad537c5132bcce57f7a0a20e317228d382c3cd61edae14650eec68b2b345c
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.
    (arm32v7)
 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 ambitious, 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/

operatorvm@vmrp01ubuntu2004web:~$

We see that it works by answering 'Hello from docker!'.

We check with 'docker ps -a' that the container is already finished:

operatorvm@vmrp01ubuntu2004web:~$ docker ps -a
CONTAINER ID   IMAGE         COMMAND    CREATED         STATUS                     PORTS     NAMES
b0d7a9cdee61   hello-world   "/hello"   2 minutes ago   Exited (0) 2 minutes ago             exciting_lamarr
operatorvm@vmrp01ubuntu2004web:~$

And with 'docker images' we already have the image:

operatorvm@vmrp01ubuntu2004web:~$ docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    851163c78e4a   17 months ago   4.85kB
operatorvm@vmrp01ubuntu2004web:~$