Docker and Kubernetes for CI/CD
In the modern Software Development Life Cycle (SDLC), Continuous Integration (CI) and Continuous Deployment (CD) are core components that ensure code quality and accelerate delivery. Introducing Docker containerization into the CI/CD process resolves the inconsistency issues inherent in traditional virtual machine environments, achieving "build once, run anywhere." When Kubernetes (K8s) acts as an orchestration platform, the entire automation system scales seamlessly from local testing to large-scale production environments. This article explores how to leverage Docker to build images and pair them with Kubernetes to achieve an efficient CI/CD closed loop.
The starting point of a CI/CD pipeline is building a clean, reusable application container image. In this phase, Docker acts as the "standardized packager," encapsulating code, runtime environments, libraries, and configuration files together. To ensure build consistency, strict image building standards must be followed, such as using Multi-stage Builds to reduce the final image size and specifying explicit FROM base image versions.
Developers typically write a Dockerfile in CI servers like Jenkins, GitLab CI, or GitHub Actions to define the build logic. Below is a simplified example demonstrating how to build a lightweight production image for a Node.js application:
# Multi-stage build example
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
The CI pipeline parses this Dockerfile, executes the docker build command to generate the image, and passes the generated image ID or Tag as a critical parameter to subsequent Kubernetes deployment steps. This ensures that regardless of code changes, the binary files delivered to the production environment are always generated from the same build context.
Declarative Configuration Drives Kubernetes Deployment
Once the application image is built, Kubernetes is responsible for distributing it into the cluster. Unlike traditional script-based deployments, Kubernetes manages resource states using declarative APIs. This means developers only need to define the desired final state of the cluster (such as the number of Pods or ReplicaSet size), and K8s automatically handles the differences in underlying infrastructure to reach that state.
In the CI/CD workflow, we typically use Kubernetes YAML files to describe the application architecture. By running the kubectl apply -f deployment.yaml command, you trigger K8s controllers to update. To support automated pipelines, two core resources must be defined: a Deployment to manage application replicas and lifecycle, and a Service to expose service ports for external access.
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: registry.example.com/my-app:v1.2.0 # Reference to the image built in CI
ports:
- containerPort: 3000
resources:
limits:
memory: "256Mi"
cpu: "500m"
When a new image version (e.g., v1.2.1) is successfully built in CI, simply update the image field in the YAML file and commit it to the Git repository. Kubernetes detects the configuration change, automatically pulls the new image, and performs a rolling update of existing Pods, achieving zero-downtime gray releases.
Integrating Automated Testing and Rollback Mechanisms
A robust CI/CD pipeline includes not only building and deploying but also strict validation phases. In containerized environments, unit tests can run within Docker containers, while integration tests can be executed via E2E (End-to-End) test suites in simulated K8s clusters. These test scripts typically run as part of the Pipeline after the image is built but before it is pushed to the production environment.
Furthermore, Kubernetes' powerful rollback mechanism serves as a critical safeguard against deployment failures. If Pods of the new version fail health checks or render the service unavailable, K8s automatically reverts to the previous stable version. In CI/CD scripts, we can configure the rollbackStrategy parameter to ensure that upon detecting errors, the system can quickly restore business continuity.
# deployment.yaml (Supplemental rolling update strategy)
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1 # Update only 50% of replicas at a time to reduce risk
maxSurge: 25%
By combining Docker's standardized build capabilities with Kubernetes' dynamic orchestration, teams can establish a highly automated, observable, and fault-tolerant CI/CD pipeline. This architecture not only accelerates software delivery but also significantly reduces deployment failures caused by environmental differences, making it an indispensable standard practice for modern cloud-native development.