docker info command request process of docker v18.09.4-rc1 series source code interpretation

Previous process diagram

It's only for you to sort out and understand the latest code process. Some details will not be dug in
1. Enter the client to receive the code block, and the runInfo method returns the content

// NewInfoCommand creates a new cobra.Command for `docker info`
func NewInfoCommand(dockerCli command.Cli) *cobra.Command {
    var opts infoOptions

    cmd := &cobra.Command{
        Use:   "info [OPTIONS]",
        Short: "Display system-wide information",
        Args:  cli.NoArgs,
        RunE: func(cmd *cobra.Command, args []string) error {
            return runInfo(dockerCli, &opts)

func runInfo(dockerCli command.Cli, opts *infoOptions) error {
    ctx := context.Background()
    info, err := dockerCli.Client().Info(ctx)   

2. The request is forwarded to the docker daemon for processing

// Info returns information about the docker server.
func (cli *Client) Info(ctx context.Context) (types.Info, error) {
    var info types.Info
    serverResp, err := cli.get(ctx, "/info", url.Values{}, nil)

3. The listener route of docker daemon enters SystemInfo for processing

// NewRouter initializes a new system router
func NewRouter(b Backend, c ClusterBackend, fscache *fscache.FSCache, builder *buildkit.Builder, features *map[string]bool) router.Router {
   router.NewGetRoute("/info", r.getInfo),

func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    info, err := s.backend.SystemInfo()

4. After entering the systemInfo processing method, it can be seen that the container status information is the data already in memory

// SystemInfo returns information about the host server the daemon is running on.
func (daemon *Daemon) SystemInfo() (*types.Info, error) {
    sysInfo := sysinfo.New(true)
    cRunning, cPaused, cStopped := stateCtr.get()

    v := &types.Info{
        ID:                 daemon.ID,
        Containers:         cRunning + cPaused + cStopped,
        ContainersRunning:  cRunning,
        ContainersPaused:   cPaused,
        ContainersStopped:  cStopped,   

5. Find the data method to set the running state of container

func (ctr *stateCounter) set(id, label string) {
    ctr.states[id] = label

6. Container status data source
6.1. Follow the setting method to find a piece of data that will be set when the container is created. This is the initialized data

// Create creates a new container from the given configuration with a given name.
func (daemon *Daemon) create(params types.ContainerCreateConfig, managed bool) (retC *container.Container, retErr error) {
   stateCtr.set(container.ID, "stopped")

6.2 container operation (pause, start, resume)

// containerPause pauses the container execution without stopping the process.
// The execution can be resumed by calling containerUnpause.
func (daemon *Daemon) containerPause(container *container.Container) error {
    container.Paused = true

// containerStart prepares the container to run by setting up everything the
// container needs, such as storage and networking, as well as links
// between containers. The container is left waiting for a signal to
// begin running.
func (daemon *Daemon) containerStart(container *container.Container, checkpoint string, checkpointDir string, resetRestartManager bool) (err error) {
    container.SetRunning(pid, true)
    container.HasBeenManuallyStopped = false
    container.HasBeenStartedBefore = true

// containerUnpause resumes the container execution after the container is paused.
func (daemon *Daemon) containerUnpause(container *container.Container) error {
    container.Paused = false

6.3. After the docker is restarted, obtain the container status from the directory

func (daemon *Daemon) restore() error {
   for _, c := range containers {
     //Get container status from config.v2.json

     //If the status in the file is running or suspended, check again and reset the status
     if c.IsRunning() || c.IsPaused() {
                            // running
                            c.Paused = false

7. Event change reset container status (windows)
7.1 information method of container state change

func (daemon *Daemon) setStateCounter(c *container.Container) {
    switch c.StateString() {
    case "paused":
        stateCtr.set(c.ID, "paused")
    case "running":
        stateCtr.set(c.ID, "running")
        stateCtr.set(c.ID, "stopped")

7.2 windows event monitoring

// ProcessEvent is called by libcontainerd whenever an event occurs
func (daemon *Daemon) ProcessEvent(id string, e libcontainerd.EventType, ei libcontainerd.EventInfo) error {
    case libcontainerd.EventExit:
    case libcontainerd.EventStart:

        // This is here to handle start not generated by docker
        if !c.Running {
            c.SetRunning(int(ei.Pid), false)
            c.HasBeenManuallyStopped = false
            c.HasBeenStartedBefore = true

    case libcontainerd.EventPaused:

        if !c.Paused {
            c.Paused = true

    case libcontainerd.EventResumed:
        if c.Paused {
            c.Paused = false

8. Turn on the debug mode when starting docker, and obtain file description, goroute and other information
dockerd --debug

if info.Debug {
        fmt.Fprintln(dockerCli.Out(), " File Descriptors:", info.NFd)
        fmt.Fprintln(dockerCli.Out(), " Goroutines:", info.NGoroutines)
        fmt.Fprintln(dockerCli.Out(), " System Time:", info.SystemTime)
        fmt.Fprintln(dockerCli.Out(), " EventsListeners:", info.NEventsListener)

Keywords: Linux Docker github Windows JSON

Added by plazz2000 on Sun, 01 Dec 2019 08:53:02 +0200