Containers Without Docker

DZone 's Guide to

Containers Without Docker

If it's time for you and Docker to take a break, take a look at these container management alternatives.

· Cloud Zone ·
Free Resource

Why do people go for Docker? Though we have many container technologies, people preferred Docker for one reason: Docker made great leaps in the simplification of containers. It was always hard implementing containers in an organization before Docker.

Is Docker the only container technology? Can we create a container without Docker? This article talks about how we can create containers without Docker

Docker is not a container technology, but a company that promotes creating of containers in the simplest way. They have their own library called “libcontainer” that helps in creating the containers. Below are few other tools that help in creating containers without Docker.


RunC is a command-line tool for spawning and running containers according to the OCI specification. This is a Docker container format and runtime that is being donated to the Oci. How do you use RunC to run containers?

1. Download the runC library based on the platform from here using:

wget https://github.com/opencontainers/runc/releases/download/v1.0.0-rc5/runc.amd64

2. Create a directory structure

mkdir runC
cd runC
mkdir test-container
cd test-container

3. Download a busybox Docker container image and export the image to the rootfs filesystem like,

docker export $(docker create busybox) | tar -C rootfs -xvf -

Now we will see a directory by the name rootfs with multiple files and directories inside

4. Run the runC spec command from the download library using,

[root@manja17-I13330 test-container]# /root/runc/runc.amd64 spec
[root@manja17-I13330 test-container]# ll
total 4
-rw-r--r--  1 root root 2614 Jul 26 07:27 config.json
drwxr-xr-x 12 root root  137 Jul 26 07:09 rootfs

A spec file is created by the name config.json. Check the file to see the configurations details for the image.

If you check the config.json, we can see what this container does and how it will run. Run the container using the runC command:

