Skip to content




debian container image

I wanted to run an OS as a pod on my Kubernetes cluster. That's because I occasionally clean install Debian on my mini fanless PCs and leave a setup memo every time in a different way and thought I should have a better note. And to do so it's best to do the initial setup and take a note in parallel, and I figured I'd just prepare a virtual one.

  1. build a custom image using [[docker buildx]]
  2. push it to my private registry on [[Harbor]]
  3. write a deployment manifest using the image

building my custom image

I look for available image tags on docker hub.

https://hub.docker.com/_/debian

I wanted to run an OS as a pod on my Kubernetes cluster. That's because I occasionally clean install Debian on my mini fanless PCs and leave a setup memo every time in a different way and thought I should have a better note. And to do so it's best to do the initial setup and take a note in parallel, and I figured I'd just prepare a virtual one.

And since I wanted to add my usual user I wrote Dockerfile to create a custom image which almost looks like it's gone through the initial OS setup including user setup.

This is the Dockerfile and .env.example to build my custom image. It uses environment variables for the FROM image tag and other non-root user information. The user information comes from .env file which looks identical to the .env.example file but of course will contain the actual information to use.

The FROM image tag comes from build.sh.

Dockerfile
# ARG - env variables within build process only
# docker buildx build --build-arg ...
ARG FROMTAG

# Use my local cache/proxy running on Harbor
FROM registry.blink-1x52.net/cache-dockerhub/library/debian:"${FROMTAG}"

# apt packages
RUN apt update && apt install -y \
  git \
  sudo \
  ssh \
  curl \
  wget \
  vim \
  fuse \
  zsh \
  gcc \
  make \
  python3-venv \
  python3-setuptools \
  python3-pynvim \
  build-essential gdb lcov pkg-config \
  libbz2-dev libffi-dev libgdbm-dev libgdbm-compat-dev liblzma-dev \
  libncurses5-dev libreadline6-dev libsqlite3-dev libssl-dev \
  lzma lzma-dev tk-dev uuid-dev zlib1g-dev \
  ripgrep \
  fd-find \
  && apt clean \
  && rm -rf /var/lib/apt/lists/*

# args
ARG USER_NAME
ARG USER_ID
ARG GROUP_ID
ARG USER_PASSWORD

# add group and user with sudo
RUN groupadd -g ${GROUP_ID} ${USER_NAME} && \
  useradd -l -u ${USER_ID} -m ${USER_NAME} -g ${USER_NAME} -G sudo -s /bin/zsh && \
  echo "${USER_NAME}:${USER_PASSWORD}" | chpasswd && \
  echo "$USER_NAME  ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

RUN mkdir -p /home/${USER_NAME} && chown -R ${USER_ID}:${GROUP_ID} /home/${USER_NAME}

WORKDIR /home/${USER_NAME}

USER "${USER_NAME}"

Here is the .env file. Since sudo without password challenge is set for the user created during the Dockerfile image build, I might remove the line.

.env.example
USER_NAME=user
USER_ID=1234
GROUP_ID=1234
USER_PASSWORD=userpassword

Here is ./build.sh to run to build and push the image to my local registry.

build.sh
#!/usr/bin/env bash

# load dotenv
[ ! -f .env ] || export $(grep -v '^#' .env | xargs)

# docker build variables
REGISTRY=registry.blink-1x52.net/gitlab
PLATFORM=linux/amd64
IMAGE=$(basename "$(pwd)")
TAG=12
FROMTAG=12

# build
docker buildx build \
  --build-arg TAG=$TAG \
  --build-arg FROMTAG=$FROMTAG \
  --build-arg USER_NAME=$USER_NAME \
  --build-arg USER_ID=$USER_ID \
  --build-arg USER_PASSWORD=$USER_PASSWORD \
  --build-arg GROUP_ID=$GROUP_ID \
  --platform $PLATFORM \
  -t "$REGISTRY/$IMAGE:$TAG" . --push

deployment

Here is the depleoyment manifest. Note that this one does not have namespace defined, because the file gets placed at the git source repository which flux knows which namespace to deploy to.

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: d12
  labels:
    app: d12
spec:
  replicas: 1
  selector:
    matchLabels:
      app: d12
  template:
    metadata:
      labels:
        app: d12
    spec:
      hostname: d12
      containers:
        - name: d12
          image: registry.blink-1x52.net/gitlab/debian:12
          imagePullPolicy: Always
          command: ["tail"]
          args: ["-f", "/dev/null"]
      nodeSelector:
        kubernetes.io/arch: amd64
        kubernetes.io/os: linux

connecting to the pod

kubectl exec deploy/d12 -i --tty -n testbed -- /bin/bash

reset

kubectl delete rs/$(kubectl get rs -n testbed -o jsonpath='{.items[0].metadata.name}') -n testbed