Nowadays, Kubernetes is the go-to way of running application containers, whether you’re running an infrastructure on a cloud provider or on-premise. Although capable of running a wide range of workloads from a simple daily batch job to a complex micro-service like architecture, k8s may be overkill if all you need is running a single or a handful of containers, for example using Docker Compose.

Today we’re introducing a new, simpler way to run Docker containers on Exoscale: Container-Optimized Instances.

Container-Optimized Instances

Container-Optimized Instances (COI) are Compute instances that use a template designed to run Docker containers at startup, with minimal overhead: in a matter of seconds after your instance has booted, your container is running and is available on the Internet.

In its simplest form, running a container on a COI comes down to this exo CLI command:

$ exo lab coi nginx --image nginxdemos/hello --port 80:80
# ... waiting a few seconds for the Compute instance to boot ...
$ curl $(exo vm show --output-template "{{.IPAddress}}" nginx) | head
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
...

The exo lab coi command essentially deploys a Compute instance configured to use the COI template using a cloud-init userdata configuration instructing it to run Docker Compose at the end of the boot process; once deployed, this instance can be managed like any other Compute instance.

Although COI has been designed with simplicity in mind (e.g. running a single container), it can go the extra mile by supporting more complex use cases by accepting a Docker Compose configuration (either by specifying a local docker-compose.yml file or a URL to it):

exo lab coi my-cool-stack --docker-compose <path/to/docker-compose.yml>

High Availability with Network Load Balancer and Container-Optimized Instances

In addition of running on a single Compute instance, COI can be considered in the context of an Instance Pool used in a Network Load Balancer service: Container-Optimized Instances are an interesting alternative to custom templates, enabling faster iteration times for software deployments. Moreover, exposing your application(s) behind a NLB ensures greater availability and scalability.

To deploy your containerized application on a COI-powered Instance Pool, use the Container-Optimized Instance template and add cloud-init userdata storing a Docker Compose configuration at the /etc/docker-compose.yml path on the Compute instances:

$ cat docker-compose.yml
version: '2'
services:
 nginx:
   image: nginxdemos/hello
   ports:
   - "80:80"

## Preparing the cloud-init configuration containing
## the Docker Compose configuration to deploy
$ printf "#cloud-config\n\nwrite_files:\n- path: /etc/docker-compose.yml\n  content: %s\n  encoding: b64\n  owner: root:root\n  permissions: '0600'\n" $(base64 -w0 docker-compose.yml) > cloud-init

## Creating the COI-powered Instance Pool
$ exo instancepool create my-app \
    --zone ch-gva-2 \
    --size 3 \
    --template 'Container-Optimized Instance' \
    --security-group web \
    --cloud-init ./cloud-init

## Creating the NLB and registering a service for the application
$ exo nlb create my-lb --zone ch-gva-2
$ exo nlb svc add my-lb my-app \
    --instance-pool-id $(exo instancepool show --output-template {{.ID}} my-app) \
    --port 80 \
    --healthcheck-mode http \
    --healthcheck-uri /

## Testing the final setup
$ for i in {1..10}; do curl http://$(exo nlb show --output-template "{{.IPAddress}}" my-lb) | grep name ; sleep 1 ; done
<p><span>Server&nbsp;name:</span> <span>eba920ec1a38</span></p>
<p><span>Server&nbsp;name:</span> <span>eba920ec1a38</span></p>
<p><span>Server&nbsp;name:</span> <span>c11807a9cf41</span></p>
<p><span>Server&nbsp;name:</span> <span>c11807a9cf41</span></p>
<p><span>Server&nbsp;name:</span> <span>eba920ec1a38</span></p>
<p><span>Server&nbsp;name:</span> <span>c11807a9cf41</span></p>
<p><span>Server&nbsp;name:</span> <span>eba920ec1a38</span></p>
<p><span>Server&nbsp;name:</span> <span>eba920ec1a38</span></p>
<p><span>Server&nbsp;name:</span> <span>c11807a9cf41</span></p>
<p><span>Server&nbsp;name:</span> <span>c11807a9cf41</span></p>

Note

Don’t deploy stateful workloads on COI-powered Instance Pools, as you’d expose yourself to data inconsistency or corruption issues.

Exoscale Container-Optimized instances are a good show-case of the potential of using discrete Exoscale API facilities in combination. If you’re looking for a way to quickly and easily deploy application containers with little to no operational complexity, COI might be a viable solution to your use case.