Using Docker for distributing command line tools - Step by Step
There are some inherent benefits of using a command line tool using Docker. This article will show you step-by-step how to distribute a command line tool using Docker. In case you are new to Docker, get up to speed with Docker.
Before I get to the details, let me share a few reasons why you might want to do this:
- It keeps your host clean
- You don't have to install all the frameworks and dependencies your tool demands
- You get better portability of your tool
- Your tool is now more reusable
- You don't get into messy version conflicts on the host
- It saves you time that for reconfiguring the tool on different hosts
For this example, let's work with a tool like
Graphviz. In short, if you give it a file (call it file.dot
for now) like this...
digraph G {
main -> parse -> execute;
main -> init;
main -> cleanup;
execute -> make_string;
execute -> printf
init -> make_string;
main -> printf;
execute -> compare;
}
...you will get an output like this (file.png
)!
Neat, huh?
Learn more about drawing graphs with Dot.
Step 1 - Create a Dockerfile
Here is how the Dockerfile looks like:
FROM alpine:3.7
RUN apk add --update graphviz ttf-ubuntu-font-family && \
mkdir /dot
WORKDIR /dot
CMD dot -Tpng
- The Alpine Linux is a ridiculously small image. It is a minimal Docker image based on Alpine Linux with a complete package index and only 5 MB in size!
- Don't confuse APK (Alpine Linux Package Management) with the
Android Application Package. It is quite like
yum
orapt-get
. - The
RUN
command installsgraphvis
andttf-ubuntu-font-family
. I tried without the font but the output was garbled. I had to install a font explicitly to get an appropriate output. - The
CMD
command executes thedot
command with certain parameters.
Step 2 - Build Docker image
$ docker build -t attosol/dot2png:1.0.0 .
Sending build context to Docker daemon 46.59kB
Step 1/4 : FROM alpine:3.7
---> 3fd9065eaf02
Step 2/4 : RUN apk add --update graphviz ttf-ubuntu-font-family && mkdir /dot
---> Running in 3ad3e58fcd69
fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/community/x86_64/APKINDEX.tar.gz
(1/30) Installing libxau (1.0.8-r2)
(2/30) Installing libbsd (0.8.6-r1)
(3/30) Installing libxdmcp (1.1.2-r4)
(4/30) Installing libxcb (1.12-r1)
(5/30) Installing libx11 (1.6.5-r1)
(6/30) Installing libxext (1.3.3-r2)
(7/30) Installing libxrender (0.9.10-r2)
(8/30) Installing expat (2.2.5-r0)
(9/30) Installing libbz2 (1.0.6-r6)
(10/30) Installing libpng (1.6.34-r1)
(11/30) Installing freetype (2.8.1-r2)
(12/30) Installing fontconfig (2.12.6-r0)
(13/30) Installing pixman (0.34.0-r3)
(14/30) Installing cairo (1.14.10-r0)
(15/30) Installing libgcc (6.4.0-r5)
(16/30) Installing libffi (3.2.1-r4)
(17/30) Installing libintl (0.19.8.1-r1)
(18/30) Installing libuuid (2.31-r0)
(19/30) Installing libblkid (2.31-r0)
(20/30) Installing libmount (2.31-r0)
(21/30) Installing pcre (8.41-r1)
(22/30) Installing glib (2.54.2-r0)
(23/30) Installing libltdl (2.4.6-r4)
(24/30) Installing libxft (2.3.2-r2)
(25/30) Installing graphite2 (1.3.10-r0)
(26/30) Installing harfbuzz (1.6.3-r0)
(27/30) Installing pango (1.40.14-r0)
(28/30) Installing libstdc++ (6.4.0-r5)
(29/30) Installing graphviz (2.40.1-r0)
(30/30) Installing ttf-ubuntu-font-family (0.83-r0)
Executing busybox-1.27.2-r7.trigger
Executing fontconfig-2.12.6-r0.trigger
Executing glib-2.54.2-r0.trigger
Executing graphviz-2.40.1-r0.trigger
OK: 30 MiB in 41 packages
---> e6b79f54e7af
Removing intermediate container 3ad3e58fcd69
Step 3/4 : WORKDIR /dot
---> 1bade4d4c4ea
Removing intermediate container e88f70bb2b50
Step 4/4 : CMD dot -Tpng
---> Running in d7ee1981e6d2
---> 308223891ee3
Removing intermediate container d7ee1981e6d2
Successfully built 308223891ee3
Successfully tagged attosol/dot2png:1.0.0
You will be amazed that this fully functional image costed you just ==30.8MB==!
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
attosol/dot2png 1.0.0 308223891ee3 About a minute ago 30.8MB
Step 3 - Convert file.dot
to file.png
In order to use this image, you can now execute:
$ cat file.dot | docker run --rm -i attosol/dot2png:1.0.0 > file.png
--rm
removes the container once it is done--i
instructs Docker to keep STDIN open even if not attached
Step 4 - Publish it to Dockerhub
Your tool is now working locally. Let's publish it to the Dockerhub. Ensure that you have registered and keep your username & password handy for the next steps.
Login
$ docker login
Username (your_user_id):
Password:
Login Succeeded
Tag (optional)
$ docker tag attosol/dot2png:1.0.0 attosol/dot2png:latest
Read more about TAG.
Publish
$ docker push attosol/dot2png
$ docker push attosol/dot2png:1.0.0
NOTE
: attosol
is our organization name at Dockerhub.
Yay! It is done. Now you can run the following on any other host and expect the command to convert the DOT file into a PNG.
$ cat file.dot | docker run --rm -i attosol/dot2png:1.0.0 > file.png
or
$ cat file.dot | docker run --rm -i attosol/dot2png > file.png
NOTE:
The second command above automatically points to the :latest tag. If you don't have the latest
tag pushed, you will be required to mention the :tag explicitly like in the the first command.
If you check Docker hub, you should be able to see this image.
Notice that Short summary & Full summary is empty. Wouldn't it be great if this is automatically filled up for us?
For this to happen, you need to have a Github/Bitbucket repository. Push your source code to Github with a README.md file. Post that, connect your account to Dockerhub.
...and create an Automated Build by clicking Create > Create Automated Build
.
The Short summary
field is supposed to be filled manually, while the Full summary
is picked up automatically from the README.md
file. Once you have created the build, go to Build settings
and select the branch & tags appropriately and Save Changes
. You can manually trigger a build from this screen as well.
After saving this... every time you push some changes to your repository, a new build will be triggered automatically and you can watch the build details as it happens (if you like).
Review the Repo again and you should see the Short & Full summary populated.
That would be all for now. I hope you found this article helpful! Happy Docking :-)
What next?
Stay tuned for upcoming articles. You may contact us for your software and consultancy requirements.