• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..01-Jun-2021-

apparmor/H01-Jun-2021-8256

cgroups/H01-Jun-2021-874610

configs/H01-Jun-2021-1,200699

devices/H01-Jun-2021-11495

nsenter/H01-Jun-2021-1,6971,011

user/H01-Jun-2021-833583

utils/H01-Jun-2021-276170

README.mdH A D01-Jun-20219.6 KiB331294

README.md

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