Journey to Dockerizement

Laine G
9 min readJul 17, 2020

A Docker-mentary

Docker logo, representing “the company’s four core values: expedition, automation, encapsulation, and simplification.” (Source: https://1000logos.net/docker-logo/)

Coming to Docker, my only previous conception of it is an idea of containers being somewhat like modules in other programming languages and the recollection of a short video where a student had created a visualization of its working in Roblox.

On Monday, June 1, 2020, I officially began my learning about Docker journey. In preparation for the adventure to come, my first lesson was found at training.play-with-docker.com. There was a little bit of a challenge at first because the site provides an onscreen web-based terminal that requires the site to have pop-up permissions. So I had to go into my browser’s preferences and create an exception to my ‘Block all popups’ setting.

Add pop-up exception in Firefox browser

That day, I saw how containers function as small super-fast virtual machines that shut themselves down automatically. The next day, as I continued to work through the introductory tutorial, I saw that the container could be held open, at least in a case where one wanted to work with an interactive shell (aka Terminal) with a special command called a flag; -it.

The terminal command docker container run --help gives a lengthy list of various ways in which the run command can be used.

Docker Compose; yaml-ing it up

The next part of my journey was learning about Docker Compose. The dockerfile in itself does the amazing work, but adding docker compose automates.

What it is

Just as dockerizing an app requires a special “Dockerfile”, docker-compose also requires an additional special file. Unlike the dockerfile, it can be named as the individual person prefers, but it must include the file extention “.yml”.

After easily completing the class exercizes for dockerizing a flask app and using docker compose, I found I still not understand the beginning aspects of docker as fully as I would like. I began to look deeper, searching with Google and DuckDuckGo to find additional resources with which to enhance my understanding. This endeavor, I took upon myself like an poorly balanced hiking pack, finding myself often staggering and stumbling upon the seemingly overgrown wilderness trail of knowledge. “Wait!” I tell myself. This is not a creative writing exercize. Get your nose back into the documentation!

Why it’s good

…preserves volumes between runs. (See the Data Persistence section below)
…re-uses previously built containers without rebuilding unless something in the containers has changed and needs to be updated. This means faster response time when you want it to docker-compose up.
…allows movement between environments to be achieved quickly and easily, because it supports customizable variables.
…by using a project name, compose isolates environments one from another and allows them to run independently, concurrently, and interdependently without conflict.

The Difference between CMD, RUN, and ENTRYPOINT

In my quest for understanding, I found myself exploring a slight way off the trodden trail. The differences between CMD, RUN, and ENTRYPOINT were the next thing I explored. From what I’ve been able to discern, RUN is the simplest of them and does what it says it does. It runs the dockerfile. CMD is a little more tricky because what it does is set a sort of baseline called a default. The default is a command that is executed if no command is given. ENTRYPOINT is the most complex because it makes the app into an executable (still grasping for how this happens) and bypasses the default set by CMD.

It also appears that these commands can be formatted for either the terminal shell with RUN …

`<instruction> <command>`

or as executable with CMD and ENTRYPOINT…

`<instruction> [“executable”, “param1”, “param2”, …]`

Data Persistence

This is a crucial feature of docker. It allows data to be saved and persisted when containers have been shut down and restarted. Redis is one form of data persistence that is popularly used.

Data persistence is a fancy way of saying save the data. This is done with volumes which I previously mentioned when going over the benifits of using docker-compose. When the name “volume” was brought up in our class lecture, I recalled the last time I had encountered this term. When I first began studying computers, we used a simple device that was called a “floppy disc” to store data and programs; kind of like an ancient flash drive but with far less memory capacity. Whenever we needed to use a new disc, there was an initialization process that was called formatting which was required in order for the computer to be able to read and write correctly to the disc. Part of that process was initializing and naming the volume.

This concept allowed me to understand volumes as a type of super fancy virtual floppy disc that existed purely as code within a docker project.

Final Project: Dockerize a Completed Project

At around the same time we began learning about data persistence, we were asked to select a completed project from our existing GitHub repositories to dockerize. I selected one that I had completed in my NodeJS course that’s a clone of the social media app, Reddit.

Day 1

Easy enough, I thought but oh how wrong I was. Dockerizing in the wild is nothing like dockerizing in the safe confines of a step by step tutorial. Frantically I scoured the internet for resources, urged on by the mantra pounding in my head like crazed war drums; “I don’t understand. I don’t understand. I don’t understand.”

Bit by bit I began to find a barely marked trail through the folliage. Finding first an article on Containerizing a Node Application, then realizing that Mongoose had its own special needs for containerization. Again I searched, and after stumbling around barely able to move through the overgrowths of confusion and unrealistic expectations I found another article: Dockerizing a Node, Express and MongoDB Application. This one seemed like it might be a good match with the code I already had and perhaps could be easily adapted.

I worked through the most recent article, implementing each step as I understood it, only modifying as necessary to match names. It built successfully but when I attempted to run it, no dice.

(terminal output for docker run errors)

With frustration levels peaking, I decide to make camp for the night and start the next day with a fresh perception.

Day 2

The next day dawned with dewey brightness as I resumed my journey, still feeling the previous days disappointments but hopeful for greater success. After some slogging through several marshes of non-applicable examples, eventually I wandered into a village-like meeting place called Slack. There I found a helpful guide who pointed out a couple of trail markers I hadn’t seen before.

scripts configuration in package.json

The issue I’d had was that the container couldn’t find server.js, which turns out needed to be pointed to by “node” in the start script configuration in package.json file. Once this was changed, the server could finally start but now was getting snagged on tangled brambles of the MongoDB connection.

As the sun sets behind the canopy of syntax in the jungle of google searches and another day draws to a close, I retrospect the day’s progress. The Dockerfile is semi-functional and the docker-compose.yml is mostly constructed, even if I may have stuck some extra twigs and moss in there that don’t quite belong. I was able to determine this about the docker-compose.yml by using the Code Beautify YAML Validator, and seeing at least one of the entries would not parse.

Day 3

The next day I woke to grey swollen skies that hinted at rain by their scent. Weary but determined, I set forth. Today I would seek out the Guru, Dani. I waited patiently for the other supplicants who’d made it to the Zoom cave of the Guru ahead of me to be helped, until at last it was my turn. In my adventures I had acquired a lot of ill-fitted pieces to my docker puzzle and had tried to put them in places where they didn’t quite fit. I’d been searching with Google to find the resources I needed to understand what I was doing, but many of the articles were out of date and didn’t have a date of publication. This made it difficult to tell if their information was useful, which in many cases, it was not. Piece by piece she helped me remove the parts of code that didn’t belong. Generously, she supplied me with the correct pieces, working through debugging with me until finally, at last, I had a working docker-compose.

Next step was to deploy. I attempted to do so by entering caprover deploy into the terminal, and following the prompts. All went as expected untill..

Terminal output “Something bad happened”

Day 4

My foraging continues as another steamy grey morning dawns across the jungle of DevOps. Having noticed the propogation of a number of files in my data folder named WiredTiger* or having the *.wt file extension, I thought that might perhaps be the problem. A WiredTiger? In the jungle of DevOps? What are the odds? Out of curiosity, I went WiredTiger hunting with my Google to find out more about it. Hidden behind a large browser frond, I peek at the WiredTiger documentation and discover that it is the default storage engine for MongoDB. While this is interesting, it’s not especially helpful. I leave the WiredTiger to do what WiredTigers do and continue my search.

The “413 Request Entity Too Large” error is my true obstacle, or at least so I think. Then I second-guess and wonder if it is merely a sympton of another issue? My search results, using the error message as the search parameter, lead me to find out that somewhere there must be a setting that is restricting the size of what can be deployed.

Somewhere along the way I decided that, yes indeed, this is a creative writing exercise in addition to being a “docker-mentary”. Otherwise it would be far too dry for my pallet. Adding elements of imagination and humor helps maintain motivation though the frustrations. As much as I’d rather not admit, this journey is much like a scavenger hunt, but then all coding is. Each exploration yields another clue that in best hopes leads to the desired outcome.

Resources

Instructional and Tutelage Credits:
Dani Roxbery — BEW Instructor
Merideth Murphy — Academic Coach
Ben Lafferty — TA

--

--