# springboot-docker-mysql
**Repository Path**: ComCtrl/springboot-docker-mysql
## Basic Information
- **Project Name**: springboot-docker-mysql
- **Description**: docker化的spring boot 应用访问暴露的mysql容器,并使用 jenkins流水线自动部署
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2018-09-17
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Spring Boot、docker、Jenkins、mysql整合
## 概述
此处将 springboot 和数据库分为两个镜像
## Spring Boot项目搭建
项目完整的 pom.xml文件
```xml
4.0.0
com.test
springboot-docker-mysql
0.0.1
jar
springboot-docker-mysql
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-parent
1.5.10.RELEASE
UTF-8
UTF-8
springboot
1.8
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-starter-web
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.1
org.springframework.boot
spring-boot-devtools
runtime
mysql
mysql-connector-java
runtime
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
com.alibaba
druid
1.0.11
dev
true
dev
test
test
org.springframework.boot
spring-boot-maven-plugin
com.spotify
docker-maven-plugin
1.1.0
${docker.image.prefix}/${project.artifactId}
.
/
${project.build.directory}
${project.build.finalName}.jar
```
### 整合 mybatis
1. 导入依赖 (略)
2. 配置 `application.properties` 文件 (多环境)
`src/main/resources` 下新建如下的三个配置文件
```
application.properties
application-dev.properties (连接本地mysql开发)
application-test.properteis (连接docker中的mysql测试)
```
`application.properties`
```properties
spring.profiles.active = @profileActive@
```
`application-dev.properties`
```properties
server.port=8082
# 数据库访问配置
# 主数据源,默认的
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot_docker_mysql?useSSL=false
spring.datasource.username=root
spring.datasource.password=root
# 下面为连接池的补充设置,应用到上面所有数据源中
# 初始化大小,最小,最大
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.filters=stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多个DruidDataSource的监控数据
#spring.datasource.useGlobalDataSourceStat=true
```
`application-test.properteis`
```properties
server.port=8082
# 数据库访问配置
# 主数据源,默认的
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.2.2:3307/springboot_docker_mysql?useSSL=false
spring.datasource.username=root
spring.datasource.password=root
# 下面为连接池的补充设置,应用到上面所有数据源中
# 初始化大小,最小,最大
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.filters=stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多个DruidDataSource的监控数据
#spring.datasource.useGlobalDataSourceStat=true
```
`pom.xml` 中配置 profiles
```xml
dev
true
dev
test
test
```
3. 建表
```sql
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`nickname` varchar(255) DEFAULT NULL,
`birthday` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
INSERT INTO `springboot_docker_mysql`.`user` (`id`, `username`, `nickname`, `birthday`) VALUES ('1', 'lisi', 'ss', NULL);
```
4. 新建实体类
```java
package com.test.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
private Integer id;
private String username;
private String nickname;
private Date birthday;
}
```
5. 新建 mapper
```java
package com.test.mapper;
import com.test.entity.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface UserMapper {
@Select("select * from user where id = #{id}")
User getById(Integer id);
@Insert("insert into user (username, nickname, birthday) values (#{user.username}, #{user.nickname}, #{user.birthday})")
void insertUser(@Param("user") User user);
}
```
6. 新建 controller
```java
package com.test.controller;
import java.util.Date;
import com.test.entity.User;
import com.test.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class UserController {
@Autowired
private UserMapper userMapper;
@GetMapping("/user/{id}")
User getUserById(@PathVariable Integer id){
return userMapper.getById(id);
}
@GetMapping("/user/{username}/{nickname}")
public String insertUser(@PathVariable("username") String username, @PathVariable("nickname") String nickname){
User user = new User();
user.setId(0);
user.setUsername(username);
user.setNickname(nickname);
user.setBirthday(new Date());
userMapper.insertUser(user);
log.info("@@@" + new Date());
return "success";
}
}
```
## Dockerfile
**最重要的事情** : 设置时区
```dockerfile
FROM java:8
VOLUME /tmp
# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ADD springboot-docker-mysql-0.0.1.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
```
## Docker 配置 mysql
1. 拉取镜像
```
[root@centos7 ~]# docker pull mysql:5.7
```
2. 运行镜像
* `-v /data/mysql:/var/lib/mysql` 数据库挂载到宿主机 `/data/mysql` 目录下
* `-v /etc/localtime:/etc/localtime:ro` 使用宿主机时区
* `--privileged=true` 解决Centos7安全Selinux禁止了一些安全权限问题
* `-e MYSQL_ROOT_PASSWORD=root` 设置密码
* `--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci` 设置字符编码
```
[root@localhost ~]# docker run -p 3307:3306 --name mysql -v /data/mysql:/var/lib/mysql -v /etc/localtime:/etc/localtime:ro --privileged=true -e MYSQL_ROOT_PASSWORD=root -d mysql --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
```
3. 允许mysql 被远程访问
```
[root@localhost mysql]# docker exec -it mysql bash #进入运行中的容器
root@746e0b3444ea:/# mysql -uroot -proot #连接mysql
mysql> ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root'; #修改访问权限
mysql> select now(); #查看当前时间
```
## 打包镜像启动容器
1. git 拉取项目
```
[root@localhost ~]# git clone git@gitee.com:ComCtrl/springboot-docker-mysql.git
```
2. 打包镜像
```
[root@localhost springboot-docker-mysql]# mvn package -Dmaven.test.skip=true -Ptest docker:build #打包的时候使用 test profile
```
3. 运行镜像
```
[root@localhost springboot-docker-mysql]# docker run -v /etc/localtime:/etc/localtime:ro --name springboot-docker-mysql -d -p 8082:8082 springboot/springboot-docker-mysql
```
4. 测试
访问 http://192.168.2.2:8082/user/1 查看结果
访问 http://192.168.2.2:8082/user/aaa/aa 查看数据库,日期是否正确
## Jenkins 一键部署
上述镜像启动成功后,进行一键部署
1. 进入Jenkins,新建流水线任务
2. groovy 脚本
```groovy
#!groovy
pipeline{
agent any
//定义仓库地址
environment {
REPOSITORY = "git@gitee.com:ComCtrl/springboot-docker-mysql.git"
project = "springboot-docker-mysql" //项目名称
image_name = "springboot/springboot-docker-mysql" //镜像名称
}
stages {
stage('获取代码'){
steps {
echo "从 git:${REPOSITORY} 拉取代码"
//清空当前目录
deleteDir()
//拉取代码
git "${REPOSITORY}"
}
}
stage('构建镜像'){
steps {
echo "开始构建"
//构建镜像
sh 'mvn package -Dmaven.test.skip=true -Ptest docker:build'
}
}
stage('停止原有服务'){
steps{
script {
try {
echo "停止服务"
sh 'docker stop ${project}'
} catch(ex) {
}
}
}
}
stage("启动服务"){
steps {
script {
try {
echo "启动服务"
// -v /etc/localtime:/etc/localtime:ro 同步时间
sh 'docker run -v /etc/localtime:/etc/localtime:ro --name ${project} -d -p 8082:8082 ${image_name}'
} catch(ex) {
sh 'docker start ${project}'
}
}
}
}
}
}
```