后端自动化部署总结
参考:
https://help.coding.net/docs/ci/start.html
前提:先在远程服务器安装好docker
先在coding.net里新建一个项目,然后新建构建计划;
在项目的与父工程的pom.xml平级的路径下新建文件:DockerFile,内容如下:
#指定基础镜像,在其上进行定制
FROM java:8
#这里的 /tmp 目录就会在运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层
VOLUME /tmp
#复制上下文目录下的jar 到容器里
# ARG JAR_FILE
# ADD target/${JAR_FILE} /TongXunDataProcessToolBack.jar
ADD website/target/reportfill.jar /reportfill.jar
#bash方式执行,使jar可访问
#RUN新建立一层,在其上执行这些命令,执行结束后, commit 这一层的修改,构成新的镜像。
RUN bash -c "touch /reportfill.jar"
#声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务
EXPOSE 9001
#指定容器启动程序及参数 <ENTRYPOINT> "<CMD>"
ENTRYPOINT ["java","-jar","reportfill.jar"]
并且在website的模块的pom.xml的build标签下加上:<finalName>reportfill</finalName>
来指明打包的jar包名称;
然后在coding.net里编辑基础信息,关联GitHub的仓库;
然后新建制品库,相当于docker的私有仓库,远程服务器会从该仓库里去拉镜像
如果找不到新建制品库的菜单,可以在新建构建计划里的这块新建制品库:
设置一些变量,并且把缓存的maven勾选上,这样不用每次构建都重新下载maven包,设置的变量如下:
DOCKER_REPO_NAME配置制品库的名称(注意名称命名规范,不要加分割线"-")
DOCKER_IMAGE_NAME配置镜像名称
DOCKER_CONTAINER_NAME配置容器名称
REMOTE_SSH_PORT配置ssh远程服务器连接端口
REMOTE_USER_NAME配置ssh远程连接用户名
REMOTE_HOST配置ssh连接的ip地址
REMOTE_CRED配置的是ssh连接的凭证(这里是新建的一个凭证,用户名+密码)
凭据在项目设置里的凭据管理里去录入凭据:
然后编辑流程配置,以文本编辑器的形式编辑,内容如下:
pipeline {
agent any
stages {
stage('检出') {
steps {
checkout([$class: 'GitSCM',
branches: [[name: GIT_BUILD_REF]],
userRemoteConfigs: [[
url: GIT_REPO_URL,
credentialsId: CREDENTIALS_ID
]]])
}
}
stage('编译') {
steps {
sh 'mvn clean install -pl website -am'
}
}
stage('构建镜像并推送到 CODING Docker 制品库') {
steps {
script {
docker.build('${CODING_DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_VERSION}', '-f DockerFile ./')
useCustomStepPlugin(key: 'coding-public:artifact_docker_push', version: 'latest', params: [image:"${CODING_DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_VERSION}",repo:"${DOCKER_REPO_NAME}"])
}
}
}
stage('部署到远端服务') {
steps {
script {
def remoteConfig = [:]
remoteConfig.name = "my-remote-server"
remoteConfig.host = "${REMOTE_HOST}"
remoteConfig.port = "${REMOTE_SSH_PORT}".toInteger()
remoteConfig.allowAnyHosts = true
withCredentials([
usernamePassword(
credentialsId: "${REMOTE_CRED}",
passwordVariable: 'password',
usernameVariable: 'userName'
),
usernamePassword(
credentialsId: "${CODING_ARTIFACTS_CREDENTIALS_ID}",
usernameVariable: 'CODING_DOCKER_REG_USERNAME',
passwordVariable: 'CODING_DOCKER_REG_PASSWORD'
)
]) {
// SSH 登陆用户名
remoteConfig.user = userName
// SSH 密码
remoteConfig.password = password
sshCommand(
remote: remoteConfig,
command: "docker login -u ${CODING_DOCKER_REG_USERNAME} -p ${CODING_DOCKER_REG_PASSWORD} ${CODING_DOCKER_REG_HOST}",
sudo: true,
)
sshCommand(
remote: remoteConfig,
command: "docker container rm -f ${DOCKER_CONTAINER_NAME} | true",
sudo: true,
)
// DOCKER_IMAGE_VERSION 中涉及到 GIT_LOCAL_BRANCH / GIT_TAG / GIT_COMMIT 的环境变量的使用
// 需要在本地完成拼接后,再传入到远端服务器中使用
DOCKER_IMAGE_URL = sh(
script: "echo ${CODING_DOCKER_REG_HOST}/${CODING_DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_VERSION}",
returnStdout: true
)
sshCommand(
remote: remoteConfig,
command: "docker run -d --network host --name ${DOCKER_CONTAINER_NAME} -e TZ=Asia/Shanghai ${DOCKER_IMAGE_URL} ",
sudo: true,
)
echo "部署成功"
}
}
}
}
}
environment {
CODING_DOCKER_REG_HOST = "${CCI_CURRENT_TEAM}-docker.pkg.${CCI_CURRENT_DOMAIN}"
CODING_DOCKER_IMAGE_NAME = "${PROJECT_NAME.toLowerCase()}/${DOCKER_REPO_NAME}/${DOCKER_IMAGE_NAME}"
}
}
其中编译执行的命令是:mvn clean install -pl website -am
,因为是对其中的子模块website进行编译,所以通过-pl制定模块编译,同时也要打包该模块所依赖的其他子模块,所以通过-am来指定,否则会报错找不到对应依赖的包
sshCommand里的运行docker的命令:docker run -d --network host --name ${DOCKER_CONTAINER_NAME} -e TZ=Asia/Shanghai ${DOCKER_IMAGE_URL}
,这里增加的-e TZ=Asia/Shanghai
是为了统一时区,不然docker运行的日志时间和当下北京时间是不一致的。
最后构建成功之后
运行docker ps -a查看docker里的镜像:
运行:docker logs 21fb -f查看21fb所对应的镜像的日志: