A Beginner's Guide to Docker Images: Layer Structure and Commands

Hemanth GangulaHemanth Gangula
7 min read

In this article, we’ll explore what a Docker image is, how its layered structure works, and the basic commands you need to manage images. Plus, we’ll walk you through creating an image from scratch.

Welcome to Day 5 of our Simplified Docker Series! Before we dive into Dockerfiles, let’s first get familiar with the basics of Docker images and how they fit into the overall Docker workflow. By the end, you'll have a solid grasp of Docker images and be ready to apply your knowledge.

What is a Docker Image?

Think of a Docker image as the ultimate blueprint for running your application. It’s a single, self-contained file that includes everything your app needs — code, libraries, dependencies, and configurations — all bundled into one neat package.

No matter how many files your app originally has, a Docker image unifies them into one, allowing you to launch your application effortlessly with a single command.

Each time a container is created, Docker pulls from this image, which acts like a snapshot of your app’s setup. Docker images are layered, meaning each change is stored in a new layer, keeping storage efficient and updates smooth without duplicating data.

This layered approach makes Docker images lightweight, portable, and consistent across environments, making development and deployment a breeze.

Did You Know Docker Builds Images in Layers? Here’s Why It’s a Game-Changer!

Alright, let’s talk about something really cool in Docker image layers. Ever wondered why Docker builds its images in layers instead of just making one big image? Let’s break it down in a way that makes total sense.

Imagine you’re building a sandwich 🥪.
You start with the bread (your base), then maybe add some lettuce, tomatoes, cheese whatever you like. Each of those ingredients is a different layer, right? Now, if you wanted to change just one thing, say swap out tomatoes for cucumbers, you wouldn’t toss the whole sandwich, would you? You’d just change that one layer.

That’s exactly how Docker works when it builds images. Each line in your Dockerfile creates a new layer. For instance, when you specify FROM python:3.9-slim in your Dockerfile, Docker pulls the base Python image, and boom—that’s your first layer. Then, as you add instructions like RUN pip install or COPY your code files, it adds more layers on top of that.

Why Layers?

Here’s the best part: Docker doesn’t have to rebuild everything when something changes. It only rebuilds the layers that need updating. Let’s say you update a package or change some app code. Docker will reuse the existing layers that haven’t changed and only rebuild the new stuff. This means faster builds, less storage, and super-efficient updates. 🚀

In this Dockerfile example, our Docker image is built in four main layers. Let’s break down each layer and understand its purpose:

FROM python:latest  
WORKDIR /app  
COPY . /app  
RUN pip install -r requirements.txt  
EXPOSE 5000  
CMD ["python", "app.py"]
  1. FROM python:latest
    This is our base layer and the foundation of the Docker image. Here, python:latest pulls the latest Python image, already set up with an OS environment. It includes system libraries and essential dependencies for Python, giving our application everything it needs to run in a familiar environment.

  2. WORKDIR /app
    The WORKDIR /app command sets /app as the working directory inside the container. This means all subsequent commands in the Dockerfile, like COPY and RUN, will execute in /app, keeping our application files organized and preventing conflicts with other directories.

  3. COPY . /app
    This command copies all files from the current directory on the host machine to the /app directory in the container. Here, we bring in our application code and resources, making them accessible and ready for the containerized environment.

  4. RUN pip install -r requirements.txt
    This command installs the dependencies listed in requirements.txt. It creates a new layer that includes all necessary Python libraries and packages, setting up the application to be ready to run.

So why should you care about layers?

Well, they save you time—especially when your project grows. Docker doesn’t have to build the whole image from scratch every time. And for big projects or continuous deployments, this is a huge win. Think of it like having a super-efficient, customizable sandwich-making machine that always makes the perfect sandwich without wasting any ingredients. 😄

I hope that makes it crystal clear! Layers might sound technical, but when you think of them as building blocks (or sandwich layers), it’s easy to see why Docker uses them to keep things fast and reusable.

Why Some Commands Don't Create Layers

Certain commands in Docker, like EXPOSE 5000 and CMD ["python", "app.py"], don’t create layers because they act more like instructions than actual changes to the image itself.

