An Introduction to Docker

I've been learning about Docker for use in my personal and professional projects. Though I've used it before, I've always had a vague understanding of what's actually going on behind the scenes. And so I decided to go back to the basics and build a better high-level understanding before diving into the weeds. Let's dive in:

What is Docker?

Docker is a tool for creating and running containers.

What is a container?

A container is a unit of software that packages up code and all its dependencies (code, system tools, system libraries and settings). When a container is running, you can consider it to be an isolated environment (separate from your local machine, or host) in which your code can run.

A container is similar to a virtual machine, but instead of requiring a separate operating system and a hypervisor program to divy up the host's resources between the host and the virtual machine, a container uses the host's operating system kernel and shares resources with it.

I won't go into the details here. But there are a multitude of blog posts on this topic, such as this one.

The bottom line: containers are isolated environments in which you can package code and run it. And they require fewer resources than virtual machines do.

How does Docker work?

So, how do you use docker to create a container? And what happens when you do?

Docker containers are built using images. An image is a blueprint for a container - it's a set of dependencies and configuration options that are installed on your image when it's created.

Note that Docker images live on Dockerhub - a repository for both user-generated and officially maintained Docker images.

When you create and run a container using Docker, you need to tell Docker several things:

  1. What image to use for your container.
  2. Where the files for your container will live on your local machine/host.
  3. Any additional files (aside from the image files) to copy to your container.
  4. Any commands you want run on the container after it starts.

You can specify these items via the command line, or you can specify them in a special file a Dockerfile.

Here's an example Dockerfile:

# Use the official image as a parent image.
FROM node:current-slim

# Set the working directory.
WORKDIR /usr/src/app

# Copy the file from your host to your current location.
COPY package.json .

# Run the command inside your image filesystem.
RUN npm install

# Inform Docker that the container is listening on the specified port at runtime.
EXPOSE 8080

# Run the specified command within the container.
CMD [ "npm", "start" ]

# Copy the rest of your app's source code from your host to your image filesystem.
COPY . .

Visual Example

Let's say you have an app you want to run in a container. Let's also assume you have a project directory with some source code for the app and a Dockerfile with the instructions on how to setup your container. When you use the command docker run , Docker will do the following:

  1. Fetch the image files from Dockerhub.
  2. Create a working directory for your container - space on your host that contains the root filesystem for your container.
  3. Install the dependencies for your app and start your container.
  4. Copy your app's source code to the container's working directory.

Here's a visual example:

Conclusion

That's all for now! Hope this helped you get an idea of how Docker works. The best resource to read for this is likely the official Docker orientation, but I wanted to write my own verison to get the ideas down in my mind.