Docker Basics

Will Breitkreutz
corpsmap
Published in
5 min readOct 7, 2016
Containers, stacked, you know, like Docker does…

Since we’re jumping on the Docker bandwagon for our server-side deployments I figured I we could all use a little bit of a primer into what Docker is and how it works as well as a little detail on how we plan to use it in CorpsMap.

So, what is this Docker thing?

I’m sure we’ve all heard and read a bunch of people talking about Docker and how great it is and how it makes their lives so much easier, without actually talking about how it actually makes their lives easier… Let’s try and fix that, at least a little bit.

I’m not an expert on Linux so some of this might be a little light on the technical details but here’s what Docker is in my (admittedly limited) understanding.

Note: you can get an e-book from the Docker folks that will go into much more detail that I can here.

Docker is a framework for containerizing applications, this is similar to setting up virtual machines (VM’s) on a single host machine to segregate applications into their own container. The difference on the Docker side is that rather than set up a suite of complete operating systems with some sort of hypervisor that manages them:

Courtesy of Docker.com, Thanks!

Docker containers share the kernel resources from the host operating system and only contain their specific individual dependencies and application code. The Docker Engine manages the resource sharing between containers and the host OS and as long as Docker Engine is running on a host, any container that runs in one place will run there as well, eliminating the “it works on my machine” issue that we often see.

Courtesy of Docker.com, Thanks!

OK, so what’s a container?

A container is basically a layer cake of dependencies and operations that are stacked together and finally compiled to a working image.

You start with a base operating system container, linux of some flavor, and begin layering resources on top of that using a configuration file called a Dockerfile.

Dockerfiles look something like this:

FROM ubuntu:trustyRUN curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
RUN sudo apt-get install -y nodejs
RUN sudo apt-get install -y build-essential

This is a stupid simple example, it states that we should start by using the Ubuntu (trusty version) container as our base OS, then install Node.js. That’s all it does, it doesn’t start anything up or add any application code at this point. We can compile this into an image on our local machine that we can build on top of and then optionally push it to some central repository like Docker Hub for others to build on top of.

Let’s say we compile the above image using the following command:

> docker build -t corpsmap/node .

There are a few parts to that command,

  • build is the operation we’re telling the Docker process to perform.
  • -t tells Docker that we want to tag the resulting container with the name corpsmap/node.
  • assuming that we’re inside the folder containing the Dockerfile, we can reference our current location with the . otherwise we would want to point to a location containing the Dockerfile we are targeting.

With that we now have a compiled image called corpsmap/node on our local machine that we can use to build on top of.

Again, let’s say we have a Node.js application that we want to add to the container and get ready to deploy.

We can create a Dockerfile in the root of the node application that looks something like this:

FROM corpsmap/nodeRUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app
COPY server.js /usr/src/app
RUN npm installEXPOSE 8080CMD [“npm”,”start”]

This Dockerfile uses the image we just compiled as our base OS, then builds on top of it by copying our node application into the container and installing its dependencies, exposing the application port and finally telling it what command to use when the container is run.

We can build the image just like we did earlier using the build command inside the directory containing the Dockerfile:

> docker build -t corpsmap/node-server .

Now we have a compiled image called corpsmap/node-server that is ready to deploy!

Deploying an Image

Deploying a compiled image is pretty easy. Instead of running docker build, we can use a docker run command.

Given the corpsmap/node-server image that we compiled above we can use the following command to get it going:

> docker run -d -v /opt/corpsmap/node_server/src:/usr/src/app/src -p 8080:8080 corpsmap/node-server

Ok, let’s parse this one out:

  • run is our Docker command that launches an image.
  • -d tells Docker we would like to run this in detached mode, by default it hooks our terminal session to the stdout of the image as it launches so you can see any start-up messages you might be interested in, if you want to see that, just remove the -d from our command above.
  • -v is used to map a volume (folder) from the host machine to a location accessible inside the running image, in this case we’re mapping our source code folder from the host into the running image so that our code can run inside the container, but also be edited from outside, I wouldn’t recommend doing this in production, but for development and testing this is awesome! We can map as many volumes into the container as necessary.
  • -p is used to map a port from the host machine to the running container, this is how our node app talks to the rest of the world. We’re mapping 8080 from the host to 8080 inside the container, but we could just as easily map any port from the host to 8080 inside the container and Docker will forward our traffic for us.
  • Last but not least is our image tag telling Docker what image we want to launch.

There is a companion python app called Docker Compose that makes running multiple interdependent containers pretty easy. We’ll save that discussion for another post, but check it out, it’s nice.

You can get a lot more complicated if you really want to, but this is all it takes to get a container up and running. I’m going to do another post on the specific Docker workflow that we’re using for CorpsMap, keep an eye out for that one if you’re interested.

--

--