For instance, EXPOSE 5000 is simply a way of saying, “This is the port to connect to when the container runs.” It’s like posting a sign that directs others on how to reach your app but doesn’t alter the contents of the image, so no new layer is needed.

Similarly, CMD ["python", "app.py"] sets the default command that will run when the container starts. Think of it as setting your app’s default action rather than modifying the image. Since it doesn’t change the actual image, it also doesn’t create a new layer.

How to Create a Docker Image from Scratch

Now that we've discussed Docker Image, let's dive into creating a Docker image from scratch. To get started, you can clone the repository by visiting :

https://github.com/HemanthGangula/docker-simplified-series.git

change the directory:

cd Day-3

you'll find a simple Python Flask application along with its Dockerfile.

If you're not familiar with the Dockerfile structure, don't worry! We’ve already covered its components in detail earlier. To build your Docker image, use the following command:

docker build -t your_image_name .

This command builds the Docker image based on the Dockerfile in the current directory.

Once the image is built, you can run your Docker container with:

docker run -t -p 5000:5000 your_image_name

This will run the container, allowing you to access the sample application at localhost:5000. Enjoy exploring your newly created Docker image!

Common Docker Image Commands With commands:

Now that we understand Docker images, let’s walk through some of the most common commands you’ll need to manage and use them. Each command comes with a quick example so you can try it out right away!

  • docker pull: This command fetches an image from a repository like Docker Hub. Think of it as downloading the blueprint for your container. For example, let’s pull the nginx image, which is a popular web server:

      docker pull nginx
    

    Running this command will pull the latest nginx image to your local system.

  • docker images: After pulling an image, you might want to check what’s available locally. The docker images command lists all images saved on your system:

      docker images
    

    This gives you a table showing repository names, tags, and sizes. This way, you can confirm that the nginx image is ready to go.

  • docker run: Now, let’s start up a container from the nginx image. The docker run command both creates and runs a container in one step. A simple example to run nginx and map it to port 8080 on your local machine:

      docker run -d -p 8080:80 nginx
    

    Here, -d runs the container in detached mode (in the background), and -p 8080:80 maps port 80 of the nginx container to port 8080 on your local machine.

    To see the application running, open your web browser and navigate to http://localhost:8080. You should see the default nginx welcome page!

  • docker rmi: When you no longer need an image, you can remove it with docker rmi. This can help keep your system clean and save disk space. For instance:

      docker rmi nginx
    

    If you try this while a container is using the image, Docker will throw an error. So, be sure to stop or delete any containers relying on the image first.

Try these commands to get a feel for Docker’s basics! From downloading images to running containers and managing storage, these steps help you put Docker to work quickly and easily.

Conclusion:

To wrap things up, grasping the concept of Docker images is a game-changer for managing and deploying your applications seamlessly. We’ve walked through the essentials—what Docker images are, how they’re structured in layers, and even how to create one from scratch. With this foundation, you’re well on your way to becoming a Docker pro!

Looking ahead, our next article will dive into the exciting world of hosting your images in registries like Docker Hub and AWS ECR. This will make it super easy for you to share and deploy your applications wherever you need them. So, keep an eye out for that exciting things are on the horizon!

"Every great journey begins with a single step." — Lao Tzu

0
Subscribe to my newsletter

Read articles from Hemanth Gangula directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Hemanth Gangula
Hemanth Gangula

🚀 Passionate about cloud and DevOps, I'm a technical writer at Hasnode, dedicated to crafting insightful blogs on cutting-edge topics in cloud computing and DevOps methodologies. Actively seeking opportunities in the DevOps domain, I bring a blend of expertise in AWS, Docker, CI/CD pipelines, and Kubernetes, coupled with a knack for automation and innovation. With a strong foundation in shell scripting and GitHub collaboration, I aspire to contribute effectively to forward-thinking teams, revolutionizing development pipelines with my skills and drive for excellence. #DevOps #AWS #Docker #CI/CD #Kubernetes #CloudComputing #TechnicalWriter