Compose specification

Compose specification #

levv uses YAML files, as defined in the compose specification, to launch applications.

The elements within the specification can determine service characteristics such as disk volumes, networking, environment variables, etc. However, levv uses only a subset of these to launch applications, depending on what it can offer to the user at a given time.

Next to that, levv also makes use of annotations (defined as labels) to indicate characteristics or behaviors, such as defining a container size, and exposing services to the internet.

This document provides information on these characteristics.

Applications #

An application is composed by one or more services. Each service resides within the services section of the file.

We can consider, as a base definition, an application with one service and one replica, launched from a public docker image, and that does not require any interaction with the world nor any specific configuration settings.

services:
    frontend:
        image: nginx
        deploy:
            replicas: 1
  • frontend corresponds to the service name, unique within each compose file.
    • image is the docker image used to create the container
    • deploy specifies the configuration for the deployment of services
      • replicas indicates that only one container replica is desired for this service.

Container size #

The container size for a service can be set explicitly by defining the label io.levv.size within the deploy.labels section. When the container size is not specified, levv creates a deployment with nano size by default.

services:
    frontend:
        image: nginx
        deploy:
            replicas: 1
            labels:
                io.levv.size: "large"

When specified, levv will translate the given size into specific resource quotas as described in this table. If the provided value is incorrect, an error is generated and the deployment cannot be launched.

Service Ports #

Exposed service ports can be defined within its ports section. Each entry consists on a service_port:container_port pair.

services:
	db:
		image: redis
		deploy:
		  replicas: 1
        ports:
	        - 6379:6379

ports entries can also be specified as a string, using the same format, e.g. "6379:6379"

Public services #

levv supports exposing HTTP services publicly. When a service requires such functionality, a label io.levv.public needs to be set to "true" for that service, and a ports mapping defined.

Only HTTP is currently supported, therefore the ports mapping for a public service requires an entry with "80" at the left side (HTTP service port), and the container port that handles HTTP requests on the right side.

services:
    frontend:
        image: nginxdemos/nginx-hello:plain-text
        deploy:
            replicas: 2
            labels:
                io.levv.size: "medium"
        labels:
            io.levv.public: "true"
        ports:
            - "80:8080" # ServicePort:ContainerPort

When launched through the cli, the public URL is displayed as part of the success message.

Secrets #

Secrets allow to securely expose sensitive information within containers. The sources for this information are defined globally, within the secrets section of the file, which is composed of a list of secret keys and their definitions depending on its type. Secrets can be either of file or environment type.

  • file will create a secret from the contents of the file at the specified path.
  • environment will create a secret from the value of an environment variable already defined in the system.

Each service within the specification, can require zero or more secrets, depending on the definition within its own secrets section. Each definition requires to indicate the source as the secret key to be mounted.

services:
    nginx-secrets:
        image: nginx
        deploy:
            replicas: 1
        secrets:
            - source: secret_file
            - source: secret_env
    db:
	    image: redis
	    deploy:
		    replicas: 1
	    secrets:
            - source: secret_env
secrets:
    secret_file:
        file: /home/user/secret.txt
    secret_env:
        environment: "SECRET_TOKEN"

In the example above, two secrets, identified as secrets_file and secret_env, are created. And both are required by the nginx-secrets service. When launched, secrets are accessible to the container via environment variables.

Secrets are project scoped which implicates that different applications within the same project can access the information. It also means that you could overwrite secrets if you reuse the secret names within a specific project.

Environment Variables #

You can define environment variables to be set in a container by using the environment section within a specific service. Each entry within this section corresponds to a key-value pair for each variable.

services:
    nginx-environment:
        image: nginx
        deploy:
            replicas: 1
        environment:
            DEPLOYMENT: production
            LOG_LEVEL: debug

Volumes #

Volumes are persistent data stores for your applications running on levv cloud. Top-level volumes declaration let you list volumes that can be reused across services and applications. Each service requiring the volume must specify it within the volumes attribute, together with its mounting point on the container’s file system.

services:
    nginx:
        image: nginx
        deploy:
            replicas: 1
            labels:
                io.levv.size: "micro"
        labels:
            io.levv.public: "true"
        ports:
            - "80:80" # ServicePort:ContainerPort
        volumes:
            - disk-one:/usr/share/nginx/html
            - disk-two:/usr/local/extra
    writer:
        image: myrepo/myimage:latest
        deploy:
            replicas: 1
        volumes:
            - disk-one:/usr/local/data
volumes:
    disk-one:
    disk-two:

In the example above, we require two volumes hosted on levv cloud: disk-one and disk-two, which are then mounted in the corresponding services.

Volumes are project scoped which implicates that different applications within the same project can mount and access the information within these volumes.

Full Example #

services:
  backend:
    image: myrepo/myimage:latest
    deploy:
      replicas: 2
      labels:
        io.levv.size: "small"
    environment:
      DEPLOYMENT: production
      LOG_LEVEL: debug
    secrets:
      - source: storage_keys
    volumes:
        - files-disk:/usr/local/data
  db:
	  image: redis
	  deploy:
		replicas: 1
		labels:
			io.levv.size: "medium"
	  secrets:
        - source: token
    ports:
	    - 6379:6379
  frontend:
    image: nginx
    deploy:
      replicas: 2
      labels:
        io.levv.size: "micro"
    labels:
      io.levv.public: "true"
    ports:
      - "80:80"
secrets:
  storage_keys:
    file: /home/user/secret.txt
  token:
    environment: "MY_SECRET_TOKEN"
volumes:
  files-disk: