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