容器配置文件

容器的顶级目录 必须 包含一个名为config.json的配置文件。 本文档中定义的是典型的结构,但是还有JSON结构schema/config-schema.json和Go版本的specs-go/config.go

配置文件包含对容器执行标准操作所需的元数据。这包括运行的进程,要注入的环境变量,要使用的沙箱功能等。

下面是配置文件中定义的每个字段的详细描述。

Specification version

  • ociVersion (string, REQUIRED) 必须 是符合SemVer v2.0.0格式的,并且指定bundle符合的开放容器运行时规范的版本。开放容器运行时规范遵守语义化版本并保证major版本的向前/后兼容性。例如,如果一个配置兼容本规范的1.1版本,则它必须兼容所有支持1.1和后续版本的运行时(runtime),但是不兼容支持1.0的运行时(runtime)。

Example

  1. "ociVersion": "0.1.0"

Root Configuration

root (object, REQUIRED) 配置容器的rootfs。

  • path (string, REQUIRED) 指定容器的rootfs路径。 路径可以是绝对路径(以/开头),也可以是相对于bundle的相对路径(不以/开头)。 For example (Linux), with a bundle at /to/bundle and a root filesystem at /to/bundle/rootfs, the path value can be either /to/bundle/rootfs or rootfs. 举个例子(Linux), bundle的目录是/to/bundle,rootfs的目录是/to/bundle/rootfs,那么path的值可以写成/to/bundle/rootf(绝对路径写法)或rootfs(相对路径写法)。 path内填写的目录 必须 存在。
  • readonly (bool, OPTIONAL) 设置成true则容器内的rootfs 必须 是只读的,默认是false。

Example

  1. "root": {
  2. "path": "rootfs",
  3. "readonly": true
  4. }

Mounts

mounts (array, OPTIONAL) 配置额外的mount(在root之上)。 运行时(runtime)必须 按列表顺序mount。 参数与the Linux mount system call类似。

  • destination (string, REQUIRED) 挂载点的目标地址:容器内的路径。 This value MUST be an absolute path. 此指必须是绝对路径。 Windows系统下,挂载点的目标地址 一定不能 和另外一个挂载点嵌套,例如c:\foo和c:\foo\bar。
  • type (string, REQUIRED) 需要mount的文件系统类型。 Linux:支持/proc/filesystems中列举的文件系统类型(如“minix”,“ext2”,“ext3”,“jfs”,“xfs”,“reiserfs”,”msdos“,”proc“,”nfs“, “iso9660”)。 Windows:ntfs。
  • source (string, REQUIRED) 设备名,也可以是目录名或虚拟设备。 Windows:挂载点目标的卷名,\?\Volume{GUID}\(Windows下source叫做target)。
  • options (list of strings, OPTIONAL) 文件系统mount参数。 Linux: supported options are listed in mount(8).

Example (Linux)

  1. "mounts": [
  2. {
  3. "destination": "/tmp",
  4. "type": "tmpfs",
  5. "source": "tmpfs",
  6. "options": ["nosuid","strictatime","mode=755","size=65536k"]
  7. },
  8. {
  9. "destination": "/data",
  10. "type": "bind",
  11. "source": "/volumes/testing",
  12. "options": ["rbind","rw"]
  13. }
  14. ]

Example (Windows)

  1. "mounts": [
  2. "myfancymountpoint": {
  3. "destination": "C:\\Users\\crosbymichael\\My Fancy Mount Point\\",
  4. "type": "ntfs",
  5. "source": "\\\\?\\Volume\\{2eca078d-5cbc-43d3-aff8-7e8511f60d0e}\\",
  6. "options": []
  7. }
  8. ]

有关详细信息,请参考mountvolSetVolumeMountPoint.aspx)(Windows)。

Process configuration

process (object, REQUIRED) 配置容器的进程。

  • terminal (bool, optional) 指定是否需要连接该进程的终端,默认是false。 On Linux, a pseudoterminal pair is allocated for the container process and the pseudoterminal slave is duplicated on the container process’s standard streams.
  • consoleSize (object, OPTIONAL) 指定终端的控制台窗口大小(如果连接了终端),包含以下属性:
    • height (uint, REQUIRED)
    • width (uint, REQUIRED)
  • cwd (string, REQUIRED) 为可执行文件设置工作目录。此值 必须 是绝对路径。
  • env (array of strings, OPTIONAL) 包含一组在进程执行前设置到其环境中的变量。数组里的元素指定为“KEY=value”格式的字符串。左侧(KEY) 必须 只包含字母,数字和下划线_,如IEEE Std 1003.1-2001.
  • args (array of strings, REQUIRED) 可执行文件和一组标志(flags)。可执行文件是第一个数组的第一个元素,并且 必须 存在于给定的路径里。如果可执行文件的路径不是绝对路径,则通过$PATH查找可执行文件。

