Docker部署Java镜像

参考

https://gitee.com/log4j/pig

https://gitee.com/y_project/RuoYi-Vue

https://segmentfault.com/a/1190000022530075

https://segmentfault.com/a/1190000022530083

docker部署流水线

简介

这篇文章以之前的白嫖敏捷开发体系为基础,从注册使用云效和阿里云,代码托管,配置个人制品仓库(主要是Maven)、个人镜像仓库,流水线创建整个流程来一遍。

代码管理

https://codeup.aliyun.com/

因为云效是为企业或是组织服务的,所以与GitHubGitee这些开放的代码托管平台不同,更加关注与内部的代码管理,更像是私有的GitLab

基本的代码仓库功能都是用的,权限管理,分支合并,代码检测,还可以配合流水线做自动化,更有为企业用户考虑的报表分析。

导入代码方式有下

导入代码

设置HTTPS密码,或是SSH公钥都可,这样就可以方便的进行代码克隆推送了。

制品仓库

https://packages.aliyun.com/

制品仓库

Maven仓库

默认就有生产库和非生产库,也就是稳定版release和快照版snapshot,不用多讲

配置

两个仓库任意点一个,进入设置即可,配置Maven或是Gradle都可,这里的配置说明已经非常详细了,我也没必要去复述了。

另外注意,这里有两种配置方式,说了不复述还是。。。😂。总之就是要注意认真看官方的文档说明,别自己漏掉了又去各种网站去搜,别人的答案也只是把官网的话重复一遍

1、推送(修改方式),适用于配置过setting.xml,需要修改的

2、推送(覆盖方式),适用于未配置过setting.xml,可直接覆盖配置

3、usernamepassword已经为我们填好了,复制去做就行

Maven配置

推送

1
mvn clean install org.apache.maven.plugins:maven-deploy-plugin:2.8:deploy -DskipTests

NPM仓库

这个我就略过了,官网也很清楚的

Docker仓库

开启容器镜像服务

容器镜像服务

设置账号密码

访问凭证,设置一下固定密码或是临时密码即可

创建命名空间

命名空间,按要求创建就行

创建镜像仓库

命名空间可有多个镜像仓库,镜像由[Docker Registry 地址]/[仓库名]:[端口号][镜像名][标签]组成,入下是DockerHubjava仓库,多个Tags对应着多个版本

官方java仓库

基本信息

创建好镜像仓库,点进去就看到基本信息了,操作指南也是很明确的

镜像仓库基本信息

流水线

https://flow.aliyun.com/

流水线的创建可以通过流水线的入口也可以在代码管理中创建,都是一样的

1、创建模版

默认已经提供了很多模版,如果合适的话直接使用当然更方便,初次使用的话,还是建议使用快速配置流水线模版,用这个更能全面了解流水线可以做哪些事情。

创建流水线

2、选择技术框架

选择技术框架

我这里选择了Java

3、步骤选择,步骤可以先先选简单点,后面也是可以改的,我就不一一贴图了,直接开始示例了

测试阶段

Java构建并发布到Maven制品库

默认已经把制品库配置好了。

添加流水线源

这里有很多代码源可选,我使用的是Codeup,然后选择代码仓库和默认分支,可以开启代码源触发,选择代码提交或是合并完成,默认分支是在使用代码源触发时直接使用的分支。

添加流水线源

创建任务

这里有很多种任务组可选,非常方便,对于Java构建,发布到Maven制品仓库选,Java构建就好,其实选择发布Maven二方库应该也没问题。

创建任务

设置任务名称,选择构建集群,下载流水线源选择,JDKMaven版本选择,构建命令如下,其实就是之前Maven制品仓库,仓库指南中推送的命令

1
mvn clean install org.apache.maven.plugins:maven-deploy-plugin:2.8:deploy -DskipTests
编辑任务

运行

设置了触发策略就会自动触发,这里我们手动触发试一下,点击-保存并运行就可。

查看流水线日志

流水线每个过程都有详细日志可查看,方便我们排查问题,这里展示了成功构建后的截图,检查Maven制品仓库也会发现有了更新

流水线日志

Java镜像构建并部署

如标题所述,这个才是重头。前面提到的我就不多说了。另外多提一下,我这个项目是仿照着pig这个开源微服务项目来组织的,使用的是Spring Cloud Alibaba的那一套。

pom

同时在根pom.xml中配置了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<profiles>
<profile>
<!--开发环境-->
<id>dev</id>
<properties>
<profiles.active>dev</profiles.active>
<nacosNamespace>xxx</nacosNamespace>
</properties>
<!-- 加了这个,默认选中 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<!--测试环境-->
<id>test</id>
<!-- 以下属性用于 bootstrap.yml 文件中 可通过 @activatedProperties@ 获取配置的变量-->
<properties>
<profiles.active>test</profiles.active>
<nacosNamespace>xxx</nacosNamespace>
</properties>
</profile>
<!--生产环境-->
<profile>
<id>prod</id>
<properties>
<profiles.active>prod</profiles.active>
<nacosNamespace>xxx</nacosNamespace>
</properties>
</profile>
</profiles>

application

application.yml配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server:
port: 3301
spring:
application:
name: @artifactId@
cloud:
nacos:
discovery:
server-addr: ${NACOS_HOST:nacos}:${NACOS_PORT:8848}
namespace: @nacosNamespace@
group: @nacos.group@
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
namespace: @nacosNamespace@
group: @nacos.group@
config:
import:
- optional:nacos:${spring.application.name}-${spring.profiles.active}.yml

profiles:
active: @profiles.active@

logging:
config: classpath:log4j2-${spring.profiles.active}.xml

所以符合微服务部署前提。

同时项目默认环境总是dev,如果需要使用不同环境,在Maven构建时带上如下参数即可

