moby / moby/moby

API: add option to inspect a container's OCI spec

Open
#51,705 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area/api kind/feature status/0-triage
Dominant language
Go
Stars
72.1k
Forks
19.2k
Avg merge
1d 18h
Merged PRs (30d)
164

Description

Description

The API currently allows inspecting a container's configuration through the GET /containers/{id}/json endpoint.

Note:

This endpoint returns low-level information of the container's config (as passed by the user) and state, but has various known limitations; some fields are ambiguous as they can either reflect the ("desired") config as passed by the user, the config after applying defaults, or "runtime" state (some fields, such as IP-addresses, are set at runtime). This is a problem to be solved, but orthogonal to this ticket.

With the integration of CDI (https://github.com/moby/moby/pull/45134), and (in progress) NRI, there's a growing list of situations where the inspect output does not reflect the actual config of the container. Both CDI and NRI have options to patch the OCI specification when a container is created or started, which can complicate debugging; for example, both CDI and NRI can add mounts or env-vars to a container, which can influence the behavior of the container, but these transformations are opaque to the user.

To help debugging and to make these transformations more transparent, we should consider extending the API to expose the OCI specification of containers. It's worth noting that, unlike docker inspect, the OCI specification for containers are only available for running containers; the OCI specification is generated when the container is started, so this information can only be shown for running containers.

Options

  • We could add additional fields to the existing inspect response; these fields could be propagated when passing additional options (e.g. ?verbose=true, or ?with-oci=true)
  • Alternatively, we could add a new endpoint specifically for obtaining a container's OCI config

In either of these options

  • we should define an API type that includes the OCI specification, to allow future expansion of the information provided
  • ideally, the response provides insight into transformations applied, for example;
    • the "original" OCI specification as generated by the Moby daemon
    • a "diff" produced by each transformation (diff applied by (e.g.) CDI {{VENDOR_ID}}/{{DEVICE_CLASS}}={{DEVICE_ID}}, or NRI plugin X)
    • ☝️ do we want the API to only return the diff, or return the full OCI spec for each step, and make it the client's responsibility to present this as a diff (if wanted)?
    • the final OCI specification as used for the container

Prior art

The containerd ctr utility allows viewing the container's OCI specification; similar to the above, the default is to return the OCI spec as a Spec field in the output;

{
  "ID": "fa3e189a84dfb77f67b68bd5a8650ecb46bcc2ab29b760b40cb6cb325078e230",
  "Labels": {
    "com.docker/engine.bundle.path": "/var/run/docker/containerd/fa3e189a84dfb77f67b68bd5a8650ecb46bcc2ab29b760b40cb6cb325078e230"
  },
  "Image": "",
  "Runtime": {
    "Name": "io.containerd.runc.v2",
    "Options": {
      "type_url": "containerd.runc.v1.Options",
      "value": "MgRydW5jOhwvdmFyL3J1bi9kb2NrZXIvcnVudGltZS1ydW5j"
    }
  },
  "SnapshotKey": "",
  "Snapshotter": "",
  "CreatedAt": "2023-05-21T06:47:42.794551686Z",
  "UpdatedAt": "2023-05-21T06:47:42.794551686Z",
  "Extensions": null,
  "Spec": {
    "OCI-spec here"
  }
}

Passing the --spec option unwraps the output, and only returns the Spec field.

Full example below;

ctr -n moby container info fa3e189a84dfb77f67b68bd5a8650ecb46bcc2ab29b760b40cb6cb325078e230
{
    "ID": "fa3e189a84dfb77f67b68bd5a8650ecb46bcc2ab29b760b40cb6cb325078e230",
    "Labels": {
        "com.docker/engine.bundle.path": "/var/run/docker/containerd/fa3e189a84dfb77f67b68bd5a8650ecb46bcc2ab29b760b40cb6cb325078e230"
    },
    "Image": "",
    "Runtime": {
        "Name": "io.containerd.runc.v2",
        "Options": {
            "type_url": "containerd.runc.v1.Options",
            "value": "MgRydW5jOhwvdmFyL3J1bi9kb2NrZXIvcnVudGltZS1ydW5j"
        }
    },
    "SnapshotKey": "",
    "Snapshotter": "",
    "CreatedAt": "2023-05-21T06:47:42.794551686Z",
    "UpdatedAt": "2023-05-21T06:47:42.794551686Z",
    "Extensions": null,
    "Spec": {
        "ociVersion": "1.0.2-dev",
        "process": {
            "user": {
                "uid": 0,
                "gid": 0,
                "additionalGids": [
                    0,
                    0,
                    1,
                    2,
                    3,
                    4,
                    6,
                    10,
                    11,
                    20,
                    26,
                    27
                ]
            },
            "args": [
                "/f3tsh"
            ],
            "env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "HOSTNAME=fa3e189a84df"
            ],
            "cwd": "/",
            "capabilities": {
                "bounding": [
                    "CAP_CHOWN",
                    "CAP_DAC_OVERRIDE",
                    "CAP_FSETID",
                    "CAP_FOWNER",
                    "CAP_MKNOD",
                    "CAP_NET_RAW",
                    "CAP_SETGID",
                    "CAP_SETUID",
                    "CAP_SETFCAP",
                    "CAP_SETPCAP",
                    "CAP_NET_BIND_SERVICE",
                    "CAP_SYS_CHROOT",
                    "CAP_KILL",
                    "CAP_AUDIT_WRITE"
                ],
                "effective": [
                    "CAP_CHOWN",
                    "CAP_DAC_OVERRIDE",
                    "CAP_FSETID",
                    "CAP_FOWNER",
                    "CAP_MKNOD",
                    "CAP_NET_RAW",
                    "CAP_SETGID",
                    "CAP_SETUID",
                    "CAP_SETFCAP",
                    "CAP_SETPCAP",
                    "CAP_NET_BIND_SERVICE",
                    "CAP_SYS_CHROOT",
                    "CAP_KILL",
                    "CAP_AUDIT_WRITE"
                ],
                "permitted": [
                    "CAP_CHOWN",
                    "CAP_DAC_OVERRIDE",
                    "CAP_FSETID",
                    "CAP_FOWNER",
                    "CAP_MKNOD",
                    "CAP_NET_RAW",
                    "CAP_SETGID",
                    "CAP_SETUID",
                    "CAP_SETFCAP",
                    "CAP_SETPCAP",
                    "CAP_NET_BIND_SERVICE",
                    "CAP_SYS_CHROOT",
                    "CAP_KILL",
                    "CAP_AUDIT_WRITE"
                ]
            },
            "apparmorProfile": "docker-default",
            "oomScoreAdj": 0
        },
        "root": {
            "path": "/var/lib/docker/overlay2/23770bf6acd50632d0dffe3fac5c654d84892c70ff2dc212fdf7360c9bfcdfc5/merged"
        },
        "hostname": "fa3e189a84df",
        "mounts": [
            {
                "destination": "/proc",
                "type": "proc",
                "source": "proc",
                "options": [
                    "nosuid",
                    "noexec",
                    "nodev"
                ]
            },
            {
                "destination": "/dev",
                "type": "tmpfs",
                "source": "tmpfs",
                "options": [
                    "nosuid",
                    "strictatime",
                    "mode=755",
                    "size=65536k"
                ]
            },
            {
                "destination": "/dev/pts",
                "type": "devpts",
                "source": "devpts",
                "options": [
                    "nosuid",
                    "noexec",
                    "newinstance",
                    "ptmxmode=0666",
                    "mode=0620",
                    "gid=5"
                ]
            },
            {
                "destination": "/sys",
                "type": "sysfs",
                "source": "sysfs",
                "options": [
                    "nosuid",
                    "noexec",
                    "nodev",
                    "ro"
                ]
            },
            {
                "destination": "/sys/fs/cgroup",
                "type": "cgroup",
                "source": "cgroup",
                "options": [
                    "ro",
                    "nosuid",
                    "noexec",
                    "nodev"
                ]
            },
            {
                "destination": "/dev/mqueue",
                "type": "mqueue",
                "source": "mqueue",
                "options": [
                    "nosuid",
                    "noexec",
                    "nodev"
                ]
            },
            {
                "destination": "/dev/shm",
                "type": "tmpfs",
                "source": "shm",
                "options": [
                    "nosuid",
                    "noexec",
                    "nodev",
                    "mode=1777",
                    "size=67108864"
                ]
            },
            {
                "destination": "/etc/resolv.conf",
                "type": "bind",
                "source": "/var/lib/docker/containers/fa3e189a84dfb77f67b68bd5a8650ecb46bcc2ab29b760b40cb6cb325078e230/resolv.conf",
                "options": [
                    "rbind",
                    "rprivate"
                ]
            },
            {
                "destination": "/etc/hostname",
                "type": "bind",
                "source": "/var/lib/docker/containers/fa3e189a84dfb77f67b68bd5a8650ecb46bcc2ab29b760b40cb6cb325078e230/hostname",
                "options": [
                    "rbind",
                    "rprivate"
                ]
            },
            {
                "destination": "/etc/hosts",
                "type": "bind",
                "source": "/var/lib/docker/containers/fa3e189a84dfb77f67b68bd5a8650ecb46bcc2ab29b760b40cb6cb325078e230/hosts",
                "options": [
                    "rbind",
                    "rprivate"
                ]
            }
        ],
        "hooks": {
            "prestart": [
                {
                    "path": "/proc/30416/exe",
                    "args": [
                        "libnetwork-setkey",
                        "-exec-root=/var/run/docker",
                        "fa3e189a84dfb77f67b68bd5a8650ecb46bcc2ab29b760b40cb6cb325078e230",
                        "34769d5621c6"
                    ]
                }
            ]
        },
        "linux": {
            "sysctl": {
                "net.ipv4.ip_unprivileged_port_start": "0",
                "net.ipv4.ping_group_range": "0 2147483647"
            },
            "resources": {
                "devices": [
                    {
                        "allow": false,
                        "access": "rwm"
                    },
                    {
                        "allow": true,
                        "type": "c",
                        "major": 1,
                        "minor": 5,
                        "access": "rwm"
                    },
                    {
                        "allow": true,
                        "type": "c",
                        "major": 1,
                        "minor": 3,
                        "access": "rwm"
                    },
                    {
                        "allow": true,
                        "type": "c",
                        "major": 1,
                        "minor": 9,
                        "access": "rwm"
                    },
                    {
                        "allow": true,
                        "type": "c",
                        "major": 1,
                        "minor": 8,
                        "access": "rwm"
                    },
                    {
                        "allow": true,
                        "type": "c",
                        "major": 5,
                        "minor": 0,
                        "access": "rwm"
                    },
                    {
                        "allow": true,
                        "type": "c",
                        "major": 5,
                        "minor": 1,
                        "access": "rwm"
                    },
                    {
                        "allow": false,
                        "type": "c",
                        "major": 10,
                        "minor": 229,
                        "access": "rwm"
                    }
                ],
                "memory": {
                    "disableOOMKiller": false
                },
                "cpu": {
                    "shares": 0
                },
                "blockIO": {
                    "weight": 0
                }
            },
            "cgroupsPath": "/docker/fa3e189a84dfb77f67b68bd5a8650ecb46bcc2ab29b760b40cb6cb325078e230",
            "namespaces": [
                {
                    "type": "mount"
                },
                {
                    "type": "network"
                },
                {
                    "type": "uts"
                },
                {
                    "type": "pid"
                },
                {
                    "type": "ipc"
                }
            ],
            "seccomp": {
                "defaultAction": "SCMP_ACT_ERRNO",
                "defaultErrnoRet": 1,
                "architectures": [
                    "SCMP_ARCH_X86_64",
                    "SCMP_ARCH_X86",
                    "SCMP_ARCH_X32"
                ],
                "syscalls": [
                    {
                        "names": [
                            "accept",
                            "accept4",
                            "access",
                            "adjtimex",
                            "alarm",
                            "bind",
                            "brk",
                            "capget",
                            "capset",
                            "chdir",

                            "chmod",
                            "chown",
                            "chown32",
                            "clock_adjtime",
                            "clock_adjtime64",
                            "clock_getres",
                            "clock_getres_time64",
                            "clock_gettime",
                            "clock_gettime64",
                            "clock_nanosleep",
                            "clock_nanosleep_time64",
                            "close",
                            "close_range",
                            "connect",
                            "copy_file_range",
                            "creat",
                            "dup",
                            "dup2",
                            "dup3",
                            "epoll_create",
                            "epoll_create1",
                            "epoll_ctl",
                            "epoll_ctl_old",
                            "epoll_pwait",
                            "epoll_pwait2",
                            "epoll_wait",
                            "epoll_wait_old",
                            "eventfd",
                            "eventfd2",
                            "execve",
                            "execveat",
                            "exit",
                            "exit_group",
                            "faccessat",
                            "faccessat2",
                            "fadvise64",
                            "fadvise64_64",
                            "fallocate",
                            "fanotify_mark",
                            "fchdir",
                            "fchmod",
                            "fchmodat",
                            "fchown",
                            "fchown32",
                            "fchownat",
                            "fcntl",
                            "fcntl64",
                            "fdatasync",
                            "fgetxattr",
                            "flistxattr",
                            "flock",
                            "fork",
                            "fremovexattr",
                            "fsetxattr",
                            "fstat",
                            "fstat64",
                            "fstatat64",
                            "fstatfs",
                            "fstatfs64",
                            "fsync",
                            "ftruncate",
                            "ftruncate64",
                            "futex",
                            "futex_time64",
                            "futex_waitv",
                            "futimesat",
                            "getcpu",
                            "getcwd",
                            "getdents",
                            "getdents64",
                            "getegid",
                            "getegid32",
                            "geteuid",
                            "geteuid32",
                            "getgid",
                            "getgid32",
                            "getgroups",
                            "getgroups32",
                            "getitimer",
                            "getpeername",
                            "getpgid",
                            "getpgrp",
                            "getpid",
                            "getppid",
                            "getpriority",
                            "getrandom",
                            "getresgid",
                            "getresgid32",
                            "getresuid",
                            "getresuid32",
                            "getrlimit",
                            "get_robust_list",
                            "getrusage",
                            "getsid",
                            "getsockname",
                            "getsockopt",
                            "get_thread_area",
                            "gettid",
                            "gettimeofday",
                            "getuid",
                            "getuid32",
                            "getxattr",
                            "inotify_add_watch",
                            "inotify_init",
                            "inotify_init1",
                            "inotify_rm_watch",
                            "io_cancel",
                            "ioctl",
                            "io_destroy",
                            "io_getevents",
                            "io_pgetevents",
                            "io_pgetevents_time64",
                            "ioprio_get",
                            "ioprio_set",
                            "io_setup",
                            "io_submit",
                            "io_uring_enter",
                            "io_uring_register",
                            "io_uring_setup",
                            "ipc",
                            "kill",
                            "landlock_add_rule",
                            "landlock_create_ruleset",
                            "landlock_restrict_self",
                            "lchown",
                            "lchown32",
                            "lgetxattr",
                            "link",
                            "linkat",
                            "listen",
                            "listxattr",
                            "llistxattr",
                            "_llseek",
                            "lremovexattr",
                            "lseek",
                            "lsetxattr",
                            "lstat",
                            "lstat64",
                            "madvise",
                            "membarrier",
                            "memfd_create",
                            "memfd_secret",
                            "mincore",
                            "mkdir",
                            "mkdirat",
                            "mknod",
                            "mknodat",
                            "mlock",
                            "mlock2",
                            "mlockall",
                            "mmap",
                            "mmap2",
                            "mprotect",
                            "mq_getsetattr",
                            "mq_notify",
                            "mq_open",
                            "mq_timedreceive",
                            "mq_timedreceive_time64",
                            "mq_timedsend",
                            "mq_timedsend_time64",
                            "mq_unlink",
                            "mremap",
                            "msgctl",
                            "msgget",
                            "msgrcv",
                            "msgsnd",
                            "msync",
                            "munlock",
                            "munlockall",
                            "munmap",
                            "nanosleep",
                            "newfstatat",
                            "_newselect",
                            "open",
                            "openat",
                            "openat2",
                            "pause",
                            "pidfd_open",
                            "pidfd_send_signal",
                            "pipe",
                            "pipe2",
                            "pkey_alloc",
                            "pkey_free",
                            "pkey_mprotect",
                            "poll",
                            "ppoll",
                            "ppoll_time64",
                            "prctl",
                            "pread64",
                            "preadv",
                            "preadv2",
                            "prlimit64",
                            "process_mrelease",
                            "pselect6",
                            "pselect6_time64",
                            "pwrite64",
                            "pwritev",
                            "pwritev2",
                            "read",
                            "readahead",
                            "readlink",
                            "readlinkat",
                            "readv",
                            "recv",
                            "recvfrom",
                            "recvmmsg",
                            "recvmmsg_time64",
                            "recvmsg",
                            "remap_file_pages",
                            "removexattr",
                            "rename",
                            "renameat",
                            "renameat2",
                            "restart_syscall",
                            "rmdir",
                            "rseq",
                            "rt_sigaction",
                            "rt_sigpending",
                            "rt_sigprocmask",
                            "rt_sigqueueinfo",
                            "rt_sigreturn",
                            "rt_sigsuspend",
                            "rt_sigtimedwait",
                            "rt_sigtimedwait_time64",
                            "rt_tgsigqueueinfo",
                            "sched_getaffinity",
                            "sched_getattr",
                            "sched_getparam",
                            "sched_get_priority_max",
                            "sched_get_priority_min",
                            "sched_getscheduler",
                            "sched_rr_get_interval",
                            "sched_rr_get_interval_time64",
                            "sched_setaffinity",
                            "sched_setattr",
                            "sched_setparam",
                            "sched_setscheduler",
                            "sched_yield",
                            "seccomp",
                            "select",
                            "semctl",
                            "semget",
                            "semop",
                            "semtimedop",
                            "semtimedop_time64",
                            "send",
                            "sendfile",
                            "sendfile64",
                            "sendmmsg",
                            "sendmsg",
                            "sendto",
                            "setfsgid",
                            "setfsgid32",
                            "setfsuid",
                            "setfsuid32",
                            "setgid",
                            "setgid32",
                            "setgroups",
                            "setgroups32",
                            "setitimer",
                            "setpgid",
                            "setpriority",

                            "setregid",
                            "setregid32",
                            "setresgid",
                            "setresgid32",
                            "setresuid",
                            "setresuid32",
                            "setreuid",
                            "setreuid32",
                            "setrlimit",
                            "set_robust_list",
                            "setsid",
                            "setsockopt",
                            "set_thread_area",
                            "set_tid_address",
                            "setuid",
                            "setuid32",
                            "setxattr",
                            "shmat",
                            "shmctl",
                            "shmdt",
                            "shmget",
                            "shutdown",
                            "sigaltstack",
                            "signalfd",
                            "signalfd4",
                            "sigprocmask",
                            "sigreturn",
                            "socketcall",
                            "socketpair",
                            "splice",
                            "stat",
                            "stat64",
                            "statfs",
                            "statfs64",
                            "statx",
                            "symlink",
                            "symlinkat",
                            "sync",
                            "sync_file_range",
                            "syncfs",
                            "sysinfo",
                            "tee",
                            "tgkill",
                            "time",
                            "timer_create",
                            "timer_delete",
                            "timer_getoverrun",
                            "timer_gettime",
                            "timer_gettime64",
                            "timer_settime",
                            "timer_settime64",
                            "timerfd_create",
                            "timerfd_gettime",
                            "timerfd_gettime64",
                            "timerfd_settime",
                            "timerfd_settime64",
                            "times",
                            "tkill",
                            "truncate",
                            "truncate64",
                            "ugetrlimit",
                            "umask",
                            "uname",
                            "unlink",
                            "unlinkat",
                            "utime",
                            "utimensat",
                            "utimensat_time64",
                            "utimes",
                            "vfork",
                            "vmsplice",
                            "wait4",
                            "waitid",
                            "waitpid",
                            "write",
                            "writev"
                        ],
                        "action": "SCMP_ACT_ALLOW"
                    },
                    {
                        "names": [
                            "process_vm_readv",
                            "process_vm_writev",
                            "ptrace"
                        ],
                        "action": "SCMP_ACT_ALLOW"
                    },
                    {
                        "names": [
                            "socket"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "args": [
                            {
                                "index": 0,
                                "value": 40,
                                "op": "SCMP_CMP_NE"
                            }
                        ]
                    },
                    {
                        "names": [
                            "personality"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "args": [
                            {
                                "index": 0,
                                "value": 0,
                                "op": "SCMP_CMP_EQ"
                            }
                        ]
                    },
                    {
                        "names": [
                            "personality"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "args": [
                            {
                                "index": 0,
                                "value": 8,
                                "op": "SCMP_CMP_EQ"
                            }
                        ]
                    },
                    {
                        "names": [
                            "personality"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "args": [
                            {
                                "index": 0,
                                "value": 131072,
                                "op": "SCMP_CMP_EQ"
                            }
                        ]
                    },
                    {
                        "names": [
                            "personality"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "args": [
                            {
                                "index": 0,
                                "value": 131080,
                                "op": "SCMP_CMP_EQ"
                            }
                        ]
                    },
                    {
                        "names": [
                            "personality"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "args": [
                            {
                                "index": 0,
                                "value": 4294967295,
                                "op": "SCMP_CMP_EQ"
                            }
                        ]
                    },
                    {
                        "names": [
                            "arch_prctl"
                        ],
                        "action": "SCMP_ACT_ALLOW"
                    },
                    {
                        "names": [
                            "modify_ldt"
                        ],
                        "action": "SCMP_ACT_ALLOW"
                    },
                    {
                        "names": [
                            "clone"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "args": [
                            {
                                "index": 0,
                                "value": 2114060288,
                                "op": "SCMP_CMP_MASKED_EQ"
                            }
                        ]
                    },
                    {
                        "names": [
                            "clone3"
                        ],
                        "action": "SCMP_ACT_ERRNO",
                        "errnoRet": 38
                    },
                    {
                        "names": [
                            "chroot"
                        ],
                        "action": "SCMP_ACT_ALLOW"
                    }
                ]
            },
            "maskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "readonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        }
    }
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the existing GET /containers/{id}/json endpoint and the container-start path that generates the OCI specification. Compare the proposed API shapes with containerd's ctr container info and its --spec output. Done means an agreed API type and endpoint or option that exposes the OCI specification for running containers, including the intended transformation details.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, go
Domain
api, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.