Mastering DevOps: From Manual Scripts to Automated Jenkins Pipelines
This guide walks through the fundamentals of DevOps, illustrating how to transition from simple command‑line deployments to sophisticated, automated CI/CD pipelines using Jenkins, Docker, and shell scripts, while covering JVM tuning, version management, and common troubleshooting tips.
DevOps is a software practice that combines development, testing, and operations to accelerate delivery, improve quality, and ensure stability through continuous integration (CI) and continuous delivery (CD).
发展进程
We will analyze four development stages to achieve continuous deployment.
命令行阶段
Before the command, the JAR must be uploaded to the working directory; this method is only suitable for single‑node, rarely updated scenarios and is no longer recommended.
# 1
# 以后台进程的方式启动jar包
nohup java -jar application.jar &;
# 2
nohup java -Xms1536m -Xmx6072m -Xss1m -Xmn256m -jar application.jar --spring.profiles.active=prod --spring.config.location=/local/server/application-prod.properties &;
# 3
ps -aux | grep javaThe JVM parameters -Xms, -Xmx, -Xss, and -Xmn control heap size, maximum heap, thread stack size, and young generation size respectively. -Xms512m sets the initial heap to 512 MB, -Xmx512m limits the maximum heap (exceeding it throws OutOfMemoryError), and -Xss1m sets each thread’s stack to 1 MB. Insufficient stack can cause StackOverflowError.
shell 脚本一键启动
Putting commands into a script and executing it with bash avoids manual entry each time.
#!/bin/bash
if [ "$3" == "prod" ]; then
echo "项目名称:$1 版本:$2 环境:$3"
# 删除容器
docker rm -f $1:$2
# 删除镜像
docker rmi -f $1:$2
# 进入目录并构建镜像
cd /local/docker_image/$1-$2
docker build -f ../$1-$2/Dockerfile --build-arg active=$3 -t myhuaweicloud.com/$3/$1-$2 .
docker login -u xxxxx -p xxxxxx myhuaweicloud.com
docker tag $1:$2 myhuaweicloud.com/$3/$1:$2
docker push myhuaweicloud.com/$3/$1:$2
else
echo "test env not for this'shell"
echo "项目名称:$1 版本:$2"
fiJenkins 管道 + Docker 容器化
Running the script via a Jenkins pipeline eliminates manual SSH steps and enables Docker image building and deployment across multiple nodes.
pipeline {
agent none
parameters {
string(name: 'CURRENT_VERSION', defaultValue: 'v1.0.0', description: '系统当前版本')
string(name: 'NEXT_VERSION', defaultValue: 'v1.0.0', description: '系统下一个版本')
choice(name:'ACTIVE',choices: ['prod'],description:'环境选择')
string(name: 'GIT_BRANCH', defaultValue: 'master', description: '分支标签')
choice(name: 'CLUSTER', choices: ['1','2','3','4'], description: '集群节点')
choice(name: 'BUILD_IMG', choices: ['FALSE','TRUE'], description: '构建镜像')
}
stages {
stage('checkout') {
agent any
steps { git branch: '${GIT_BRANCH}', credentialsId: gitCredentialsId, url: gitRepoUrl }
}
stage('packaging') {
agent {
docker { image 'maven:3-alpine' args '-v /root/.m2:/root/.m2' }
}
steps {
dir('') {
sh 'mvn -v'
configFileProvider([configFile(fileId: 'xx-xx-xx', variable: 'MAVEN_SETTINGS')]) {
sh 'mvn -s $MAVEN_SETTINGS clean package -P ${ACTIVE} -Dmaven.test.skip=true -U'
}
}
}
}
stage('build docker') {
agent any
steps {
dir('global-push-web') {
script {
if ( BUILD_IMG == 'TRUE' ) {
sh "mkdir -p ${DOCKER_IMAGE_DIR}/${PROJECT_NAME}-${NEXT_VERSION}"
sh "cp ./Dockerfile ${DOCKER_IMAGE_DIR}/${PROJECT_NAME}-${NEXT_VERSION}"
sh "cp ./target/global-push.jar ${DOCKER_IMAGE_DIR}/${PROJECT_NAME}-${NEXT_VERSION}"
sh "${DOCKER_IMAGE_DIR}/start_deploy.sh ${PROJECT_NAME} ${NEXT_VERSION} ${ACTIVE} ${CLUSTER} ${CURRENT_VERSION}"
}
sshCommand remote: remoteCfg, command: "cd ${DOCKER_IMAGE_DIR}/${PROJECT_NAME} && bash start_images.sh ${PROJECT_NAME} ${NEXT_VERSION} ${ACTIVE} ${CLUSTER} ${CURRENT_VERSION}"
}
}
}
}
stage('record version') {
agent any
steps {
dir('') {
script {
if ( BUILD_IMG == 'TRUE' && GIT_BRANCH == 'master' ) {
sshCommand remote: remoteCfg, command: "cd ${DOCKER_IMAGE_DIR}/${PROJECT_NAME} && bash version_history.sh ${NEXT_VERSION} ${NEXT_VERSION_INFO}"
}
}
}
}
}
}
}K8s 服务动态扩容;
Kubernetes dynamic scaling automatically adjusts the number of Pods based on load, ensuring high availability and performance. This feature is mentioned but not yet implemented.
常见问题
Jenkins 构建项目失败
Problem: mvn -s setting.xml clean package fails due to missing Dubbo dependencies.
Solution: Manually copy the missing dependencies into a new local repository, then the build succeeds.
Notes:
Jenkins clones the Git repository to /local/jenkins/workspace and builds with Maven inside a Docker container.
Ensure the Docker‑deployed Jenkins can access mounted directories; check user permissions with docker exec -it <container> whoami.
Use cp -r source_dir target_dir for quick copying.
Run mvn clean install -U to force remote dependency download; mvn -X shows detailed output.
Specify a user when starting a container with docker run -d -u <username> ….
Jenkins 持续交付功能优化
Support version iteration with custom version numbers while retaining the previous version.
Enable one‑click rollback by keeping historical images.
Record each update’s version history.
Graceful shutdown without redundant image builds.
项目上线一直启动失败
Investigation steps:
Check if the build script has issues.
Verify the startup script.
Confirm configuration file paths and contents; production failures often stem from incorrect configs rather than code.
Lin is Dream
Sharing Java developer knowledge, practical articles, and continuous insights into computer engineering.
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.