对于基于Linux的系统,进程结构支持以下特定字段:

  • capabilities (array of strings, OPTIONAL) capabilities是一个数组,用于指定可以提供给容器内部进程的capabilities。有效值均是字符串,且定义在the man page
  • rlimits (array of rlimits, OPTIONAL) rlimits is an array of rlimits that allows setting resource limits for a process inside the container. The kernel enforces the soft limit for a resource while the hard limit acts as a ceiling for that value that could be set by an unprivileged process. Valid values for the ‘type’ field are the resources defined in the man page.
  • apparmorProfile (string, OPTIONAL) 指定容器使用的apparmor配置文件名字。有关Apparmor的更多信息,请参考Apparmor documentation
  • selinuxLabel (string, OPTIONAL) 指定容器内进程运行时使用的SELinux标签。有关SELinux的更多信息,请参考Selinux documentation
  • noNewPrivileges (bool, OPTIONAL) 将noNewPrivileges设置成true可以阻止容器内的进程申请额外的权限。 The kernel doc上有更多关于该功能如何使用prctl系统调用实现的信息。

User

进程的用户是平台特定的结构,允许控制进程以哪个具体的用户运行。

Linux and Solaris User

基于Linux和Solaris的系统,用户结构有以下字段:

Note: 分别用于uid和gid的symbolic name,例如uname和game,留给更高级去导出(如解析/etcpasswd,NSS等)。

Note: Solaris下,uid和gid指定容器内进程的uid和gid,并且不需要和宿主机一致。

Example (Linux)

  1. "process": {
  2. "terminal": true,
  3. "consoleSize": {
  4. "height": 25,
  5. "width": 80
  6. },
  7. "user": {
  8. "uid": 1,
  9. "gid": 1,
  10. "additionalGids": [5, 6]
  11. },
  12. "env": [
  13. "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  14. "TERM=xterm"
  15. ],
  16. "cwd": "/root",
  17. "args": [
  18. "sh"
  19. ],
  20. "apparmorProfile": "acme_secure_profile",
  21. "selinuxLabel": "system_u:system_r:svirt_lxc_net_t:s0:c124,c675",
  22. "noNewPrivileges": true,
  23. "capabilities": [
  24. "CAP_AUDIT_WRITE",
  25. "CAP_KILL",
  26. "CAP_NET_BIND_SERVICE"
  27. ],
  28. "rlimits": [
  29. {
  30. "type": "RLIMIT_NOFILE",
  31. "hard": 1024,
  32. "soft": 1024
  33. }
  34. ]
  35. }

Example (Solaris)

  1. "process": {
  2. "terminal": true,
  3. "consoleSize": {
  4. "height": 25,
  5. "width": 80
  6. },
  7. "user": {
  8. "uid": 1,
  9. "gid": 1,
  10. "additionalGids": [2, 8]
  11. },
  12. "env": [
  13. "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  14. "TERM=xterm"
  15. ],
  16. "cwd": "/root",
  17. "args": [
  18. "/usr/bin/bash"
  19. ]
  20. }

Windows User

基于Windows的系统,用户结构有以下的字段:

  • username (string, OPTIONAL) 指定进程的用户名。

Example (Windows)

  1. "process": {
  2. "terminal": true,
  3. "user": {
  4. "username": "containeradministrator"
  5. },
  6. "env": [
  7. "VARIABLE=1"
  8. ],
  9. "cwd": "c:\\foo",
  10. "args": [
  11. "someapp.exe",
  12. ]
  13. }

Hostname

  • hostname (string, OPTIONAL) 配置容器中运行的进程能看到的容器主机名。Linux环境下,你只能在创建了新的UTS namespace后才能设置此值。

Example

  1. "hostname": "mrsdalloway"

Platform

