美文网首页SpringBoot
Spring Boot的容器化改造

Spring Boot的容器化改造

作者: 樂浩beyond | 来源:发表于2018-05-21 19:28 被阅读246次

Spring Boot的容器化改造

目前最流行的容器引擎:Docker,微服务领域最热门的框架Spring Boot, 两强联手会产生什么样的化学反应呢?

最近偶然看到了纯洁的微笑的这篇文章,是一篇不错的入门docker文章,决定自己动手实践一下,纯洁的微笑这篇文章里用的是JPA操作数据库,我这里做了改动,用的是MyBatis框架操作数据库,docker-compose 文件也做了改动,这篇文章会把自己遇到的坑记录下来。文末会给出整个项目地址。

Spring Boot

使用Spring Boot 搭建一个web服务,在数据库中记录每个访问者的ip 和访问次数,并且返回给前端展示。

依赖包

主要依赖Spring boot web框架、Mysql驱动和MyBatis框架。

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
    </dependencies>

核心代码

Controller 层主要负责对接收到请求进行判断,操作数据库记录ip 和访问次数。

@RestController
public class VisitorController {

    @Autowired
    private VisitorMapper visitorMapper;

    @RequestMapping("/")
    public String index(HttpServletRequest request) {
        String ip=request.getRemoteAddr();
        Visitor visitor = visitorMapper.getOne(ip);

        if(visitor==null){
            visitor=new Visitor();
            visitor.setIp(ip);
            visitor.setTimes(1);
            visitorMapper.insert(visitor);
        }else {
            visitor.setTimes(visitor.getTimes()+1);
            visitorMapper.update(visitor);
        }

        return "I have been seen ip "+visitor.getIp()+" "+visitor.getTimes()+" times.";
    }
}

MyBatis的Mapper 负责操作数据库。

@Mapper
@Component(value = "visitorMapper")
public interface VisitorMapper {

    @Select("SELECT * FROM visitor WHERE ip =#{ip}")
    Visitor getOne(String ip);

    @Update("UPDATE visitor SET ip=#{ip} ,times=#{times} WHERE ip =#{ip}")
    void update(Visitor visitor);

    @Insert("INSERT INTO visitor(ip,times) VALUES(#{ip},#{times})")
    void insert(Visitor visitor);
}

容器化改造

首先看一下目录结构。DockerCompose是Spring Boot的项目工程文件,docker-compose.yaml是描述如何构建服务。nginx 里是关于nginx的配置。mysql 是mount到容器里的文件,下面会具体介绍。

image.png

docker-compose.yaml

docker-compose.yaml 与纯洁的微笑里的文件相比做了些许改动,下面具体说明。

version: '3'
services:
  nginx:
   container_name: v-nginx
   build: ./nginx
   restart: always
   ports:
   - 80:80
   - 443:443
   volumes:
   - ./nginx/conf.d:/etc/nginx/conf.d

  mysql:
   container_name: v-mysql
   image: mysql/mysql-server:5.7
   volumes:
   - ./mysql/data:/var/lib/mysql
   environment:
    MYSQL_DATABASE: test
    MYSQL_ROOT_PASSWORD: root
    MYSQL_ROOT_HOST: '%'
   ports:
   - "3306:3306"
   restart: always

  app:
    restart: always
    build: ./DockerCompose
    working_dir: /DockerCompose
    volumes:
      - ./DockerCompose:/DockerCompose
      - ~/.m2:/root/.m2
    expose:
      - "8080"
    depends_on:
      - nginx
      - mysql
    command: mvn clean spring-boot:run -Dspring-boot.run.profiles=docker

改动一:nginx
在纯洁的微笑里nginx里并没有build: ./nginx,而是直接用image:nginx:1.13基础镜像。

关于build的定义:

服务除了可以基于指定的镜像,还可以基于一份 Dockerfile,在使用 up 启动之时执行构建任务,这个构建标签就是 build,它可以指定 Dockerfile 所在文件夹的路径。

因为nginx:1.13基础镜像并不能满足我的在容器中使用vim命令的需求,所以在这里重新构建了一个镜像。使用apt-get安装vim,可以方便在nginx容器中使用vim命令。

nginx目录下的Dockerfile:


image.png

改动二:mysql
纯洁的微笑在结束运行容器之后,并没有保存数据库中的表,这是因为每次启动容器都会在宿主机中创建一个新的数据卷,所以只要一直是使用同一个数据卷,就不会有数据丢失的问题。可以具体参照这篇文章
关于volumes的定义:

挂载一个目录或者一个已存在的数据卷容器,可以直接使用 [HOST:CONTAINER] 这样的格式

在Spring Boot 项目的同级目录下创建一个mysql/data目录,挂载完成之后,进入data目录,可以看到有test目录对应到数据库中的test

image.png

进入到test目录中,看到visitor命名的文件,就是对应到数据库中visitor表,这两种后缀是InnoDB引擎的存储方式。

image.png
除了上面两处改动,其他关键字的说明如下:
  • version: '3': 表示使用第三代语法来构建 docker-compose.yaml 文件。
  • services: 用来表示 compose 需要启动的服务,我们可以看出此文件中有三个服务分别为:nginx、mysql、app。
  • container_name: 容器名称
  • environment: 此节点下的信息会当作环境变量传入容器,此示例中 mysql 服务配置了数据库、密码和权限信息。
  • ports: 表示对外开放的端口
  • restart: always 表示如果服务启动不成功会一直尝试。
  • volumes: 加载本地目录下的配置文件到容器目标地址下
  • depends_on:可以配置依赖服务,表示需要先启动 depends_on 下面的服务后,再启动本服务。
  • command: mvn clean spring-boot:run -Dspring-boot.run.profiles=docker: 表示以这个命令来启动项目,-Dspring-- boot.run.profiles=docker表示使用 application-docker.properties文件配置信息进行启动。

docker compose 的书写规则可以参照Docker Compose 配置文件详解

Nginx配置

Nginx没有改动,需要注意的一点是proxy_pass http://app:8080这块要使用app,必须要和compose中的service 名称对应。不熟悉Nginx配置的同学可以参考Nginx配置文章

server {
        listen 80;
        charset utf-8;
        access_log off;

        location / {
        proxy_pass http://app:8080;
        proxy_set_header Host $host:$server_port;
        proxy_set_header X-Forwarded-Host $server_name;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        location /static {
        access_log   off;
        expires      30d;

        alias /app/static;
    }
}

部署与运行

docker-compose up -d:以后端运行的方式启动容器

image.png

docker ps:查看正在运行的所有容器

image.png

docker-compose down: 关闭项目中的所有容器

image.png

运行结果:


image.png

总结

使用Docker可以解决部署中的环境问题,不必再去一个个安装配置Mysql 、Nginx,安装配置完在和Spring Boot联调,非常麻烦。写个docker-compose.yaml文件,docker会帮你搞定这一切。即使是部署新的一个环境,docker也能帮你完美的避开安装配置的坑。


示例代码:GitHub地址

相关文章

网友评论

    本文标题:Spring Boot的容器化改造

    本文链接:https://www.haomeiwen.com/subject/bomqjftx.html