(十二) Docker-compose容器编排

news2024/9/21 5:38:46

Docker-compose

  • 一、概述
    • 1、简介
    • 2、作用
    • 3、下载
  • 二、核心概念
  • 三、使用步骤
  • 四、Compose常用命令
  • 五、Compose编排微服务实践
    • 一、构建项目的镜像
      • 1、建立数据库表
      • 2、POM文件
      • 3、YAML
      • 4、主启动类
      • 5、业务类
        • 1、生成简易代码
        • 2、配置类
        • 3、实体类
        • 4、Mapper
        • 5、Service
        • 6、Controller
      • 6、打 Jar 包上传服务器,编写 DockerFile
      • 7、构建镜像
    • 二、不用Compose的情况下
    • 三、使用Compose
      • 1、编写docker-compose.yml文件
      • 3、修改项目配置文件重新打Jar包
      • 3、执行Compose
      • 4、进入mysql容器实例并新建库db2023以及新建表t_user
      • 5、测试
      • 6、停止容器

一、概述

1、简介

Docker-Compose是Docker官方的开源项目,负责实现对Docker容器集群的快速编排

Compose 是 Docker 公司推出的一个工具软件,可以管理多个 Docker 容器组成一个应用。你需要定义一个 YAML 格式的配置文件docker-compose.yml,写好多个容器之间的调用关系。然后,只要一个命令,就能同时启动/关闭这些容器

这是类似于Spring的对比

在这里插入图片描述

2、作用

如果需要同时部署多个服务,这样每个服务都需要单独写Dockerfile然后在构建镜像,构建容器,这是非常繁琐的,为了解决这个问题,所以有了Compose

Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project) 可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。

Docker-Compose 解决了容器与容器之间如何管理编排的问题

3、下载

现在都是Docker Desktop进行管理,具体可以参考官方文档

官网文档说明

https://docs.docker.com/compose/compose-file/compose-file-v3/

官网下载

https://docs.docker.com/compose/install/

安装

新版本不用下,一般自带可以通过命令docker compose -v查看

在这里插入图片描述

下载命令

curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

chmod +x /usr/local/bin/docker-compose

docker-compose --version

卸载

rm /usr/local/bin/com.docker-compose

二、核心概念

一文件

docker-compose.yml

两要素

  • 服务(service)

    一个个应用容器实例,比如订单微服务、库存微服务、mysql容器、nginx容器或者redis容器

  • 工程(project)

    由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。

三、使用步骤

  • 编写Dockerfile定义各个微服务应用并构建出对应的镜像文件
  • 使用 docker-compose.yml 定义一个完整业务单元,安排好整体应用中的各个容器服
  • 最后,执行docker-compose up命令 来启动并运行整个应用程序,完成一键部署上线

四、Compose常用命令

docker-compose -h                           # 查看帮助
docker-compose up                           # 启动所有docker-compose服务
docker-compose up -d                        # 启动所有docker-compose服务并后台运行
docker-compose down                         # 停止并删除容器、网络、卷、镜像。
docker-compose exec  yml里面的服务id                 # 进入容器实例内部  docker-compose exec docker-compose.yml文件中写的服务id /bin/bash
docker-compose ps                      # 展示当前docker-compose编排过的运行的所有容器
docker-compose top                     # 展示当前docker-compose编排过的容器进程
 
docker-compose logs  yml里面的服务id     # 查看容器输出日志
docker-compose config     # 检查配置
docker-compose config -q  # 检查配置,有问题才有输出
docker-compose restart   # 重启服务
docker-compose start     # 启动服务
docker-compose stop      # 停止服务

五、Compose编排微服务实践

一、构建项目的镜像

Jar包源码:https://gitee.com/feng2828/docker-compose.git

1、建立数据库表

create database db01;
use db01;

