How to Use Docker Images, Containers, and Dockerfiles

With an Infographic and Cheatsheet

Mike Cronin
Oct 26, 2020 · 8 min read
Docker lifecycle: A Dockerfile BUILDing an image, which CREATEs Containers. RUN is a shortcut for CREATE, START, and ATTACH
Docker lifecycle: A Dockerfile BUILDing an image, which CREATEs Containers. RUN is a shortcut for CREATE, START, and ATTACH

The overview

We’re going to step through every piece of this graphic, but it’s helpful to see the three main stages upfront as a roadmap. In short, Dockerfiles are used to build images. Images are used to create containers. You then have to start and attach to the containers. The run command allows you to combine the create, start, and attach commands all at once.

Scroll to the end for a cheatsheet of every command we’ll use.

Our example server

In order for our project to do something, we’re going to make a server.js file that sends a simple text response. This is the only Node code in the tutorial. You do not need to know Node.

const http = require("http");const app = (req, res) => {
console.log("ping!");
res.end("Hello there.", "utf-8");
}
http.createServer(app).listen(3000);
console.log("server started");

What are Dockerfiles?

A Dockerfile is simply a text file with instructions that Docker will interpret to make an image. It is relatively short most of the time and primarily consists of individual lines that build on one another. It is expected to be called Dockerfile (case sensitive) and does not have a file extension. Here is a simple example:

FROM node:12-slimCOPY server.js server.jsCMD ["node", "server.js"]

Building our image

The way to build an image from a Dockerfile is to run build on the command line. The following command assumes we’re in the same directory as our server.js and Dockerfile:

docker build -t my-node-img .
docker image ls my-node-img# to see all images on your machine
docker image ls

What is a Docker image?

If a Dockerfile is a set of instructions used to create an image, it’s helpful to think that an image is just a template used to create a container. An image is responsible for setting up the application and environment that will exist inside the container. The important thing to understand is that images are read-only. You do not make edits to an image, you make edits to the Dockerfile and then build a new image.

Create a Container

Finally, we’re getting to the good stuff. This is technically all you need to do to create a container:

# don't type this yet
docker
create my-node-img
docker create --name my-app --init -p 3000:3000 my-node-img

What is a container?

The container is what actually runs our app. Think of the container like an isolated Linux box. It’s essentially a lighter weight virtual machine. The point of having a container is standardization. An application only has to care about the container it’s run in. No more, “But it works on my machine!” If an app runs in a container, it will work the same way no matter where the container itself is hosted. This makes both local development and production deployments much, much easier.

Starting a container

All create did was create the container, it didn’t start it. You can still see that it exists with docker ps and some extra filters:

docker ps -a --filter "name=my-app"
docker start my-app

Attaching to a container

How do we see our container’s outputs and logs? Well, there’s technically a command you can run, but hang on before typing it:

docker attach my-app
docker logs -f my-app

Exploring the container

If you want to go into the container to explore the file system, you’d want to run this:

docker exec -it my-app bash

Shortcut with Run

As you remember with the infographic, run is a shortcut that takes care of create, start, and attach all at once:

docker run --name my-app -p 3000:3000 --init --rm my-node-img
docker run -d --name my-app -p 3000:3000 --init --rm my-node-img

Stop and remove containers

Of course, you will want to stop and remove old/stuck containers, and that’s luckily straightforward:

docker stop my-app
docker rm my-app
docker stop $(docker ps -q)

Images from DockerHub and Run Commands

run doesn’t actually need the image to be on the host machine. If Docker can’t find the specified image locally, it will try to find it on DockerHub. This is useful when paired with another feature of run: it can execute a command on the newly created container. For example, you could spin up a Node image and then start it in bash instead of the default Node repl:

docker run -it node:12-slim bash
$ docker run node:12-slim cat /etc/issue
>>> Debian GNU/Linux 9

Next steps

We’ve had one container yes, but what about a second container? That’s another powerful feature of Docker: you can easily network containers together. But once you have 2 or more containers to manage, I wouldn’t recommended that you try to control them from the command line. No, what you’ll want to start using is a container orchestration system, usually it’ll be Docker Compose for local development and Kubernetes for actual production. I recommend watching this video to pick up the basics of Compose and this series to take a deeper dive with Kubernetes.

— — The Cheatsheet — —

# Build your image 
docker build -t my-node-img .
# Show specific image
docker image ls my-node-img
# to see all images on your machine
docker image ls
# Create a container with the tiny package, a name, and port
docker create --init --name my-app -p 3000:3000 my-node-img
# Show newly created container
docker ps -a --filter "name=my-app"
# Start your container
docker start my-app
# Attach to container (not recommended)
docker attach my-app
# See containers logs (recommended)
docker logs -f my-app
# access container's system
docker exec -it my-app bash
# using the run shortcut
docker run --name my-app -p 3000:3000 -d --init --rm my-node-img
# Stop a running container
docker stop my-app
# Remove a non-running container
docker rm my-app
# see all running containers
docker ps
# stop all running containers
docker stop $(docker ps -q)
# Check version of linux for container
docker run node:12-slim cat /etc/issue

The Startup

Get smarter at building your thing. Join The Startup’s +789K followers.

Sign up for Top 10 Stories

By The Startup

Get smarter at building your thing. Subscribe to receive The Startup's top 10 most read stories — delivered straight into your inbox, once a week. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Mike Cronin

Written by

I’m Mostly Focused on JS and web development, but anything coding related is fair game

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +789K followers.

Mike Cronin

Written by

I’m Mostly Focused on JS and web development, but anything coding related is fair game

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +789K followers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store