How to run dockerized CLI programs with input redirection
Most of the time, when I see someone using a containerized application, it involves a long-running process, typically a web server and its associated services, such as databases, message brokers, etc.
But it does not need to be like this. You can actually use containerized short-lived processes as well, like CLI tools.
First time I was presented to this possibility that I remember happened when I was trying to add a new CI step to scan the component of a system, using aquasec/trivy project. Out of all the possible ways to configure it, one uses basically a Docker container. In fact, it's as easy as running this command:
# suppose you want to scan some local directory for misconfigurations
docker run -v $PWD:/myapp aquasec/trivy config /myapp
# I got this example from https://hub.docker.com/r/aquasec/trivy
Notice that for this to work, you need to create a volume binding your local directory ($PWD), to a folder inside the container's file system (/myapp).
By the time I found this, I thought this strategy was pretty cool, but decided to not dig deeper, since I had no real goal in mind. Then, after many months, the situation has changed.
I was working on a task of building a CLI tool, and there was a demand to dockerize the program to make it more portable and easy to use. But, instead of demanding a volume binding, it would make more sense to use the input redirection feature of Linux to send the file contents to the CLI program, something like:
# example of input redirection
./my-program < ./samples/example1.txt
After some initial failed tests, I eventually decided to read the Docker official documentation, looking for potential flags that could be used to send the data to the Docker process. Then, I rediscovered the -i
flag - I had experiences before using it along with -t
to get an interactive shell inside a container.
Basically, the -i
flag is used to keep the container's STDIN open, and it lets we send input to the container through standard input (from link).
And it worked!
Then I decided to write this post, creating a simple CLI program to exemplify how one can use a dockerized CLI program with input redirection. The code is available at: 64J0/dockerized-cli-with-input-redirection.
The idea is that you'll first build the image, selecting either the "normal" .NET runtime base image or a chiseled one. Program will work exactly the same for either case, the difference is that the chiseled image is way more safe and production-ready.
If you don't know, .NET chiseled images are Microsoft's equivalents to Google's distroless containers. You can find more information about it at this post: Announcing .NET Chiseled Containers.
After this short digression towards chiseled and distroless images, the commands used were basically:
# build the cli image
docker build -t add-cli:v1-chiseled --file Dockerfile.cli --target runtime-chiseled .
# use it with input redirection
docker container run -i add-cli:v1-chiseled < ./samples/example1.txt
# use it piping data to it
cat ./samples/example1.txt | docker container run -i add-cli:v1-chiseled