CREATE TABLE `t_user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL DEFAULT '' COMMENT '用户名',
  `password` varchar(50) NOT NULL DEFAULT '' COMMENT '密码',
  `sex` tinyint(4) NOT NULL DEFAULT '0' COMMENT '性别 0=女 1=男 ',
  `deleted` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '删除标志,默认0不删除,1删除',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户表'

2、POM文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <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>

    <groupId>com.feng</groupId>
    <artifactId>docker_boot</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.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 Google 开源的 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通用依赖模块-->
        <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与Redis整合依赖-->
        <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连接池依赖包-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!-- jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.3.0</version>
        </dependency>
        <!--Mysql数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--SpringBoot集成druid连接池-->
        <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和springboot整合-->
        <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>
        <!--通用基础配置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>
        <!--通用Mapper-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
            <version>${mapper.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.1.0</version>
            </plugin>
        </plugins>
    </build>

</project>


3、YAML

server.port=6001
# ========================alibaba.druid相关配置=====================
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://你的服务器IP:3306/db01?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.druid.test-while-idle=false
# ========================redis相关配置=====================
spring.redis.database=0
spring.redis.host=你的服务器IP
spring.redis.port=6380
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相关配置===================
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.feng.docker_boot.pojo
# ========================swagger=====================
spring.swagger2.enabled=true

4、主启动类

package com.feng.docker_boot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;


import java.util.UUID;

@SpringBootApplication
@MapperScan("com.feng.docker_boot.mapper") //import tk.mybatis.spring.annotation.MapperScan;
public class DockerBootApplication {

    public static void main(String[] args) {
        SpringApplication.run(DockerBootApplication.class, args);
    }

}

5、业务类

1、生成简易代码

IDEA插件MybatisX
在这里插入图片描述

IDEA自带的数据库里面右键表就可以看见自动生成代码功能

在这里插入图片描述

可以自定义生成代码的设置
在这里插入图片描述

这里如果你的项目用的是Mybatis不是plus,注解以及模板选择选自己用的,最好不要同时导入mybatis和mybatis_plus,可能会有版本差异
在这里插入图片描述

2、配置类

Redis

package com.feng.docker_boot.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.io.Serializable;

@Configuration
@Slf4j
public class RedisConfig
{
    /**
     * @param lettuceConnectionFactory
     * @return
     *
     * redis序列化的工具配置类,下面这个请一定开启配置
     * 127.0.0.1:6379> keys *
     * 1) "ord:102"  序列化过
     * 2) "\xac\xed\x00\x05t\x00\aord:102"   野生,没有序列化过
     */
    @Bean
    public RedisTemplate<String,Serializable> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory)
    {
        RedisTemplate<String,Serializable> redisTemplate = new RedisTemplate<>();

        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        //设置key序列化方式string
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置value的序列化方式json
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.afterPropertiesSet();

        return redisTemplate;
    }

}

 
 

Swagger

package com.feng.docker_boot.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.text.SimpleDateFormat;
import java.util.Date;


@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.feng.docker_boot")) //你自己的package
                .paths(PathSelectors.any())
                .build();
    }

    public ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("小怪"+"\t"+new SimpleDateFormat("yyyy-MM-dd").format(new Date()))
                .description("docker-compose")
                .version("1.0")
                .termsOfServiceUrl("https://www.guai.com/")
                .build();
    }
}

 
 

3、实体类

User

package com.feng.docker_boot.pojo;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;

@Table(name = "t_user")
public class User {
    @Id
    @GeneratedValue(generator = "JDBC")
    private Integer id;

    /**
     * 用户名
     */
    private String username;

    /**
     * 密码
     */
    private String password;

    /**
     * 性别 0=女 1=男
     */
    private Byte sex;

    /**
     * 删除标志,默认0不删除,1删除
     */
    private Byte deleted;

    /**
     * 更新时间
     */
    @Column(name = "update_time")
    private Date updateTime;

    /**
     * 创建时间
     */
    @Column(name = "create_time")
    private Date createTime;

    /**
     * @return id
     */
    public Integer getId() {
        return id;
    }

    /**
     * @param id
     */
    public void setId(Integer id) {
        this.id = id;
    }

    /**
     * 获取用户名
     *
     * @return username - 用户名
     */
    public String getUsername() {
        return username;
    }

    /**
     * 设置用户名
     *
     * @param username 用户名
     */
    public void setUsername(String username) {
        this.username = username;
    }

    /**
     * 获取密码
     *
     * @return password - 密码
     */
    public String getPassword() {
        return password;
    }

    /**
     * 设置密码
     *
     * @param password 密码
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * 获取性别 0=女 1=男
     *
     * @return sex - 性别 0=女 1=男
     */
    public Byte getSex() {
        return sex;
    }

    /**
     * 设置性别 0=女 1=男
     *
     * @param sex 性别 0=女 1=男
     */
    public void setSex(Byte sex) {
        this.sex = sex;
    }

    /**
     * 获取删除标志,默认0不删除,1删除
     *
     * @return deleted - 删除标志,默认0不删除,1删除
     */
    public Byte getDeleted() {
        return deleted;
    }

    /**
     * 设置删除标志,默认0不删除,1删除
     *
     * @param deleted 删除标志,默认0不删除,1删除
     */
    public void setDeleted(Byte deleted) {
        this.deleted = deleted;
    }

    /**
     * 获取更新时间
     *
     * @return update_time - 更新时间
     */
    public Date getUpdateTime() {
        return updateTime;
    }

    /**
     * 设置更新时间
     *
     * @param updateTime 更新时间
     */
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    /**
     * 获取创建时间
     *
     * @return create_time - 创建时间
     */
    public Date getCreateTime() {
        return createTime;
    }

    /**
     * 设置创建时间
     *
     * @param createTime 创建时间
     */
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}


UserDto

package com.feng.docker_boot.pojo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Date;

@NoArgsConstructor
@AllArgsConstructor
@Data
@ApiModel(value = "用户信息")
public class UserDTO implements Serializable
{
    @ApiModelProperty(value = "用户ID")
    private Integer id;

    @ApiModelProperty(value = "用户名")
    private String username;

    @ApiModelProperty(value = "密码")
    private String password;

    @ApiModelProperty(value = "性别 0=女 1=男 ")
    private Byte sex;

    @ApiModelProperty(value = "删除标志,默认0不删除,1删除")
    private Byte deleted;

    @ApiModelProperty(value = "更新时间")
    private Date updateTime;

    @ApiModelProperty(value = "创建时间")
    private Date createTime;

    /**
     * @return id
     */
    public Integer getId() {
        return id;
    }

    /**
     * @param id
     */
    public void setId(Integer id) {
        this.id = id;
    }

    /**
     * 获取用户名
     *
     * @return username - 用户名
     */
    public String getUsername() {
        return username;
    }

    /**
     * 设置用户名
     *
     * @param username 用户名
     */
    public void setUsername(String username) {
        this.username = username;
    }

    /**
     * 获取密码
     *
     * @return password - 密码
     */
    public String getPassword() {
        return password;
    }

    /**
     * 设置密码
     *
     * @param password 密码
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * 获取性别 0=女 1=男 
     *
     * @return sex - 性别 0=女 1=男 
     */
    public Byte getSex() {
        return sex;
    }

    /**
     * 设置性别 0=女 1=男 
     *
     * @param sex 性别 0=女 1=男 
     */
    public void setSex(Byte sex) {
        this.sex = sex;
    }

    /**
     * 获取删除标志,默认0不删除,1删除
     *
     * @return deleted - 删除标志,默认0不删除,1删除
     */
    public Byte getDeleted() {
        return deleted;
    }

    /**
     * 设置删除标志,默认0不删除,1删除
     *
     * @param deleted 删除标志,默认0不删除,1删除
     */
    public void setDeleted(Byte deleted) {
        this.deleted = deleted;
    }

    /**
     * 获取更新时间
     *
     * @return update_time - 更新时间
     */
    public Date getUpdateTime() {
        return updateTime;
    }

    /**
     * 设置更新时间
     *
     * @param updateTime 更新时间
     */
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    /**
     * 获取创建时间
     *
     * @return create_time - 创建时间
     */
    public Date getCreateTime() {
        return createTime;
    }

    /**
     * 设置创建时间
     *
     * @param createTime 创建时间
     */
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", sex=" + sex +
                '}';
    }
}
 

4、Mapper

package com.feng.docker_boot.mapper;

import com.feng.docker_boot.pojo.User;
import tk.mybatis.mapper.common.Mapper;
/**
* @author Hey!boy
* @description 针对表【t_user(用户表)】的数据库操作Mapper
* @createDate 2023-02-02 18:30:33
* @Entity com.feng.docker_boot.pojo.User
*/
public interface UserMapper extends Mapper<User>  {

}

5、Service

package com.feng.docker_boot.service;


import com.feng.docker_boot.mapper.UserMapper;
import com.feng.docker_boot.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

/**
 * @author guai
 * @createDate 2023-02-02 18:30:33
 */
@Service
@Slf4j
public class UserService {

    public static final String CACHE_KEY_USER = "user:";

    @Resource
    private UserMapper userMapper;
    @Resource
    private RedisTemplate redisTemplate;

    /**
     * addUser
     * @param user
     */
    public void addUser(User user)
    {
        //1 先插入mysql并成功
        int i = userMapper.insertSelective(user);

        if(i > 0)
        {
            //2 需要再次查询一下mysql将数据捞回来并ok
            user = userMapper.selectByPrimaryKey(user.getId());
            //3 将捞出来的user存进redis,完成新增功能的数据一致性。
            String key = CACHE_KEY_USER+user.getId();
            redisTemplate.opsForValue().set(key,user);
        }
    }

    /**
     * findUserById
     * @param id
     * @return
     */
    public User findUserById(Integer id)
    {
        User user = null;
        String key = CACHE_KEY_USER+id;

        //1 先从redis里面查询,如果有直接返回结果,如果没有再去查询mysql
        user = (User) redisTemplate.opsForValue().get(key);

        if(user == null)
        {
            //2 redis里面无,继续查询mysql
            user = userMapper.selectByPrimaryKey(id);
            if(user == null)
            {
                //3.1 redis+mysql 都无数据
                //你具体细化,防止多次穿透,我们规定,记录下导致穿透的这个key回写redis
                return user;
            }else{
                //3.2 mysql有,需要将数据写回redis,保证下一次的缓存命中率
                redisTemplate.opsForValue().set(key,user);
            }
        }
        return user;
    }
}

6、Controller

package com.feng.docker_boot.controller;

import cn.hutool.core.util.IdUtil;
import com.feng.docker_boot.pojo.User;
import com.feng.docker_boot.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Random;

/**
 * @author Hey!boy
 * @createDate 2023-02-02 18:30:33
 */
@Api(description = "用户User接口")
@RestController
@Slf4j
public class UserController {
    @Resource
    private UserService userService;

    @ApiOperation("数据库新增3条记录")
    @RequestMapping(value = "/user/add", method = RequestMethod.POST)
    public void addUser() {
        for (int i = 1; i <= 3; i++) {
            User user = new User();

            user.setUsername("guai" + i);
            user.setPassword(IdUtil.simpleUUID().substring(0, 6));
            //这个就是两个整数随机,也就是 0 和 1
            user.setSex((byte) new Random().nextInt(2));

            userService.addUser(user);
        }
    }

    @ApiOperation("查询1条记录")
    @RequestMapping(value = "/user/find/{id}", method = RequestMethod.GET)
    public User findUserById(@PathVariable Integer id) {
        return userService.findUserById(id);
    }
}

6、打 Jar 包上传服务器,编写 DockerFile

在这里插入图片描述

上传到服务器的/mydocker目录

在这里插入图片描述
DockerFile

# 基础镜像使用java
FROM java:8
# 作者
MAINTAINER guai
# VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
# 将jar包添加到容器中并更名为guai_docker.jar
ADD docker_boot-0.0.1-SNAPSHOT.jar guai_docker.jar
# 运行jar包
RUN bash -c 'touch /guai_docker.jar'
ENTRYPOINT ["java","-jar","/guai_docker.jar"]
#暴露6001端口作为微服务
EXPOSE 6001 

7、构建镜像

docker build -t guai_docker:1.6 .

在这里插入图片描述
在这里插入图片描述

二、不用Compose的情况下

要一个个启动我们需要的服务实例

启动Mysql容器实例,并且进入实例进行数据库表的构建

docker run -p 3306:3306 --name mysql57 --privileged=true -v /guai/mysql/conf:/etc/mysql/conf.d -v /guai/mysql/logs:/logs -v /guai/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
create database db01;
use db01;

CREATE TABLE `t_user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL DEFAULT '' COMMENT '用户名',
  `password` varchar(50) NOT NULL DEFAULT '' COMMENT '密码',
  `sex` tinyint(4) NOT NULL DEFAULT '0' COMMENT '性别 0=女 1=男 ',
  `deleted` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '删除标志,默认0不删除,1删除',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户表'

