ROS container with ctr command

### Background

[kubernetes dockershim will be removed in upcoming v1.24](https://kubernetes.io/blog/2022/01/07/kubernetes-is-moving-on-from-dockershim/).
When dockershim is removed, it will not be doable using `docker` command to check the localhost containers.
`docker` command is not necessary in kubernetes aspect since `kubectl exec` will take care of the same operation using CRI(Container Runtime Interface), but developer tends to debug localhost container with `docker` command to see if what is going on in the specific container.

So let's,

- play with `ctr` command that comes with `containerd`.
- control ROS 2 container with `ctr` as example.


### `ctr` command

- It is still unsupported debug and administrative CLI...

```bash
NAME:
   ctr - 
        __
  _____/ /______
 / ___/ __/ ___/
/ /__/ /_/ /
\___/\__/_/

containerd CLI


USAGE:
   ctr [global options] command [command options] [arguments...]

VERSION:
   1.5.5-0ubuntu3~20.04.2

DESCRIPTION:
   
ctr is an unsupported debug and administrative client for interacting
with the containerd daemon. Because it is unsupported, the commands,
options, and operations are not guaranteed to be backward compatible or
stable from release to release of the containerd project.
```

- download image and list

```bash
tomoyafujita@~/DVT >sudo ctr image pull docker.io/library/hello-world:latest
docker.io/library/hello-world:latest:                                             resolved       |++++++++++++++++++++++++++++++++++++++| 
index-sha256:bfea6278a0a267fad2634554f4f0c6f31981eea41c553fdf5a83e95a41d40c38:    done           |++++++++++++++++++++++++++++++++++++++| 
manifest-sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4: done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:2db29710123e3e53a794f2694094b9b4338aa9ee5c40b930cb8063a1be392c54:    done           |++++++++++++++++++++++++++++++++++++++| 
config-sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412:   done           |++++++++++++++++++++++++++++++++++++++| 
elapsed: 2.2 s                                                                    total:  5.4 Ki (2.5 KiB/s)                                       
unpacking linux/amd64 sha256:bfea6278a0a267fad2634554f4f0c6f31981eea41c553fdf5a83e95a41d40c38...
done: 68.620298ms	

tomoyafujita@~/DVT >sudo ctr images list
REF                                  TYPE                                                      DIGEST                                                                  SIZE    PLATFORMS                                                                                                                           LABELS 
docker.io/library/hello-world:latest application/vnd.docker.distribution.manifest.list.v2+json sha256:bfea6278a0a267fad2634554f4f0c6f31981eea41c553fdf5a83e95a41d40c38 6.9 KiB linux/386,linux/amd64,linux/arm/v5,linux/arm/v7,linux/arm64/v8,linux/mips64le,linux/ppc64le,linux/riscv64,linux/s390x,windows/amd64 -      
```

- run container and start application

```bash
tomoyafujita@~/DVT >sudo ctr container create docker.io/library/hello-world:latest demo

tomoyafujita@~/DVT >sudo ctr container list
CONTAINER    IMAGE                                   RUNTIME                  
demo         docker.io/library/hello-world:latest    io.containerd.runc.v2    

tomoyafujita@~/DVT >sudo ctr task start demo

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.
    (amd64)
 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/
```

- remove container

```bash
tomoyafujita@~/DVT >sudo ctr container list
CONTAINER    IMAGE                                   RUNTIME                  
demo         docker.io/library/hello-world:latest    io.containerd.runc.v2    

tomoyafujita@~/DVT >sudo ctr container rm demo

tomoyafujita@~/DVT >sudo ctr container list
CONTAINER    IMAGE    RUNTIME    
```

- debug container (with busybox image)

```bash
tomoyafujita@~/DVT >sudo ctr i pull docker.io/library/busybox:latest
docker.io/library/busybox:latest:                                                 resolved       |++++++++++++++++++++++++++++++++++++++| 
index-sha256:caa382c432891547782ce7140fb3b7304613d3b0438834dce1cad68896ab110a:    done           |++++++++++++++++++++++++++++++++++++++| 
manifest-sha256:14d4f50961544fdb669075c442509f194bdc4c0e344bde06e35dbd55af842a38: done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:554879bb300427c7301c1cbdf266a7eba24a85b10d19f270b3d348b9eb9ca7df:    done           |++++++++++++++++++++++++++++++++++++++| 
config-sha256:2fb6fc2d97e10c79983aa10e013824cc7fc8bae50630e32159821197dda95fe3:   done           |++++++++++++++++++++++++++++++++++++++| 
elapsed: 2.2 s                                                                    total:  4.2 Ki (1.9 KiB/s)                                       
unpacking linux/amd64 sha256:caa382c432891547782ce7140fb3b7304613d3b0438834dce1cad68896ab110a...
done: 80.719287ms	

tomoyafujita@~/DVT >sudo ctr container create  docker.io/library/busybox:latest busyboxdemo

tomoyafujita@~/DVT >sudo ctr container list
CONTAINER      IMAGE                               RUNTIME                  
busyboxdemo    docker.io/library/busybox:latest    io.containerd.runc.v2    

tomoyafujita@~/DVT >sudo ctr task start -d busyboxdemo

tomoyafujita@~/DVT >sudo ctr task list
TASK           PID      STATUS    
busyboxdemo    35058    RUNNING

tomoyafujita@~/DVT >sudo ctr task exec -t --exec-id bashdemo busyboxdemo sh
/ # ls
bin   dev   etc   home  proc  root  run   sys   tmp   usr   var
/ # whoami
root
/ # exit

tomoyafujita@~/DVT >sudo ctr task rm -f busyboxdemo
WARN[0000] task busyboxdemo exit with non-zero exit code 137 

tomoyafujita@~/DVT >sudo ctr task list
TASK    PID    STATUS    

tomoyafujita@~/DVT >sudo ctr container list
CONTAINER      IMAGE                               RUNTIME                  
busyboxdemo    docker.io/library/busybox:latest    io.containerd.runc.v2    

tomoyafujita@~/DVT >sudo ctr container delete busyboxdemo

tomoyafujita@~/DVT >sudo ctr container list
CONTAINER    IMAGE    RUNTIME    
```


### Iterate with Docker Container (ros:rolling)

- start docker ros:rolling container

```bash
tomoyafujita@~/DVT >docker pull ros:rolling
rolling: Pulling from library/ros
...

tomoyafujita@~/DVT >docker run -it --privileged --network host --name ros2_rolling -e DISPLAY=unix$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix -v /home/tomoyafujita/DVT/docker_ws:/root/docker_ws ros:rolling

tomoyafujita@~/DVT >docker ps
CONTAINER ID   IMAGE         COMMAND                  CREATED             STATUS             PORTS     NAMES
7900668f4e07   ros:rolling   "/ros_entrypoint.sh …"   About an hour ago   Up About an hour             ros2_rolling
```

- Docker images cannot be managed via `ctr`
  Not really sure about details, but storage and APIs are different between docker and ctr, so that they cannot cross-manage each other.

- `containerd-shim` uses namespace and id for each container initiated by docker.


```bash
tomoyafujita@~/DVT >sudo ctr container list
CONTAINER    IMAGE    RUNTIME    
(we cannot see any container runtime)

tomoyafujita@~/DVT >ps -ef | grep containerd-shim
root       17136       1  0 16:14 ?        00:00:00 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 7900668f4e07706c18328ef66037a8a93a86e254b0d2547b93c747b2646f1411 -address /run/containerd/containerd.sock
(we can see it uses namespace moby)

tomoyafujita@~/DVT >sudo ctr -n moby container list
CONTAINER                                                           IMAGE    RUNTIME                  
7900668f4e07706c18328ef66037a8a93a86e254b0d2547b93c747b2646f1411    -        io.containerd.runc.v2    

(and this container id is printed as docker container id)

tomoyafujita@~/DVT >docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED             STATUS             PORTS     NAMES
7900668f4e07   ros:rolling            "/ros_entrypoint.sh …"   About an hour ago   Up About an hour             ros2_rolling
^^^^^^^^^^^^ HERE
```

- debug ros:rolling container

```bash
tomoyafujita@~/DVT >sudo ctr -n moby task list
TASK                                                                PID      STATUS    
7900668f4e07706c18328ef66037a8a93a86e254b0d2547b93c747b2646f1411    17164    RUNNING

tomoyafujita@~/DVT >sudo ctr -n moby task exec -t --exec-id bashdemo 7900668f4e07706c18328ef66037a8a93a86e254b0d2547b93c747b2646f1411 bash

root@tomoyafujita-HP-Compaq-Elite-8300-SFF:/# source /opt/ros/rolling/setup.bash 
root@tomoyafujita-HP-Compaq-Elite-8300-SFF:/# ros2 daemon status
The daemon is not running
```


### Trouble Shooting

- root permission required

```bash
tomoyafujita@~/DVT >ctr images list
ctr: failed to dial "/run/containerd/containerd.sock": connection error: desc = "transport: error while dialing: dial unix /run/containerd/containerd.sock: connect: permission denied"
tomoyafujita@~/DVT >sudo ls -lt /run/containerd/containerd.sock
[sudo] password for tomoyafujita: 
srw-rw---- 1 root root 0 Mar 29 15:38 /run/containerd/containerd.sock
```

  `containerd` rootless mode, see https://github.com/containerd/containerd/blob/main/docs/rootless.md


### Reference

- https://github.com/containerd/containerd
- https://github.com/containerd/containerd/tree/main/cmd/ctr