Implementing DevOps with Container Orchestration: CI/CD Pipeline, Docker Image Optimization, and Automated Operations
This article explains how to build a DevOps workflow using container orchestration, covering agile development with Docker image slimming, a Jenkins‑based CI/CD pipeline, simplified Gitflow, container monitoring with cAdvisor‑InfluxDB‑Grafana, and auto‑scaling via Marathon, while separating automated deployment from production release.
With the rise of DevOps and SRE, developers are moving from traditional deployment to a continuous loop model, which the article divides into three parts: agile development, continuous integration and delivery, and automated operations.
Agile Development emphasizes speed and micro‑services, recommending Docker image slimming using a Dockerfile based on java:8-jre-alpine and including timezone configuration. The resulting image is about 80 MB and starts in ~5 seconds.
FROM java:8-jre-alpine
# add timezone and set to Shanghai
RUN apk --update add --no-cache tzdata
ENV TZ=Asia/Shanghai
RUN mkdir -p /app/log
COPY ./target/xxx.jar /app/xxx.jar
EXPOSE 9999
VOLUME ["/app/log"]
WORKDIR /app/
ENTRYPOINT ["java","-Xms2048m","-Xmx2048m","-Xss512k","-jar","xxx.jar"]
CMD []All environment configuration files are packaged into the image, enabling the same image to run on any Docker host. A typical project structure is shown.
├── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ │ ├── application.yaml
│ │ ├── application-dev.yaml
│ │ ├── application-qa.yaml
│ │ ├── application-yz.yaml
│ │ ├── application-prod.yaml
│ │ └── logback.xml
│ └── test
├── scripts
│ ├── Dockerfile
│ └── InitDB.sql
└── pom.xmlContinuous Integration & Delivery uses Jenkins Pipeline with plugins (Pipeline, Git, SonarQube, Docker Pipeline, Marathon). The pipeline stages include checkout, Maven build, SonarQube analysis, Docker image build & push, deployment to test, automated tests, optional manual tests, and production deployment.
stage('Check out')
git branch: "dev", credentialsId: "deploy-key", url: gitUrl
stage('Build')
sh "${mvnHome}/bin/mvn -U clean install"
stage('SonarQube analysis')
def scannerHome = tool 'SonarQube.Scanner-2.8'
withSonarQubeEnv('SonarQube-Prod') {
sh "${scannerHome}/bin/sonar-scanner -e -Dsonar.links.scm=${gitUrl} -Dsonar.sources=. -Dsonar.projectKey=lms-barrages -Dsonar.projectName=xxx"
}
stage('Build image')
docker.withRegistry('https://dockerhub.xxx.com','dockerhub-login') {
docker.build('dockerhub.xxx.com/xxxx').push('test')
}
stage('Deploy on Test')
sh "mkdir -pv deploy"
dir('./deploy') {
git branch: 'dev', credentialsId: 'deploy-key', url: '[email protected]:lms/xxx-deploy.git'
marathon docker: imageName, dockerForcePull: true, forceUpdate: true, url: marathon_url, filename: 'qa-deploy.json'
}
stage('Test')
parallel(
autoTests: {
sh "docker run -it --rm -v $PWD:/code nosetests -s -v -c conf\\run\\api_test.cfg --attr safeControl=1"
},
manualTests: { sleep 30000 }
)
stage('Deploy on Prod')
input "Do tests OK?"
dir('./deploy') {
marathon docker: imageName, dockerForcePull: true, forceUpdate: true, url: 'http://marathon-prod', filename: 'prod-deploy.json'
}The article also proposes a simplified Gitflow with three branches (master, dev, feature) to reduce merge overhead for small teams.
Automated Operations covers container monitoring (cAdvisor + InfluxDB + Grafana) and auto‑scaling. Metrics from cAdvisor are stored in InfluxDB and visualized in Grafana. An auto‑scaler reads metrics and uses the Marathon API to scale services when CPU or memory usage is high.
node('docker-qa'){
if (ReleaseVersion=="") { echo "Release version cannot be empty"; return }
stage('Prepare image') {
def moduleName = "${ApplicationModule}".toLowerCase()
def resDockerImage = "${imageName}:latest"
def desDockerImage = "${imageName}:${ReleaseVersion}"
if (GenDockerVersion=="true") {
sh "docker pull ${resDockerImage}"
sh "docker tag ${resDockerImage} ${desDockerImage}"
sh "docker push ${desDockerImage}"
sh "docker rmi -f ${resDockerImage} ${desDockerImage}"
}
}
stage('Deploy on Mesos') {
git branch: 'dev', credentialsId: 'deploy-key', url: '[email protected]:lms/xxx-test.git'
// determine marathon_url based on DeployDC and DeployEnv
marathon docker: imageName, dockerForcePull: true, forceUpdate: true, url: marathon_url, filename: "${DeployEnv}-deploy.json"
}
}Finally, the article stresses separating automated deployment from production release, assigning appropriate permissions, and acknowledges that the presented examples may need adaptation for different environments.
Hujiang Technology
We focus on the real-world challenges developers face, delivering authentic, practical content and a direct platform for technical networking among developers.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
