0


DockerCompose - 微服务项目部署全过程(最佳实践)

一、微服务项目部署


1.1、项目介绍

a)技术选型:SpringCloud 2021.0.1 、SpringCloud Alibaba 2021.0.1.0、SpringBoot 2.6.3、Docker & DockerCompose、JDK 17.

b)软件环境:MySQL、Nacos.

c)服务拆分:blog、user、gateway.

d)其他模块:common(公共模块)、OpenFeign.

e)父项目 pom.xml 配置:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>com.cyk</groupId>
  7. <artifactId>cloud_blog</artifactId>
  8. <version>1.0-SNAPSHOT</version>
  9. <packaging>pom</packaging>
  10. <modules>
  11. <module>user</module>
  12. <module>blog</module>
  13. <module>openfeign</module>
  14. <module>common</module>
  15. <module>gateway</module>
  16. </modules>
  17. <parent>
  18. <groupId>org.springframework.boot</groupId>
  19. <artifactId>spring-boot-starter-parent</artifactId>
  20. <version>2.6.3</version>
  21. <relativePath/> <!-- lookup parent from repository -->
  22. </parent>
  23. <properties>
  24. <java.version>17</java.version>
  25. <mybatis-spring-boot.version>2.3.1</mybatis-spring-boot.version>
  26. <mysql.version>5.1.49</mysql.version>
  27. <spring-cloud.version>2021.0.1</spring-cloud.version>
  28. <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
  29. </properties>
  30. <!--维护依赖-->
  31. <dependencyManagement>
  32. <dependencies>
  33. <!-- spring-cloud -->
  34. <dependency>
  35. <groupId>org.springframework.cloud</groupId>
  36. <artifactId>spring-cloud-dependencies</artifactId>
  37. <version>${spring-cloud.version}</version>
  38. <type>pom</type>
  39. <scope>import</scope>
  40. </dependency>
  41. <!-- spring-cloud-alibaba -->
  42. <dependency>
  43. <groupId>com.alibaba.cloud</groupId>
  44. <artifactId>spring-cloud-alibaba-dependencies</artifactId>
  45. <version>${spring-cloud-alibaba.version}</version>
  46. <type>pom</type>
  47. <scope>import</scope>
  48. </dependency>
  49. <!--mybatis-->
  50. <dependency>
  51. <groupId>org.mybatis.spring.boot</groupId>
  52. <artifactId>mybatis-spring-boot-starter</artifactId>
  53. <version>${mybatis-spring-boot.version}</version>
  54. </dependency>
  55. <!--mysql-->
  56. <dependency>
  57. <groupId>mysql</groupId>
  58. <artifactId>mysql-connector-java</artifactId>
  59. <version>${mysql.version}</version>
  60. </dependency>
  61. <!--spring-boot-test-->
  62. <dependency>
  63. <groupId>org.springframework.boot</groupId>
  64. <artifactId>spring-boot-starter-test</artifactId>
  65. <scope>test</scope>
  66. </dependency>
  67. <!--mybatis-test-->
  68. <dependency>
  69. <groupId>org.mybatis.spring.boot</groupId>
  70. <artifactId>mybatis-spring-boot-starter-test</artifactId>
  71. <version>${mybatis-spring-boot.version}</version>
  72. <scope>test</scope>
  73. </dependency>
  74. </dependencies>
  75. </dependencyManagement>
  76. </project>

Ps:麻雀虽小,五脏俱全~ 如果还有其他中间件(RabbitMQ、ES......)需要部署,如果人不是小傻瓜,都能配出来~

1.2、准备 MySQL 初始化文件

a)当我们把项目部署到云服务上之后,数据库可能是空的,因此强烈建议提前编写好 SQL 文件,之后就可以通过 docker-compose.yml 的 volumes 映射 docker 的 mysql 初始化脚本文件,完成初始化操作.

b)db.sql 文件如下

  1. create database if not exists demo;
  2. use demo;
  3. drop table if exists user;
  4. create table user (
  5. id bigint primary key auto_increment comment '自增主键id',
  6. username varchar(20) not null unique comment '用户名',
  7. password varchar(20) not null comment '密码',
  8. create_time datetime default now() comment '创建时间',
  9. update_time datetime default now() comment '修改时间'
  10. );
  11. drop table if exists blog;
  12. create table blog (
  13. id bigint primary key auto_increment comment '自增主键',
  14. userId bigint not null comment '用户id',
  15. title varchar(32) not null comment '标题',
  16. content varchar(256) not null comment '正文',
  17. read_count bigint default 0 comment '阅读量',
  18. create_time datetime default now() comment '创建时间',
  19. update_time datetime default now() comment '修改时间'
  20. );
  21. insert into user(username, password) values('cyk', '1111');
  22. insert into blog(userId ,title, content) values(1, '今天真开心', '今天真开行啊,我要好好学习,然后晚上出去玩!');

