Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Runtime CLI Spec #513

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ DOC_FILES := \
bundle.md \
runtime.md \
runtime-linux.md \
command-line-interface.md \
config.md \
config-linux.md \
config-solaris.md \
Expand Down
260 changes: 260 additions & 0 deletions command-line-interface.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
# Runtime Command Line Interface

This section defines the runtime command line interface version 1.0.0.
It is one of potentially several [runtime APIs defined by this specification](README.md).

## Versioning

The command line interface is versioned with [SemVer v2.0.0][semver].
The command line interface version is independent of the OCI Runtime Specification as a whole (which is tied to the [configuration format](config.md#specification-version)).
For example, if a caller is compliant with version 1.1 of the command line interface, they are compatible with all runtimes that support any 1.1 or later release of the command line interface, but are not compatible with a runtime that supports 1.0 and not 1.1.

## Global usage

The [runtime][] MUST provide an executable (called `funC` in the following examples).
That executable MUST support commands with the following template:

```
$ funC [global-options] <COMMAND> [command-specific-options] <command-specific-arguments>
```

## Global options

None are required, but the runtime MAY support options that start with at least one hyphen.
Global options MAY take positional arguments (e.g. `--log-level debug`).
Command names MUST NOT start with hyphens.
The option parsing MUST be such that `funC <COMMAND>` is unambiguously an invocation of `<COMMAND>` (even for commands not specified in this document).
If the runtime is invoked with an unrecognized command, it MUST exit with a nonzero exit code and MAY log a warning to stderr.
Beyond the above rules, the behavior of the runtime in the presence of commands and options not specified in this document is unspecified.

## Character encodings

This API specification does not cover character encodings, but runtimes SHOULD conform to their native operating system.
For example, POSIX systems define [`LANG` and related environment variables][posix-lang] for [declaring][posix-locale-encoding] [locale-specific character encodings][posix-encoding], so a runtime in an `en_US.UTF-8` locale SHOULD write its [state](#state) to stdout in [UTF-8][].

## Commands

### create

[Create][create] a container from a [bundle directory][bundle].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add one line to each command showing usage syntax - e.g.

funC [ options ] create ID

When all you care about (quickly) is the syntax of the command, this is much easier to read.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Thu, Jul 28, 2016 at 11:54:26AM -0700, Doug Davis wrote:

+[Create][create] a container from a [bundle directory][bundle].

Let's add one line to each command showing usage syntax - e.g.

funC [ options ] create ID

When all you care about (quickly) is the syntax of the command, this
is much easier to read.

So:

funC [global-options] create [command-specific-options]

Or:

funC [global-options] create [--bundle ] [--pid-file ]

I'm ok with that, although I think “how do I use this quickly” is
better answered by the example sections 1.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please, no spec by example! :-)

I would choose to not include each option in there just because it could get kind of long - but I'm not totally against it since we don't have too many. Tested just a few linux commands and their usage line seemed to just show generic [OPTIONS] type of stuff - so I'd go for that. e.g. Usage: tar [OPTION...] [FILE]...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Thu, Jul 28, 2016 at 12:37:06PM -0700, Doug Davis wrote:

please, no spec by example! :-)

The normative spec is already covered by the initial MUST template
[1], global options section [2], and option/argument docs [3]. This
command-specific template would be informative. Anyhow, I'll push
those per-command templates shortly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Thu, Jul 28, 2016 at 01:01:02PM -0700, W. Trevor King wrote:

Anyhow, I'll push those per-command templates shortly.

Hmm, I was working this up, but it just ends up being:

$ funC [global-options] create [command-specific-options]
$ funC [global-options] start [command-specific-options]
$ funC [global-options] state [command-specific-options]
$ funC [global-options] kill [command-specific-options]
$ funC [global-options] delete [command-specific-options]

Is that really all that useful for you 1? We need the
[global-options] and [command-specific-options] bits because we allow
runtimes to add additional command line options as they see fit (as
long as invocations that only use commands and options defined in this
spec work as expected).


* *Arguments*
* *`<ID>`* Set the container ID to create.
* *Options*
* *`--bundle <PATH>`* Override the path to the [bundle directory][bundle] (defaults to the current working directory).
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This matches runC implementation but conflicts with the runtime specification:
https://github.com/opencontainers/runtime-spec/blob/master/runtime.md#create

There the bundle path is an argument, not a command line option.

Copy link
Member

@cyphar cyphar Nov 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really convinced, my reading of that entire document is that you have to have an operation called create which must take the arguments for a bundle and a container ID. However, in the CLI the bundle path is implicitly the current directory so you don't need to explicitly pass it (but you can explicitly pass it if you want).

Maybe we should just fix the way create is explained but then you have to make a distinction about having no bundle means that the runtime can have an arbitrary default.

Ultimately it all boils down to the fact that using runC like this would get super annoying super quick:

% runc run --bundle . container

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Tue, Nov 15, 2016 at 03:07:30AM -0800, Aleksa Sarai wrote:

… my reading of that entire document is that you have to have an operation called create which must take the arguments for a bundle and a container ID. However, in the CLI the bundle path is implicitly the current directory so you don't need to explicitly pass it (but you can explicitly pass it if you want).

This is my understanding as well, with the key line here (#450).

* *`--pid-file <PATH>`* The runtime MUST write the container PID to this path.
* *Standard streams:*
* If [`process.terminal`][process] is true:
* *stdin:* The runtime MUST NOT attempt to read from its stdin.
* *stdout:* The handling of stdout is unspecified.
* *stderr:* The runtime MAY print diagnostic messages to stderr, and the format for those lines is not specified in this document.
* If [`process.terminal`][process] is not true:
* *stdin:* The runtime MUST pass its stdin file descriptor through to the container process without manipulation or modification.
"Without manipulation or modification" means that the runtime MUST not seek on the file descriptor, or close it, or read or write to it, or [`ioctl`][ioctl.3] it, or perform any other action on it besides passing it through to the container process.

When using a container to drop privileges, note that providing a privileged terminal's file descriptor may allow the container to [execute privileged operations via `TIOCSTI`][TIOCSTI-security] or other [TTY ioctls][tty_ioctl.4].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this level of detail here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this level of detail here.

@cyphar requested a TIOCSTI mention. I don't care either way, so sort it out with him and tell me what to do.

On Linux, [`TIOCSTI` requires `CAP_SYS_ADMIN`][capabilities.7] unless the target terminal is the caller's [controlling terminal][controlling-terminal].
* *stdout:* The runtime MUST pass its stdout file descriptor through to the container process without manipulation or modification.
* *stderr:* When `create` exists with a zero code, the runtime MUST pass its stderr file descriptor through to the container process without manipulation or modification.
When `create` exits with a non-zero code, the runtime MAY print diagnostic messages to stderr, and the format for those lines is not specified in this document.
* *Environment variables*
* *`LISTEN_FDS`:* The number of file descriptors passed.
For example, `LISTEN_FDS=2` would mean that the runtime MUST pass file descriptors 3 and 4 to the container process (in addition to the standard streams) to support [socket activation][systemd-listen-fds].
* *Additional file descriptors*
* If [`process.terminal`][process] is true, the caller MUST provide an open [`AF_UNIX` socket][unix-socket] on file descriptor `$LISTEN_FDS + 3`.
The runtime MUST pass the [pseudoterminal master][posix_openpt.3] through the socket; the protocol is [described below](#console-socket).
* *Exit code:* Zero if the container was successfully created and non-zero on errors.

Callers MAY block on this command's successful exit to trigger post-create activity.

#### Console socket

The [`AF_UNIX`][unix-socket] used by [`--console-socket`](#create) handles request and response messages between a runtime and server.
The socket type MUST be [`SOCK_SEQPACKET`][socket-types] or [`SOCK_STREAM`][socket-types].
The server MUST send a single response for each runtime request.
The [normal data][socket-queue] ([`msghdr.msg_iov*`][socket.h]) of all messages MUST be [UTF-8][] [JSON](glossary.md#json).

There are [JSON Schemas](schema/README.md) and [Go bindings](specs-go/socket/socket.go) for the messages specified in this section.

##### Requests

All requests MUST contain a **`type`** property whose value MUST one of the following strings:

* `terminal`, if the request is passing a [pseudoterminal master][posix_openpt.3].
When `type` is `terminal`, the request MUST also contain the following properties:

* **`container`** (string, REQUIRED) The container ID, as set by [create](#create).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we please also put this structure into the spec, and give it a name? I'd prefer that we move libcontainer.TerminalInfo out of there as soon as possible. :D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done with 4bf0a63b36d3a3.


The message's [ancillary data][socket-queue] (`msg_control*`) MUST contain at least one [`cmsghdr`][socket.h]).
The first `cmsghdr` MUST have:

* `cmsg_type` set to [`SOL_SOCKET`][socket.h],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will have to check how cross platform console-socket is.
cc: @RobDolinMS

* `cmsg_level` set to [`SCM_RIGHTS`][socket.h],
* `cmsg_len` greater than or equal to `CMSG_LEN(sizeof(int))`, and
* `((int*)CMSG_DATA(cmsg))[0]` set to the pseudoterminal master file descriptor.

##### Responses

All responses MUST contain a **`type`** property whose value MUST be one of the following strings:

* `success`, if the request was successfully processed.
* `error`, if the request was not successfully processed.

In addition, responses MAY contain any of the following properties:

* **`message`** (string, OPTIONAL) A phrase describing the response.

#### Example

```
# in a bundle directory with a process that echos "hello" and exits 42
$ test -t 1 && echo 'stdout is a terminal'
stdout is a terminal
$ funC create hello-1 <&- >stdout 2>stderr
$ echo $?
0
$ wc stdout
0 0 0 stdout
$ funC start hello-1
$ echo $?
0
$ cat stdout
hello
$ block-on-exit-and-collect-exit-code hello-1
$ echo $?
42
$ funC delete hello-1
$ echo $?
0
```

#### Container process exit

The [example's](#example) `block-on-exit-and-collect-exit-code` is platform-specific and is not specified in this document.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to drop this markdown link as we have already get so many links in this doc, "example" here is clear enough to explain itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like having the link, but don't feel particularly strongly about it. If more folks chime in asking to remove the link, I'll remove it.

On Linux, it might involve an ancestor process which had set [`PR_SET_CHILD_SUBREAPER`][prctl.2] and collected the container PID [from the state][state], or a process that was [ptracing][ptrace.2] the container process for [`exit_group`][exit_group.2], although both of those race against the container process exiting before the watcher is monitoring.

### start

[Start][start] the user-specified code from [`process`][process].

* *Arguments*
* *`<ID>`* The container to start.
* *Standard streams:*
* *stdin:* The runtime MUST NOT attempt to read from its stdin.
* *stdout:* The handling of stdout is unspecified.
* *stderr:* The runtime MAY print diagnostic messages to stderr, and the format for those lines is not specified in this document.
* *Exit code:* Zero if the container was successfully started and non-zero on errors.

Callers MAY block on this command's successful exit to trigger post-start activity.

See [create](#example) for an example.

### state

[Request][state-request] the container [state][state].

* *Arguments*
* *`<ID>`* The container whose state is being requested.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ID of the container...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather talk about “the container” and leave the fact that we're referencing it by ID to the <ID> name. I've standardized around that approach with 9db8f494dd1a13. But if that doesn't make sense to you and you prefer “the ID of the container…” for all by-ID references, I can push a further update to go that way instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wking I think it is fine as long as we are consistent.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to tie it better .. id for the container is better than id of the container.

Copy link
Contributor Author

@wking wking Oct 28, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mikebrow, are you not satisfied with the consistent-since-4dd1a13 phrasing (which didn't change this line)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is fine.. just saying if you're going to change it .. I would suggest using "id for the container" vs "id of the container." More particularly in this case it would be:
<ID> - for the container whose state is being requested.

* *Standard streams:*
* *stdin:* The runtime MUST NOT attempt to read from its stdin.
* *stdout:* The runtime MUST print the [state JSON][state] to its stdout.
* *stderr:* The runtime MAY print diagnostic messages to stderr, and the format for those lines is not specified in this document.
* *Exit code:* Zero if the state was successfully written to stdout and non-zero on errors.

#### Example

```
# in a bundle directory with a process that sleeps for several seconds
$ funC start --id sleeper-1 &
$ funC state sleeper-1
{
"ociVersion": "1.0.0-rc1",
"id": "sleeper-1",
"status": "running",
"pid": 4422,
"bundlePath": "/containers/sleeper",
"annotations" {
"myKey": "myValue"
}
}
$ echo $?
0
```

### kill

[Send a signal][kill] to the container process.

* *Arguments*
* *`<ID>`* The container being signaled.
* *Options*
* *`--signal <SIGNAL>`* The signal to send (defaults to `TERM`).
The runtime MUST support `TERM` and `KILL` signals with [the POSIX semantics][posix-signals].
The runtime MAY support additional signal names.
On platforms that support [POSIX signals][posix-signals], the runtime MUST implement this command using POSIX signals.
On platforms that do not support POSIX signals, the runtime MAY implement this command with alternative technology as long as `TERM` and `KILL` retain their POSIX semantics.
Runtime authors on non-POSIX platforms SHOULD submit documentation for their TERM implementation to this specificiation, so runtime callers can configure the container process to gracefully handle the signals.
* *Standard streams:*
* *stdin:* The runtime MUST NOT attempt to read from its stdin.
* *stdout:* The handling of stdout is unspecified.
* *stderr:* The runtime MAY print diagnostic messages to stderr, and the format for those lines is not specified in this document.
* *Exit code:* Zero if the signal was successfully sent to the container process and non-zero on errors.
Successfully sent does not mean that the signal was successfully received or handled by the container process.

#### Example

```
# in a bundle directory with a process ignores TERM
$ funC start --id sleeper-1 &
$ funC kill sleeper-1
$ echo $?
0
$ funC kill --signal KILL sleeper-1
$ echo $?
0
```

### delete

[Release](#delete) container resources after the container process has exited.

* *Arguments*
* *`<ID>`* The container to delete.
* *Standard streams:*
* *stdin:* The runtime MUST NOT attempt to read from its stdin.
* *stdout:* The handling of stdout is unspecified.
* *stderr:* The runtime MAY print diagnostic messages to stderr, and the format for those lines is not specified in this document.
* *Exit code:* Zero if the container was successfully deleted and non-zero on errors.

See [create](#example) for an example.

[bundle]: bundle.md
[controlling-terminal]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap11.html#tag_11_01_03
[create]: runtime.md#create
[delete]: runtime.md#delete
[exit_group.2]: http://man7.org/linux/man-pages/man2/exit_group.2.html
[ioctl.3]: http://pubs.opengroup.org/onlinepubs/9699919799/
[kill]: runtime.md#kill
[kill.2]: http://man7.org/linux/man-pages/man2/kill.2.html
[process]: config.md#process-configuration
[posix-encoding]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap06.html#tag_06_02
[posix-lang]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_02
[posix-locale-encoding]: http://www.unicode.org/reports/tr35/#Bundle_vs_Item_Lookup
[posix_openpt.3]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html
[posix-signals]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html#tag_13_42_03
[prctl.2]: http://man7.org/linux/man-pages/man2/prctl.2.html
[ptrace.2]: http://man7.org/linux/man-pages/man2/ptrace.2.html
[runtime]: glossary.md#runtime
[semver]: http://semver.org/spec/v2.0.0.html
[socket-queue]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_10_11
[socket-types]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_10_06
[socket.h]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html
[standard-streams]: https://github.com/opencontainers/specs/blob/v0.1.1/runtime-linux.md#file-descriptors
[start]: runtime.md#start
[state]: runtime.md#state
[state-request]: runtime.md#query-state
[systemd-listen-fds]: http://www.freedesktop.org/software/systemd/man/sd_listen_fds.html
[TIOCSTI-security]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=628843
[tty_ioctl.4]: http://man7.org/linux/man-pages/man4/tty_ioctl.4.html
[unix-socket]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_10_17
[UTF-8]: http://www.unicode.org/versions/Unicode8.0.0/ch03.pdf
6 changes: 0 additions & 6 deletions runtime-linux.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
# <a name="linuxRuntime" />Linux Runtime

## <a name="runtimeLinuxFileDescriptors" />File descriptors

By default, only the `stdin`, `stdout` and `stderr` file descriptors are kept open for the application by the runtime.
The runtime MAY pass additional file descriptors to the application to support features such as [socket activation](http://0pointer.de/blog/projects/socket-activated-containers.html).
Some of the file descriptors MAY be redirected to `/dev/null` even though they are open.

## <a name="runtimeLinuxDevSymbolicLinks" /> Dev symbolic links

After the container has `/proc` mounted, the following standard symlinks MUST be setup within `/dev/` for the IO.
Expand Down
11 changes: 11 additions & 0 deletions runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,14 @@ Once a container is deleted its ID MAY be used by a subsequent container.
## Hooks
Many of the operations specified in this specification have "hooks" that allow for additional actions to be taken before or after each operation.
See [runtime configuration for hooks](./config.md#hooks) for more information.

## Container environment

The following sections discuss portions of the container environment which are not configurable via the [configuration JSON](config.md).
Beyond the sections below, there are additional platform-specific requirements for [Linux](runtime-linux.md).

### Standard streams

All OCI-specified runtime APIs MUST allow runtime-callers to specify the file descriptors which will be inherited by the container process, with the [POSIX *exec* caveat][exec] that if file descriptor 0, 1, or 2 would otherwise be closed, the container process may have unspecified files opened for those file descriptors.

[exec]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/execve.html
2 changes: 2 additions & 0 deletions schema/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ The layout of the files is as follows:
* [config-linux.json](config-linux.json) - the [Linux-specific configuration sub-structure](../config-linux.md)
* [config-solaris.json](config-solaris.json) - the [Solaris-specific configuration sub-structure](../config-solaris.md)
* [config-windows.json](config-windows.json) - the [Windows-specific configuration sub-structure](../config-windows.md)
* [socket-terminal-request-schema.json](socket-terminal-request-schema.json) - the primary entrypoint for the [`terminal` request](../command-line-interface.md#requests)
* [socket-response-schema.json](socket-response-schema.json) - the primary entrypoint for the [`success` and `error` responses](../command-line-interface.md#responses)
* [state-schema.json](state-schema.json) - the primary entrypoint for the [state JSON](../runtime.md#state) schema
* [defs.json](defs.json) - definitions for general types
* [defs-linux.json](defs-linux.json) - definitions for Linux-specific types
Expand Down
24 changes: 24 additions & 0 deletions schema/socket-response-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"description": "Open Container Runtime Socket Response Schema",
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://opencontainers.org/schema/runtime/socket/response",
"type": "object",
"properties": {
"type": {
"id": "https://opencontainers.org/schema/runtime/socket/response/type",
"type": "string",
"enum": [
"success",
"error"
]
},
"message": {
"id": "https://opencontainers.org/schema/runtime/socket/response/message",
"description": "A phrase describing the response.",
"type": "string"
}
},
"required": [
"type"
]
}
24 changes: 24 additions & 0 deletions schema/socket-terminal-request-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"description": "Open Container Runtime Socket Terminal Request Schema",
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://opencontainers.org/schema/runtime/socket/terminal-request",
"type": "object",
"properties": {
"type": {
"id": "https://opencontainers.org/schema/runtime/socket/terminal-request/type",
"type": "string",
"enum": [
"terminal"
]
},
"container": {
"id": "https://opencontainers.org/schema/runtime/state/id",
"description": "the container's ID",
"type": "string"
}
},
"required": [
"type",
"container"
]
}
13 changes: 10 additions & 3 deletions spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@

The [Open Container Initiative](http://www.opencontainers.org/) develops specifications for standards on Operating System process and application containers.


Protocols defined by this specification are:
* Linux containers: [runtime.md](runtime.md), [config.md](config.md), [config-linux.md](config-linux.md), and [runtime-linux.md](runtime-linux.md).
* Solaris containers: [runtime.md](runtime.md), [config.md](config.md), and [config-solaris.md](config-solaris.md).
* Windows containers: [runtime.md](runtime.md), [config.md](config.md), and [config-windows.md](config-windows.md).

* Linux containers: [runtime.md](runtime.md), [config.md](config.md), [config-linux.md](config-linux.md), [runtime-linux.md](runtime-linux.md), and at least one API.
* Solaris containers: [runtime.md](runtime.md), [config.md](config.md), [config-solaris.md](config-solaris.md), and at least one API.
* Windows containers: [runtime.md](runtime.md), [config.md](config.md), [config-windows.md](config-windows.md), and at least one API.

APIs defined by this specification are:

* The [command line API](command-line-interface.md).

# Table of Contents

Expand All @@ -15,6 +21,7 @@ Protocols defined by this specification are:
- [Filesystem Bundle](bundle.md)
- [Runtime and Lifecycle](runtime.md)
- [Linux-specific Runtime and Lifecycle](runtime-linux.md)
- [Runtime Command Line Interface](command-line-interface.md)
- [Configuration](config.md)
- [Linux-specific Configuration](config-linux.md)
- [Solaris-specific Configuration](config-solaris.md)
Expand Down
Loading