Hands-On Docker Projects and Kubernetes Basics

Akshansh SinghAkshansh Singh
7 min read

Introduction

Hello thereπŸ‘‹! This past week was both exciting and intense. After understanding Docker, I wanted to explore it more practically, so I decided to create a couple of mini projects. I also got started with Kubernetes, and to say it's confusing at first would be an understatement. In this article, I'll talk about my experience with the Docker projects and my first impressions of Kubernetes.

Mini Project 1: Web App with Nginx + MySQL

After getting the hang of Docker and its different components and concepts, I was ready to experiment by implementing what I learned to deploy something real. I decided to choose a simple Notes application with CRUD operations using Django for the backend, Nginx as a proxy, and MySQL as the database. I started with an EC2 instance and installed Docker and Docker Compose. Then I cloned the selected repository into the EC2 instance.

The repository was divided into frontend, backend, and nginx sections, and it had pre-existing Dockerfiles which I double-checked for reference. I created a fresh docker-compose.yml file with 3 services: Nginx, MySQL, and Django.

Here, the Nginx service depends on Django, and Django depends on the database service since the database needs to initialize first. For each service, I configured the ports, network, container name, and build image. Since the project had Django and MySQL, to connect Django and MySQL, we need to use the migrate command to create the database and tables, and Gunicorn is used to serve the Django application. All the database credentials were passed through the environment file.

To ensure proper initialization of services and proper connection, I used health checks in both the database service and Django app service. I had some problems with the containers not connecting to each other due to networking issues, but after some troubleshooting, I was able to initialize and connect the services properly.

Mini Project 2: Spring Boot Application

As part of my second mini project, I chose a Spring Boot application containing 3 components: Thymeleaf (UI), Spring Boot (backend), and MySQL (database), with Maven as the build tool. In the Dockerfile, I chose to go with a multi-stage build - the first stage to install all dependencies and build the application as an artifact, and the second stage with a smaller base image to run the application.

After completing the Dockerfile, it was time to configure the docker-compose file. This project had two main services: the main application and the database (MySQL). I followed the same process as the previous project - configuring container name, base image, ports, creating a separate network and volume, and setting up health checks to ensure proper initialization and connection.

The difference was in configuring environment variables. Using the application.properties file, I noted all the required parameters and provided them in the docker-compose file using the environment object. After some trial and error, I got the containers running and checked the application on the instance's public IP.

Getting Started with Kubernetes

After completing the projects using Docker, it was time to start something new. After Docker, I decided to start learning one of the most important tools in the DevOps field - Kubernetes. Kubernetes sits at the heart of modern cloud-native application deployment and management.

I started with "What is Kubernetes?" The answer I found through Kubernetes official documentation is that Kubernetes (often abbreviated as "K8s") is an open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications. It's like the "operating system for the cloud" - just as your computer's OS manages programs and resources, Kubernetes manages containers and compute resources across multiple machines.

Then I wanted to know what problems Kubernetes actually solves. K8s solves problems like:

  1. Manual scaling

  2. Service discovery

  3. Load distribution

  4. Health monitoring

  5. Resource optimization

While solving all of these critical problems, K8s also delivers concrete business value such as faster release cycles, cost efficiency, reliability, high scalability, and developer productivity. With the rise of containers, the moving trend from monolith to microservices, and the rising demand to manage hundreds of containers, container orchestration tools like Kubernetes have become an essential part of the software development and deployment lifecycle.

K8s Architecture

Understanding the Kubernetes architecture is essential as it provides the fundamental framework for managing containerized applications effectively. Kubernetes follows a master-worker pattern (also called control plane and data plane).

The key components of a Kubernetes cluster are:

  • Pod: The smallest deployable unit in Kubernetes, grouping one or more containers that share storage, network, and a specification.

  • kube-api-server: The central "front door" that receives and processes all REST requests for the cluster.

  • etcd: A lightweight, distributed key-value store that persistently holds all cluster configuration and state.

  • kube-scheduler: Watches for new pods with no assigned node and assigns them to the most appropriate node.

  • kube-controller-manager: Runs background controllers (like replication and endpoint controllers) to ensure the cluster's desired state matches the actual state.

  • cloud-controller-manager: Integrates Kubernetes with your cloud provider's API to manage cloud-specific resources (e.g., load balancers, volumes).

  • kubelet: An agent running on each node that ensures containers described in PodSpecs are up and healthy.

  • kube-proxy: Maintains network rules on nodes to allow communication to your pods from inside or outside the cluster.

  • kubectl: The command-line tool used to send commands to the kube-api-server and manage your cluster.

The architecture follows a declarative workflow:

  1. You submit a request (via kubectl) β†’ API Server receives it

  2. API Server validates and stores β†’ Information goes to etcd

  3. Scheduler assigns work β†’ Decides which node should run the pod

  4. kubelet executes β†’ Node agent creates and manages containers

  5. Controllers monitor β†’ Ensure everything stays as desired

  6. kube-proxy handles networking β†’ Manages traffic routing

Through this, I understood how the components work together. I also learned about different installation methods for Kubernetes such as Minikube, Kubeadm, and KinD. As I got to know more about K8s, the more confusing it became for me, and I expected that since Kubernetes is not easy to learn and is a big and complex tool. But slowly and steadily, I hope I can learn K8s effectively and use it for practical and real-world implementations.

Resources I Used

  1. Kubernetes Crash Course | Techworld with Nana

  2. Kubernetes | TrainWithShubham

  3. Docker | TrainWithShubham

  4. Kubernetes Official Docs

Challenges I Faced

1️⃣ Containers couldn't connect to network

This was frustrating because the containers were running individually, but they couldn't communicate with each other. I spent quite some time debugging this issue before realizing the root cause.

Solution: I hadn't configured the network properly between the services in the docker-compose file. I needed to explicitly define a custom network and ensure all services were part of the same network to enable inter-container communication.

2️⃣ Application redirecting to Nginx welcome page instead of the notes app

When I opened the application on port 80, it kept showing the default Nginx welcome page instead of my notes application. This was confusing because the containers seemed to be running fine.

Solution: The issue was in the Nginx configuration. I had to change the container name to match the service name in the default.conf file in Nginx. This allowed Nginx to properly proxy requests to the Django application container.

3️⃣ Difficulty understanding the key components of K8s and its flow

Kubernetes felt overwhelming at first. There are so many components and concepts, and understanding how they all work together was challenging. The official documentation, while comprehensive, felt too technical for a beginner.

Solution: I referred to a Kubernetes crash course video to better understand the big picture and components. Visual explanations and practical examples helped me grasp the concepts much better than just reading documentation.

What's Next?

As I said, Kubernetes is a complex and difficult tool to master, so I will continue to learn and understand the basics first and build a strong foundation before moving on to advanced concepts. I plan to set up a local Kubernetes cluster and deploy some simple applications to get hands-on experience.

Let's Connect!

πŸ”— My LinkedIn πŸ”— My GitHub

If you have any recommended resources, better approaches to my challenges, or insights, I'd love to hear them! Drop your thoughts in the comments.

Have a wonderful day!

1
Subscribe to my newsletter

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

Written by

Akshansh Singh
Akshansh Singh

Driven by curiosity and a continuous learning mindset, always exploring and building new ideas.