c)docker 根据别名创建目录默认在 /var/lib/docker/volumes/ 中,因此可以在此目录创建一个 mysql-init 文件夹(将来 docker-compose 文件需要挂载的宿主机数据卷),在将 db.sql 文件放入该文件夹中即可.

  1. mysql-init pwd
  2. /var/lib/docker/volumes/mysql-init
  3. mysql-init ll
  4. 总用量 4.0K
  5. -rw-r--r--. 1 root root 1.1K 1 13 22:23 db.sql
  6. mysql-init cat db.sql
  7. create database if not exists demo;
  8. use demo;
  9. drop table if exists user;
  10. create table user (
  11. id bigint primary key auto_increment comment '自增主键id',
  12. username varchar(20) not null unique comment '用户名',
  13. password varchar(20) not null comment '密码',
  14. create_time datetime default now() comment '创建时间',
  15. update_time datetime default now() comment '修改时间'
  16. );
  17. drop table if exists blog;
  18. create table blog (
  19. id bigint primary key auto_increment comment '自增主键',
  20. userId bigint not null comment '用户id',
  21. title varchar(32) not null comment '标题',
  22. content varchar(256) not null comment '正文',
  23. read_count bigint default 0 comment '阅读量',
  24. create_time datetime default now() comment '创建时间',
  25. update_time datetime default now() comment '修改时间'
  26. );
  27. insert into user(username, password) values('cyk', '1111');
  28. insert into blog(userId ,title, content) values(1, '今天真开心', '今天真开行啊,我要好好学习,然后晚上出去玩!');

1.3、pom.xml 插件

所有需要运行的微服务都需要有这个插件(父工程不需要任何插件),否则找不到程序入口,没法编译运行(如下图).

插件如下:

  1. <build>
  2. <plugins>
  3. <plugin>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-maven-plugin</artifactId>
  6. </plugin>
  7. </plugins>
  8. </build>

1.4、测试工作

强烈建议,先把需要运行的微服务的 jar 包,都在本地通过 java -jar 运行一下,检查是否能运行成功,这是一个好习惯~

1.5、编写 Dockerflie 文件

a)user 微服务

  1. FROM openjdk:17
  2. # 指定容器工作目录为 apps
  3. WORKDIR /apps
  4. EXPOSE 9090
  5. # 将宿主机上的 ./user-1.0-SNAPSHOT.jar 文件拷贝到容器的工作目录下,并改名为 user.jar
  6. COPY ./user-1.0-SNAPSHOT.jar ./user.jar
  7. # --spring.profiles.active=prod 表示按照 application-prod.yml 配置文件加载
  8. ENTRYPOINT ["java", "-jar", "user.jar", "--spring.profiles.active=prod"]

b)blog 微服务

  1. FROM openjdk:17
  2. # 指定容器工作目录为 apps
  3. WORKDIR /apps
  4. # 将宿主机上的 ./blog-1.0-SNAPSHOT.jar 文件拷贝到容器的工作目录下,并改名为 blog.jar
  5. COPY blog-1.0-SNAPSHOT.jar blog.jar
  6. EXPOSE 9091
  7. # --spring.profiles.active=prod 表示按照 application-prod.yml 配置文件加载
  8. ENTRYPOINT ["java", "-jar", "/apps/blog.jar", "--spring.profiles.active=prod"]

c)gateway 微服务

  1. FROM openjdk:17
  2. # 指定容器工作目录为 apps
  3. WORKDIR /apps
  4. # 将宿主机上的 ./gateway-1.0-SNAPSHOT.jar 文件拷贝到容器的工作目录下,并改名为 gateway.jar
  5. COPY ./gateway-1.0-SNAPSHOT.jar ./gateway.jar
  6. EXPOSE 10010
  7. # --spring.profiles.active=prod 表示按照 application-prod.yml 配置文件加载
  8. ENTRYPOINT ["java", "-jar", "gateway.jar", "--spring.profiles.active=prod"]

1.6、编写 DockerCompose.yml 文件

a)强烈建议:学过 DockerCompose 的朋友可能都知道有个配置叫做 "depends_on",可以指定容器的启动顺序,但是并不能指定谁先启动完成!!! 是不稳定的!!!因此强烈建议编写两个 DockerCompose 文件,一个是 docker-compose.env.yml(运行必备环境),另一个是 docker-compose.service.yml(微服务),部署的时候只需要启动 env,完成后再启动 service 即可.

