github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/runc/libcontainer/README.md (about)

     1  Libcontainer provides a native Go implementation for creating containers
     2  with namespaces, cgroups, capabilities, and filesystem access controls.
     3  It allows you to manage the lifecycle of the container performing additional operations
     4  after the container is created.
     5  
     6  
     7  #### Container
     8  A container is a self contained execution environment that shares the kernel of the
     9  host system and which is (optionally) isolated from other containers in the system.
    10  
    11  #### Using libcontainer
    12  
    13  Because containers are spawned in a two step process you will need a binary that
    14  will be executed as the init process for the container. In libcontainer, we use
    15  the current binary (/proc/self/exe) to be executed as the init process, and use
    16  arg "init", we call the first step process "bootstrap", so you always need a "init"
    17  function as the entry of "bootstrap".
    18  
    19  ```go
    20  func init() {
    21  	if len(os.Args) > 1 && os.Args[1] == "init" {
    22  		runtime.GOMAXPROCS(1)
    23  		runtime.LockOSThread()
    24  		factory, _ := libcontainer.New("")
    25  		if err := factory.StartInitialization(); err != nil {
    26  			logrus.Fatal(err)
    27  		}
    28  		panic("--this line should have never been executed, congratulations--")
    29  	}
    30  }
    31  ```
    32  
    33  Then to create a container you first have to initialize an instance of a factory
    34  that will handle the creation and initialization for a container.
    35  
    36  ```go
    37  factory, err := libcontainer.New("/var/lib/container", libcontainer.Cgroupfs, libcontainer.InitArgs(os.Args[0], "init"))
    38  if err != nil {
    39  	logrus.Fatal(err)
    40  	return
    41  }
    42  ```
    43  
    44  Once you have an instance of the factory created we can create a configuration
    45  struct describing how the container is to be created. A sample would look similar to this:
    46  
    47  ```go
    48  defaultMountFlags := syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV
    49  config := &configs.Config{
    50  	Rootfs: "/your/path/to/rootfs",
    51  	Capabilities: []string{
    52  		"CAP_CHOWN",
    53  		"CAP_DAC_OVERRIDE",
    54  		"CAP_FSETID",
    55  		"CAP_FOWNER",
    56  		"CAP_MKNOD",
    57  		"CAP_NET_RAW",
    58  		"CAP_SETGID",
    59  		"CAP_SETUID",
    60  		"CAP_SETFCAP",
    61  		"CAP_SETPCAP",
    62  		"CAP_NET_BIND_SERVICE",
    63  		"CAP_SYS_CHROOT",
    64  		"CAP_KILL",
    65  		"CAP_AUDIT_WRITE",
    66  	},
    67  	Namespaces: configs.Namespaces([]configs.Namespace{
    68  		{Type: configs.NEWNS},
    69  		{Type: configs.NEWUTS},
    70  		{Type: configs.NEWIPC},
    71  		{Type: configs.NEWPID},
    72  		{Type: configs.NEWUSER},
    73  		{Type: configs.NEWNET},
    74  	}),
    75  	Cgroups: &configs.Cgroup{
    76  		Name:   "test-container",
    77  		Parent: "system",
    78  		Resources: &configs.Resources{
    79  			MemorySwappiness: nil,
    80  			AllowAllDevices:  nil,
    81  			AllowedDevices:   configs.DefaultAllowedDevices,
    82  		},
    83  	},
    84  	MaskPaths: []string{
    85  		"/proc/kcore",
    86  		"/sys/firmware",
    87  	},
    88  	ReadonlyPaths: []string{
    89  		"/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus",
    90  	},
    91  	Devices:  configs.DefaultAutoCreatedDevices,
    92  	Hostname: "testing",
    93  	Mounts: []*configs.Mount{
    94  		{
    95  			Source:      "proc",
    96  			Destination: "/proc",
    97  			Device:      "proc",
    98  			Flags:       defaultMountFlags,
    99  		},
   100  		{
   101  			Source:      "tmpfs",
   102  			Destination: "/dev",
   103  			Device:      "tmpfs",
   104  			Flags:       syscall.MS_NOSUID | syscall.MS_STRICTATIME,
   105  			Data:        "mode=755",
   106  		},
   107  		{
   108  			Source:      "devpts",
   109  			Destination: "/dev/pts",
   110  			Device:      "devpts",
   111  			Flags:       syscall.MS_NOSUID | syscall.MS_NOEXEC,
   112  			Data:        "newinstance,ptmxmode=0666,mode=0620,gid=5",
   113  		},
   114  		{
   115  			Device:      "tmpfs",
   116  			Source:      "shm",
   117  			Destination: "/dev/shm",
   118  			Data:        "mode=1777,size=65536k",
   119  			Flags:       defaultMountFlags,
   120  		},
   121  		{
   122  			Source:      "mqueue",
   123  			Destination: "/dev/mqueue",
   124  			Device:      "mqueue",
   125  			Flags:       defaultMountFlags,
   126  		},
   127  		{
   128  			Source:      "sysfs",
   129  			Destination: "/sys",
   130  			Device:      "sysfs",
   131  			Flags:       defaultMountFlags | syscall.MS_RDONLY,
   132  		},
   133  	},
   134  	UidMappings: []configs.IDMap{
   135  		{
   136  			ContainerID: 0,
   137  			HostID: 1000,
   138  			Size: 65536,
   139  		},
   140  	},
   141  	GidMappings: []configs.IDMap{
   142  		{
   143  			ContainerID: 0,
   144  			HostID: 1000,
   145  			Size: 65536,
   146  		},
   147  	},
   148  	Networks: []*configs.Network{
   149  		{
   150  			Type:    "loopback",
   151  			Address: "127.0.0.1/0",
   152  			Gateway: "localhost",
   153  		},
   154  	},
   155  	Rlimits: []configs.Rlimit{
   156  		{
   157  			Type: syscall.RLIMIT_NOFILE,
   158  			Hard: uint64(1025),
   159  			Soft: uint64(1025),
   160  		},
   161  	},
   162  }
   163  ```
   164  
   165  Once you have the configuration populated you can create a container:
   166  
   167  ```go
   168  container, err := factory.Create("container-id", config)
   169  if err != nil {
   170  	logrus.Fatal(err)
   171  	return
   172  }
   173  ```
   174  
   175  To spawn bash as the initial process inside the container and have the
   176  processes pid returned in order to wait, signal, or kill the process:
   177  
   178  ```go
   179  process := &libcontainer.Process{
   180  	Args:   []string{"/bin/bash"},
   181  	Env:    []string{"PATH=/bin"},
   182  	User:   "daemon",
   183  	Stdin:  os.Stdin,
   184  	Stdout: os.Stdout,
   185  	Stderr: os.Stderr,
   186  }
   187  
   188  err := container.Run(process)
   189  if err != nil {
   190  	container.Destroy()
   191  	logrus.Fatal(err)
   192  	return
   193  }
   194  
   195  // wait for the process to finish.
   196  _, err := process.Wait()
   197  if err != nil {
   198  	logrus.Fatal(err)
   199  }
   200  
   201  // destroy the container.
   202  container.Destroy()
   203  ```
   204  
   205  Additional ways to interact with a running container are:
   206  
   207  ```go
   208  // return all the pids for all processes running inside the container.
   209  processes, err := container.Processes()
   210  
   211  // get detailed cpu, memory, io, and network statistics for the container and
   212  // it's processes.
   213  stats, err := container.Stats()
   214  
   215  // pause all processes inside the container.
   216  container.Pause()
   217  
   218  // resume all paused processes.
   219  container.Resume()
   220  
   221  // send signal to container's init process.
   222  container.Signal(signal)
   223  
   224  // update container resource constraints.
   225  container.Set(config)
   226  
   227  // get current status of the container.
   228  status, err := container.Status()
   229  
   230  // get current container's state information.
   231  state, err := container.State()
   232  ```
   233  
   234  
   235  #### Checkpoint & Restore
   236  
   237  libcontainer now integrates [CRIU](http://criu.org/) for checkpointing and restoring containers.
   238  This let's you save the state of a process running inside a container to disk, and then restore
   239  that state into a new process, on the same machine or on another machine.
   240  
   241  `criu` version 1.5.2 or higher is required to use checkpoint and restore.
   242  If you don't already  have `criu` installed, you can build it from source, following the
   243  [online instructions](http://criu.org/Installation). `criu` is also installed in the docker image
   244  generated when building libcontainer with docker.
   245  
   246  
   247  ## Copyright and license
   248  
   249  Code and documentation copyright 2014 Docker, inc. Code released under the Apache 2.0 license.
   250  Docs released under Creative commons.
   251