Deploying a Docker Container to Kubernetes using Helm and Helm Charts

Deploying a Docker Container to Kubernetes using Helm and Helm Charts

When you're working on large projects that require multiple containers to be deployed to Kubernetes, managing these containers manually can quickly become overwhelming.

This is because you'll probably have to write a separate deployment file, service file, and other configurations for each container. Imagine doing this for ten containers; it can be a nightmare. Well, there's a solution to this problem, and it's called Helm.

Helm helps you simplify the deployment process by allowing you to package all your Kubernetes resources into a single package called a Helm Chart. This article guides you through deploying a Docker container to Kubernetes using Helm. By the end of this article, you'll be able to deploy large projects with a single Helm command.

Prerequisites

This article will take you through this process in a step-by-step manner. However, before you begin, you need to have the following installed on your machine:

  • Docker. If you don't have Docker installed, download it from the Docker website.

  • Helm. You can use the installation steps on the Helm installation guide.

  • Kubernetes. If you're using Docker Desktop, you only need to enable it in the settings. If you're using Minikube, follow the installation steps on the Minikube installation guide.

What is Helm?

Helm is a package manager for Kubernetes applications. It helps you define, install, and manage Kubernetes applications and their dependencies more easily. Think of Helm as similar to package managers like apt (for Ubuntu) or yum (for CentOS) in the Linux world but tailored explicitly for Kubernetes.

When you have an application, Helm can package all the Kubernetes resources like deployments, services, and configmaps required to run that application into a single package called a Helm Chart. This Helm Chart can then be shared with others, making it easy for them to deploy the application to their Kubernetes cluster.

What is a Helm Chart?

A Helm chart is a collection of files that describe a set of Kubernetes resources, such as deployments, services, configmaps, and more, needed to run a particular application. Charts can be versioned, shared, and reused.

A Helm chart has the following structure:

mychart/
 Chart.yaml
 values.yaml
 charts/
 templates/
 .helmignore
 ...
  • Chart.yaml: The Chart.yaml file contains metadata about the chart, such as the name, version, and description.

  • values.yaml: This file contains the default values for the chart. These values can be overridden when installing the chart.

  • charts/: This directory contains any subcharts on which the chart depends.

  • templates/: This directory contains the Kubernetes resource templates that will be deployed to the cluster. Helm uses Go templating to allow for parameterization and customization of Kubernetes manifests within charts. Templates enable you to dynamically generate Kubernetes resource definitions based on values provided at deployment time.

  • .helmignore: Like .gitignore, this file specifies files that should be ignored when packaging the chart.

All these files are generated when you create a new Helm chart using the helm create command.

Why would you use Helm?

While you can deploy Kubernetes resources manually using kubectl apply, Helm provides several benefits that make it a better choice, especially for complex applications:

  1. Package Management: Helm provides a package management system for Kubernetes applications. With Helm charts, you can package all the Kubernetes resources (e.g., deployments, services, configmaps) your application needs into a single, version-controlled artifact.

  2. Reusability: Helm charts are reusable templates you can share with others. By leveraging Helm charts created by the community or within your organization, you can avoid reinventing the wheel and accelerate your development and deployment workflows.

  3. Versioning and Rollbacks: Helm allows you to version your Helm charts and releases. This enables you to track changes to your application over time and easily roll back to a previous version if necessary. Helm's rollback feature simplifies reverting to a known stable state in case of deployment issues.

  4. Configuration Management: Helm charts support parameterization through values files. This allows you to customize your application's configuration for different environments (e.g., development, staging, production) without modifying the underlying chart. You can override default values or provide environment-specific configurations using values files or command-line flags.

  5. Dependency Management: Helm supports chart dependencies, allowing you to define dependencies on other charts. This is useful for composing complex applications from multiple components or microservices. Helm handles the installation and management of dependencies, simplifying the deployment process.

NOTE: While Helm offers many benefits, it's important to note that it introduces additional complexity and dependencies to your Kubernetes ecosystem. Depending on your use case and requirements, you may use Helm or alternative deployment strategies such as plain Kubernetes manifests, Kubernetes Operators, or GitOps workflows.

Deploying a Docker Container to Kubernetes using Helm

As a brief overview, we had to talk about Helm before going into the deployment process. Now, that's out of the way; get ready to get your hands dirty.

This section will walk you through deploying a Docker container to Kubernetes using Helm.

Project Setup

This project will involve creating a simple Docker container that serves a static HTML page using Nginx. You'll build and push this Docker image to Docker Hub. Then, you'll create a Helm chart to deploy this Docker container to a Kubernetes cluster. Although the application is simple, the process will give you a glimpse of how Helm can be used to deploy more complex applications.

Step 1: Create a Docker Container