platform 指定了配置的目标平台。

  • os (string, REQUIRED) 指定这个镜像对应的操作系统系列。 如果运行时(runtime)不支持配置的 os 必须 报错。 Bundles SHOULD use, and runtimes SHOULD understand, os entries listed in the Go Language document for $GOOS. 如果某个操作系统没有列在$GOOS的文档里,那么它 应该 被提交到这个规范里做标准化。
  • arch (string, REQUIRED) 指定了镜像内二进制文件编译用到的指令集。 如果运行时(runtime)不支持配置的 arch 必须 报错。 Values for arch SHOULD use, and runtimes SHOULD understand, arch entries listed in the Go Language document for $GOARCH. 如果某个架构没有列在$GOARCH文档里,那么它 应该 被提交到这个规范里做标准化。

Example

  1. "platform": {
  2. "os": "linux",
  3. "arch": "amd64"
  4. }

Platform-specific configuration

platform.os 用于检查进一步的平台相关的配置。

Example (Linux)

  1. {
  2. "platform": {
  3. "os": "linux",
  4. "arch": "amd64"
  5. },
  6. "linux": {
  7. "namespaces": [
  8. {
  9. "type": "pid"
  10. }
  11. ]
  12. }
  13. }

Hooks

hooks (object, OPTIONAL) 用来配置容器生命周期事件的回调。 Liftcycle hooks允许对容器运行时(runtime)的许多(逻辑)点自定义事件。 目前有PrestartPoststartPoststop

  • Prestart 容器进程运行前被调用的一组钩子。
  • Poststart 容器进程运行后立即被调用的一组钩子。
  • Poststop 容器进程退出后被调用的一组钩子。

钩子允许在容器的各种生命周期事件之前/之后运行代码。钩子 必须 按照列表顺序(声明顺序)被调用。容器的状态会通过stdin传入到钩子内,这样钩子(程序)就可以拿到它们工作需要的信息。

钩子的路径是绝对路径,并且可以在runtime namespace中执行。

Prestart

pre-start钩子在容器进程产生后,用户提供的命令执行之前被调用。Linux下,他们在容器的namespaces创建以后被调用,因此提供了自定义容器的机会。举个例子, 在此钩子里可以配置network namespace。

如果钩子返回了非零的退出码(参考shell中的$?),则一个包含了退出码和stderr的错误被返回给调用者,同时容器被回收。

Poststart

post-start钩子在用户进程运行启动后被调用。举个例子,这个钩子可以通知用户真正产生的进程(的PID或其他balabala)。

如果钩子返回了非零的退出码(参考shell中的$?),记录下错误并继续执行剩下的钩子。

Poststop

post-stop钩子在容器进程停止后被调用。可以在此钩子中执行清理或调试工作。

如果钩子返回了非零的退出码(参考shell中的$?),记录下错误并继续执行剩下的钩子。

Example

  1. "hooks": {
  2. "prestart": [
  3. {
  4. "path": "/usr/bin/fix-mounts",
  5. "args": ["fix-mounts", "arg1", "arg2"],
  6. "env": [ "key1=value1"]
  7. },
  8. {
  9. "path": "/usr/bin/setup-network"
  10. }
  11. ],
  12. "poststart": [
  13. {
  14. "path": "/usr/bin/notify-start",
  15. "timeout": 5
  16. }
  17. ],
  18. "poststop": [
  19. {
  20. "path": "/usr/sbin/cleanup.sh",
  21. "args": ["cleanup.sh", "-f"]
  22. }
  23. ]
  24. }

path is REQUIRED for a hook. args and env are OPTIONAL. timeout is the number of seconds before aborting the hook. The semantics are the same as Path, Args and Env in golang Cmd.

Annotations

annotations (object, OPTIONAL) 包含了容器的任意元数据。 这些元数据信息 可能 是结构化的或非结构化的。 注解 必须 是键值对映射,而且键值 必须 是字符串。 值 必须 存在,但 可能 是空字符串(Java对照HashMap理解)。 键在映射中 必须 是唯一的,最好的办法就是使用命名空间。 键 应该 以反向域名的方式命名 —— 比如 com.example.myKeyorg.opencontainers命名空间下的键是保留关键字,并且 一定不能 被后续的规范使用。 如果没有注解,此值 可能 不存在或者是空映射。 正在读取/处理配置文件的(runtime)实现 一定不能 在遇到一个未知属性时报错。

  1. "annotations": {
  2. "com.example.gpu-cores": "2"
  3. }

Extensibility

正在读取/处理配置文件的(runtime)实现 一定不能 在遇到一个未知属性时报错,而是 必须 忽略这些未知的属性。

Configuration Schema Example

