Swiftorial Logo
Home
Swift Lessons
Tutorials
Learn More
Career
Resources

Docker Kubernetes

Using Kubernetes with Docker allows you to manage containerized applications at scale with features like automated deployment, scaling, and operations. This guide covers key concepts, steps to set up Kubernetes with Docker, examples, and best practices for deploying Dockerized Express.js applications to Kubernetes.

Key Concepts of Kubernetes

  • Pod: The smallest deployable unit in Kubernetes, which can contain one or more containers.
  • Service: An abstraction that defines a logical set of Pods and a policy to access them.
  • Deployment: Manages the deployment and scaling of Pods.
  • ConfigMap: Stores configuration data as key-value pairs.
  • Secret: Stores sensitive data such as passwords and API keys.
  • Ingress: Manages external access to services, typically HTTP/HTTPS.
  • Namespace: A way to divide cluster resources between multiple users.

Setting Up the Project

Initialize a new Express.js project and create a Dockerfile:

// Initialize a new project
// npm init -y

// Install Express
// npm install express

// Create the project structure
// mkdir src
// touch src/index.js Dockerfile .dockerignore .gitignore

// .gitignore
node_modules
.env

// .dockerignore
node_modules
npm-debug.log

Creating an Express Application

Create a simple Express application:

Example: index.js

// src/index.js
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
    res.send('Hello, Docker Kubernetes!');
});

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}/`);
});

Creating a Dockerfile

Create a Dockerfile to containerize your Express application:

Example: Dockerfile

// Dockerfile
FROM node:14

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
COPY package*.json ./
RUN npm install

# Bundle app source
COPY . .

# Expose port 3000 to the outside world
EXPOSE 3000

# Run app when the container launches
CMD ["node", "src/index.js"]

Building and Running the Docker Container

Build and run the Docker container for your Express application:

// Build the Docker image
docker build -t my-express-app .

// Run the Docker container
docker run -d -p 3000:3000 --name my-express-app my-express-app

// Open http://localhost:3000 in your browser to see the application running

Setting Up Kubernetes

Set up a Kubernetes cluster and deploy your application:

Creating a Kubernetes Deployment

// deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-express-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-express-app
  template:
    metadata:
      labels:
        app: my-express-app
    spec:
      containers:
      - name: my-express-app
        image: my-express-app:latest
        ports:
        - containerPort: 3000

Creating a Kubernetes Service

// service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-express-service
spec:
  selector:
    app: my-express-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
  type: LoadBalancer

Deploying to Kubernetes

// Apply the deployment and service
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

// Check the status of the deployment
kubectl get deployments

// Check the status of the service
kubectl get services

// Open the external IP of the service in your browser to see the application running

Using ConfigMaps and Secrets

Manage configuration and sensitive data:

Creating a ConfigMap

// configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
data:
  NODE_ENV: production
  MONGO_URL: mongodb://db:27017/mydatabase

Creating a Secret

// secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  db_password: $(echo -n "mysecretpassword" | base64)

Using ConfigMap and Secret in Deployment

// deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-express-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-express-app
  template:
    metadata:
      labels:
        app: my-express-app
    spec:
      containers:
      - name: my-express-app
        image: my-express-app:latest
        ports:
        - containerPort: 3000
        envFrom:
        - configMapRef:
            name: my-config
        env:
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: my-secret
              key: db_password

Setting Up Ingress

Manage external access to your services:

Creating an Ingress Resource

// ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-express-service
            port:
              number: 80
// Apply the ingress resource
kubectl apply -f ingress.yaml

// Check the status of the ingress
kubectl get ingress

// Update your DNS settings to point to the external IP of the ingress controller
// Open http://myapp.example.com in your browser to see the application running

Best Practices for Kubernetes with Docker

  • Use Namespaces: Isolate resources by using namespaces for different environments and teams.
  • Implement Health Checks: Use readiness and liveness probes to ensure container health.
  • Automate Deployments: Use CI/CD pipelines to automate the deployment process.
  • Monitor and Log: Integrate monitoring and logging tools to track the health and performance of your applications.
  • Secure Access: Use RBAC (Role-Based Access Control) to manage access to your Kubernetes cluster.
  • Optimize Resources: Set resource requests and limits to optimize resource usage and prevent overcommitment.
  • Use ConfigMaps and Secrets: Manage configuration and sensitive data separately from your application code.

Testing Kubernetes Setup

Test your Kubernetes setup to ensure it works correctly:

Example: Testing with Mocha and Chai

// Install Mocha and Chai
// npm install --save-dev mocha chai

// test/app.test.js
const chai = require('chai');
const expect = chai.expect;
const axios = require('axios');

describe('Express App', () => {
    it('should return Hello, Docker Kubernetes!', async () => {
        const response = await axios.get('http://localhost:3000');
        expect(response.data).to.equal('Hello, Docker Kubernetes!');
    });
});

// Add test script to package.json
// "scripts": {
//   "test": "mocha"
// }

// Run tests
// docker build -t my-express-app .
// docker run -p 3000:3000 my-express-app
// npm test

Key Points

  • Pod: The smallest deployable unit in Kubernetes, which can contain one or more containers.
  • Service: An abstraction that defines a logical set of Pods and a policy to access them.
  • Deployment: Manages the deployment and scaling of Pods.
  • ConfigMap: Stores configuration data as key-value pairs.
  • Secret: Stores sensitive data such as passwords and API keys.
  • Ingress: Manages external access to services, typically HTTP/HTTPS.
  • Namespace: A way to divide cluster resources between multiple users.
  • Follow best practices for using Kubernetes with Docker, such as using namespaces, implementing health checks, automating deployments, monitoring and logging, securing access, optimizing resources, and managing configuration and sensitive data with ConfigMaps and Secrets.

Conclusion

Using Kubernetes with Docker allows you to manage containerized applications at scale with features like automated deployment, scaling, and operations. By understanding and implementing the key concepts, steps, examples, and best practices covered in this guide, you can effectively deploy Dockerized Express.js applications to Kubernetes. Happy coding!