Sideloader: An InitContainer to Sideload Stuff to Your Main Container

After having played with ArgoCD for a few days, I came cross a blog post on how to get Grafana Tanka to work with ArgoCD. I like the idea to have Tanka as a plugin of ArgoCD, because:

  • The main ArgoCD docker image doesn’t get bloated by all those binaries we want to use with ArgoCD
  • Also I don’t need to wait for a ArgoCD release to use newer plugins

But eventually I need tk( the CLI file of Tanka ) in the ArgoCD’s runtime container so it’s made available to ArgoCD applications. There are 2 ways to get tk into ArgoCD’s docker image: the docker way and the kubernetes way.

The Docker Way

It’s quite straight-forward to build a new docker image based on an upstream one and add stuff to the new one.

FROM quay.io/argoproj/argocd:v2.1.2
# downloading tk and jb binaries and mark them executable
RUN curl -sL -o /tools/tk https://... && \
    curl -sl -o /tools/jb https://... && \
    chmod +x /tools/*

This works but sorta defeats the purpose to have tk as a plugin, ie. the container image will have to be rebuilt when either ArgoCD or tk has a new release.

The Kubernetes Way

ArgoCD has instructions to load additional tools via volumeMounts already. But the shell commands are all over the place in the yaml. I built a tiny(8.3MB) sideloader docker image to get the job done in a DRYer fashion.

Here’s how to use the sideloader to add tk and jb binaries to the argocd-repo-server container:

# this is the argocd-repo-server deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: argocd-repo-server
...
spec:
  template:
     spec:
     # same shared volume
       volumes:
         - name: sideloader
           emptyDir: {}
     # let the original repo-server container use the shared volume
       containers:
         - name: argocd-repo-server
           volumeMounts:
             - name: sideloader
               mountPath: /sideloader
     # use the sideloader as initContainer to load stuff
       initContainers:
         - name: sideloader
           image: ghcr.io/raynix/sideloader:latest
           args:
           # args are processed in pairs
             - tk
             - https://github.com/grafana/tanka/releases/download/v0.17.3/tk-linux-amd64
             - jb
             - https://github.com/jsonnet-bundler/jsonnet-bundler/releases/download/v0.4.0/jb-linux-amd64
           volumeMounts:
             - name: sideloader
               mountPath: /sideloader
     

After the new pods are running, I can verify that tk and jb are downloaded into the argocd-repo-server container as expected:

[email protected]:~$ ls -lht /sideloader/
total 18M
-rwxr-xr-x 1 _apt ssh 7.5M Sep 28 13:38 jb
-rwxr-xr-x 1 _apt ssh 9.8M Sep 28 13:38 tk

The user _apt and group ssh were actually curl_user and curl_group set by the curl container which sideloader based on. Not perfect but this won’t block anything.

🙂