Make writing a habit together! This is the 11th day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details.

Introduction to the

In the previous chapter, we realized the exec command to re-enter the container running in the background. This chapter will realize the stop command to stop the container running

The source code that

It is available on both Gitee and Github

  • Gitee: https://gitee.com/free-love/docker-demo
  • GitHub: https://github.com/lw1243925457/dockerDemo

The corresponding version label in this section is 5.5. You can switch to the label version to check if there are too many codes

Code implementation

The main idea of this function is as follows:

Procedure 1 Locate the configuration file based on the container name

2 Read the configuration file, obtain the PID of the container, and send the kill signal to stop the process

3 Save the updated stop information in the configuration file

Added the stop command

Add the stop command to the main function:

func main(a) {
	app.Commands = []cli.Command{
		command.InitCommand,
		command.RunCommand,
		command.CommitCommand,
		command.ListCommand,
		command.LogCommand,
		command.ExecCommand,
		command.StopCommand,
	}
}
Copy the code

Main_command. Go Add related commands:

var StopCommand = cli.Command{
	Name:  "stop",
	Usage: "stop container",
	Action: func(context *cli.Context) {
		if len(context.Args()) < 1 {
			log.Errorf("missing container name")
			return
		}
		containerName := context.Args().Get(0)
		iferr := run.StopContainer(containerName); err ! =nil {
			log.Errorf("stop container err: %v", err)
		}
	},
}
Copy the code

Read the container configuration file to stop and update the container

Based on the container name, we find the location of the container configuration file

After reading the configuration file, we can get the PID of the container on the host

More PID, we can send the kill command to stop the container

After stopping the container, change the container state in the configuration file to Stop, and then update the storage configuration file

The specific code is as follows:

func StopContainer(containerName string) error {
	// Get PID from container name
	pid, err := getContainerPidByName(containerName)
	iferr ! =nil {
		return err
	}

	pidInt, err := strconv.Atoi(pid)
	iferr ! =nil {
		return fmt.Errorf("convert pid %s to int err: %v", pid, err)
	}

	// Send the kill name to stop the container process
	iferr := syscall.Kill(pidInt, syscall.SIGTERM); err ! =nil {
		return fmt.Errorf("send sigterm %d, err: %v", pid, err)
	}

	// Update storage container information
	containerInfo, err := getContainerInfoByName(containerName)
	iferr ! =nil {
		return fmt.Errorf("get container info err: %v", err)
	}

	containerInfo.Status = container.STOP
	containerInfo.Pid = ""
	newContainerInfo, err := json.Marshal(containerInfo)
	iferr ! =nil {
		return fmt.Errorf("json marshal %v,err: %v", containerInfo, err)
	}

	dirUrl := fmt.Sprintf(container.DefaultInfoLocation, containerName)
	configPath := dirUrl + container.ConfigName
	if err := ioutil.WriteFile(configPath, newContainerInfo, 0622); err ! =nil {
		return fmt.Errorf("write file %s err: %v", configPath, err)
	}
	return nil
}
Copy the code

This code uses two functions, one is to get the PID of the container according to the name of the container, one is to get the configuration of the container according to the name of the container.


func getContainerPidByName(containerName string) (string, error) {
	dirUrl := fmt.Sprintf(container.DefaultInfoLocation, containerName)
	configFilePath := dirUrl + container.ConfigName
	contentBytes, err := ioutil.ReadFile(configFilePath)
	iferr ! =nil {
		return "", fmt.Errorf("read file %s err: %v", configFilePath, err)
	}

	var containerInfo container.ContainerInfo
	iferr := json.Unmarshal(contentBytes, &containerInfo); err ! =nil {
		return "", fmt.Errorf("json ummarshal err: %v", err)
	}
	return containerInfo.Pid, nil
}

func getContainerInfoByName(containerName string) (*container.ContainerInfo, error) {
	dirUrl := fmt.Sprintf(container.DefaultInfoLocation, containerName)
	configFilePath := dirUrl + container.ConfigName
	contentBytes, err := ioutil.ReadFile(configFilePath)
	iferr ! =nil {
		return nil, fmt.Errorf("read file %s err: %v", configFilePath, err)
	}

	var containerInfo container.ContainerInfo
	iferr := json.Unmarshal(contentBytes, &containerInfo); err ! =nil {
		return nil, fmt.Errorf("json ummarshal err: %v", err)
	}
	return &containerInfo, nil
}
Copy the code

Run the test

Our tests are as follows:

  • Start a container of top commands running in the background
  • Ps Check the status: see that there is an expected running container
  • Check whether there is a corresponding host process, and a corresponding TOP process exists
  • Use the stop command
  • Ps Check the status: The node is stopped
  • Check whether there is a TOP process on the host
root@lw-Code-01-Series-PF5NU1G  ~/code/go/dockerDemo   main ● ./main run --name bird-d top bank roll up link link 07:28:53 {"level":"info","msg":"memory cgroup path: /sys/fs/cgroup/memory/mydocker-cgroup","time":"2022-04-09T07:29:00+08:00"} {"level":"info","msg":"memory cgroup path: /sys/fs/cgroup/memory/mydocker-cgroup","time":"2022-04-09T07:29:00+08:00"} {"level":"info","msg":"all command is : top","time":"2022-04-09T07:29:00+08:00"} {"level":"info","msg":"parent process run","time":"2022-04-09T07:29:00+08:00"} root@lw-Code-01-Series-PF5NU1G  ~/code/go/dockerDemo   main ● ./ Main ps port SIG(127) Password password 418 秒 07:29:00 ID NAME PID STATUS COMMAND CREATED 1808352378 Bird 126298 Running Top 9000-04-04 00:00:00 root@lw-Code-01-Series-PF5NU1G  ~ / code/go/dockerDemo   main low  ps - ef | grep top  ✔  ⚡  419  07:29:05 root in April 2751, 1776, 07? 00:00:01 /usr/libexec/xdg-desktop-portal root 2778 1776 0 4月07? 00:00:00 /usr/libexec/xdg-desktop-portal-gtk root 126298 1 0 07:28 pts/2 00:00:00 top root 126537 22616 0 07:29 pts/2 00:00:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn -- excide-dir =.idea -- excide-dir =.tox top root@lw-Code-01-Series-PF5NU1G  ~/code/go/dockerDemo   main ● ./main Stop bird  ✔ ✔  ⚡  420  07:29:09 fb /code/go/dockerDemo email main ● open  421  07:29:20 ID NAME PID STATUS COMMAND CREATED 1808352378 bird Stop Top 9000-04-04 00:00:00 Root @ lw - Code - 01 - Series - PF5NU1G  ~ / Code/go/dockerDemo   main low  ps - ef | grep top  ✔  ⚡  422  07:29:24 root, 2751 1776 0 April 07? 00:00:01 /usr/libexec/xdg-desktop-portal root 2778 1776 0 4月07? 00:00:00 /usr/libexec/xdg-desktop-portal-gtk root 126883 22616 0 07:29 pts/2 00:00:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn --exclude-dir=.idea --exclude-dir=.tox topCopy the code