It is possible without having a heavier-weight container engine like docker
or kubernetes
installed and without using Dockerfiles
to create container images that will run as a container from the command line and from scratch.
There is value in doing so:
I had 2 goals in starting to do this. First was to understand more about the actual structure of a container image. How it was constructed and what the pieces were. The Open Container Initiative specifications made this task somewhat easier, not by providing me a specification to analyze and understand, but allowing a bunch of excellent tooling written to that standard to be created that could be used to explore the process by both inspecting functioning containers and trying to create one by hand.
The second goal was to explore alternate patterns in container construction. When I started I knew that container image filesystems used an overlay filesystem (overlayFS) that effectively sequentially unpacked gzipped tar images of a disk layout and then deltas (adds, modifies, and deletes) against that first layout. In many instances those container images are or can be heavily shared and the container management system (a docker
or a kubernetes
) is typically efficient at caching and re-using layers that are identical where it can.
Given that, I wanted to see if reducing the build process to just constructing the layers in as efficient a manner as possible and without the overhead of a container orchestration engine that could run the container layers would open up new ways of thinking about container image construction, its packaging, and dependency management. More on that later.
Ideally, do this on Linux because the tools we'll use all build/run/release most easily there. Most of this does work on OSX, but it was quicker/easier to get it up on Linux. multipass
is good stuff for this on OSX. Instructions for installing it are at https://multipass.run/
Install the following tools:
umoci
: umoci
is the tool that actually creates configures, and manipulates container image layouts on disk. Install it by downloading a release from their releases page and installing it somewhere on your pathskopeo
(installation instructions): skopeo
is a command line utility we will use to manage, pack, unpack, and inspect Open Container Initiative (OCI) container images, and move containers into/out of and between registries and/or local disk. This is what we use to take the umoci
-manipulated containers and package them up to be accessible to a container engine like docker
or a container registry, and to handle moving container images we create around between local storage and container registriesrunc
: runc
is a standard container runner that trades performance and features for standards-compliance against the OCI specification. runc
is useful to validate that the built containers function without needing all of a docker
or kubernetes
available, but is not required to actually build a containerWe will reproduce the equivalent of a docker
"scratch"
image with the following steps. It will effectively function like the hello-world:latest
container image in Dockerhub.
umoci init the storage area for the container images
go
-Based Executable For the ContainerCoding and building an actual go
executable that can be used are outside the scope of what I want to cover. However, don't forget GOOS=linux GOARCH=amd64
if you're not compiling the code on an Intel x86-based Linux machine.
In my simple case, I created a hello.go file that just printed "Hello, world!" to stdout and compiled it to a binary called hello
.
You only have to do this when you start a new image. Once this is done, everything is just making changes to your image layout.
Done!