Container build tool
Recently I decided to learn the Go language. After reading the code in the docker and buildah github repos I thought why not write my own image building tool for educational purposes.
So I decided to break down how containers work at a low level. Building container images is simple and the same time quite complex task.
It’s simple because images are nothing more than a tar archive. If we take the contents of a directory, add it to a tar archive, add some configuration files according to OCI image spec, we get a fully compliant container image.
Read How-to build OCI Image by hands for more info.
It’s complex because of the run
command. The common way of building container images is to use dockerfile and a building tool like docker, buildah, podman, or kaniko.
# syntax=docker/dockerfile:1
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "app.js"]
EXPOSE 3000
The yarn install --production
must be run inside of isolated environment, aka container. The container level isolation is achieved by using linux namespaces:
- The user namespace creates an isolated view of user and group IDs. This allows host user
alice
to be mapped toroot
user in a container/isolated process. - A PID namespace provides an isolated process ID number space, so that our isolated process always has id of 1.
- A network namespace provides an isolated network stack.
- A mount namespace provides an isolated view of the file system. This allows for any folder to be mounted at root
/
. - The IPC namespace provides an isolated System V Inter-Process Communication
- UTS namespaces provide isolation for the NIS domain name and hostname.
Another important aspect of container technology is security. In linux there are multiple ways to secure a process: linux capabilities, Secure Computing Mode (seccomp), and Security Enhanced Linux (SELinux).
We will look into namespaces and security controls in later posts.
So to build an image we need two things:
- Image layers and configuration according to OCI image spec. Each layer is file system snapshot, or diff, stored in tar archive. Image configuration defines things like which command to run and ports to expose.
- Isolated & secured environment to execute
run
commands.
Let’s start with a low hanging fruit and figure out how to build a simple image using linux tools.
This post is part of a series.
- Part 1: Container build tool
- Part 2: How-to build OCI Image by hands
- Part 3: Building OCI images with Go. No run command yet
- Part 4: How to Tar/Untar container layers in Go
- Part 5: Linux kernel namespaces
- Part 6: Mini container runtime in Go
- Part 7: Union mount