DockerCompose deploys SpringBoot project
Prepare SpringBoot project
List of project catalogs
Project source code Gitee address
Prepare the database
CREATE TABLE `t_user` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL DEFAULT '' COMMENT 'username', `password` varchar(50) NOT NULL DEFAULT '' COMMENT 'password', `sex` tinyint(4) NOT NULL DEFAULT '0' COMMENT 'Sex 0=female 1=male ', `deleted` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT 'Delete flag, default 0 not delete, 1 delete', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'update time', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'create time', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='user table';
Add pom dependencies
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.6</version> <!--<version>2.3.10.RELEASE</version>--> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <junit.version>4.12</junit.version> <log4j.version>1.2.17</log4j.version> <lombok.version>1.16.18</lombok.version> <mysql.version>5.1.47</mysql.version> <druid.version>1.1.16</druid.version> <mapper.version>4.1.5</mapper.version> <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version> </properties> <dependencies> <!--guava Bloom filter that comes with Google's open source Guava --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>23.0</version> </dependency> <!-- redisson --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.13.4</version> </dependency> <!--SpringBoot common dependency module--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--swagger2--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> <!--SpringBoot and Redis integration dependencies --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--springCache--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <!--springCache connection pool dependency package --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!-- jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.1.0</version> </dependency> <!--Mysql database driver--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!--SpringBoot integrated druid connection pool--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <!--mybatis and springboot integration--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis.spring.boot.version}</version> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.10</version> </dependency> <!--Common basic configuration junit/devtools/test/log4j/lombok/hutool--> <!--hutool--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.2.3</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> <optional>true</optional> </dependency> <!--persistence--> <dependency> <groupId>javax.persistence</groupId> <artifactId>persistence-api</artifactId> <version>1.0.2</version> </dependency> <!--General Mapper--> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper</artifactId> <version>${mapper.version}</version> </dependency> </dependencies>
Main startup class
@SpringBootApplication @MapperScan("com.zhuang.docker.mapper") public class DockerBootApplication {<!-- --> public static void main(String[] args) {<!-- --> SpringApplication.run(DockerBootApplication.class, args); } }
Config layer
RedisConfig
@Configuration @Slf4j public class RedisConfig {<!-- --> /** * @param lettuceConnectionFactory * @return redis serialized tool configuration class, please be sure to open the configuration below * 127.0.0.1:6379> keys * * 1) "ord:102" serialized * 2) "\xac\xed\x00\x05t\x00\aord:102" wild, not serialized */ @Bean public RedisTemplate<String, Serializable> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {<!-- --> RedisTemplate<String, Serializable> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(lettuceConnectionFactory); //Set key serialization method string redisTemplate.setKeySerializer(new StringRedisSerializer()); //Set the serialization method of value json redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; } }
SwaggerConfig
@Configuration @EnableSwagger2 public class SwaggerConfig {<!-- --> @Value("${spring. swagger2. enabled}") private Boolean enabled; @Bean public Docket createRestApi() {<!-- --> return new Docket(DocumentationType. SWAGGER_2) .apiInfo(apiInfo()) .enable(enabled) .select() .apis(RequestHandlerSelectors.basePackage("com.zhuang.docker")) //your own package .paths(PathSelectors. any()) .build(); } public ApiInfo apiInfo() {<!-- --> return new ApiInfoBuilder() .title("Kang Xiaozhuang's Docker project" + "\t" + new SimpleDateFormat("yyyy-MM-dd").format(new Date())) .description("docker-compose") .version("1.0") .termsOfServiceUrl("https://itkxz.cn/") .build(); } }
Entity layer
@Table(name = "t_user") public class User {<!-- --> @Id @GeneratedValue(generator = "JDBC") private Integer id; /** * username */ private String username; /** * password */ private String password; /** * Gender 0=female 1=male */ private Byte sex; /** * Delete flag, default 0 is not deleted, 1 is deleted */ private Byte deleted; /** * update time */ @Column(name = "update_time") private Date updateTime; /** * Creation time */ @Column(name = "create_time") private Date createTime; /** * @return id */ public Integer getId() {<!-- --> return id; } /** * @param id */ public void setId(Integer id) {<!-- --> this.id = id; } /** * get username * * @return username - username */ public String getUsername() {<!-- --> return username; } /** * set username * * @param username username */ public void setUsername(String username) {<!-- --> this. username = username; } /** * get password * * @return password - the password */ public String getPassword() {<!-- --> return password; } /** * set password * * @param password password */ public void setPassword(String password) {<!-- --> this.password = password; } /** * Get gender 0=female 1=male * * @return sex - sex 0=female 1=male */ public Byte getSex() {<!-- --> return sex; } /** * Set gender 0=female 1=male * * @param sex sex 0=female 1=male */ public void setSex(Byte sex) {<!-- --> this. sex = sex; } /** * Get the delete flag, the default is 0 to not delete, 1 to delete * * @return deleted - delete flag, default 0 is not deleted, 1 is deleted */ public Byte getDeleted() {<!-- --> return deleted; } /** * Set the delete flag, default 0 is not deleted, 1 is deleted * * @param deleted delete flag, default 0 not delete, 1 delete */ public void setDeleted(Byte deleted) {<!-- --> this.deleted = deleted; } /** * get update time * * @return update_time - update time */ public Date getUpdateTime() {<!-- --> return updateTime; } /** * Set update time * * @param updateTime update time */ public void setUpdateTime(Date updateTime) {<!-- --> this. updateTime = updateTime; } /** * Get creation time * * @return create_time - the creation time */ public Date getCreateTime() {<!-- --> return createTime; } /** * Set creation time * * @param createTime creation time */ public void setCreateTime(Date createTime) {<!-- --> this.createTime = createTime; } }
UserDTO
@NoArgsConstructor @AllArgsConstructor @Data @ApiModel(value = "User Information") public class UserDTO implements Serializable {<!-- --> @ApiModelProperty(value = "User ID") private Integer id; @ApiModelProperty(value = "username") private String username; @ApiModelProperty(value = "Password") private String password; @ApiModelProperty(value = "Gender 0=Female 1=Male ") private Byte sex; @ApiModelProperty(value = "delete flag, default 0 is not deleted, 1 is deleted") private Byte deleted; @ApiModelProperty(value = "update time") private Date updateTime; @ApiModelProperty(value = "creation time") private Date createTime; /** * @return id */ public Integer getId() {<!-- --> return id; } /** * @param id */ public void setId(Integer id) {<!-- --> this.id = id; } /** * get username * * @return username - username */ public String getUsername() {<!-- --> return username; } /** * set username * * @param username username */ public void setUsername(String username) {<!-- --> this. username = username; } /** * get password * * @return password - the password */ public String getPassword() {<!-- --> return password; } /** * set password * * @param password password */ public void setPassword(String password) {<!-- --> this.password = password; } /** * Get gender 0=female 1=male * * @return sex - sex 0=female 1=male */ public Byte getSex() {<!-- --> return sex; } /** * Set gender 0=female 1=male * * @param sex sex 0=female 1=male */ public void setSex(Byte sex) {<!-- --> this. sex = sex; } /** * Get the delete flag, the default is 0 to not delete, 1 to delete * * @return deleted - delete flag, default 0 is not deleted, 1 is deleted */ public Byte getDeleted() {<!-- --> return deleted; } /** * Set the delete flag, default 0 is not deleted, 1 is deleted * * @param deleted delete flag, default 0 not delete, 1 delete */ public void setDeleted(Byte deleted) {<!-- --> this.deleted = deleted; } /** * get update time * * @return update_time - update time */ public Date getUpdateTime() {<!-- --> return updateTime; } /** * Set update time * * @param updateTime update time */ public void setUpdateTime(Date updateTime) {<!-- --> this. updateTime = updateTime; } /** * Get creation time * * @return create_time - the creation time */ public Date getCreateTime() {<!-- --> return createTime; } /** * Set creation time * * @param createTime creation time */ public void setCreateTime(Date createTime) {<!-- --> this.createTime = createTime; } @Override public String toString() {<!-- --> return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", sex=" + sex + '}'; } }
Mapper layer
public interface UserMapper extends Mapper<User> {<!-- --> }
Service layer
@Service @Slf4j public class UserService {<!-- --> public static final String CACHE_KEY_USER = "user:"; @Resource private UserMapper userMapper; @Resource private RedisTemplate redisTemplate; /** * addUser * * @param user User */ public void addUser(User user) {<!-- --> //1 insert mysql first and succeed int i = userMapper.insertSelective(user); if (i > 0) {<!-- --> //2 You need to query mysql again to get the data back and it's ok user = userMapper.selectByPrimaryKey(user.getId()); //3 Save the fished out user into redis to complete the data consistency of the new function. String key = CACHE_KEY_USER + user. getId(); redisTemplate.opsForValue().set(key, user); } } /** * findUserById * * @param id Integer * @return User */ public User findUserById(Integer id) {<!-- --> User user = null; String key = CACHE_KEY_USER + id; //1 First query from redis, if there is a direct return result, if not, then query mysql user = (User) redisTemplate.opsForValue().get(key); if (user == null) {<!-- --> //2 There is nothing in redis, continue to query mysql user = userMapper. selectByPrimaryKey(id); if (user == null) {<!-- --> //3.1 redis + mysql have no data //You specify the details to prevent multiple penetrations. We stipulate that the key that caused the penetration should be recorded and written back to redis return user; } else {<!-- --> //3.2 mysql has it, and the data needs to be written back to redis to ensure the next cache hit rate redisTemplate.opsForValue().set(key, user); } } return user; } /** * @param id */ public void deleteUser(Integer id) {<!-- --> userMapper.deleteByPrimaryKey(id); } /** * @param user User */ public void updateUser(User user) {<!-- --> userMapper. updateByPrimaryKey(user); } }
Controller layer
@Api(description = "User Interface") @RestController @Slf4j public class UserController {<!-- --> @Resource private UserService userService; @ApiOperation("New 3 records in the database") @RequestMapping(value = "/user/add", method = RequestMethod. POST) public void addUser() {<!-- --> for (int i = 1; i <= 3; i ++ ) {<!-- --> User user = new User(); user.setUsername("zk" + i); user.setPassword(IdUtil.simpleUUID().substring(0, 6)); user.setSex((byte) new Random().nextInt(2)); userService. addUser(user); } } @ApiOperation("Delete 1 record") @RequestMapping(value = "/user/delete/{id}", method = RequestMethod. POST) public void deleteUser(@PathVariable Integer id) {<!-- --> userService.deleteUser(id); } @ApiOperation("Modify 1 record") @RequestMapping(value = "/user/update", method = RequestMethod. POST) public void updateUser(@RequestBody UserDTO userDTO) {<!-- --> User user = new User(); BeanUtils. copyProperties(userDTO, user); userService. updateUser(user); } @ApiOperation("Query 1 record") @RequestMapping(value = "/user/find/{id}", method = RequestMethod.GET) public User findUserById(@PathVariable Integer id) {<!-- --> return userService. findUserById(id); } }
Configuration file
server.port=6001 # =========================== alibaba.druid related configuration ====================== = spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://ip:3306/docker?useUnicode=true &characterEncoding=utf-8 &useSSL=false spring.datasource.username=root spring.datasource.password=root spring.datasource.druid.test-while-idle=false # =========================== redis related configuration ====================== spring.redis.database=0 spring.redis.host=ip spring.redis.port=6379 spring.redis.password= spring.redis.lettuce.pool.max-active=8 spring.redis.lettuce.pool.max-wait=-1ms spring.redis.lettuce.pool.max-idle=8 spring.redis.lettuce.pool.min-idle=0 # =========================== mybatis related configuration ===================== mybatis.mapper-locations=classpath:mapper/*.xml mybatis.type-aliases-package=com.zhuang.docker.entity # =========================== swagger======================= spring.swagger2.enabled=true
Project run test
Prepare the database
Prepare Redis
Start the project successfully
browser test
http://localhost:6001/user/find/88
Visit the swagger page for testing
http://localhost:6001/swagger-ui.html
Test success
Query database inserted successfully
Redis inserted successfully
Deploy with Docker
docker run -p 3307:3306 --name mysql57 --privileged=true -v /mydata/mysql-master/log:/var/log/mysql -v /mydata/mysql-master/data:/var/ lib/mysql -v /mydata/mysql-master/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
Enter the container bash
docker exec -it mysql57 /bin/bash
create database
mysql -uroot -p create database docker; CREATE TABLE `t_user` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL DEFAULT '' COMMENT 'username', `password` varchar(50) NOT NULL DEFAULT '' COMMENT 'password', `sex` tinyint(4) NOT NULL DEFAULT '0' COMMENT 'Sex 0=female 1=male ', `deleted` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT 'Delete flag, default 0 not delete, 1 delete', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'update time', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'create time', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='user table'; use docker;
Separate redis container instance
docker run -p 6399:6379 --name redis608 --privileged=true -v /app/redis/redis.conf:/etc/redis/redis.conf -v /app/redis/data:/data - d redis:6.0.8 redis-server /etc/redis/redis.conf
Modify application.properties
Package and upload to the Linux virtual machine
Write DockerFile
# The basic image uses java FROM java:8 # author MAINTAINER zk # VOLUME specifies the temporary file directory as /tmp, creates a temporary file in the host /var/lib/docker directory and links it to the container's /tmp VOLUME /tmp # Add the jar package to the container and rename it to zk_docker.jar ADD DockerDemo-1.0-SNAPSHOT.jar zk_docker.jar # Run the jar package RUN bash -c 'touch /zk_docker.jar' ENTRYPOINT ["java","-jar","/zk_docker.jar"] #Expose port 6001 as a microservice EXPOSE 6001
Compile the dockerFile file and specify to package it into a specified version of the image
docker build -f docker_demo -t zk_docker:1.8 .
Query Mirror
docker images # Expose the port externally docker run -d -p 6001:6001 container ID docker ps
Run successfully!
Enter browser test
http://ip:6001/user/find/88
http://ip:6001/swagger-ui.html
Using Compose to deploy
Write docker-compose.yml file
version: "3" services: microService: image: zk_docker:1.9 container_name: ms01 ports: - "6001:6001" volumes: - /app/microService:/data networks: - zk_net depends_on: -redis -mysql redis: image: redis:6.0.8 ports: - "6399:6379" volumes: - /app/redis/redis.conf:/etc/redis/redis.conf - /app/redis/data:/data networks: - zk_net command: redis-server /etc/redis/redis.conf mysql: image: mysql:5.7 container_name: mysql environment: MYSQL_ROOT_PASSWORD: 'root' MYSQL_ALLOW_EMPTY_PASSWORD: 'no' MYSQL_DATABASE: 'docker' MYSQL_USER: 'zzkk' MYSQL_PASSWORD: 'zzkk123' ports: - "3307:3306" volumes: - /app/mysql/db:/var/lib/mysql - /app/mysql/conf/my.cnf:/etc/my.cnf - /app/mysql/init:/docker-entrypoint-initdb.d networks: - zk_net command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci networks: zk_net:
Modify application.properties
Create a new folder mydocker
mkdir docker cd docker docker build -f docker_demo -t zk_docker:1.9 . docker-compose up -d
Make sure the 3 files are in the same folder
Modify the dokcerfile file
Now we have 2 versions, one is deployed without DockerCompose and the other is deployed with DockerCompose
One-click deployment of 3 projects
Enter the mysql container instance and create a new library docker + create a new table t_user
docker exec -it container instance id /bin/bash
mysql -uroot -p create database docker; use docker; CREATE TABLE `t_user` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `username` VARCHAR(50) NOT NULL DEFAULT '' COMMENT 'username', `password` VARCHAR(50) NOT NULL DEFAULT '' COMMENT 'password', `sex` TINYINT(4) NOT NULL DEFAULT '0' COMMENT 'Sex 0=female 1=male ', `deleted` TINYINT(4) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Delete flag, default 0 is not deleted, 1 is deleted', `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'update time', `create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'create time', PRIMARY KEY (`id`) ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='user table';
Test
Query data successfully
Check the log to insert data successfully
docker-compose logs
Redis port 6399 is also connected successfully
Enter the mysql container to view data
Enter the redis container to view data
So far, the process of deploying SpringBoot by Docker has been completed. In the future, you only need to write a DockerFile
and docker-compose.yml
to achieve one-click deployment!