创建redis实例

docker run  -p 6380: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

启动项目实例

docker run -d -p 6001:6001 guai_docker:1.6

通过Swagger测试

http://你的IP:你的微服务端口/swagger-ui.html#/

成功

在这里插入图片描述

问题

  • 先后顺序要求固定,先mysql+redis才能微服务访问成功
  • 多个run命令,比较繁琐
  • 容器间的启停或宕机,有可能导致IP地址对应的容器实例变化,映射出错,
    要么生产IP写死(可以但是不推荐),要么通过服务调用

三、使用Compose

1、编写docker-compose.yml文件

# docker-compose文件版本号
version: "3"
# 配置各个容器服务 
services:
  microService:
    image: guai_docker:1.6
    container_name: ms01  # 容器名称,如果不指定,会生成一个服务名加上前后缀的容器名
    ports:
      - "6001:6001"
    volumes:
      - /app/microService:/data
    networks: 
      - guai_net 
    depends_on: # 配置该容器服务所依赖的容器服务
      - redis
      - mysql
 
  redis:
    image: redis:6.0.8
    ports:
      - "6379:6379"
    volumes:
      - /app/redis/redis.conf:/etc/redis/redis.conf
      - /app/redis/data:/data
    networks: 
      - guai_net
    command: redis-server /etc/redis/redis.conf
 
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: '123456'
      MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
      MYSQL_DATABASE: 'db2023'
      MYSQL_USER: 'guai'
      MYSQL_PASSWORD: 'guai123'
    ports:
       - "3306:3306"
    volumes:
       - /app/mysql/db:/var/lib/mysql
       - /app/mysql/conf/my.cnf:/etc/my.cnf
       - /app/mysql/init:/docker-entrypoint-initdb.d
    networks:
      - guai_net
    command: --default-authentication-plugin=mysql_native_password #解决外部无法访问

