---
authors: Josh Wilsdon <jwilsdon@joyent.com>, Angela Fong <angela.fong@joyent.com>
state: publish
---

# RFD 18 Support for using labels to select networks and packages

## Current support for packages/networks in sdc-docker

Currently a user creating a docker container does not select their networks in
their `docker run` commandline though they can specify the -P in order to get a
an external NIC. The external NIC is based on the default network configured
for the data center. The fabric network they're given is always the network
configured in UFDS as the default for their account.

Users also do not directly select their package. The package is chosen based on
the `-m` parameter if passed (if not, we treat as 1024m). We'll find the
smallest package that fits their memory limit, and since all the packages have
the same ratios of cpu/disk/memory all the other parameters are scaled
appropriately.


## Impetus

In order to allow customers to specify non-default networks, we'd like the
ability for them to add these at container creation. This will allow them to use
different network setups for different containers without needing to interact
with cloudapi, except to create and manage the networks themselves.

In order to support SDC setups where there are multiple hardware profiles with
different different ratios of cpu/disk/memory, we need to be able to support
selecting a package. If a customer has for example one set of hardware that has
a higher ratio of CPU to disk/memory (high-cpu) and another set that has a
higher ratio of disk to memory/cpu (high-disk) and a 3rd set of servers in the
middle (normal), their users would currently not be able to specify which
package/hardware family to use.

The proposal here is to allow them to use docker labels to select a package so
that they can create separate packages for each of these hardware profiles and
add traits (normal, high-disk, high-cpu in this case) to both the hardware and
packages to ensure that things are distributed to the correct hardware for the
package.


## Relevant Docker syntax

When creating a container you can add labels via:

```
docker create [...] --label <LabelName>=<LabelValue> [...]
docker run [...] --label <LabelName>=<LabelValue> [...]
```

labels can only be set in a `docker run` or in your Dockerfile when doing a
`docker build`. It is not possible to change labels for an existing container.

For existing containers, you can see labels on the container with:

```
docker inspect <container>
```

Which will return as Config.Labels an object containing the key/value pairs of
the container's labels. You can also filter by label when doing `docker ps` such
as:

```
docker ps --filter "label=<LabelName>[=<LabelValue>]"
```

with LabelValue being optional.


## Proposed Implementation

What we propose here is to make a reserved namespace for labels that have
special meanings for sdc-docker. These would look like:

```
com.joyent.<key>=<value>     # Joyent/Triton-specific use cases
```
or
```
triton.<key>=<value>         # Triton-specific use cases
```

and the first of these would be `com.joyent.package`. If a user specifes this
key and a value that's either a package UUID, package name or package shortend
uuid (as used by `triton`), we'll ignore any -m value or other current package
selection criteria and give the user the specific package they referenced. If
their `<value>` here does not match an existing package, an error will be
returned and the docker container will not be provisioned. When provisioned the
actual label we'll attach to the container can be the package uuid (this is what
you'll see if you `docker inspect`).

We would also add a corresponding "magic" lookup when using a `docker ps`
filter. What we would do is allow any of:

```
docker ps --filter "label=com.joyent.package=<PackageName>"
docker ps --filter "label=com.joyent.package=<ShortUUID>"
docker ps --filter "label=com.joyent.package=<UUID>"
```

to match packages, even though the actual label is just the uuid. We'll do the
lookup from PAPI to allow all 3 of these to work so that customers can set and
query based on them.

Similar to package, we'd add `triton.networks` and `triton.network.public` to
provide users the flexibility of selecting networks from the ones they have
access to. As users may want more than one network attached to a container,
`triton.networks` should allow multiple values. Since we cannot have multiple
`--network` or `--label` options with the same key, the current thinking is
that we'd allow:

```
docker create --label "triton.networks=networkA,networkB [...]
```

where the value for the key here is a comma separated list of one or more
networks. Then when doing filtering we could allow:

```
docker ps --filter "label=triton.networks=networkA,networkB"
docker ps --filter "label=triton.networks=networkA"
```

so that you could look up VMs with a specific combination of networks, or all
VMs matching a single network.

When user wants a container to present itself on a public network that is
different from the default external network configured in the data center, the
user would specify the `triton.network.public` label to set the desired
"public" network, whether it is external or internal.

The single-value `--network` argument will still be supported for compatibility
with Docker. It should work together with `--label triton.network.public`.
However if both `--network` and `--label triton.networks` are specified, the
`--network` value will be ignored.

Combining the different network arguments above would enable the user to
attach a container to the desired default or non-default, fabric or non-fabric
networks at provisioning time.

When the same network is passed more than once through these argunments, the
duplicated values should be eliminated so that the container does not end up
having more than one NIC on the same network.

Finally network pools should be allowed and work in the same way as individual
networks when it comes to specifying networks in these network arguments.


## Future Considerations

 * should add a cache for PAPI data in sdc-docker


## Tickets

 * [DOCKER-502](https://devhub.joyent.com/jira/browse/DOCKER-502) -- adding support for selecting packages
 * [DOCKER-585](https://devhub.joyent.com/jira/browse/DOCKER-585) -- adding support for selecting networks
 * [DOCKER-897](https://devhub.joyent.com/jira/browse/DOCKER-897) -- expanding support to non-fabric networks
 * [DOCKER-936](https://devhub.joyent.com/jira/browse/DOCKER-936) -- expanding support to multiple networks
 * [DOCKER-1020](https://devhub.joyent.com/jira/browse/DOCKER-1020) -- adding support for selecting network for exposed ports
