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) }