这是一个可供参考的完整的config.json例子。

  1. {
  2. "ociVersion": "0.5.0-dev",
  3. "platform": {
  4. "os": "linux",
  5. "arch": "amd64"
  6. },
  7. "process": {
  8. "terminal": true,
  9. "user": {
  10. "uid": 1,
  11. "gid": 1,
  12. "additionalGids": [
  13. 5,
  14. 6
  15. ]
  16. },
  17. "args": [
  18. "sh"
  19. ],
  20. "env": [
  21. "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  22. "TERM=xterm"
  23. ],
  24. "cwd": "/",
  25. "capabilities": [
  26. "CAP_AUDIT_WRITE",
  27. "CAP_KILL",
  28. "CAP_NET_BIND_SERVICE"
  29. ],
  30. "rlimits": [
  31. {
  32. "type": "RLIMIT_CORE",
  33. "hard": 1024,
  34. "soft": 1024
  35. },
  36. {
  37. "type": "RLIMIT_NOFILE",
  38. "hard": 1024,
  39. "soft": 1024
  40. }
  41. ],
  42. "apparmorProfile": "acme_secure_profile",
  43. "selinuxLabel": "system_u:system_r:svirt_lxc_net_t:s0:c124,c675",
  44. "noNewPrivileges": true
  45. },
  46. "root": {
  47. "path": "rootfs",
  48. "readonly": true
  49. },
  50. "hostname": "slartibartfast",
  51. "mounts": [
  52. {
  53. "destination": "/proc",
  54. "type": "proc",
  55. "source": "proc"
  56. },
  57. {
  58. "destination": "/dev",
  59. "type": "tmpfs",
  60. "source": "tmpfs",
  61. "options": [
  62. "nosuid",
  63. "strictatime",
  64. "mode=755",
  65. "size=65536k"
  66. ]
  67. },
  68. {
  69. "destination": "/dev/pts",
  70. "type": "devpts",
  71. "source": "devpts",
  72. "options": [
  73. "nosuid",
  74. "noexec",
  75. "newinstance",
  76. "ptmxmode=0666",
  77. "mode=0620",
  78. "gid=5"
  79. ]
  80. },
  81. {
  82. "destination": "/dev/shm",
  83. "type": "tmpfs",
  84. "source": "shm",
  85. "options": [
  86. "nosuid",
  87. "noexec",
  88. "nodev",
  89. "mode=1777",
  90. "size=65536k"
  91. ]
  92. },
  93. {
  94. "destination": "/dev/mqueue",
  95. "type": "mqueue",
  96. "source": "mqueue",
  97. "options": [
  98. "nosuid",
  99. "noexec",
  100. "nodev"
  101. ]
  102. },
  103. {
  104. "destination": "/sys",
  105. "type": "sysfs",
  106. "source": "sysfs",
  107. "options": [
  108. "nosuid",
  109. "noexec",
  110. "nodev"
  111. ]
  112. },
  113. {
  114. "destination": "/sys/fs/cgroup",
  115. "type": "cgroup",
  116. "source": "cgroup",
  117. "options": [
  118. "nosuid",
  119. "noexec",
  120. "nodev",
  121. "relatime",
  122. "ro"
  123. ]
  124. }
  125. ],
  126. "hooks": {
  127. "prestart": [
  128. {
  129. "path": "/usr/bin/fix-mounts",
  130. "args": [
  131. "fix-mounts",
  132. "arg1",
  133. "arg2"
  134. ],
  135. "env": [
  136. "key1=value1"
  137. ]
  138. },
  139. {
  140. "path": "/usr/bin/setup-network"
  141. }
  142. ],
  143. "poststart": [
  144. {
  145. "path": "/usr/bin/notify-start",
  146. "timeout": 5
  147. }
  148. ],
  149. "poststop": [
  150. {
  151. "path": "/usr/sbin/cleanup.sh",
  152. "args": [
  153. "cleanup.sh",
  154. "-f"
  155. ]
  156. }
  157. ]
  158. },
  159. "linux": {
  160. "devices": [
  161. {
  162. "path": "/dev/fuse",
  163. "type": "c",
  164. "major": 10,
  165. "minor": 229,
  166. "fileMode": 438,
  167. "uid": 0,
  168. "gid": 0
  169. },
  170. {
  171. "path": "/dev/sda",
  172. "type": "b",
  173. "major": 8,
  174. "minor": 0,
  175. "fileMode": 432,
  176. "uid": 0,
  177. "gid": 0
  178. }
  179. ],
  180. "uidMappings": [
  181. {
  182. "hostID": 1000,
  183. "containerID": 0,
  184. "size": 32000
  185. }
  186. ],
  187. "gidMappings": [
  188. {
  189. "hostID": 1000,
  190. "containerID": 0,
  191. "size": 32000
  192. }
  193. ],
  194. "sysctl": {
  195. "net.ipv4.ip_forward": "1",
  196. "net.core.somaxconn": "256"
  197. },
  198. "cgroupsPath": "/myRuntime/myContainer",
  199. "resources": {
  200. "network": {
  201. "classID": 1048577,
  202. "priorities": [
  203. {
  204. "name": "eth0",
  205. "priority": 500
  206. },
  207. {
  208. "name": "eth1",
  209. "priority": 1000
  210. }
  211. ]
  212. },
  213. "pids": {
  214. "limit": 32771
  215. },
  216. "hugepageLimits": [
  217. {
  218. "pageSize": "2MB",
  219. "limit": 9223372036854772000
  220. }
  221. ],
  222. "oomScoreAdj": 100,
  223. "memory": {
  224. "limit": 536870912,
  225. "reservation": 536870912,
  226. "swap": 536870912,
  227. "kernel": 0,
  228. "kernelTCP": 0,
  229. "swappiness": 0
  230. },
  231. "cpu": {
  232. "shares": 1024,
  233. "quota": 1000000,
  234. "period": 500000,
  235. "realtimeRuntime": 950000,
  236. "realtimePeriod": 1000000,
  237. "cpus": "2-3",
  238. "mems": "0-7"
  239. },
  240. "disableOOMKiller": false,
  241. "devices": [
  242. {
  243. "allow": false,
  244. "access": "rwm"
  245. },
  246. {
  247. "allow": true,
  248. "type": "c",
  249. "major": 10,
  250. "minor": 229,
  251. "access": "rw"
  252. },
  253. {
  254. "allow": true,
  255. "type": "b",
  256. "major": 8,
  257. "minor": 0,
  258. "access": "r"
  259. }
  260. ],
  261. "blockIO": {
  262. "blkioWeight": 10,
  263. "blkioLeafWeight": 10,
  264. "blkioWeightDevice": [
  265. {
  266. "major": 8,
  267. "minor": 0,
  268. "weight": 500,
  269. "leafWeight": 300
  270. },
  271. {
  272. "major": 8,
  273. "minor": 16,
  274. "weight": 500
  275. }
  276. ],
  277. "blkioThrottleReadBpsDevice": [
  278. {
  279. "major": 8,
  280. "minor": 0,
  281. "rate": 600
  282. }
  283. ],
  284. "blkioThrottleWriteIOPSDevice": [
  285. {
  286. "major": 8,
  287. "minor": 16,
  288. "rate": 300
  289. }
  290. ]
  291. }
  292. },
  293. "rootfsPropagation": "slave",
  294. "seccomp": {
  295. "defaultAction": "SCMP_ACT_ALLOW",
  296. "architectures": [
  297. "SCMP_ARCH_X86"
  298. ],
  299. "syscalls": [
  300. {
  301. "name": "getcwd",
  302. "action": "SCMP_ACT_ERRNO"
  303. }
  304. ]
  305. },
  306. "namespaces": [
  307. {
  308. "type": "pid"
  309. },
  310. {
  311. "type": "network"
  312. },
  313. {
  314. "type": "ipc"
  315. },
  316. {
  317. "type": "uts"
  318. },
  319. {
  320. "type": "mount"
  321. },
  322. {
  323. "type": "user"
  324. },
  325. {
  326. "type": "cgroup"
  327. }
  328. ],
  329. "maskedPaths": [
  330. "/proc/kcore",
  331. "/proc/latency_stats",
  332. "/proc/timer_stats",
  333. "/proc/sched_debug"
  334. ],
  335. "readonlyPaths": [
  336. "/proc/asound",
  337. "/proc/bus",
  338. "/proc/fs",
  339. "/proc/irq",
  340. "/proc/sys",
  341. "/proc/sysrq-trigger"
  342. ],
  343. "mountLabel": "system_u:object_r:svirt_sandbox_file_t:s0:c715,c811"
  344. },
  345. "annotations": {
  346. "com.example.key1": "value1",
  347. "com.example.key2": "value2"
  348. }
  349. }