Search code examples
dockercontainerscontainerd

How to run docker images in containerd using ctr in CLI?


Am exploring on how to use containerd in place of dockerd. This is for learning only and as a cli tool rather than with any pipelines or automation.

So far, documentation in regards to using containerd in cli (via ctr) is very limited. Even the official docs are using Go lang to utilize containerd directly.

What I have learnt is ctr command plays the role of docker command to control containerd. I have thus far created a docker image and exported it to .tar format. Now using ctr i import hello.tar I have imported it as an image.

Now ctr i ls gives me the following output:

REF                                     TYPE                                       DIGEST                                                                  SIZE      PLATFORMS   LABELS
docker.io/library/hello-java-app:latest application/vnd.oci.image.manifest.v1+json sha256:ef4acfd85c856ea020328959ff3cac23f37fa639b7edfb1691619d9bfe1e06c7 628.7 MiB linux/amd64 -

Trying to run a container asks me for the image id:

root@slave-node:~/images/sample# ctr run
ctr: image ref must be provided
root@slave-node:~/images/sample# ctr run docker.io/library/hello-java-app:latest
ctr: container id must be provided

I am not sure on where to get the image id from. Are there any docs related to ctr or containerd that could be helpful for a beginner?

Just running the image as a container would be sufficient for me.


Solution

  • The ctr run command creates a container and executes it

    ctr run <imageName> <uniqueValue>
    

    e.g., ctr run --rm docker.io/library/hello-java-app:latest mypod

    This executes my basic docker java image with a print statement:

    ~~~~
    HelloWorld from Java Application running in Docker.
    ~~~~
    

    Steps followed:

    1 - A java file:

    public class HelloWorld {
        public static void main(String[] args) {
            System.out.println("~~~~\nHelloWorld from Java Application running in Docker.\n~~~~");
        }
    }
    

    2 - An image:

    FROM java:8
    COPY HelloWorld.java .
    RUN javac HelloWorld.java
    CMD ["java", "HelloWorld"]
    

    3 - Build image and export as .tar

    • docker build -t hello-java-app .
    • docker save -o ~/images/sample/hello-java-app.tar hello-java-app

    4 - Import image (.tar) into containerd:

    • ctr i import hello-java-app.tar
    unpacking docker.io/library/hello-java-app:latest (sha256:ef4acfd85c856ea020328959ff3cac23f37fa639b7edfb1691619d9bfe1e06c7)...done
    
    • ctr i ls
    REF                                     TYPE                                       DIGEST                                                                  SIZE      PLATFORMS   LABELS
    docker.io/library/hello-java-app:latest application/vnd.oci.image.manifest.v1+json sha256:ef4acfd85c856ea020328959ff3cac23f37fa639b7edfb1691619d9bfe1e06c7 628.7 MiB linux/amd64 -
    

    5 - Run the image:

    • ctr run --rm docker.io/library/hello-java-app:latest mypod
    ~~~~
    HelloWorld from Java Application running in Docker.
    ~~~~
    

    I am still unsure of the use of creating a container. The run command creates a container and executes it once. ctr c create just creates a container which can then be listed with ctr c ls but I am not able to utilize them in any meaningful way. Can anyone clarify its purpose?


    PS: Without the --rm flag, a new unique value is needed to be entered for every run as the old container is retained and we get an error: ctr: snapshot "mypod": already exists