1. 部署 MariaDB(MySQL)
1) 部署环境
IP 地址(本地测试环境):192.168.0.10
操作系统:Linux CentOS 7.9
Docker 版本: 20.10.7
注:CentOS 7.9 下不需要安装 Java 环境。
2) 拉取 MariaDB 镜像
$ sudo docker pull mariadb:10.4
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mariadb 10.4 0552982c09ae 7 days ago 404MB
java 8 d23bdf5b1b1b 5 years ago 643MB
...
注:可以访问 Dockers Hub(https://hub.docker.com/_/mariadb?tab=tags)查询 MariaDB 镜像,本文使用 MariaDB 10.4。
3) 配置 MariaDB
在 Docker 主机上创建 /home/mysql/conf 目录。
在 /home/mysql/conf 目录下创建 my_mariadb.cnf 文件,内容如下:
[mysqld]
server-id=1
port=3306
#basedir=/usr/local/mysql
#tmpdir=/tmp
datadir=/var/lib/mysql
# 查询日志,默认在 /var/lib/mysql 目录下
#general_log=1
#general_log_file=mysql_general.log
# 二进制日志,默认在 /var/lib/mysql 目录下
#log_bin=mysql_log_bin-1
# 慢查询日志,默认在 /var/log/mysql 目录下
#slow_query_log=1
#long_query_time=1
#slow_query_log_file=mysql_slow_query.log
# 错误日志,指定到 /var/log/mysql 目录
log_error=/var/log/mysql/mysql_err.log
4) 运行 MariaDB 容器
$ sudo docker run --name mariadb-10.4 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456\
-v /home/mysql/conf:/etc/mysql/conf.d\
-v /home/mysql/data:/var/lib/mysql\
-v /home/mysql/log:/var/log/mysql\
--privileged=true\
-d mariadb:10.4
参数说明:
-p 3306:3306:映射容器服务的 3306 端口到宿主机的 3306 端口。外部可以直接通过宿主机 ip:3306 访问到 mariadb 的服务;
MYSQL_ROOT_PASSWORD=123456:设置 mariadb 服务 root 用户的密码;
-v:将本地文件夹与容器文件夹挂载;
--privileged=true:使用该参数,容器内的 root 拥有真正的 root 权限。否则,容器内的 root 只是外部的一个普通用户权限。
-d:设置容器在后台一直运行。
mariadb:10.4: 镜像:tag。
注:MariaDB (MySQL) 的默认配置文件是 /etc/mysql/my.cnf 文件。如果想要自定义配置,在 /etc/mysql/conf.d 目录中创建 *.cnf 文件。新建的文件可以任意起名,只要保证后缀名是 cnf 即可。新建的文件中的配置项可以覆盖 /etc/mysql/my.cnf 中的配置项。
容器内的程序要在 /home/mysql/log 目录下创建 log 文件,需要确保 root/root 以外的用户也有 /home/mysql/log 目录的写权限,修改该目录的权限,命令如下:
$ cd /home/mysql
$ chmod a+w log
修改后需要重启容器,命令如下:
$ sudo docker restart mariadb-10.4
$ sudo docker ps # 查看运行的容器列表
CONTAINER ID IMAGE COMMAND PORTS NAMES
1a424e905075 mariadb:10.4 "docker-entrypoint.s…" 0.0.0.0:3306->3306/tcp mariadb-10.4
...
$ sudo docker exec -it mariadb-10.4 /bin/bash
root@1a424e905075:/# mysql -u root -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 8
Server version: 10.4.26-MariaDB-1:10.4.26+maria~ubu2004 mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
+--------------------+
3 rows in set (0.001 sec)
MariaDB [(none)]> show variables like '%log%';
+---------------------------+--------------------------------------------+
| Variable_name | Value |
+---------------------------+--------------------------------------------+
| general_log | ON |
| general_log_file | /var/log/mysql/mysql_general.log |
| log_bin | ON |
| log_bin_basename | /var/lib/mysql/mysql_log_bin |
| log_bin_index | /var/lib/mysql/mysql_log_bin.index |
| log_error | /var/log/mysql/mysql_err.log |
| slow_query_log_file | /var/log/mysql/mysql_slow_query.log |
...
+---------------------------+--------------------------------------------+
80 rows in set (0.001 sec)
注:MariaDB (MySQL) 命令的关键字,大小写不敏感,比如 show、like 可以写成 SHOW、LIKE。
4) 创建数据库 testdb 和 user 表
SQL 脚本如下:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`createtime` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
可以在容器内的 MariaDB [(none)]> 命令行下创建,操作命令如下:
MariaDB [(none)]> CREATE DATABASE IF NOT EXISTS testdb;
Query OK, 1 row affected (0.000 sec)
MariaDB [(none)]> USE testdb;
Database changed
MariaDB [testdb]> CREATE TABLE `user` (
-> `id` int(11) NOT NULL AUTO_INCREMENT,
-> `username` varchar(50) NOT NULL,
-> `password` varchar(255) DEFAULT NULL,
-> `age` int(11) DEFAULT NULL,
-> `createtime` timestamp NULL DEFAULT NULL,
-> PRIMARY KEY (`id`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.010 sec)
MariaDB [testdb]> show tables;
+------------------+
| Tables_in_testdb |
+------------------+
| user |
+------------------+
1 row in set (0.000 sec)
MariaDB [testdb]> select * from user;
Empty set (0.000 sec)
2. 修改 SpringbootWebDocker 项目
1) 导入 JDBC、MariaDB、MyBatis 等相关依赖包
访问 http://www.mvnrepository.com/ 查询依赖包。
修改 pom.xml:
1 <project ... >
2 ...
3
4 <dependencies>
5 ...
6
7 <dependency>
8 <groupId>org.mariadb.jdbc</groupId>
9 <artifactId>mariadb-java-client</artifactId>
10 </dependency>
11 <dependency>
12 <groupId>org.springframework.boot</groupId>
13 <artifactId>spring-boot-starter-data-jdbc</artifactId>
14 </dependency>
15 <dependency>
16 <groupId>org.mybatis.spring.boot</groupId>
17 <artifactId>mybatis-spring-boot-starter</artifactId>
18 <version>2.2.0</version>
19 </dependency>
20
21 <dependency>
22 <groupId>org.projectlombok</groupId>
23 <artifactId>lombok</artifactId>
24 <version>1.18.8</version>
25 </dependency>
26
27 ...
28 </dependencies>
29
30 ...
31 </project>
注:lombok 提供了一些简化实体类定义的注解。要使用 lombok,IDEA 需要安装 lombok 插件,这里以 Windows 版的 IDEA 为例,安装步骤如下:
菜单 File -> Settings -> 选中左侧 Plugin -> 搜索 "lombok" -> Install lombok plugin -> Restart IDEA
在 IDE 中项目列表 -> SpringbootWebDocker -> 点击鼠标右键 -> Maven -> Reload Project
2) 修改 src/main/resources/application.properties 文件
spring.main.banner-mode=off
# Web server
server.display-name=SpringBootWebDocker-Test
#server.address=localhost
server.port=9090
# Data source
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://192.168.0.10:3306/testdb
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
mybatis.mapper-locations=classpath:mapper/*.xml
注:不要设置 server.address。
3) 实体类、配置 MyBatis
(1) 创建 src/main/java/com/example/entity/User.java 文件
1 package com.example.entity;
2
3 import java.util.Date;
4 import java.io.Serializable;
5
6 import lombok.Data;
7 import lombok.NoArgsConstructor;
8 import lombok.experimental.Accessors;
9
10 @NoArgsConstructor // 无参构造函数
11 @Data // 提供类的 get、set、equals、hashCode、canEqual、toString 方法
12 @Accessors(chain = true)
13 public class User implements Serializable {
14 private Integer id;
15 private String username;
16 private String password;
17 private Integer age;
18 private Date createtime;
19
20 }
(2) 创建 src/main/java/com/example/mapper/UserMapper.java 文件
1 package com.example.mapper;
2
3 import org.apache.ibatis.annotations.Mapper;
4
5 import com.example.entity.User;
6
7 @Mapper
8 public interface UserMapper {
9 int insert(User user);
10 User selectByUsername(String username);
11 }
当 mapper 接口较多时,可以在 Spring Boot 主启动类上使用 @MapperScan 注解扫描指定包下的 mapper 接口,而不再需要在每个 mapper 接口上都标注 @Mapper 注解。
(3) 创建 src/main/resources/mapper/UserMapper.xml 文件
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
3 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
4 <mapper namespace="com.example.mapper.UserMapper">
5 <resultMap id="BaseResultMap" type="com.example.entity.User">
6 <id column="id" jdbcType="BIGINT" property="id"/>
7 <result column="username" jdbcType="VARCHAR" property="username"/>
8 <result column="password" jdbcType="VARCHAR" property="password"/>
9 <result column="age" jdbcType="INTEGER" property="age"/>
10 <result column="createtime" jdbcType="DATE" property="createtime"/>
11 </resultMap>
12 <sql id="Base_Column_List">
13 id, username, password, age, createtime
14 </sql>
15 <insert id="insert" parameterType="com.example.entity.User">
16 INSERT INTO user (id, username, password, age, createtime)
17 VALUES (#{id,jdbcType=BIGINT}, #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR},
18 #{age,jdbcType=INTEGER}, #{createtime,jdbcType=DATE})
19 </insert>
20 <select id="selectByUsername" parameterType="java.lang.String" resultMap="BaseResultMap">
21 SELECT
22 <include refid="Base_Column_List"/>
23 FROM user
24 WHERE username = #{username,jdbcType=VARCHAR}
25 </select>
26 </mapper>
4) 服务和控制
(1) 创建 src/main/java/com/example/service/UserService.java 文件
1 package com.example.service;
2
3 import com.example.entity.User;
4
5 public interface UserService {
6
7 int insert(User user);
8 User selectByUsername(String username);
9
10 }
(2) 创建 src/main/java/com/example/service/UserServiceImpl.java 文件
1 package com.example.service;
2
3 import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.stereotype.Service;
5
6 import com.example.entity.User;
7 import com.example.mapper.UserMapper;
8
9 @Service("userService")
10 public class UserServiceImpl implements UserService {
11 @Autowired
12 UserMapper UserMapper;
13
14 @Override
15 public int insert(User user) {
16 return UserMapper.insert(user);
17 }
18
19 @Override
20 public User selectByUsername(String username) {
21 return UserMapper.selectByUsername(username);
22 }
23
24 }
(3) 创建 src/main/java/com/example/controller/UserController.java 文件
1 package com.example.controller;
2
3 import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.web.bind.annotation.RestController;
5 import org.springframework.web.bind.annotation.RequestParam;
6 import org.springframework.web.bind.annotation.RequestMapping;
7
8 import com.example.entity.User;
9 import com.example.service.UserService;
10
11 @RestController
12 public class UserController {
13 @Autowired
14 UserService userService;
15
16 @RequestMapping("/hello")
17 public String hello() {
18 return "Hello Page - SpringBoot Web Docker";
19 }
20
21 @RequestMapping("/create")
22 public String create(String username, String password, Integer age) {
23
24 if ("".equals(username) || "".equals(password)) {
25 return "Invalid username or password.";
26 }
27
28 User user = userService.selectByUsername(username);
29 System.out.println("user = " + user);
30 if (user != null) {
31 return "'" + username + "' exists, please enter a new username.";
32 }
33
34 user = new User();
35 user.setUsername(username);
36 user.setPassword(password);
37 user.setAge(age);
38 user.setCreatetime(new Date());
39 Integer ret = userService.insert(user);
40 if (ret <= 0) {
41 return "Failed to create '" + username + "'.";
42 }
43
44 return "Create '" + username + "' successfully.";
45 }
46
47 }
5) Jar 打包
菜单 View -> Tool Windows -> Maven -> SpringbootWebDocker -> Lifecycle -> Clean & Package
jar 包生成在目录 target/ 里
SpringbootWebDocker.jar
SpringbootWebDocker.jar.original
点击 IDEA 底部 Terminal 标签页,执行如下命令。
java -jar target/SpringbootWebDocker.jar
...
Spring boot web project
浏览器访问 http://localhost:9090/create?username=admin&password=123456&age=20,页面显示:
Create 'admin' successfully.
查看数据库 testdb 里 user 表,内容如下:
id username password age createtime
1 admin 123456 20 2022-09-02 00:00:00
3. 部署 SpringbootWebDocker 项目 Jar 包
1) 部署环境
IP 地址(本地测试环境):192.168.0.10
操作系统:Linux CentOS 7.9
Docker 版本: 20.10.7
注:CentOS 7.9 下不需要安装 Java 环境。
2) 创建 Dockerfile
创建 /home/docker 目录,把 SpringbootWebDocker.jar 和 application.properties 上传到该目录。
创建 /home/docker/logs 文件夹存放日志文件,该路径与 SpringBoot 项目中 logging.file.path 设置的一致。
创建 home/docker/Dockerfile 文件,内容如下:
# 指定基础镜像
FROM java:8
# 维护者
MAINTAINER Tester
# 将文件添加到容器中,并更名为 webdocker.jar
ADD SpringbootWebDocker.jar /home/docker/webdocker.jar
ADD application.properties /home/docker/application.properties
# 指定端口,与 SpringBoot 项目配置文件中的端口一致
EXPOSE 9090
# 容器启动时,运行该程序
ENTRYPOINT ["java", "-jar", "/home/docker/webdocker.jar", "--spring.config.location=/home/docker/application.properties"]
注:这里使用 Java 8 基础镜像来演示,建议实际应用中使用较新的 Java 版本,可以访问 https://hub.docker.com/_/openjdk/tags 查询。
3) 构建镜像
$ cd /home/docker
$ sudo docker build -t webdocker .
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
webdocker latest 8b1cd7959abf 14 seconds ago 668MB
mariadb 10.4 0552982c09ae 8 days ago 404MB
java 8 d23bdf5b1b1b 5 years ago 643MB
...
4) 创建并启动容器
$ sudo docker run -p 9090:9090 --name webdocker\
-v /home/docker/logs:/home/docker/logs\
-v /home/docker/application.properties:/home/docker/application.properties\
-d webdocker
dde73d87638c8516847c68ead5a9de5ff624fb2534f3ef675b5ab9b354c4f56a
$ sudo docker ps # 查看容器
CONTAINER ID IMAGE COMMAND ... PORTS NAMES
dde73d87638c webdocker "java -jar /home/doc…" 0.0.0.0:9090->9090/tcp webdocker
...
$ sudo docker exec -it webdocker /bin/bash # 进入容器
5) 页面访问
浏览器访问 http://192.168.0.10:9090/create?username=user&password=333666&age=30,页面显示:
Create 'user' successfully.
查看数据库 testdb 里 user 表,内容如下:
id username password age createtime
1 admin 123456 20 2022-09-02 00:00:00
2 user 333666 30 2022-09-02 00:00:00