1
mvn package -Pdev

前提大概就是这样,如果有时间我会把这个项目详细讲一讲(目前还在玩这个,还没结束)

Dockerfile

我的Dockerfile文件如下,目录就在项目根路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
FROM registry.cn-shanghai.aliyuncs.com/wnhyang/openjdk:8-jre

# 创建目录
RUN mkdir -p /home/app
# 指定路径
WORKDIR /home/app

ARG JAR_FILE=./target/okay-shortLink-service.jar

COPY ${JAR_FILE} app.jar

EXPOSE 3301

ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms128m -Xmx256m -Djava.security.egd=file:/dev/./urandom"

ENTRYPOINT ["java","-jar","app.jar","$JAVA_OPTS"]

选择任务组

这里选择Java镜像构建,默认添加任务组:Java构建和镜像构建并推送至阿里云镜像仓库个人版

选择任务组

Java构建

这个改一下JDKMaven版本就好,注意⚠️:我的DockerfileARG JAR_FILE=./target/okay-shortLink-service.jar就是对应了构建物的路径和文件名,这个一定要对应的。构建名在pombuild中配置,构建完成都在target目录下,Dockerfile构建镜像时将构建物装进Docker镜像,大概就是这个流程。

编辑Java构建

镜像构建并推送至阿里云镜像仓库个人版

这个很重要,服务连接不多讲了,按照步骤来就好,选择之前配置好的仓库,注意⚠️:仓库名要和项目一致,看一下我前面举的java官方镜像例子,一个仓库就是一种镜像,依靠标签区分,我这里就是用了默认的${DATETIME}为标签;Dockerfile路径一定要正确,不明白路径的点一下小问号?会提示

Dockerfile路径为Dockerfile文件相对于代码库根目录所在路径,如META/config/Dockerfile或Dockerfile

镜像构建并推送至阿里云镜像仓库个人版

最后,任务还有输出,这里输出的是镜像名和镜像公网地址和镜像VPC地址,流线线承接就体现在这,上游输出,下游输入。

任务输出

Docker部署

选部署中选择Docker部署

Docker部署

Docker部署编辑

主机组需要自己配置一下,我这里使用的华为云服务器,非阿里云主机要稍微麻烦一点,不过也就一点,按步骤来就行,不多提了。

执行用户需要注意,我目前试的,在docker组的用户也是会运行失败的,所以我还是使用了root

Docker部署编辑

部署脚本命令如下

1
2
3
4
5
#部署脚本会在部署组的每台机器上执行。一个典型Docker部署脚本如下:
#示例中使用的$image是您在脚本下方的变量处定义的变量(上游输出或自定义)
#docker run $image

sh /home/app/deploy.sh restart $APP_NAME $APP_NAME $port $image;

变量可以自定义,也可以自己设置,这里image就是上游输出。因为我只有一台机器所以部署策略相对于我没用,如果你有多台机器,可以设置一下。

部署配置

部署脚本

这个脚本就不详细解释了,这个要提前放在主机组中,部署命令对应,注意修改nacos地址哦

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/bin/bash

SH_NAME=$0
ACTION=$1
APP_NAME=$2
APP_LOG_NAME=$3
APP_PORT=$4
DOCKER_URL=$5

usage() {
echo "Not Support this operation: "${ACTION}
echo "Usage: ${SH_NAME} {start|stop|restart} {APP_NAME} {APP_LOG_NAME} {APP_PORT} {ENV_PROFILES}"
}

stop_app() {
echo 'stopping......'
# 获取容器id
CONTAINER=`docker ps -a |grep "${APP_NAME}" | awk '{print $1}'`
# -n 字符串不为空返回true
# 删除容器
if [[ -n "${CONTAINER}" ]]
then
docker stop ${CONTAINER}
docker rm ${CONTAINER}
echo "The container named ${APP_NAME} has been stopped and deleted"
else
echo "The container named ${APP_NAME} does not exist"
fi
# 删除镜像
if [[ -n "${DOCKER_URL}" ]]
then
REPO_URL=`echo ${DOCKER_URL%%:*}`
TAG_NAME=`echo ${DOCKER_URL##*:}`
fi
if [[ -n "${TAG_NAME}" ]]
then
IMAGE=`docker images | grep ${REPO_URL} | grep ${TAG_NAME} |awk '{print $3}'`
else
IMAGE=`docker images | grep ${REPO_URL}|awk '{print $3}'`
fi
if [[ -n "${IMAGE}" ]]
then
docker rmi ${IMAGE}
echo "The image named ${APP_NAME} has been deleted"
else
echo "The image named ${APP_NAME} does not exist"
fi

}

create_log_dir(){
#日志路径要真实存在
log_path="/home/app/logs/"${APP_LOG_NAME}
mkdir -p ${log_path}
echo "create a log path: ${log_path}"
}

start_app() {
echo '镜像版本:'${DOCKER_URL}

# 运行容器
docker run -v /home/app/logs:/home/app/logs \
-p ${APP_PORT}:${APP_PORT} \
--add-host nacos:你的nacos地址 \
--name ${APP_NAME} \
-d ${DOCKER_URL}
CONTAINER_ID=`docker ps -a | grep -v "grep" | grep ${APP_NAME} | awk -F: '{print $1}' | awk '{print $1}' | head -n 1`
if [[ -n "${CONTAINER_ID}" ]]
then
RESULT=`docker inspect -f '{{.State.Running}}' ${CONTAINER_ID}`
if [[ ${RESULT} = 'true' ]]
then
echo "部署成功"
exit
fi
fi
echo "部署失败"
}

start() {
create_log_dir
start_app
}

stop() {
stop_app
}

case "$ACTION" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
usage
;;
esac

运行

部署单