环境: 本文的所有服务都部署在阿里云ECS服务器(2H4G)上面, 前后端分离项目使用gitee上面的开源项目若依(ruoyi-vue)为例, 从零开始教学
1、先停止服务器, 再重装系统, 用最干净的系统从头教学, 保证大家环境一样
2、系统选择Centos最新版本, 然后开始安装, 等待安装完成
3、安装完成后用远程工具连接到阿里云服务器, 开始安装docker
cat /etc/centos-release
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
4、验证docker安装完成
docker version
5、启动docker, 设置开机启动
systemctl start docker
systemctl enable docker
6、安装docker-compose, 添加可执行权限, 验证
sudo curl -L "https://get.daocloud.io/docker/compose/releases/download/v2.6.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
7、编写docker-compose.yml, 安装若依项目的基础环境
在根目录下创建 docker-compose.yml
version: '3'
services:
mysql:
image: mysql:8.0.29
container_name: mysql
restart: always
ports:
- 3306:3306
privileged: true
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123456
command:
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
volumes:
- /mydata/mysql/data/db:/var/lib/mysql #数据文件挂载
- /mydata/mysql/data/conf:/etc/mysql/conf.d #配置文件挂载
- /mydata/mysql/log:/var/log/mysql #日志文件挂载
redis:
image: redis:7
container_name: redis
restart: always
command: redis-server --requirepass 123456 --appendonly yes
volumes:
- /mydata/redis/data:/data #数据文件挂载
- /etc/localtime:/etc/localtime
ports:
- 6379:6379
jenkins:
image: jenkinsci/blueocean
container_name: jenkins
restart: always
user: root
ports:
- 8080:8080
- 50000:50000
volumes:
- /mydata/jenkins_home:/var/jenkins_home
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock
8、因为若依项目编译需要用到maven, 所以导一份maven的seeting文件到jenkins_home目录
mkdir -p /mydata/jenkins_home/appconfig/maven
将settings.xml文件放到上面的目录中
nexus-aliyun
central
Nexus aliyun
http://maven.aliyun.com/nexus/content/groups/public
/root/.m2
jdk-1.8
1.8
1.8
1.8
1.8
9、启动docker-compose
10、查看容器启动状态
11、环境准备完毕, 现在开始配置jenkins
在阿里云服务器的安全组中添加3306 6379 8080端口, 8888后端项目, 8889前端项目
在浏览器访问jenkins
12、查看管理员密码
docker logs jenkins
安装插件Docker Pipeline, 后面构建流水线需要
16、现在开始准备前后端分离的项目, 以RuoYi-Vue为例进行部署, 下载zip包
17、解压, 然后将ruoyi-ui剪切出来放在外面, 形成前后端分离的两个项目
18、在RuoYi-Vue-master项目中编写Dockerfile和Jenkinsfile两个文件, Dockerfile是将jar包生成镜像, Jenkinsfile是执行流水线的脚本
FROM java:8
# 将当前目录下的jar包复制到docker容器的/目录下
COPY *.jar /app.jar
# 运行过程中创建一个xx.jar文件
RUN touch /app.jar
ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms128m -Xmx256m -Djava.security.egd=file:/dev/./urandom"
ENV PARAMS="--spring.profiles.active=prod"
# 声明服务运行在8080端口
EXPOSE 8080
# 指定docker容器启动时运行jar包
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -jar /app.jar $PARAMS" ]
pipeline{
agent any
environment {
IMAGE_NAME = "ruoyi-admin"
WS = "${WORKSPACE}"
}
//定义流水线的加工流程
stages {
//流水线的所有阶段
stage('1.环境检查'){
steps {
sh 'pwd && ls -alh'
sh 'printenv'
sh 'docker version'
sh 'java -version'
sh 'git --version'
}
}
stage('2.编译'){
agent {
docker {
image 'maven:3-alpine'
args '-v maven-repository:/root/.m2'
}
}
steps {
sh 'pwd && ls -alh'
sh 'mvn -v'
sh 'cd ${WS} && mvn clean package -s "/var/jenkins_home/appconfig/maven/settings.xml" -Dmaven.test.skip=true'
}
}
stage('3.打包'){
steps {
sh 'pwd && ls -alh'
sh 'echo ${WS}'
// sh 'mv ${WS}/${IMAGE_NAME}/target/*.jar ${WS}/${IMAGE_NAME}.jar && pwd && ls -alh && docker build -t ${IMAGE_NAME} .'
sh 'docker build -t ${IMAGE_NAME} -f Dockerfile ${WS}/${IMAGE_NAME}/target/'
}
}
stage('4.部署'){
// 删除容器和虚悬镜像
steps {
sh 'pwd && ls -alh'
sh 'docker rm -f ${IMAGE_NAME} || true && docker rmi $(docker images -q -f dangling=true) || true'
sh 'docker run -d -p 8888:8080 --name ${IMAGE_NAME} -v /mydata/logs/${IMAGE_NAME}:/logs/${IMAGE_NAME} ${IMAGE_NAME}'
}
}
}
}
19、新增配置文件, 使用我们刚才创建的mysql和redis
# 数据源配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
# 主库数据源
master:
url: jdbc:mysql://xx.xx.xx.xx:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456
# 从库数据源
slave:
# 从数据源开关/默认关闭
enabled: false
url:
username:
password:
# 初始连接数
initialSize: 5
# 最小连接池数量
minIdle: 10
# 最大连接池数量
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username: ruoyi
login-password: 123456
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
redis:
# 地址
host: xx.xx.xx.xx
password: 123456
21、在前端项目ruoyi-ui中编写Dockerfile和Jenkinsfile两个文件, 并创建两个环境的nginx的配置文件(前端项目要在nginx中运行), 案例演示两个nginx的配置文件除了名字不同, 里面的内容是一相同
FROM nginx:1.22
# 构建参数,在Jenkinsfile中构建镜像时定义
ARG PROFILE
# 将dist文件中的内容复制到 `/usr/share/nginx/html/` 这个目录下面
COPY dist/ /usr/share/nginx/html/
# 用本地配置文件来替换nginx镜像里的默认配置
COPY nginx/nginx-${PROFILE}.conf /etc/nginx/nginx.conf
EXPOSE 80
# 以前台形式持续运行
CMD ["nginx", "-g", "daemon off;"]
pipeline{
agent any
environment {
// 镜像名称
IMAGE_NAME = "ruoyi-ui"
// 工作目录
WS = "${WORKSPACE}"
// 后台项目镜像名称
API_IMAGE_NAME = "ruoyi-admin"
// 自定义的构建参数
PROFILE = "prod"
}
//定义流水线的加工流程
stages {
//流水线的所有阶段
stage('1.环境检查'){
steps {
sh 'pwd && ls -alh'
sh 'printenv'
sh 'docker version'
sh 'git --version'
}
}
stage('2.编译'){
agent {
docker {
image 'node:12-alpine'
}
}
steps {
sh 'pwd && ls -alh'
sh 'node -v'
sh 'cd ${WS} && npm install --registry=https://registry.npmmirror.com --no-fund && npm run build:prod'
}
}
stage('3.打包'){
steps {
sh 'pwd && ls -alh'
sh 'docker build --build-arg PROFILE=${PROFILE} -t ${IMAGE_NAME} .'
}
}
stage('4.部署'){
// 删除容器和虚悬镜像
steps {
sh 'pwd && ls -alh'
sh 'docker rm -f ${IMAGE_NAME} || true && docker rmi $(docker images -q -f dangling=true) || true'
sh 'docker run -d -p 8889:80 --name ${IMAGE_NAME} --link ruoyi-admin:ruoyi-admin ${IMAGE_NAME}'
}
}
}
}
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location /prod-api/{
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#访问容器地址
proxy_pass http://ruoyi-admin:8080/;
#访问外网地址, 后台容器端口映射8888:8080
#proxy_pass http://47.114.186.174:8888/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
一个项目可能会有很多分支, 添加过滤之会只会创建master和dev分支的流水线
26、配置完成保存, 开始构建流水线, 这个过程有点慢, 耐心等待SUCCESS再刷新页面
27、打开Blue Ocean, 可以看见我们的多分支流水线已经构建成功! 因为ruoyi后端项目我们没有创建其他分支, 所以只有master一个流水线
28、手动运行一次
29、测试后端项目接口, 后端项目自动构建部署成功!!
30、下面开始部署前端项目, 创建一个dev分支, 测试多分支流水线, 步骤和部署后端项目类似
32、构建master的流水线, 访问若依前端首页
33、奥利给! 全部部署成功
如果有问题可以在评论区提问