Image for post
Image for post

Quick start to runC with Tomcat container

Note: This post is part of a series Beginner’s Guide to runC

runc is a command line tool for spawning and running containers according to the OCI specification. I found myself searching for it while going thru docker and linux namespaces topics, so after doing a search on runC and found Alex Ellis’ blog post “runc in 30 seconds, I decided to give it a try.

Launched a new EC2 instance on AWS using CentOS AMI. Then I updated all packages

$ sudo yum update

Then install runc

$ sudo yum install runC

yum also installed container-selinux, criu, libnet and protobuf-c packages as dependencies

Then I checked that it’s installed and version :

$ runc -v
runc version spec: 1.0.0

Good…so far.

Now to run a container with runc I needed two things:A root filesystem of what I wanted to run and a configuration file

To get a rootfs, I asked for help from Docker to pull and image and create the container, then export the root filesystem. For this exercise I used a Tomcat container (I’m using Tomcat 9 on jre11)

$ mkdir -p tomcat_container/rootfs$ cd tomcat_container$ docker export $(docker run -d tomcat:9-jre11) |tar -C rootfs -xv$ ls rootfs
bin boot dev docker-java-home etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

As it can be seen, this generated the whole debian stretch since tomcat:9-jre11 has openjdk:11 as starting point and openjsk’s starting point is debian:stretch.

Time to create the the config file for the runc container. This time asked runc help to give me the subcommand to crate the file:

tomcat_container] $ runc -h

spec create a new specification file
tomcat_container] $ runc spec
tomcat_container] $ ls -l
total 4
-rw-rw-r — . 1 centos centos 2614 May 13 19:22 config.json
drwxrwxr-x. 21 centos centos 266 May 13 19:16 rootfs

This generated a config.json file. Generated file contains lots of parameters we can use to customize how we want to run our container. Let’s stick to defaults except for what we will run when we launch the container. By default runc spec specifies ‘sh’ :

“process”: {
“terminal”: true,
“user”: {
“uid”: 0,
“gid”: 0
“args”: [

I changed that args “sh” to run Tomcat(catalina script) at launch.

“args”: [

At this point I ran into a problem due to file permissions. I changed process arg back to “sh” to run a shell and examine the container. I tried to run tomcat from the shell and run into problem with creating log files under Tomcat’s log directory.

Everything was owned by 1000:1000 except for /proc and /sys :

# ls -l
total 12
drwxr-xr-x. 2 1000 1000 4096 May 8 05:05 bin
drwxr-xr-x. 2 1000 1000 6 Mar 28 09:12 boot
drwxr-xr-x. 5 root root 360 May 13 20:24 dev
lrwxrwxrwx. 1 1000 1000 34 May 8 05:05 docker-java-home -> /usr/lib/jvm/java-11-openjdk-amd64
drwxr-xr-x. 40 1000 1000 4096 May 13 19:45 etc
drwxr-xr-x. 2 1000 1000 6 Mar 28 09:12 home
drwxr-xr-x. 8 1000 1000 96 May 8 13:34 lib
drwxr-xr-x. 2 1000 1000 34 May 6 00:00 lib64
drwxr-xr-x. 2 1000 1000 6 May 6 00:00 media
drwxr-xr-x. 2 1000 1000 6 May 6 00:00 mnt
drwxr-xr-x. 2 1000 1000 6 May 6 00:00 opt
dr-xr-xr-x. 115 root root 0 May 13 20:24 proc
drwx — — — . 2 1000 1000 37 May 6 00:00 root
drwxr-xr-x. 4 1000 1000 45 May 13 19:45 run
drwxr-xr-x. 2 1000 1000 4096 May 6 00:00 sbin
drwxr-xr-x. 2 1000 1000 6 May 6 00:00 srv
dr-xr-xr-x. 13 root root 0 May 13 14:26 sys
drwxrwxr-x. 3 1000 1000 29 May 8 13:34 tmp
drwxr-xr-x. 10 1000 1000 105 May 6 00:00 usr
drwxr-xr-x. 11 1000 1000 139 May 6 00:00 var

This is due to the fact that the root fs is owned by centos:centos outside the container and centos uid and gid are 1000:

uid=1000(centos) gid=1000(centos) groups=1000(centos)

So I made a few more changes to config.json as :

“user”: {
“uid”: 1000,
“gid”: 1000
“root”: {
“path”: “rootfs”,

Time to try again:

$ sudo runc run tomcat
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
13-May-2019 01:08:09.225 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [990] milliseconds

Of course at this point network is not configured, container is running without any network setup whatsoever, but this gives a good idea of running a simple container with runc.

Update: I added networking to this container in my new post Network Setup With runC Containers.

This series about runC continues here → Simple rootless containers with runC on Centos & Redhat

Happy containerizing…

Written by

Have been passionately working with computers since childhood. My first programming language was BASIC, my last one is Go.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store