b)docker-compose.env.yml 文件如下:

  1. version: "3"
  2. networks:
  3. blog_net:
  4. volumes:
  5. data:
  6. init:
  7. services:
  8. nacos:
  9. image: nacos/nacos-server:1.4.2
  10. ports:
  11. - "8848:8848"
  12. environment:
  13. - "MODE=standalone"
  14. restart: always
  15. networks:
  16. - blog_net
  17. mysql:
  18. image: mysql:5.7
  19. ports:
  20. - "3306:3306"
  21. environment:
  22. - "MYSQL_ROOT_PASSWORD=1111"
  23. volumes:
  24. - /root/cyk/cloud_blog/mysql/data:/var/lib/mysql # 映射数据,防止容器重启丢失数据
  25. - /root/cyk/cloud_blog/mysql/init:/docker-entrypoint-initdb.d
  26. restart: always
  27. networks:
  28. - blog_net

Ps:docker-retrypoint-initdb.d 是 Docker 官方 MySQL 镜像的目录,用于初始化数据库和表,因此通过映射我们配置好的初始化文件 mysql-init,就可以实现自定义初始化数据库和表.

如果需要执行多个脚本文件(sql 文件)来初始化数据库,可以使用以下方法:

  1. 将 sql 文件以数字开头命名,例如 001_create_table.sql、002_insert_data.sql.
  2. 数字小的优先执行.

c)docker-compose.service.yml 文件如下:

  1. version: "3"
  2. networks:
  3. blog_net:
  4. services:
  5. gateway: # 网关
  6. build:
  7. context: ./gateway
  8. dockerfile: Dockerfile
  9. ports:
  10. - "10010:10010"
  11. networks:
  12. - blog_net
  13. blog: # 博客服务
  14. build:
  15. context: ./blog
  16. dockerfile: Dockerfile
  17. ports:
  18. - "9091:9091"
  19. networks:
  20. - blog_net
  21. user: # 用户服务
  22. build:
  23. context: ./user
  24. dockerfile: Dockerfile
  25. ports:
  26. - "9090:9090"
  27. networks:
  28. - blog_net

1.7、修改 application.yml 文件

a)强烈建议:提供两个配置文件,一个处理开发环境,另一个处理生产环境(线上环境). 这样本地测试和线上测试就不用老去修改配置文件,关键不小心还容易改错~

b)例如 user 微服务,当前项目需要修改的就是 nacos 和 mysql 连接地址,都修改为 docker-compose 文件中配置的服务Id 名称即可(前提是配置了 networks 在同一网络下):

