How to Build SaaS Using Docker-based Tools - Kontena

This article focuses on how you can use Kontena to build SaaS and is the second article in a two part series by Kontena Community blogger, Igor Petrov. This series reviews Docker orchestration tools and you can find the first part of this series here: How to Build SaaS Using Docker-based Tools — Part 1.

Kontena CLI

My first impression of Kontena is “really cool” and “very developer friendly”. You can easily get started by installing Kontena CLI. I’ve installed it both on MacOS and Ubuntu by following the documentation and didn’t have any problems with that. After installation, you can start using it right away because it’s very simple to use and Kontena's documentation is good enough (as opposed to Docker Cloud CLI).

For using Kontena, you need to have a master node — this is a machine that you could bootstrap on any cloud provider and that could be used as a central point for managing other nodes, grids, and services.

Supported cloud providers

At this moment, as mentioned in docs, Kontena supports 5 cloud providers: AWS, Azure, Digital Ocean, Packer and UpCloud. I’ve tried to setup it with Amazon Web Services. To start installing your master node on AWS, you need to setup an AWS user with security credentials. Just go to AWS IAM and create a new user. For example, “kontena-master” or any other name. Make sure to check the “Programmatic access” checkbox because you need to have access and secret keys. Then set permissions for the just created user by selecting the “AmazonEC2FullAccess” policy.

In the last step, you’ll get an “Access Key ID” and a “Secret access key”. Save it somewhere in your project.

But that’s not all: you need to have an AWS EC2 Key Pair — these are keys you need for Kontena to be able to login into your nodes. Just switch your AWS Console to Amazon EC2 service and create a key pair. Once done, now you have all the information to setup your Kontena Master node on AWS. Let's do this by using the CLI command described in docs (don’t forget to change — storage and — type options according to your needs):

  --access-key <aws_master_key> \
  --secret-key <aws_secret_key> \
  --key-pair <aws_key_pair_name> \
  --type m3.medium \
  --storage 100 \
  --region eu-west-1

During the Master node creation process, you will be asked several questions. One is about authentication for accessing your Kontena managed infrastructure and the recommended variant at this point is to go with authentication via Kontena Cloud (which is what I’ve chosen). Aside from Kontena Cloud, any other OAuth2-compatible authentication providers could be used.

Grids, Stacks and Services

Let’s create the first grid: recommended initial node counts are 3,5,7 — according to etcd rules. These nodes will form a etcd cluster infrastructure — main nodes responsible for your cluster stability and failover.

$ kontena grid create --initial-size=<initial_node_count> aws-grid
# Now let's create AWS EC2 node in the current grid
$ kontena aws node create \
  --access-key <aws_master_key> \
  --secret-key <aws_secret_key> \
  --key-pair <aws_key_pair_name> \
  --type m4.medium \
  --storage 100 \
  --zone a \
  --region eu-west-1

After your grid is ready for operating, you are becoming closer to prepare your infrastructure. Let’s say you have a web app that needs a database and of course, web server/load balancer. I’ve come to using the micro-services approach and having each component in a separate container. There are two ways of organizing your containers:

  • Via separate independent Services (that could be linked together)
  • Via Stacks (which is the preferred way and recommended by Kontena team)

So Kontena Stack is actually an organized group of Services and Service is a group of containers using the same Docker image. The second option is what I’ve chosen and started preparing my stacks: stack for a web app, stack for DB, stack for a load balancer. You could use pre-defined Kontena images for the database and load balancer, but you need to pack your web app into an image as well. I’ve already had one for my web app — APIQ CMS. So my services are Ruby on Rails apps packed into a Docker image, PostgreSQL and Load Balancer (web server with public HTTP exposure). Here are examples of my Stacks definition (you define it using YAML format and according to Kontena.yml)

# lb-stack.yml
stack: apiq/lb  
description: APIQ LB  
expose: internet_lb  
services:  
  internet_lb:
    image: kontena/lb:latest
    ports:
      - 80:80
      - 443:443    
    deploy:
      strategy: daemon

Need to note the expose: option here — this allows you to expose your service to other stacks.

# db-stack.yml
stack: apiq/db  
description: APIQ DB  
expose: db  
services:  
  db:
    image: postgres:latest
    stateful: true

