spring-boot使用maven构建docker镜像(多服务)

系列:
spring-boot使用maven构建docker镜像(单服务)
spring-boot使用maven构建docker镜像(单服务+MySQL)
spring-boot使用maven构建docker镜像(多服务)

多服务 构建docker镜像 + 运行

使用Dockerfile构建镜像,使用docker-compose.yml定义多个容器的启动参数

前提:

  • 开启docker远程管理端口(此案例演示暂不考虑安全问题,直接开启2375端口)
    参考链接:[…]

示例项目

项目模拟一般的分布式项目,有多个服务(用户服务、订单服务)还有数据库(MySQL)。

项目结构
在这里插入图片描述
实现方式
分别构建每个服务的镜像,通过统一管理模块(或父模块)编写docker-compose.yml管理多个服务容器的启停。

正文

1. 编写每个服务的 Dockerfile(基本相同)

Dockerfile官方文档:https://docs.docker.com/engine/reference/builder/

FROM openjdk:8-jdk-alpine
ADD *.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-Duser.timezone=GMT+08", "-jar", "/app.jar"]

2. 每个服务的 pom.xml 引入 io.fabric8/docker-maven-plugin 插件(基本相同)

io.fabric8/docker-maven-plugin官方文档:http://dmp.fabric8.io/

<plugin>
    <groupId>io.fabric8</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.33.0</version>
    <configuration>
        <verbose>true</verbose>
        <!-- docker远程管理url -->
        <dockerHost>tcp://192.168.121.129:2375</dockerHost>
        <images>
            <image>
                <!-- 镜像名称 -->
                <name>${project.artifactId}:${project.version}</name>
                <build>
                    <!-- 使用Dockerfile定义镜像构建流程 -->
                    <dockerFile>${project.basedir}/src/main/docker/Dockerfile</dockerFile>
                    <assembly>
                        <name>/</name>
                        <!-- artifact是预定义的值,表示将项目打包后的jar拷贝到编译上下文中,便于Dockerfile ADD指令 -->
                        <descriptorRef>artifact</descriptorRef>
                    </assembly>
                </build>
            </image>
        </images>
    </configuration>
</plugin>

3. 新增一个模块(或用父模块)用来统一管理容器启停,编写 docker-compose.yml

Compose file官方文档:https://docs.docker.com/compose/compose-file/

version: "2"
services:
  database:
    image: mysql:5.7
    ports:
    - 3306:3306
    volumes:
    - /home/mysqldata:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: test-db #默认创建数据库名
    command: ['mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci'] #指定MySQL的编码(覆盖CMD指令)
    networks:
      my-custom-network:
        aliases:
        - mysql-server #在同个网络的其他服务可以通过此别名访问此服务

  user-service:
    image: user-service:1.0.0
    ports:
    - 8081:8080
    environment:
      MYSQL_SERVER: mysql-server:3306 #在同个网络,可以通过服务名/别名访问
    depends_on:
    - database
    networks:
      my-custom-network:
        aliases:
        - user-service

  order-service:
    image: order-service:1.0.0
    ports:
    - 8082:8080
    environment:
      MYSQL_SERVER: mysql-server:3306 #在同个网络,可以通过服务名/别名访问
      USER_SERVICE: user-service:8081 #在同个网络,可以通过服务名/别名访问
    depends_on:
    - database
    - user-service
    networks:
      my-custom-network:
        aliases:
        - order-service

networks:
  my-custom-network:
    driver: overlay

4. maven 命令

  • 构建镜像 mvn clean package docker:build
  • 删除镜像 mvn docker:remove
  • 启动容器 mvn docker:run
  • 停止容器(自动删除容器) mvn docker:stop

4.1 一般流程

  1. 在每个服务中执行构建镜像命令 mvn clean package docker:build
  2. 在同一管理模块启动所有服务:mvn docker:run
  3. 在同一管理模块停止所有服务:mvn docker:stop

要点说明

  • 数据库是由MySQL容器拉起时自动创建的。(MYSQL_DATABASE环境变量)
  • 数据库初始化是由Spring框架自动执行SQL脚本功能完成的。(spring.datasource.initialization-mode属性)

后期维护需求

当项目第一次构建镜像运行时,按照上面的流程基本没什么问题。但是,当第二次构建镜像时,可能会有以下需求。

更新项目时,不想销毁MySQL容器,使用已有历史数据

默认情况下,docker:stop,docker:run会操作所有在docker-compose.yml定义的服务。
所以,我们只需要将docker-compose.yml里关于MySQL服务的配置注释掉,这样就不会重新拉起或关闭MySQL容器。(可能还需要将其他服务的 depends_on 注释掉)

version: "2"
services:
  # database:
  #   image: mysql:5.7
  #   ports:
  #   - 3306:3306
  #   volumes:
  #   - /home/mysqldata:/var/lib/mysql
  #   environment:
  #     MYSQL_ROOT_PASSWORD: root
  #     MYSQL_DATABASE: test-db #默认创建数据库名
  #   command: ['mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci'] #指定MySQL的编码(覆盖CMD指令)
  #   networks:
  #     my-custom-network:
  #       aliases:
  #       - mysql-server #在同个网络的其他服务可以通过此别名访问此服务

省略...

还有一点要注意,上文’关键要点’提到,数据库初始化是由Spring框架完成的,所以如果想保留MySQL的历史数据,则要把自动初始化SQL脚本功能关闭。
(设置spring.datasource.initialization-mode = never)

常见问题

2375 端口不通问题排查

  • 是否开启docker远程访问(lsof -i 2375)
  • 是否关闭防火墙(systemctl status firewalld)
    • systemct stop firewalld && systemct disable firewalld //关闭&禁用防火墙

使用插件引用docker-compose.yml文件启动容器的方式和直接使用命令引用docker-compose.yml启动容器是不一样的。

docker swarm init
docker stack deploy -c docker-compose.yml stack-demo

reference:
Docker Compose是什么?
Docker Compose https://docs.docker.com/compose/
Docker Swarm https://docs.docker.com/engine/swarm/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章