开发环境如下

  1. server:
  2. port: 9090
  3. spring:
  4. application:
  5. name: user-server
  6. cloud:
  7. nacos:
  8. server-addr: localhost:8848
  9. datasource:
  10. url: jdbc:mysql://localhost:3306/demo?characterEncoding=utf8&useSSL=false
  11. username: root
  12. password: 1111
  13. driver-class-name: com.mysql.jdbc.Driver
  14. # 时间处理
  15. jackson:
  16. date-format: yyyy-MM-dd
  17. time-zone: GMT+8
  18. # mybatis xml save path
  19. mybatis:
  20. mapper-locations: classpath:mapper/*Mapper.xml
  21. configuration:
  22. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  23. logging:
  24. pattern:
  25. dateformat: HH:mm:ss
  26. level:
  27. com:
  28. cyk: debug

生产环境如下

  1. server:
  2. port: 9090
  3. spring:
  4. application:
  5. name: user-server
  6. cloud:
  7. nacos:
  8. server-addr: nacos:8848
  9. datasource:
  10. url: jdbc:mysql://mysql:3306/demo?characterEncoding=utf8&useSSL=false
  11. username: root
  12. password: 1111
  13. driver-class-name: com.mysql.jdbc.Driver
  14. # 时间处理
  15. jackson:
  16. date-format: yyyy-MM-dd
  17. time-zone: GMT+8
  18. # mybatis xml save path
  19. mybatis:
  20. mapper-locations: classpath:mapper/*Mapper.xml
  21. configuration:
  22. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  23. logging:
  24. pattern:
  25. dateformat: HH:mm:ss
  26. level:
  27. com:
  28. cyk: debug

1.8、打包上传服务器

a)强烈建议:打包前先 clean,避免一些不必要的缓存 class 干扰.

b)打包

b)上传时,建议按服务名称分包,因为每个 Dockerfile 构建成镜像时会把所有工作目录下的所有 Dockerfile 文件都加载一遍,因此不要都放一个目录下,而是分开放.

1.9、微服务,启动!

a)先启动 env 环境容器.

  1. cloud_blog docker-compose -f docker-compose.env.yml up -d
  2. [+] Running 24/24
  3. mysql Pulled 57.7s
  4. 72a69066d2fe Pull complete 31.9s
  5. 93619dbc5b36 Pull complete 31.9s
  6. 99da31dd6142 Pull complete 32.1s
  7. 626033c43d70 Pull complete 32.2s
  8. 37d5d7efb64e Pull complete 32.2s
  9. ac563158d721 Pull complete 36.7s
  10. d2ba16033dad Pull complete 36.7s
  11. 0ceb82207cd7 Pull complete 36.7s
  12. 37f2405cae96 Pull complete 56.7s
  13. e2482e017e53 Pull complete 56.7s
  14. 70deed891d42 Pull complete 56.7s
  15. nacos Pulled 64.8s
  16. 5ad559c5ae16 Pull complete 23.7s
  17. aa9bf71274b4 Pull complete 23.7s
  18. 039d8b3d6a90 Pull complete 62.4s
  19. c96722e52477 Pull complete 62.8s
  20. 93185cc2628e Pull complete 63.6s
  21. 6ddaf1829637 Pull complete 63.8s
  22. af68d9507f36 Pull complete 63.9s
  23. 2684f86bd7ff Pull complete 63.9s
  24. b3c841104577 Pull complete 63.9s
  25. a0643cc92b59 Pull complete 63.9s
  26. a6a1256662e3 Pull complete 63.9s
  27. [+] Running 5/5
  28. Network cloud_blog_blog_net Created 0.1s
  29. Volume "cloud_blog_mysqlData" Created 0.0s
  30. Volume "cloud_blog_mysql-init" Created 0.0s
  31. Container cloud_blog-mysql-1 Started 1.3s
  32. Container cloud_blog-nacos-1 Started 1.2s

b)启动 service 服务容器

  1. cloud_blog docker-compose -f docker-compose.service.yml up -d
  2. [+] Building 44.8s (18/18) FINISHED
  3. => [cloud_blog_user internal] load .dockerignore 0.0s
  4. => => transferring context: 2B 0.0s
  5. => [cloud_blog_blog internal] load .dockerignore 0.0s
  6. => => transferring context: 2B 0.0s
  7. => [cloud_blog_gateway internal] load build definition from Dockerfile 0.0s
  8. => => transferring dockerfile: 511B 0.0s
  9. => [cloud_blog_gateway internal] load .dockerignore 0.0s
  10. => => transferring context: 2B 0.0s
  11. => [cloud_blog_user internal] load build definition from Dockerfile 0.0s
  12. => => transferring dockerfile: 491B 0.0s
  13. => [cloud_blog_blog internal] load build definition from Dockerfile 0.0s
  14. => => transferring dockerfile: 499B 0.0s
  15. => [cloud_blog_blog internal] load metadata for docker.io/library/openjdk:17 16.3s
  16. => [cloud_blog_blog 1/3] FROM docker.io/library/openjdk:17@sha256:74bad65c9e59d6410bdd67d71a14e14175ddd33d654419ecfabf03ddbe70fff4 27.6s
  17. => => resolve docker.io/library/openjdk:17@sha256:74bad65c9e59d6410bdd67d71a14e14175ddd33d654419ecfabf03ddbe70fff4 0.0s
  18. => => sha256:74bad65c9e59d6410bdd67d71a14e14175ddd33d654419ecfabf03ddbe70fff4 1.29kB / 1.29kB 0.0s
  19. => => sha256:ab43cabb2140ecf2fc1b32b4981ead56960a59e5b64f742ad30ada7e47bb8870 954B / 954B 0.0s
  20. => => sha256:5f94f53bbced4225dbe770cd98834716ed540315bf131b38a648378c418a6012 4.45kB / 4.45kB 0.0s
  21. => => sha256:155aced2666332ddff5a741b0236f360820e7aa3fc3dde2224fc17a91fc48db6 42.11MB / 42.11MB 15.0s
  22. => => sha256:ac5901c58ecb29b61159b5e3a63dfbb0fb520b2de1d33c9fb038d9b697e3fcd4 13.52MB / 13.52MB 7.6s
  23. => => sha256:6b1076e441ffb58eee60f1bab40db6ca69a01e33346eff212eac1191e6b754bd 187.17MB / 187.17MB 23.7s
  24. => => extracting sha256:155aced2666332ddff5a741b0236f360820e7aa3fc3dde2224fc17a91fc48db6 2.4s
  25. => => extracting sha256:ac5901c58ecb29b61159b5e3a63dfbb0fb520b2de1d33c9fb038d9b697e3fcd4 0.6s
  26. => => extracting sha256:6b1076e441ffb58eee60f1bab40db6ca69a01e33346eff212eac1191e6b754bd 3.9s
  27. => [cloud_blog_gateway internal] load build context 1.0s
  28. => => transferring context: 37.22MB 1.0s
  29. => [cloud_blog_blog internal] load build context 1.1s
  30. => => transferring context: 42.58MB 1.1s
  31. => [cloud_blog_user internal] load build context 0.9s
  32. => => transferring context: 42.58MB 0.9s
  33. => [cloud_blog_gateway 2/3] WORKDIR /apps 0.2s
  34. => [cloud_blog_blog 3/3] COPY blog-1.0-SNAPSHOT.jar blog.jar 0.5s
  35. => [cloud_blog_gateway 3/3] COPY ./gateway-1.0-SNAPSHOT.jar ./gateway.jar 0.5s
  36. => [cloud_blog_user 3/3] COPY ./user-1.0-SNAPSHOT.jar ./user.jar 0.5s
  37. => [cloud_blog_user] exporting to image 0.1s
  38. => => exporting layers 0.1s
  39. => => writing image sha256:c339d5ec9b3dc9cb81d033b31eafab456e534527923f5df7c479e4e383d19c28 0.0s
  40. => => naming to docker.io/library/cloud_blog_user 0.0s
  41. => [cloud_blog_gateway] exporting to image 0.1s
  42. => => exporting layers 0.1s
  43. => => writing image sha256:b06ecc27be3690c5d345bd042143ca7d72cf1e55f165e46678f92ea2bc39914b 0.0s
  44. => => naming to docker.io/library/cloud_blog_gateway 0.0s
  45. => [cloud_blog_blog] exporting to image 0.1s
  46. => => exporting layers 0.1s
  47. => => writing image sha256:75d36043551d0200ab71694078530806f3b5846e03551f06042771597bb07179 0.0s
  48. => => naming to docker.io/library/cloud_blog_blog 0.0s
  49. WARN[0044] Found orphan containers ([cloud_blog-nacos-1 cloud_blog-mysql-1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.
  50. [+] Running 3/3
  51. Container cloud_blog-blog-1 Started 0.9s
  52. Container cloud_blog-user-1 Started 0.8s
  53. Container cloud_blog-gateway-1 Started 0.8s
  54. cloud_blog docker ps -a
  55. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  56. af78c01da9fd cloud_blog_user "java -jar user.jar …" 50 seconds ago Up 48 seconds 0.0.0.0:9090->9090/tcp, :::9090->9090/tcp cloud_blog-user-1
  57. 9b1e12367d13 cloud_blog_gateway "java -jar gateway.j…" 50 seconds ago Up 48 seconds 0.0.0.0:10010->10010/tcp, :::10010->10010/tcp cloud_blog-gateway-1
  58. 74a33d6ecd62 cloud_blog_blog "java -jar /apps/blo…" 50 seconds ago Up 48 seconds 0.0.0.0:9091->9091/tcp, :::9091->9091/tcp cloud_blog-blog-1
  59. 32c9be5f7372 nacos/nacos-server:1.4.2 "bin/docker-startup.…" About a minute ago Up About a minute 0.0.0.0:8848->8848/tcp, :::8848->8848/tcp cloud_blog-nacos-1
  60. 74830ac95115 mysql:5.7 "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp cloud_blog-mysql-1

c)注意:如果在此过程中,操作失误了,例如上传了错误的 jar 包,并且还运行过了,但你知道他是错误的,接着你重新上传 jar 包.

此时!!!一定要执行一次 build 命令重新构建!!!否则执行的还是旧的 jar 包(docker 会把执行执行过的容器的镜像保存下载,下次执行会直接通过之前运行过的镜像来运行)

例如是 service 容器中的 jar 重新上传了,那么就执行以下指令重新构建,之后再运行即可.

  1. docker-compose -f docker-compose.service.yml build

1.10、测试结果

通过网关访问以下:

标签: 微服务 java 架构

本文转载自: https://blog.csdn.net/CYK_byte/article/details/135491845
版权归原作者 陈亦康 所有, 如有侵权,请联系我们删除。

“DockerCompose - 微服务项目部署全过程(最佳实践)”的评论:

还没有评论