DEV Community

Cover image for Docker for Beginners: Images, Containers, Ports, and Volumes Explained
Chetan Inaganti
Chetan Inaganti

Posted on

Docker for Beginners: Images, Containers, Ports, and Volumes Explained

Docker for Beginners: Images, Containers, Ports, and Volumes Explained

If you've ever followed a programming tutorial and seen something like:

docker run ...
Enter fullscreen mode Exit fullscreen mode

you've probably wondered:

What exactly is Docker doing?

I had the same question when I started learning Docker.

At first, I thought Docker was simply a way to "run applications in containers."

But there is much more to it.

Once I understood four concepts — images, containers, ports, and volumes — Docker became much easier to understand.

So let's break it down from the beginning.


What Is Docker?

Docker is a platform for building, packaging, and running applications in isolated environments called containers.

The basic idea is simple:

Package an application together with the things it needs to run, and make that package portable.

For example, imagine you build a Python application.

Your application might depend on:

  • Python 3.12
  • FastAPI
  • Uvicorn
  • Several Python packages
  • Environment variables
  • Certain system libraries

On your computer, everything works.

Then someone else downloads your project.

They install a different Python version.

A package is missing.

Something behaves differently.

Now you have:

"It works on my machine."

Docker helps reduce this problem by allowing you to define the environment your application should run in.


The Four Concepts You Need to Understand

Before learning Docker commands, understand these four things:

Docker Image
      ↓
Docker Container
      ↓
Ports
      ↓
Volumes
Enter fullscreen mode Exit fullscreen mode

Let's look at each one.


1. What Is a Docker Image?

A Docker image is a packaged, read-only template used to create containers.

Think of it like a blueprint.

For example:

Docker Image
│
├── Ubuntu
├── Python
├── Application code
├── Dependencies
└── Configuration
Enter fullscreen mode Exit fullscreen mode

An image contains the instructions and filesystem needed to create a container.

You can download images from container registries such as Docker Hub.

For example:

docker pull nginx
Enter fullscreen mode Exit fullscreen mode

This downloads the Nginx image.

You can see your downloaded images with:

docker images
Enter fullscreen mode Exit fullscreen mode

You might see something like:

REPOSITORY    TAG       IMAGE ID       SIZE
nginx         latest    abc123...      ...
Enter fullscreen mode Exit fullscreen mode

2. What Is a Container?

A container is a running instance of an image.

This distinction is important.

Think about it like this:

Image       = Blueprint
Container   = Running thing created from the blueprint
Enter fullscreen mode Exit fullscreen mode

For example:

docker run nginx
Enter fullscreen mode Exit fullscreen mode

Docker takes the Nginx image and creates a container from it.

You can see running containers with:

docker ps
Enter fullscreen mode Exit fullscreen mode

To see both running and stopped containers:

docker ps -a
Enter fullscreen mode Exit fullscreen mode

You might see:

CONTAINER ID   IMAGE   STATUS
abc123         nginx   Up 2 minutes
Enter fullscreen mode Exit fullscreen mode

Image vs Container

This is one of the most important Docker concepts.

Image Container
Template Running instance
Read-only Has a writable container layer
Used to create containers Created from an image
Can be stored in a registry Exists on your Docker host

A single image can be used to create multiple containers.

For example:

          Nginx Image
          /    |    \
         /     |     \
        ↓      ↓      ↓
   Container  Container  Container
Enter fullscreen mode Exit fullscreen mode

3. What Are Ports?

Here's where Docker can initially feel confusing.

Suppose you have a web application running inside a container.

Your application might listen on:

Port 8000
Enter fullscreen mode Exit fullscreen mode

But that port belongs to the container's network environment.

Your browser needs a way to access it from your computer.

That's where port mapping comes in.

For example:

docker run -p 8080:80 nginx
Enter fullscreen mode Exit fullscreen mode

This means:

Your computer       Container
     8080      →       80
Enter fullscreen mode Exit fullscreen mode