A database is a stateful service and I guess you want to store you database's data somewhere and database nodes removal won’t affect your data.

# kontena.yml
stack: apiq/core  
description: APIQ Core  
variables:  
  secret_token: # variable name
    type: string  # type (string, integer, boolean, uri, enum)
    from: # where to obtain a value for this variable
      random_string: 64 # still no value, auto generate a random
    to:
      env: SECRET_TOKEN # send this value to the vault on kontena master
services:  
  app:
    image: webgradus/kms
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    environment:
      SECRET_TOKEN: ${SECRET_TOKEN}
      RAILS_SERVE_STATIC_FILES: 'true'
      KONTENA_LB_INTERNAL_PORT: 3000
      KMS_ASSETS_STORAGE: 'fog'      
    hooks:
      post_start:
        - name: db_create
          cmd: rails db:create
          instances: 1
          oneshot: true
        - name: db_migration
          cmd: rails db:migrate
          instances: 1
    links:
      - lb/internet_lb
      - db/db
    ports:
      - "3000:3000"
    secrets:
      - secret: AWS_ACCESS_KEY_ID
        name: AWS_ACCESS_KEY_ID
        type: env
      - secret: AWS_SECRET_ACCESS_KEY
        name: AWS_SECRET_ACCESS_KEY
        type: env
      - secret: AWS_REGION
        name: AWS_REGION
        type: env

Let’s review this in details. First, the variables section. This section allows you to define variables and the way of obtaining them that could be used in Kontena.yml. In my Stack file, I generate a random string and pass it to the SECRET_TOKEN environment variable (that should be specified for the app). command defines the way the app should be launched, environment — environment variables for an app as well as special Kontena variables (for example, KONTENA_LB_INTERNAL_PORT that links web app and load balancer). Next, I’ve defined several hooks executing Rails-specific tasks necessary for correct app bootstrapping — database creation and migration. It’s pretty clear that the links section links the app service with the db and the internet_lb services exposed from the first two stacks. And the secrets section is what Kontena Vault is responsible for — you’re specifying keys for an API or database passwords accessible at the Grid level. In my example, I’m using the Amazon S3 service in my web app and want any app service node to have access to my Amazon credentials. Prepare your secrets by saving them into Vault:

$ kontena vault write AWS_REGION us-east-1

Now we could install prepared stacks on nodes:

$ kontena stack install lb-stack.yml $ kontena stack install db-stack.yml $ kontena stack install --name cms-1 kontena.yml

After this, I’ve got the APIQ CMS instance connected to my database and load balancer and available on the web. To find out your public IP and check out your app in browser:

$ kontena service show cms-1

Where is SaaS actually?

Ok, very good question :-) So now after you’ve tried everything using CLI, it’s time to perform the same operations via Kontena Master REST API. Just generate API token and start installing app stacks on your customer demand. Follow the API documentation and write the code in your favorite language.

$ kontena master token create --expires-in 0 --token

Kontena Cloud

Once you’ve signed up to Kontena Cloud and used it for authentication, you could login anytime and view the dashboard of your Kontena-based infrastructure (absolutely for free now). Really cool! There you’ll find your Grids, Nodes, Services, resources usage, and logs.

Community

The next thing about Kontena that I need to mention is very good support from the core team. I’ve asked two questions on the Kontena Forum and always got responses. Also, there are many new resources appearing: video tutorials on YouTube, the regular email digest of the Kontena Newsletter and updates, as well as blog posts.

In conclusion, I’d recommend to give it a try even if you don’t need to build SaaS. You could just manage infrastructure for your app by easily scaling your services, adding more nodes and grids.

About Kontena

Want to learn about real life use cases of Kontena, case studies, best practices, tips & tricks? Need some help with your project? Want to contribute to a project or help other people? Join the Kontena Forum to discuss more about our Kontena Platform, chat with other happy developers on our Slack discussion channel or meet people in person at one of our Meetup groups located all around the world.

Image Credits: SAAS written on a wooden cube in front of a laptop by Gustavo Frazao.

Igor Petrov

Read more posts by this author.

comments powered by Disqus