I'm not gonna lie... it took me a while to adopt Docker. A devout Vagrant follower, Docker just didn't feel mature enough to me until very recently, but boy have I seen the light. As a development environment, Docker has completely replaced Vagrant for me, but what really brought me around to the concept of containerization is just how versatile it is. Beyond simply acting as a vehicle for application servers, a particularly impressive use-case for Docker is as a tool for replacing my most commonly-used command-line tools.
Containerizing All the Things!
You see, Docker is a low-resourced, self-contained environment that not only allows you to execute applications in isolation, but also completely sidesteps the need to actually install any applications or their dependencies. To highlight just how awesome this is, let's take a look at how to install and execute a Docker-based version of one of my favorite command-line applications: tldr
.
Manual pages are super useful, but damn if they aren't exceptionally complicated sometimes. To solve for this problem, an open-source command-line tool called tldr
has been built to provide concrete, practical examples of nearly every command you can think of. In the words of the tldr
repository itself:
New to the command-line world? Or just a little rusty? Or perhaps you can't always remember the arguments to lsof, or tar?
Maybe it doesn't help that the first option explained in man tar is:
-b blocksize Specify the block size, in 512-byte records, for tape drive I/O. As a rule, this argument is only needed when reading from or writing to tape drives, and usually not even then as the default block size of 20 records (10240 bytes) is very common.
Surely people could benefit from simplified man pages focused on practical examples.
This repository is just that: an ever-growing collection of examples for the most common UNIX / Linux / macOS / SunOS commands.
Avoiding Dependency Hell
Now, to install tldr
, you only have to run the following command:
npm install -g tldr
Unfortunately, this command requires that node.js is installed on your local machine, which has an impressively large set of dependencies and can be installed in at least a half-dozen ways (depending on your operating system and package manager of choice).
This is where Docker comes in. Instead of diving into the dependency-deep-end, a simple command can be run to both download a containerized image of tldr
and execute it:
$ docker run --rm --interactive --tty --volume ${HOME}/.tldr:/root/.tldr nutellinoit/tldr Usage: tldr command [options] Simplified and community-driven man pages Options: -V, --version output the version number -l, --list List all commands for the chosen platform in the cache -a, --list-all List all commands in the cache -1, --single-column List single command per line (use with options -l or -a) -r, --random Show a random command -e, --random-example Show a random example -f, --render [file] Render a specific markdown [file] -m, --markdown Output in markdown format -o, --os [type] Override the operating system [linux, osx, sunos] --linux Override the operating system with Linux --osx Override the operating system with OSX --sunos Override the operating system with SunOS -t, --theme [theme] Color theme (simple, base16, ocean) -s, --search [keywords] Search pages using keywords -u, --update Update the local cache -c, --clear-cache Clear the local cache -h, --help output usage information Examples: $ tldr tar $ tldr du --os=linux $ tldr --search "create symbolic link to file" $ tldr --list $ tldr --list-all $ tldr --random $ tldr --random-example To control the cache: $ tldr --update $ tldr --clear-cache To render a local file (for testing): $ tldr --render /path/to/file.md
Easy, but a bit of a mouthful, isn't it? Nobody wants to type docker run --rm --interactive --tty --volume ${HOME}/.tldr:/root/.tldr nutellinoit/tldr
every time they want to check the tldr
of a command.
Keep it Simple, Stupid
So, how do we improve this? .bashrc
to the rescue! Instead of executing a mouthful of a Docker command every time we want to access tldr
, let's instead create a Bash function to simplify the process for us. To do this, open up your ~/.bashrc
file and add the following block of code (while some shells rely on .bash_profile
, or even .profile
, for the purposes of this example I'm going to use .bashrc
):
tldr() { if which tldr > /dev/null; then tldr "$@" else if [[ ! -d "${HOME}/.tldr" ]]; then mkdir -p "${HOME}/.tldr" fi docker run --rm --interactive --tty \ --volume ${HOME}/.tldr:/root/.tldr \ nutellinoit/tldr "$@" fi }
What the above function does is define a new command in your shell called tldr
that will first check if tldr
is actually installed on the local machine (if which tldr > /dev/null
). If it is, then we will execute it directly, otherwise we will execute our docker run
command (and, in the process, make sure that the ~/.tldr
volume exists). After reloading our shell, we should be able to execute tldr
like any other command without installing any local dependencies:
$ tldr scp scp Secure copy. Copy files between hosts using Secure Copy Protocol over SSH. - Copy a local file to a remote host: scp path/to/local_file remote_host:path/to/remote_file - Copy a file from a remote host to a local directory: scp remote_host:path/to/remote_file path/to/local_directory - Recursively copy the contents of a directory from a remote host to a local directory: scp -r remote_host:path/to/remote_directory path/to/local_directory - Copy a file between two remote hosts transferring through the local host: scp -3 host1:path/to/remote_file host2:path/to/remote_directory - Use a specific username when connecting to the remote host: scp path/to/local_file remote_username@remote_host:path/to/remote_directory - Use a specific ssh private key for authentication with the remote host: scp -i ~/.ssh/private_key local_file remote_host:/path/remote_file
More, more, and more
That's it! Pretty cool, right? While this is just a simplistic example, I'm slowly but surely replacing my own command line tools with Dockerified ones for increased portability and ease-of-use in my own dotfiles.
Cheers!
--
If you like this post or one of my projects, you can buy me a coffee, or send me a note. I'd love to hear from you!