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
github.com/docker/cli/cli/command/system/info.go

// 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
github.com/docker/cli/vendor/github.com/docker/docker/client/info.go

// 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
github.com/docker/docker/api/server/router/system/system.go

// 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),  

github.com/docker/docker/api/server/router/system/system_routes.go

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
github.com/docker/docker/daemon/info.go

// 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
github.com/docker/docker/daemon/metrics.go

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

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
github.com/docker/docker/daemon/create.go

// 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)
github.com/docker/docker/daemon/pause.go

// 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
    daemon.setStateCounter(container)

github.com/docker/docker/daemon/start.go

// 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
    daemon.setStateCounter(container)

github.com/docker/docker/daemon/unpause.go

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

6.3. After the docker is restarted, obtain the container status from the directory
github.com/docker/docker/daemon/daemon.go

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

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

7. Event change reset container status (windows)
7.1 information method of container state change
github.com/docker/docker/daemon/monitor.go

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

7.2 windows event monitoring
github.com/docker/docker/daemon/monitor.go

// 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:
       daemon.setStateCounter(c)
    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
            daemon.setStateCounter(c)

    case libcontainerd.EventPaused:

        if !c.Paused {
            c.Paused = true
            daemon.setStateCounter(c)

    case libcontainerd.EventResumed:
        if c.Paused {
            c.Paused = false
            daemon.setStateCounter(c)   

8. Turn on the debug mode when starting docker, and obtain file description, goroute and other information
dockerd --debug
github.com/docker/cli/cli/command/system/info.go

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