CoreOS-logo-cropped.svg rocket-logo-horizontal-color

In December 2014, a key player in the Docker ecosystem, CoreOS, announced "Rocket", a competing container runtime to Docker. They spelled out their motivations for creating Rocket in this blog post. While this caused some controversy amongst the Linux Container community we are simply looking at how to deploy and evaluate Rocket in this tutorial.

Rocket is an alternative to the Docker runtime, designed for server environments with the most rigorous security and production requirements. Rocket is oriented around the App Container specification, a new set of simple and open specifications for a portable container format.

According to CoreOS the important factors in the design of a container are:

  • Composable. All tools for downloading, installing, and running containers should be well integrated, but independent and composable.
  • Security. Isolation should be pluggable, and the crypto primitives for strong trust, image auditing and application identity should exist from day one.
  • Image distribution. Discovery of container images should be simple and facilitate a federated namespace, and distributed retrieval. This opens the possibility of alternative protocols, such as BitTorrent, and deployments to private environments without the requirement of a registry.
  • Open. The format and runtime should be well-specified and developed by a community. We want independent implementations of tools to be able to run the same container consistently.

As we have done previously with Docker, in this tutorial we will show how to install and run Rocket on the CenturyLink Cloud and use it to deploy containerized applications. Note that Rocket is in a very early and immature state so we need to install component by component, the CoreOS team is soliciting input and contributions by the community.

CenturyLink Labs recently did a podcast with Brandon Philips, the CTO of CoreOS and you can hear his view on Rocket, Docker, and the future of containerization.

Create a server

We will create a standard server with the following characteristics: Standard default of 2 cores and 4GB of memory, with Ubuntu 14.04 (64 bit) installed as the base operating system. Create a public ip and open these standard ports:

  • HTTP (80)
  • HTTPS (443)
  • HTTP (8080)
  • SSH (22)

In addition open port 5000, this is the port that our Rocket contained application will listen on.

rocket-vm-info_08-04-25-am

Login to your server and ensure that you are running the newest base OS bits:

$ apt-get update $ apt-get upgrade

If you check the OS version version via:

$ lsb_release -a

You should see something like:

rocket-ubuntu-14-04-trusty_08-36-12-am

Install Golang (Go)

$ wget https://storage.googleapis.com/golang/go1.3.3.linux-amd64.tar.gz $ tar -xf go1.3.3.linux-amd64.tar.gz

You now have a directory called "go" under your home directory. Move this to /opt which is the Go default (or else you need to adjust some of the base defaults).

$ mv go /opt/

For everything to work like it should, you will need to do the following to complete your Go setup.

Create two system variables called GOROOT and GOPATH. These two variables will be used by Golang itself when building your application. You will also need to create a directory to store any dependencies being pulled.

$ mkdir /opt/gopkg $ export GOPATH="/opt/gopkg" $ export GOROOT="/opt/go" $ export PATH=$PATH:$GOPATH/bin:$GOROOT/bin

Run the following to make these updates persistent after reboots:

$ echo export GOPATH=/opt/gopkg >> ~/.bashrc $ echo export GOROOT=/opt/go >> ~/.bashrc $ echo export PATH=$PATH:$GOROOT/bin:$GOPATH/bin >> ~/.bashrc

Create a working directory ~/rkttest and switch (cd) to it. In order to validate the installation we will create a simple "Hello World" program. Create a file called goworld.go and enter the following:

package main import "fmt" func main(){

    fmt.Printf("Hello worldn");

}

After saving the file you can run the program by:

$ go run goworld.go

You should see "Hello World" printed to the screen. Go ahead and delete the "goworld.go" program as we will be creating a more complex version of the app later.

Install CoreOS Rocket

Move back to the home directory.

$ cd

Grab the Rocket release from GitHub:

$ wget https://github.com/coreos/rocket/releases/download/v0.1.1/rocket-v0.1.1.tar.gz $ tar xzvf rocket-v0.1.1.tar.gz $ cd rocket-v0.1.1

You can validate the Rocket install by:

$ ./rkt help

And you should see something like:

rocket-console-help_08-33-34-am

Move back to the home directory.

$ cd