So when you visit:

http://localhost:8080
Enter fullscreen mode Exit fullscreen mode

Docker forwards the traffic to port 80 inside the container.

The general syntax is:

-p HOST_PORT:CONTAINER_PORT
Enter fullscreen mode Exit fullscreen mode

For example:

-p 8080:80
Enter fullscreen mode Exit fullscreen mode

means:

Host:      8080
Container: 80
Enter fullscreen mode Exit fullscreen mode

This distinction is extremely important when working with web applications.


4. What Are Volumes?

Containers are designed to be replaceable.

But sometimes your application needs to keep data.

Imagine you run a PostgreSQL database inside a container.

If the container is removed, you don't want your database data to disappear with it.

That's where volumes come in.

A volume stores persistent data outside the container's writable layer.

You can create one with:

docker volume create mydata
Enter fullscreen mode Exit fullscreen mode

Then attach it to a container:

docker run -v mydata:/data some-image
Enter fullscreen mode Exit fullscreen mode

Conceptually:

Container
    │
    │ writes data
    ↓
 Docker Volume
    │
    ↓
Persistent storage
Enter fullscreen mode Exit fullscreen mode

So even if the container is removed, the volume can remain.


Let's Run Our First Container

Let's start with something simple.

Run:

docker run hello-world
Enter fullscreen mode Exit fullscreen mode

Docker will:

  1. Look for the hello-world image locally.
  2. Download it if necessary.
  3. Create a container from the image.
  4. Start the container.
  5. The container prints its message.
  6. The process exits.

You can check what happened with:

docker ps -a
Enter fullscreen mode Exit fullscreen mode

You'll see the container even though it has stopped.

This was one of the first Docker commands I tried while learning Docker.


Running Nginx

Let's try something that stays running.

Run:

docker run -d -p 8080:80 --name my-nginx nginx
Enter fullscreen mode Exit fullscreen mode

Let's break this command down.

docker run
Enter fullscreen mode Exit fullscreen mode

Create and start a container.

-d
Enter fullscreen mode Exit fullscreen mode

Run it in detached mode, meaning the container runs in the background.

-p 8080:80
Enter fullscreen mode Exit fullscreen mode

Map port 8080 on your computer to port 80 in the container.

--name my-nginx
Enter fullscreen mode Exit fullscreen mode

Give the container a memorable name.

nginx
Enter fullscreen mode Exit fullscreen mode

Use the Nginx image.

Now open:

http://localhost:8080
Enter fullscreen mode Exit fullscreen mode

You should see the Nginx welcome page.


Managing the Container

See running containers:

docker ps
Enter fullscreen mode Exit fullscreen mode

Stop the container:

docker stop my-nginx
Enter fullscreen mode Exit fullscreen mode

Start it again:

docker start my-nginx
Enter fullscreen mode Exit fullscreen mode

Remove it:

docker rm my-nginx
Enter fullscreen mode Exit fullscreen mode

See its logs:

docker logs my-nginx
Enter fullscreen mode Exit fullscreen mode

Inspect detailed information:

docker inspect my-nginx
Enter fullscreen mode Exit fullscreen mode

These commands are worth learning because you'll use them constantly.


Where Does the Nginx Image Come From?

When you run:

docker run nginx
Enter fullscreen mode Exit fullscreen mode

Docker first checks whether the image exists locally.

If it doesn't, Docker pulls the image from a container registry.

The general workflow looks like this:

Docker Hub
    │
    │ docker pull
    ↓
Docker Image
    │
    │ docker run
    ↓
Docker Container
Enter fullscreen mode Exit fullscreen mode

A registry is essentially a place where container images can be stored and distributed.


What Is a Dockerfile?

So far we've been using existing images.

But what if we want to package our own application?

That's where a Dockerfile comes in.

A Dockerfile is a text file containing instructions for building a Docker image.

For example:

FROM python:3.12

WORKDIR /app

COPY . .

