github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/README.md (about) 1 # libcontainer 2 3 [](https://pkg.go.dev/github.com/opencontainers/runc/libcontainer) 4 5 Libcontainer provides a native Go implementation for creating containers 6 with namespaces, cgroups, capabilities, and filesystem access controls. 7 It allows you to manage the lifecycle of the container performing additional operations 8 after the container is created. 9 10 11 ## Container 12 A container is a self contained execution environment that shares the kernel of the 13 host system and which is (optionally) isolated from other containers in the system. 14 15 ## Using libcontainer 16 17 ### Container init 18 19 Because containers are spawned in a two step process you will need a binary that 20 will be executed as the init process for the container. In libcontainer, we use 21 the current binary (/proc/self/exe) to be executed as the init process, and use 22 arg "init", we call the first step process "bootstrap", so you always need a "init" 23 function as the entry of "bootstrap". 24 25 In addition to the go init function the early stage bootstrap is handled by importing 26 [nsenter](https://github.com/opencontainers/runc/blob/master/libcontainer/nsenter/README.md). 27 28 For details on how runc implements such "init", see 29 [init.go](https://github.com/opencontainers/runc/blob/master/init.go) 30 and [libcontainer/init_linux.go](https://github.com/opencontainers/runc/blob/master/libcontainer/init_linux.go). 31 32 ### Device management 33 34 If you want containers that have access to some devices, you need to import 35 this package into your code: 36 37 ```go 38 import ( 39 _ "github.com/opencontainers/runc/libcontainer/cgroups/devices" 40 ) 41 ``` 42 43 Without doing this, libcontainer cgroup manager won't be able to set up device 44 access rules, and will fail if devices are specified in the container 45 configuration. 46 47 ### Container creation 48 49 To create a container you first have to create a configuration 50 struct describing how the container is to be created. A sample would look similar to this: 51 52 ```go 53 defaultMountFlags := unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV 54 var devices []*devices.Rule 55 for _, device := range specconv.AllowedDevices { 56 devices = append(devices, &device.Rule) 57 } 58 config := &configs.Config{ 59 Rootfs: "/your/path/to/rootfs", 60 Capabilities: &configs.Capabilities{ 61 Bounding: []string{ 62 "CAP_CHOWN", 63 "CAP_DAC_OVERRIDE", 64 "CAP_FSETID", 65 "CAP_FOWNER", 66 "CAP_MKNOD", 67 "CAP_NET_RAW", 68 "CAP_SETGID", 69 "CAP_SETUID", 70 "CAP_SETFCAP", 71 "CAP_SETPCAP", 72 "CAP_NET_BIND_SERVICE", 73 "CAP_SYS_CHROOT", 74 "CAP_KILL", 75 "CAP_AUDIT_WRITE", 76 }, 77 Effective: []string{ 78 "CAP_CHOWN", 79 "CAP_DAC_OVERRIDE", 80 "CAP_FSETID", 81 "CAP_FOWNER", 82 "CAP_MKNOD", 83 "CAP_NET_RAW", 84 "CAP_SETGID", 85 "CAP_SETUID", 86 "CAP_SETFCAP", 87 "CAP_SETPCAP", 88 "CAP_NET_BIND_SERVICE", 89 "CAP_SYS_CHROOT", 90 "CAP_KILL", 91 "CAP_AUDIT_WRITE", 92 }, 93 Permitted: []string{ 94 "CAP_CHOWN", 95 "CAP_DAC_OVERRIDE", 96 "CAP_FSETID", 97 "CAP_FOWNER", 98 "CAP_MKNOD", 99 "CAP_NET_RAW", 100 "CAP_SETGID", 101 "CAP_SETUID", 102 "CAP_SETFCAP", 103 "CAP_SETPCAP", 104 "CAP_NET_BIND_SERVICE", 105 "CAP_SYS_CHROOT", 106 "CAP_KILL", 107 "CAP_AUDIT_WRITE", 108 }, 109 Ambient: []string{ 110 "CAP_CHOWN", 111 "CAP_DAC_OVERRIDE", 112 "CAP_FSETID", 113 "CAP_FOWNER", 114 "CAP_MKNOD", 115 "CAP_NET_RAW", 116 "CAP_SETGID", 117 "CAP_SETUID", 118 "CAP_SETFCAP", 119 "CAP_SETPCAP", 120 "CAP_NET_BIND_SERVICE", 121 "CAP_SYS_CHROOT", 122 "CAP_KILL", 123 "CAP_AUDIT_WRITE", 124 }, 125 }, 126 Namespaces: configs.Namespaces([]configs.Namespace{ 127 {Type: configs.NEWNS}, 128 {Type: configs.NEWUTS}, 129 {Type: configs.NEWIPC}, 130 {Type: configs.NEWPID}, 131 {Type: configs.NEWUSER}, 132 {Type: configs.NEWNET}, 133 {Type: configs.NEWCGROUP}, 134 }), 135 Cgroups: &configs.Cgroup{ 136 Name: "test-container", 137 Parent: "system", 138 Resources: &configs.Resources{ 139 MemorySwappiness: nil, 140 Devices: devices, 141 }, 142 }, 143 MaskPaths: []string{ 144 "/proc/kcore", 145 "/sys/firmware", 146 }, 147 ReadonlyPaths: []string{ 148 "/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus", 149 }, 150 Devices: specconv.AllowedDevices, 151 Hostname: "testing", 152 Mounts: []*configs.Mount{ 153 { 154 Source: "proc", 155 Destination: "/proc", 156 Device: "proc", 157 Flags: defaultMountFlags, 158 }, 159 { 160 Source: "tmpfs", 161 Destination: "/dev", 162 Device: "tmpfs", 163 Flags: unix.MS_NOSUID | unix.MS_STRICTATIME, 164 Data: "mode=755", 165 }, 166 { 167 Source: "devpts", 168 Destination: "/dev/pts", 169 Device: "devpts", 170 Flags: unix.MS_NOSUID | unix.MS_NOEXEC, 171 Data: "newinstance,ptmxmode=0666,mode=0620,gid=5", 172 }, 173 { 174 Device: "tmpfs", 175 Source: "shm", 176 Destination: "/dev/shm", 177 Data: "mode=1777,size=65536k", 178 Flags: defaultMountFlags, 179 }, 180 { 181 Source: "mqueue", 182 Destination: "/dev/mqueue", 183 Device: "mqueue", 184 Flags: defaultMountFlags, 185 }, 186 { 187 Source: "sysfs", 188 Destination: "/sys", 189 Device: "sysfs", 190 Flags: defaultMountFlags | unix.MS_RDONLY, 191 }, 192 }, 193 UIDMappings: []configs.IDMap{ 194 { 195 ContainerID: 0, 196 HostID: 1000, 197 Size: 65536, 198 }, 199 }, 200 GIDMappings: []configs.IDMap{ 201 { 202 ContainerID: 0, 203 HostID: 1000, 204 Size: 65536, 205 }, 206 }, 207 Networks: []*configs.Network{ 208 { 209 Type: "loopback", 210 Address: "127.0.0.1/0", 211 Gateway: "localhost", 212 }, 213 }, 214 Rlimits: []configs.Rlimit{ 215 { 216 Type: unix.RLIMIT_NOFILE, 217 Hard: uint64(1025), 218 Soft: uint64(1025), 219 }, 220 }, 221 } 222 ``` 223 224 Once you have the configuration populated you can create a container 225 with a specified ID under a specified state directory: 226 227 ```go 228 container, err := libcontainer.Create("/run/containers", "container-id", config) 229 if err != nil { 230 logrus.Fatal(err) 231 return 232 } 233 ``` 234 235 To spawn bash as the initial process inside the container and have the 236 processes pid returned in order to wait, signal, or kill the process: 237 238 ```go 239 process := &libcontainer.Process{ 240 Args: []string{"/bin/bash"}, 241 Env: []string{"PATH=/bin"}, 242 User: "daemon", 243 Stdin: os.Stdin, 244 Stdout: os.Stdout, 245 Stderr: os.Stderr, 246 Init: true, 247 } 248 249 err := container.Run(process) 250 if err != nil { 251 container.Destroy() 252 logrus.Fatal(err) 253 return 254 } 255 256 // wait for the process to finish. 257 _, err := process.Wait() 258 if err != nil { 259 logrus.Fatal(err) 260 } 261 262 // destroy the container. 263 container.Destroy() 264 ``` 265 266 Additional ways to interact with a running container are: 267 268 ```go 269 // return all the pids for all processes running inside the container. 270 processes, err := container.Processes() 271 272 // get detailed cpu, memory, io, and network statistics for the container and 273 // it's processes. 274 stats, err := container.Stats() 275 276 // pause all processes inside the container. 277 container.Pause() 278 279 // resume all paused processes. 280 container.Resume() 281 282 // send signal to container's init process. 283 container.Signal(signal) 284 285 // update container resource constraints. 286 container.Set(config) 287 288 // get current status of the container. 289 status, err := container.Status() 290 291 // get current container's state information. 292 state, err := container.State() 293 ``` 294 295 296 ## Checkpoint & Restore 297 298 libcontainer now integrates [CRIU](http://criu.org/) for checkpointing and restoring containers. 299 This lets you save the state of a process running inside a container to disk, and then restore 300 that state into a new process, on the same machine or on another machine. 301 302 `criu` version 1.5.2 or higher is required to use checkpoint and restore. 303 If you don't already have `criu` installed, you can build it from source, following the 304 [online instructions](http://criu.org/Installation). `criu` is also installed in the docker image 305 generated when building libcontainer with docker. 306 307 308 ## Copyright and license 309 310 Code and documentation copyright 2014 Docker, inc. 311 The code and documentation are released under the [Apache 2.0 license](../LICENSE). 312 The documentation is also released under Creative Commons Attribution 4.0 International License. 313 You may obtain a copy of the license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/.