Next we will be downloading the tools necessary to build the containers that Rocket will deploy. The containers are defined by the _App Container Specification_ that can be found on GitHub here.

The "App Container" defines an image format, image discovery mechanism and execution environment that can exist in several independent implementations. The core goals include:

  • Design for fast downloads and starts of the containers
  • Ensure images are cryptographically verifiable and highly-cacheable
  • Design for composability and independent implementations
  • Use common technologies for crypto, archive, compression and transport
  • Use the DNS namespace to name and discover container images

To achieve these goals this specification is split out into a number of smaller sections.

  1. The App Container Image defines: how files are assembled together into a single image, verified on download and placed onto disk to be run.
  2. The App Container Executor defines: how an app container image on disk is run and the environment it is run inside including cgroups, namespaces and networking.
  3. The Metadata Server defines how a container can introspect and get a cryptographically verifiable identity from the execution environment.
  4. The App Container Image Discovery defines: how to take a name like example.com/reduce-worker and translate that into a downloadable image.

Download the current App Container Specification (ACI) to get the actool program:

$ wget https://github.com/appc/spec/releases/download/v0.1.1/appc-spec-v0.1.1.tar.gz $ tar xzvf v0.1.1.tar.gz

Change to the new spec directory:

$ cd spec-0.1.1

Execute the following to build the tools:

$ ./build

Add to the path and make persistent:

$ export PATH=$PATH:~/rocket-v0.1.1:~/spec-0.1.1/bin $ echo export             PATH=$PATH:~/rocket-v0.1.1:~/spec-0.1.1/bin >> ~/.bashrc

Move back to the home directory.

$ cd

Create a "Hello World" application

Next we will create yet another "Hello World" app in Go in the rkttest directory. This one is a bit more complex, as we will be making it accessible through HTTP. Create a file called _rktworld.go_ and enter the following:

package main import (

"log" "net/http"

) func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        log.Printf("request from %vn", r.RemoteAddr) w.Write([]byte("Hello, from     Rocket on the CenturyLink CLoud!n"))

    })
    log.Fatal(http.ListenAndServe(":5000", nil))
}

Build the static binary by:

CGO_ENABLED=0 GOOS=linux go build -o rktworld -a -tags netgo -ldflags '-w' .

You will now have two files in your directory: rktworld.go and the binary rktworld. In order to run the container we need to build a manifest file. Create a file called mainifest.json and enter the following:

    {
    "acVersion": "1.0.0", "acKind": "ImageManifest", "name":                     "coreos.com/rktworld-1.0.0", "os": "linux", "arch": "amd64", "app": {

        "exec": ["/bin/rktworld"]
    }, "ports": [
        {
            "name": "www", "protocol": "tcp", "port": 5000
        }

    ], "annotations": {
        "project": "Rocket for the CenturyLink Cloud"
    }
}

Validate the newly created mainfest file by using the actool:

$ actool --debug=true validate manifest.json

You should see output like:

rocket-valid-manifest_10-20-47-am]

Finally, we are going to build the actual container application. To do so we will execute the following steps:

  • Create a new directory for our application
  • Create the root filesystem for the container
  • Copy the binary application to the root filesystem
  • Copy the manifest to the application directory
  • Build the Application Container Image
  • Validate the newly created container image
$ md rktworld-app
$ mkdir rktworld-app/rootfs
$ mkdir rktworld-app/rootfs/bin
$ cp ./rktworld rktworld-app/rootfs/bin
$ cp ./manifest.json rktworld-app/mainfest
$ actool ––debug=true build rktworld-app rktworld.aci
$ actool ––debug=true validate rktworld.aci

And you should see output that looks like:

console-valid-app-container_10-29-59-am

Have Rocket launch the local container image

In order to start the rktworld container application, run the following:

$ rkt run rktworld.aci

Validate by logging into a second terminal locally and running:

$ curl 127.0.0.1:5000

You should see:

hello-from-rocket-on-console_10-38-15-am

Finally, point your browser to http://{PUBLIC_IP}:5000 and you should see:

hello-from-rocket_10-40-02-am]

Congratulations! You are now able to create and run ACI container applications via CoreOS Rocket on the CenturyLink Cloud.