# Cybus::Container

The **Cybus::Container** resource creates a Docker container that is enabled to communicate with the Connectware’s internal broker via MQTT. A Docker container can implement any choice of data processing or presentation, such as data analytics with Python, a dashboard with Grafana, or anything else that can be wrapped into a container.

{% hint style="warning" %}
This resource is supported only in Docker Compose deployments. It is not available in Kubernetes deployments of Connectware. Attempting to use it in Kubernetes will result in an error.
{% endhint %}

## Container Images

Within Connectware, Docker containers from various sources (called Docker registries or repositories) can be loaded at runtime. The source registry of any particular Docker container is specified in the `image` property. You can use both the Cybus registry or the public Docker Hub registry, or alternatively additional private registries. See [image](#image).

### Files

Service commissioning files can additionally specify files as [Cybus::File](https://docs.cybus.io/2-0-6/documentation/services/service-commissioning-files/resources/cybus-file) resources, which will be created inside [volumes](https://docs.cybus.io/2-0-6/documentation/services/service-commissioning-files/resources/cybus-volume). Containers can then mount those volumes using the [volumes](#volumes) property to access the file content that was written by the Cybus::File resource.

### Container Name

The name of the newly created Docker container will be built from the [service ID](https://docs.cybus.io/2-0-6/documentation/services/serviceid) and the [resource ID](https://docs.cybus.io/2-0-6/documentation/services/service-commissioning-files/resources/..#resource-id), separated by a hyphen. Example: A container resource with the resource ID `my_container`, used in a service that is installed using the service ID `myService`, will be created with the container name `myService-my_container`.

The container `name` will also be used as the container’s `hostname` property, which is the hostname visible to the application inside the container. When intending to communicate from one container to another container inside the same service, the `name` can be used to connect to this container.

Note that a container `hostname` argument must not be longer than 63 characters (according to RFC 1183). Hence, the resulting container `name` consisting of the service ID and resource ID must not exceed this limit. Otherwise, the creation of the container resource will be refused with an appropriate error message.

### Docker Networks

All Docker containers of one common service and service commissioning file will be run inside a separate Docker network. This service-specific Docker network is named by the [service ID](https://docs.cybus.io/2-0-6/documentation/services/serviceid). This network connects all containers of this service and also the ingress proxy container of Connectware, whose container name is `connectware`.

This structure ensures that all custom containers within one service can securely communicate with each other, but not interfere with other containers of other services. If the communication of containers between different services is intended, or the communication of outside requests with any such custom containers, suitable [Ingress::Routes](https://docs.cybus.io/2-0-6/documentation/services/service-commissioning-files/resources/cybus-ingressroute) resources need to be defined to allow any connection setups in detail.

There is one somewhat unexpected caveat in the event of changing Docker network configurations, leading to the temporary loss of certain data connections each time this occurs. This event can occur only during the enabling or disabling of a Connectware service. For more information, see [Docker problem with network changes](https://docs.cybus.io/2-0-6/documentation/services/service-commissioning-files/resources/cybus-container/docker-problem-with-network-changes).

## Container Properties

| Property                    | Type       | Required     | Default |
| --------------------------- | ---------- | ------------ | ------- |
| [capAdd](#capadd)           | `enum[]`   | Optional     |         |
| [command](#command)         | `string[]` | Optional     |         |
| [cpus](#cpus)               | `number`   | Optional     | `0.0`   |
| [devices](#devices)         | `object[]` | Optional     |         |
| [entrypoint](#entrypoint)   | `string[]` | Optional     |         |
| [environment](#environment) | `object`   | Optional     |         |
| [image](#image)             | `string`   | **Required** |         |
| [labels](#labels)           | `object`   | Optional     |         |
| [memory](#memory)           | `integer`  | Optional     | `0`     |
| [ports](#ports)             | `string[]` | Optional     |         |
| [privileged](#privileged)   | `boolean`  | Optional     | `false` |
| [restart](#restart)         | `enum`     | Optional     | `"no"`  |
| [volumes](#volumes)         | `string[]` | Optional     |         |
| [workingDir](#workingdir)   | `string`   | Optional     |         |
| [ulimit](#ulimit)           | `number`   | Optional     |         |

### capAdd

A list of kernel capabilities to add to the container.

* **Optional**
* Type: `enum[]`
* All items must be of the type: `string`

The value of this property **must** be one of the following:

```
- `ALL`
- `AUDIT_CONTROL`
- `AUDIT_WRITE`
- `CHOWN`
- `DAC_OVERRIDE`
- `DAC_READ_SEARCH`
- `FOWNER`
- `FSETID`
- `IPC_LOCK`
- `IPC_OWNER`
- `KILL`
- `LEASE`
- `LINUX_IMMUTABLE`
- `MAC_ADMIN`
- `MAC_OVERRIDE`
- `MKNOD`
- `NET_ADMIN`
- `NET_BIND_SERVICE`
- `NET_BROADCAST`
- `NET_RAW`
- `SETFCAP`
- `SETGID`
- `SETPCAP`
- `SETUID`
- `SYSLOG`
- `SYS_ADMIN`
- `SYS_BOOT`
- `SYS_CHROOT`
- `SYS_MODULE`
- `SYS_NICE`
- `SYS_PACCT`
- `SYS_PTRACE`
- `SYS_RAWIO`
- `SYS_RESOURCE`
- `SYS_TIME`
- `SYS_TTY_CONFIG`
- `WAKE_ALARM`
```

### command

Command to run specified as a string or an array of strings.

* **Optional**
* Type: `string[]`
  * All items must be of the type: `string`

### cpus

Specify how much of the available CPU resources a container can use. If zero, no limit is set. If you want to set a limit here specify a non-zero value. For instance, if the host machine has two CPUs and you set `cpus` to `1.5`, the container is guaranteed at most one and a half of the CPUs.

* **Optional**
* Type: `number`
* default: `0.0`

### devices

A list of devices to add to the container. Each device entry is specified as an object with mandatory keys `PathOnHost`, `PathInContainer` and `CgroupPermissions`.

* **Optional**
* Type: `object[]`

### entrypoint

The entry point for the container as a string or an array of strings.

* **Optional**
* Type: `string[]`
  * All items must be of the type: `string`

### environment

A list of environment variables to set inside the container.

* **Optional**
* Type: `object`
* You can refer to some default parameters like this:

{% code lineNumbers="true" %}

```yaml
myServiceContainer:
  type: Cybus::Container
  properties:
    image: registry.cybus.io/cybus-services/baz-dashboard:0.2.0
    environment:
      CYBUS_MQTT_HOST: !ref Cybus::MqttHost
      CYBUS_MQTT_PORT: !ref Cybus::MqttPort
      CYBUS_MQTT_USER: !ref Cybus::MqttUser
      CYBUS_MQTT_PASSWORD: !ref Cybus::MqttPassword
```

{% endcode %}

### image

Specifies the image to use for this container. The image specifier may consist of several parts:

* The image `name`, which can either be written as a filesystem path or just as a plain name, e.g. `alpine` or `cybus-services/baz-dashboard`.
* Optional: The `repository` address, which is the domain name of a Docker repository server, also known as `registry`, e.g. `registry.cybus.io`.
* Optional: The image `tag`, which usually is the version number, e.g. `0.2.0`.

**Basic Example**

The following is a basic image specification for use with the latest Alpine Linux container:

{% code lineNumbers="true" %}

```yaml
image: alpine
```

{% endcode %}

**Advanced Example**

An image specification for a container from the Docker repository `registry.cybus.io`, in particular the container image name `cybus-services/baz-dashboard`, in version `0.2.0`, is:

{% code lineNumbers="true" %}

```yaml
image: registry.cybus.io/cybus-services/baz-dashboard:0.2.0
```

{% endcode %}

Connectware uses the current license key as credentials for the Cybus repository server at the address `registry.cybus.io`. Additionally, the public `hub.docker.com` repository could be used if public Docker images should be used.

* **Required**
* Type: `string`

### labels

User-defined key/value metadata.

* **Optional**
* Type: `object`

### memory

The maximum amount of memory the container can use, in bytes. If zero, no limit is set. If you set a limit (by specifying a non-zero value here) the minimum allowed value is 4194304 bytes (equal to 4 megabyte).

* **Optional**
* Type: `integer`
* Default: `0` (i.e. no limit is set)

### ports

Defines port mappings between host and container OS

* **Optional**
* Type: Array of `string[]`
* All items must be of the type `string`: `<hostPort>:<containerPort>`

### privileged

Defines whether the container is privileged, i.e. the container has full access to the host.

* **Optional**
* Type: `boolean`
* Default: `false`

### restart

The behavior to apply when the container exits.

* **Optional**
* Type: `enum`
* Default: `"no"` (i.e. the default is not to restart)
* The value of this property **must** be one of:
  * `no`
  * `always`
  * `on-failure`
  * `unless-stopped`

### volumes

A reference to a volume resource that should be attached to this container

* **Optional**
* Type: `string[]`
  * All items must be of the type: `string`

### workingDir

The working directory for commands to run in.

* **Optional**
* Type: `string`

### ulimit

Specifies how many open files per processes are allowed in this container. If given, both soft and hard ulimit values (called `NOFILES` for `number of files`) is set to this value.

If not given, the system default (or Docker environment’s default) for the maximum number of open files is in effect, instead of any specified limit.

Given that this property configures values related to shared resources some environments will not allow for it to be changed, this is especially true when the Docker host is running inside a virtualized environment.

* **Optional**
* Type: `number`

## Example

{% code lineNumbers="true" %}

```yaml
myServiceContainer:
  type: Cybus::Container
  properties:
    image: registry.cybus.io/cybus-services/baz-dashboard:0.2.0
    volumes:
      - !sub ${myVolume}:/some/path/in/container
    ports:
      - 8080:8080
    environment:
      SOME_ENV_VARIABLE: 'important setting'
```

{% endcode %}