# 自定义 docker 网络 
networks: 
   guai_net: 

3、修改项目配置文件重新打Jar包

因为上面的compose配置文件里使用了同一个自定义的docker网络,所以可以不用IP地址进行访问服务,直接通过服务名来进行访问,所以修改yaml配置文件的mysql以及redis地址

server.port=6001
# ========================alibaba.druid相关配置=====================
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#spring.datasource.url=jdbc:mysql://你的IP:3306/db01?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.url=jdbc:mysql://mysql:3306/db2023?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.druid.test-while-idle=false
# ========================redis相关配置=====================
spring.redis.database=0
#spring.redis.host=你的IP
spring.redis.host=redis
spring.redis.port=6380
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相关配置===================
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.feng.docker_boot.pojo
# ========================swagger=====================
spring.swagger2.enabled=true

打Jar包上传,注意自己的端口要和compose的一样

在这里插入图片描述

编写Dockerfile(这个没有变化,所以不需要改)

删除原有的镜像重新构建

docker build -t guai_docker:1.6 .

在这里插入图片描述

3、执行Compose

# 检查配置,有问题才有输出
dokcer-compose config -q 
# 启动所有docker-compose服务并后台运行
docker-compose up -d
# 或者
docker-compose up 

在这里插入图片描述

4、进入mysql容器实例并新建库db2023以及新建表t_user