[root@manja17-I13330 test-container]# cat config.json
        "ociVersion": "1.0.0",
        "process": {
                "terminal": true,
                "user": {
                        "uid": 0,
                        "gid": 0
                "args": [
                "env": [
                "cwd": "/",
                "capabilities": {
                        "bounding": [
                        "effective": [

Run the container as below,

[root@manja17-I13330 test-container]# /root/runc/runc.amd64 run container1
/ # ps ux
    1 root      0:00 sh
    6 root      0:00 ps ux
/ # exit

  • Run the container background using /root/runc/runc.amd64 run container1 &

  • Get a list of running containers using /root/runc/runc.amd64 list

All commands that we run are based on the Container ID. Let's run some more commands.

[root@manja17-I13330 runc]# ./runc.amd64 ps container1
UID        PID     PPID   C STIME TTY          TIME    CMD
root     21033     21025  0 00:20 ?           00:00:00 sh
[root@manja17-I13330 runc]# ./runc.amd64 exec container1 free
                total          used           free        shared    buffers     cached
Mem:            8175444       8013024        162420          0       2776    5760124
-/+ buffers/cache:     2250124     5925320
Swap:             0             0                 0


Podman is a tool designed for managing pods and containers without requiring a container daemon. Unlike Docker, we will not be having any container runtime over here. Podman takes care of creating and managing containers, and the Podman CLI is based on Docker's CLI. This is intended to be a user-friendly interface and is capable of providing summaries of containers, images, and more.

Podman manages pods as well as containers. So when we say that Podman does not have a container runtime, how can we build images, start containers, or do any of the things Docker does? Podman creates the containerized processes and makes the necessary changes on the disk itself. This is based on the library called “container/images” for pulling images from the registry. The same library is used to manage images on the disk.

Installing Podman is quite easy. Just enable the epel-release repo on Centos and run the  yum install godman.x86_64 or you can download the repo from here.

The Podman commands will be pretty much similar to the Docker commands.

[root@rkt-machine vagrant]# podman run -d --name testing docker.io/jagadesh1982/testing-service
Trying to pull docker.io/jagadesh1982/testing-service...Getting image source signatures
Copying config sha256:60c1b93cd9f4920aba848d5d457a5f9d24bd1bc4afd0cb4bbcf510a9528c43d2
 9.06 KB / 9.06 KB [========================================================] 0s
Writing manifest to image destination
Storing signatures

Check the running container using podman ps . If we try to check with the Docker command  docker ps , we will not be able to see any running containers since the containers started by Podman are subprocesses of the Podman process.

To get the container details, Podman provides us with an inspect command which is similar to Docker. We can use that using podman inspect  <container ID>.

Podman provides us with same commands as Docker to list the images as below:

[root@rkt-machine vagrant]# podman images
REPOSITORY                                TAG      IMAGE ID.           CREATED        SIZE
docker.io/jagadesh1982/testing-service    latest   60c1b93cd9f4      4 months ago     705MB

Similarly to Docker, Podman provides us with a way to run a container in a foreground way using:

[root@rkt-machine vagrant]# podman run -it --name testingService docker.io/jagadesh1982/testing-service /bin/bash
root@7972e841af05:/usr/src/app# hostname -I 
root@7972e841af05:/usr/src/app# exit

Systems-spawn is a system tool to run containers like a virtual machine. The isolation environments created by nspawn are called machines and are managed by the tool called “machinectl.” This is the same tool that will interface with the nspawn machines and also containers.

Install the minimal packages necessary for starting the container using,

[root@rkt-machine install]# sudo yum -y --nogpg --releasever=7 --installroot=/srv/mycontainer install systemd passwd yum vim-minimal

Start our container using:

[root@rkt-machine install]# sudo systemd-nspawn -D /srv/mycontainer
Spawning container mycontainer on /srv/mycontainer.
Press ^] three times within 1s to kill container.
-bash-4.2# hostname -I
-bash: hostname: command not found
-bash-4.2# ls         
-bash-4.2# pwd
-bash-4.2# exit
Container mycontainer exited successfully.

List the container using:

[root@rkt-machine install]# machinectl 
mycontainer container nspawn 

A single machine is listed.


Another container technology that is gaining up along with Docker is Rocket. A CoreOS container runtime built like Docker is no locker according to the open standards. Docker runs with a daemon that manages all components. If the process disappears, the containers disappear. Rocket tries to solve these problems.

Download and install the latest rkt rpm using

Wget https://github.com/rkt/rkt/releases/download/v1.30.0/rkt-1.30.0-1.x86_64.rpm
yum install rkt*

Pull an image using:

[root@manja17-I13330 ~]# rkt fetch --insecure-options=image docker://jagadesh1982/testing-service
Downloading sha256:74eaa8be722 [=============================] 43.3 MB / 43.3 MB
Downloading sha256:f2b6b4884fc [=============================] 52.6 MB / 52.6 MB
Downloading sha256:bb0bcc8d7f6 [=============================] 14.8 MB / 14.8 MB
Downloading sha256:727d0f4e04b [=============================]     133 B / 133 B
Downloading sha256:4fb899b4df2 [=============================] 19.3 MB / 19.3 MB
Downloading sha256:da74659b918 [=============================] 4.33 MB / 4.33 MB
Downloading sha256:2d6e98fe404 [=============================]   131 MB / 131 MB
Downloading sha256:414666f7554 [=============================] 3.17 MB / 3.17 MB
Downloading sha256:ace2d3087f5 [=============================] 1.78 MB / 1.78 MB
Downloading sha256:17c4133ca61 [=============================]     667 B / 667 B
Downloading sha256:9940cbd4fb3 [=============================]     206 B / 206 B
Downloading sha256:b6477608bbd [=============================]     864 B / 864 B
Downloading sha256:fb20ef6fe17 [=============================] 1.35 MB / 1.35 MB

Check for the downloaded images using:

[root@manja17-I13330 ~]# rkt image list
ID                      NAME                               
sha512-d5628ec41849     registry-1.docker.io/jagadesh1982/testing-service:latest

Run a container using: 

[root@manja17-I13330 ~]# rkt run sha512-d5628ec41849

Access the application using:

[root@manja17-I13330 ~]# rkt list | grep testing-service3e42fb73      
testing-service registry-1.docker.io/jagadesh1982/testing-service:latest  running 3 minutes ago   3 minutes ago default:ip4=

Enter into the container using:

[root@manja17-I13330 ~]# rkt enter 3e42fb73 /bin/bash
root@rkt-3e42fb73-ef08-4876-b996-759c7849aa99:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  testing_service.py  tmp  usr  var
root@rkt-3e42fb73-ef08-4876-b996-759c7849aa99:/# exit

CRI-O - Kubernetes is an orchestration engine that uses a container run time to run a container or a Pod. So kubernetes was built on top of docker as the container runtime. Soon as CoreOS announced the rkt container runtime, kubernetes was asked to support it. So finally kubernetes ended up supporting both container runtime.

The problem here is that Docker was growing in a faster pace. It is always complex to upgrade our existing Kubernetes cluster runtime with newer versions. Moreover, the runtime is now enhanced by adding more features like Swarm which are not necessary to Kubernetes.

The Container Runtime Interface (CRI) was introduced to solve these problems. The idea is to build a container runtime that will decouple the Kubernetes kubelet service (which is responsible for sending requests to container runtime on a machine to start a container) from the container runtime.

The CRI-O was started to create a minimal maintainable runtime dedicated for Kubernetes. CRI-O is an implementation of Kubernetes CRI that allows Kubernetes to use any OCI-compliant runtime as container runtime for creating and running pods. The runtime will be part of the Kubernetes library itself so that we don’t need to install a separate runtime like Docker or Rocket for starting containers.

CRI-O supports OCI container images and can pull from any compliant container registry. It is a lightweight alternative to using Docker as the runtime for Kubernetes.

cloud, containers and containerization, docker, podman, rocket

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}