This step involves creating a simple Docker container that uses Nginx to serve a static HTML page. You'll create a Dockerfile and an index.html file to build the Docker image.

  • Create a new directory for your project and navigate into it:

      mkdir HELM
      cd HELM
    
  • Create an index.html file. This file can contain any HTML content you want to serve. For this example, we'll create a simple HTML file that displays a welcome message:

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Demo</title>
          <style>
              body {
                  font-family: Arial, sans-serif;
                  margin: 0;
                  padding: 0;
                  background-color: #f0f0f0;
                  display: flex;
                  justify-content: center;
                  align-items: center;
                  height: 100vh;
              }
              .container {
                  text-align: center;
              }
              h1 {
                  color: #333;
              }
          </style>
      </head>
      <body>
          <div class="container">
              <h1>Sample Nginx Website</h1>
              <p>This is a sample web page deployed using Docker, Helm and Kubernetes.</p>
          </div>
      </body>
      </html>
    
  • Create a Dockerfile in the project directory with the following content:

      FROM nginx:alpine
    
      # Remove the default NGINX welcome page
      RUN rm -rf /usr/share/nginx/html/*
    
      # Copy your custom index.html file to the NGINX document root
      COPY index.html /usr/share/nginx/html/
    
  • Build the Docker image using the following command:

      docker build -t helm-nginx .
    
  • Run the Docker container to test the image:

      docker run -d -p 8080:80 helm-nginx
    
  • Open a web browser and navigate to http://localhost:8080 to view the sample web page.

  • Stop the running container:

      docker stop <container_id>
    

Step 2: Push the Docker Image to Docker Hub

You'd need to tag and push the image to a container registry to deploy the Docker image to Kubernetes. In this example, we'll use Docker Hub as the container registry.

  • Log in to Docker Hub using the docker login command:

      docker login
    
  • Tag the Docker image with your Docker Hub username and repository name:

      docker tag helm-nginx <username>/helm-nginx:latest
    
  • Push the Docker image to Docker Hub:

      docker push <username>/helm-nginx:latest
    

Step 3: Create a Helm Chart

Usually, this is where you'd write your Kubernetes deployment and service files. However, with Helm, you can package all these resources into a Helm chart. In this step, you'll create a Helm chart for the Nginx Docker container you built earlier.

  • Create a new Helm chart named helm-nginx:

      helm create helm-nginx
    

This command will create a new directory named helm-nginx with a structure similar to the one shown above.

  • Edit the values.yaml file in the helm-nginx directory to customize the chart values. You can define default values for your chart in this file.

      image:
      repository: <username>//helm-nginx
      pullPolicy: IfNotPresent
      # Overrides the image tag whose default is the chart appVersion.
      tag: "latest"
    

This configuration specifies the Docker image repository, pull policy, and tag for deployment. Replace <username> with your Docker Hub username.

Step 4: Deploy the Helm Chart to Kubernetes

Now that your Helm chart is ready, you can deploy the Nginx Docker container to Kubernetes.

  • Install the Helm chart by running the following command:

      helm install my-release ./helm-nginx
    

Replace my-release with a name for your release. This command will deploy the Nginx Docker container to your Kubernetes cluster.

If this is your first time deploying a Helm chart, you may see a message with instructions on accessing your application. This should look something like this:

NAME: my-release
LAST DEPLOYED: Fri Apr 26 14:31:05 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
    1. Get the application URL by running these commands:
    export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=helm-nginx,app.kubernetes.io/instance=my-release" -o jsonpath="{.items[0].metadata.name}")
    export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
    echo "Visit http://127.0.0.1:8080 to use your application"
    kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT
  • Verify that the deployment was successful by checking the status of the pods:

      kubectl get pods
      kubectl get services
    

Notice that you didn't have to write Kubernetes deployment or service files. Helm abstracts these details and simplifies the deployment process.

  • Access the application by running the command from the Helm output:

      kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT
    

This command forwards traffic from your local machine to the Nginx container running in the Kubernetes cluster. You can then access the application by navigating to http://localhost:8080 in your web browser.

Step 5: Clean Up

Another cool thing about Helm is that you can easily uninstall a release and clean up the resources by running the following command:

helm uninstall my-release

This command will remove the Helm release and delete its associated resources. There is no need to delete Kubernetes resources manually.

Conclusion

In this article, you learned how to deploy a Docker container to Kubernetes using Helm. You created a simple Docker container that serves a static HTML page using Nginx.

You built and pushed the Docker image to Docker Hub and created a Helm chart to deploy the Docker container to Kubernetes.

This article only scratches the surface of what Helm can do. Helm stands out because it is parameterized. This means you can customize your deployments using values files or command-line flags.

You can explore this feature and other advanced Helm concepts like templating, subcharts, and Helm plugins.

I hope you found this article helpful. If you have any questions or feedback, feel free to reach out.