docker exec -it 容器实例id /bin/bash

mysql -uroot -p
create database db2023;
use db2023;

CREATE TABLE `t_user` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `username` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '用户名',
  `password` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '密码',
  `sex` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '性别 0=女 1=男 ',
  `deleted` TINYINT(4) UNSIGNED NOT NULL DEFAULT '0' COMMENT '删除标志,默认0不删除,1删除',
  `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

这里之前compose配置文件设置了db2023,所以db2023已经存在了。不需要创建,或者之前的数据卷已经存在了就可以直接用

在这里插入图片描述

5、测试

插入数据

在这里插入图片描述

Mysql

在这里插入图片描述

redis

在这里插入图片描述

查询数据

在这里插入图片描述

6、停止容器

docker-compose stop 

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/196790.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3.SQL

梳理 名词解释 视图&#xff1a;视图是一个虚表&#xff0c;其本质就是一条SELECT语句&#xff0c;而查询结果被赋予了一个名字&#xff0c;也即视图名字。或者说视图本身不包含任何数据&#xff0c;它只包含映射到基表的一个查询语句&#xff0c;当基表数据发生变化时&#x…

【JavaGuide面试总结】Spring篇·中

【JavaGuide面试总结】Spring篇中1.谈谈自己对于 AOP 的了解2.Spring AOP 和 AspectJ AOP 有什么区别&#xff1f;3.AspectJ 定义的通知类型有哪些&#xff1f;4.Spring AOP多个切面的执行顺序如何控制&#xff1f;5.说说自己对于 Spring MVC 了解?6.Spring MVC 的核心组件有哪…

企业数字化转型的五大关键要素

数字化转型是顺应新一轮科技革命和产业变革趋势&#xff0c;不断深化应用云计算、大数据、物联网、人工智能、区块链等新一代信息技术&#xff0c;激发数据要素创新驱动潜能&#xff0c;打造提升信息时代生存和发展能力&#xff0c;加速业务优化升级和创新转型&#xff0c;改造…

软测(概念) · 开发模型 · 软件的生命周期 · 瀑布模型 · 螺线模型 · 增量模型 · 迭代模型 · 敏捷模型 · scrum

一、开发模型的由来二、软件的生命周期三、瀑布模型&#xff08;Waterfall Model&#xff09;四、螺线模型&#xff08;Spiral Model&#xff09;五、增量模型&#xff08;Incremental Model&#xff09;六、迭代模型&#xff08;Rational UnifiedProcess&#xff09;七、敏捷模…

daz ue和maya插件配置

daz ue插件配置用这个插件方便导入材质&#xff0c;毕竟材质球还是挺多的我安装的时候DAZ Install Manager需要定位&#xff0c;没成功就直接用dll放在daz安装里面也可以直接用&#xff0c;daz ue插件放在插件目录daz maya2022插件配置首先用DAZ Install Manager安装daz maya插…

进程间通信之共享内存(简单介绍消息队列和信号量)

进程间通信之共享内存system V共享内存共享内存示意图常见的共享内存操作共享内存数据结构共享内存函数消息队列信号量&#x1f4cc;————本章重点————&#x1f4cc; &#x1f517;基本掌握system V共享内存的使用方法 &#x1f517;了解消息队列&#x1f517;了解信号量…

vue v-model的详细介绍

v-model是什么&#xff1f; v-model 是Vue框架的一种内置的API指令&#xff0c;本质是一种语法糖写法。它负责监听用户的输入事件以更新数据&#xff0c;并对一些极端场景进行一些特殊处理 为什么使用v-model&#xff1f; v-model指令可以在表单input、textarea以及select元素上…

Power BI中如何实现移动平均功能

一、移动平均 移动平均&#xff0c;是一种常用的统计分析方法&#xff0c;它是指将一定时间范围内的数据&#xff0c;按一定的时间间间隔进行计算平均&#xff0c;然后将平均值形成一条折线。常用的时间间隔有10天、20天、30天、60天等。 当原数据折线图波动比较大时&#xff…

利用GPAC生成MP4文件

GPAC主要针对学生和内容创作者&#xff0c;代表了一个跨平台的多媒体框架&#xff0c;开发人员可以使用它在 LGPL 许可下制作开源媒体。GPAC多媒体框架兼容范围广泛的流行文件类型&#xff0c;从常见格式(如 AVI、MPEG 和 MOV)到复杂格式(如 MPEG-4 系统或 VRML/X3D)和 360 电影…

哈工大机器学习复习笔记(二)

本篇文章是在参考西瓜书、PPT课件、网络上相关博客等资料的基础上整理出的机器学习复习笔记&#xff0c;希望能给大家的机器学习复习提供帮助。这篇笔记只是复习的一个参考&#xff0c;大家一定要结合书本、PPT来进行复习&#xff0c;有些公式的推导最好能够自己演算一遍。由于…

JVM结构 类加载

类加载 类加载子系统 类加载器子系统负责从文件系统或者网络中加载class文件。classLoadr只负责class文件的加载&#xff0c;至于它是否可以运行&#xff0c;则由Exception Engine&#xff08;执行引擎&#xff09;决定。加载类的信息存放于一块成为方法区的内存空间 class fi…

【GPLT 二阶题目集】L2-007 家庭房产

给定每个人的家庭成员和其自己名下的房产&#xff0c;请你统计出每个家庭的人口数、人均房产面积及房产套数。 输入格式&#xff1a; 输入第一行给出一个正整数N&#xff08;≤1000&#xff09;&#xff0c;随后N行&#xff0c;每行按下列格式给出一个人的房产&#xff1a; 编号…

Java创建线程的七种方法,全网最全面总结~

目录 前言 一、继承Thread&#xff0c;重写run方法 二、实现Runnable接口&#xff0c;重写run方法 三、使用匿名内部类创建 Thread 子类对象 四、使用匿名内部类&#xff0c;实现Runnable接口 五、lambda表达式 六、实现Callable接口 七、使用线程池创建线程 前言 属于基…

末端工具重力辨识

辨识工具重力 法一&#xff1a;6点标定 已知&#xff0c;工件重力在世界坐标系的大小为{0,0,−G}\{0,0,-G\}{0,0,−G},假设工件重心在工具坐标系下的坐标为 {Lx,Ly,Lz}\{L_x,L_y,L_z\}{Lx​,Ly​,Lz​}&#xff0c;重力在工件的三个坐标轴分量为 {Gx,Gy,Gz}\{G_x,G_y,G_z\}{G…

Docker安装MySQL8数据库

&#x1f388; 作者&#xff1a;互联网-小啊宇 &#x1f388; 简介&#xff1a; CSDN 运维领域创作者、阿里云专家博主。目前从事 Kubernetes运维相关工作&#xff0c;擅长Linux系统运维、开源监控软件维护、Kubernetes容器技术、CI/CD持续集成、自动化运维、开源软件部署维护…

为什么要拒绝嵌套代码?

linux 内核的最早作者 linus torvalds 在 linux 内核样式指南 第一节中提到&#xff1a; if you need more than 3 levels of indentation, you’re screwed anyway, and should fix your program. 如果你需要超过3级的缩进&#xff0c;你无论如何都搞砸了&#xff0c;应该修复…

ABBYY15免费照片识别文字识别软件

照片识别文字的软件有哪些&#xff1f;在日常的工作的时候&#xff0c;小伙伴们是不是经常会借助拍摄照片记录一些比较重要的事情或者是一些比较重要的笔记&#xff0c;等回头空闲出来的时候在去整理&#xff0c;那么这时候&#xff0c;如果我们运用好图片识别文字这项技术&…

线性代数篇

主线为花书第二章-线性代数&#xff0c;但其上面一些表述属实费解&#xff0c;于是参考B站3Blue1Brown线性代数和B站同济子豪兄的视频讲解。 先放一句3B1B的话共勉&#xff0c;伙计们不要被数学公式吓到&#xff0c;慢慢钻研&#xff0c;慢慢推肯定能学懂。线性代数这一部分相信…

cannot redeclare block-scoped variable

使用 Vue3.0 的时在模块类中声明方法的时候抛出了如下的异常:cannot redeclare block-scoped variable解决办法检查是否集成了 Vetur 插件,若存在禁用或卸载即可,该插件Vue3.0 的时候会冲突;Vue3.0 集成如下两款即可:名称: TypeScript Vue Plugin (Volar)ID: Vue.vscode-typesc…

Qt 自定义控件 带UI 不带 UI

一般自定义控件原因 有时Qt 现有控件不能满足我们的开发需求&#xff0c;这时候就需要我们进行自定义控件的使用&#xff0c;自定义控件,这大大提高了设计UI的通用性,程序利用&#xff0c;封装&#xff1b; Part1 easy one 继续 Lab 自定义Label控件&#xff1a;文本太长省略…