RUN pip install -r requirements.txt

CMD ["python", "app.py"]
Enter fullscreen mode Exit fullscreen mode

Let's understand it.


FROM

FROM python:3.12
Enter fullscreen mode Exit fullscreen mode

This specifies the base image.

We're starting with a Python 3.12 environment.


WORKDIR

WORKDIR /app
Enter fullscreen mode Exit fullscreen mode

This sets the working directory inside the image.


COPY

COPY . .
Enter fullscreen mode Exit fullscreen mode

This copies files from our project into the image.


RUN

RUN pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

This executes a command while the image is being built.

Here, we're installing Python dependencies.


CMD

CMD ["python", "app.py"]
Enter fullscreen mode Exit fullscreen mode

This specifies the default command that runs when a container starts from the image.


Building Our Own Image

Suppose our project looks like this:

my-app/
│
├── Dockerfile
├── app.py
└── requirements.txt
Enter fullscreen mode Exit fullscreen mode

From inside the project directory, run:

docker build -t my-python-app .
Enter fullscreen mode Exit fullscreen mode

The -t option gives the image a name.

The . tells Docker to use the current directory as the build context.

Now check your images:

docker images
Enter fullscreen mode Exit fullscreen mode

You should see:

my-python-app
Enter fullscreen mode Exit fullscreen mode

We can now create a container from it:

docker run my-python-app
Enter fullscreen mode Exit fullscreen mode

The Docker Workflow

At this point, the whole process starts to make sense.

             Dockerfile
                 │
                 │ docker build
                 ↓
            Docker Image
                 │
                 │ docker run
                 ↓
           Docker Container
                 │
          ┌──────┴──────┐
          ↓             ↓
        Ports         Volumes
          ↓             ↓
       Network       Persistent
       access          data
Enter fullscreen mode Exit fullscreen mode

This is the mental model I wish I had when I first started learning Docker.


A Simple Mental Model

If you remember nothing else from this article, remember this:

Dockerfile

Instructions for building an image.

Image

A packaged template for an application.

Container

A running instance of an image.

Port

A way to make a container's network service accessible.

Volume

Persistent storage that can outlive a container.


The Commands I Would Learn First

You don't need to memorize every Docker command.

Start with these:

docker --version

docker pull IMAGE

docker images

docker run IMAGE

docker ps

docker ps -a

docker stop CONTAINER

docker start CONTAINER

docker logs CONTAINER

docker exec -it CONTAINER bash

docker build -t IMAGE .

docker rm CONTAINER

docker rmi IMAGE

docker volume ls
Enter fullscreen mode Exit fullscreen mode

Once these become familiar, learning more Docker features becomes much easier.


What I Learned

The biggest thing I learned while starting Docker is that the commands aren't the difficult part.

The mental model is.

Once I understood:

Dockerfile
    ↓
Image
    ↓
Container
    ↓
Ports + Volumes
Enter fullscreen mode Exit fullscreen mode

the commands started making much more sense.

Docker stopped feeling like a collection of random commands and started feeling like a system.


What's Next?

This is only the beginning.

The next step for me is taking something I've actually built and putting it inside a container.

For example:

FastAPI Application
        ↓
     Dockerfile
        ↓
   Docker Image
        ↓
    Container
        ↓
      Port
        ↓
    Web API
Enter fullscreen mode Exit fullscreen mode

That's where Docker becomes much more interesting.


Final Thoughts

If you're learning Docker right now, don't try to memorize 100 commands.

Start with the fundamentals:

Images → Containers → Ports → Volumes

Understand what each one does.

Then build something.

That's when Docker starts to click.


What About You?

When did Docker finally start making sense to you?

And if you're just starting:

What part of Docker is confusing you right now?

I'd be interested to hear about it in the comments.


Related

This is the second article in my journey toward building a modern development environment.

Part 1: From Windows to WSL (Ubuntu) + Docker

More articles coming as I learn and build.

Top comments (0)