Bootstrap

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

目录

一、微服务项目部署

1.1、项目介绍

1.2、准备 MySQL 初始化文件

1.3、pom.xml 插件

1.4、测试工作

1.5、编写 Dockerflie 文件

1.6、编写 DockerCompose.yml 文件

1.7、修改 application.yml 文件

1.8、打包上传服务器

1.9、微服务,启动!

1.10、测试结果


一、微服务项目部署


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 配置:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cyk</groupId>
    <artifactId>cloud_blog</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>user</module>
        <module>blog</module>
        <module>openfeign</module>
        <module>common</module>
        <module>gateway</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <java.version>17</java.version>
        <mybatis-spring-boot.version>2.3.1</mybatis-spring-boot.version>
        <mysql.version>5.1.49</mysql.version>
        <spring-cloud.version>2021.0.1</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
    </properties>

    <!--维护依赖-->
    <dependencyManagement>
        <dependencies>

            <!-- spring-cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- spring-cloud-alibaba -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--mybatis-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis-spring-boot.version}</version>
            </dependency>

            <!--mysql-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>

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

            <!--mybatis-test-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter-test</artifactId>
                <version>${mybatis-spring-boot.version}</version>
                <scope>test</scope>
            </dependency>
        </dependencies>

    </dependencyManagement>

</project>

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

1.2、准备 MySQL 初始化文件

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

b)db.sql 文件如下

create database if not exists demo;

use demo;

drop table if exists user;
create table user (
    id bigint primary key auto_increment comment '自增主键id',
    username varchar(20) not null unique comment '用户名',
    password varchar(20) not null comment '密码',
    create_time datetime default now() comment '创建时间',
    update_time datetime default now() comment '修改时间'
);

drop table if exists blog;
create table blog (
    id bigint primary key auto_increment comment '自增主键',
    userId bigint not null comment '用户id',
    title varchar(32) not null comment '标题',
    content varchar(256) not null comment '正文',
    read_count bigint default 0 comment '阅读量',
    create_time datetime default now() comment '创建时间',
    update_time datetime default now() comment '修改时间'
);

insert into user(username, password) values('cyk', '1111');
insert into blog(userId ,title, content) values(1, '今天真开心', '今天真开行啊,我要好好学习,然后晚上出去玩!');

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

➜  mysql-init pwd
/var/lib/docker/volumes/mysql-init
➜  mysql-init ll   
总用量 4.0K
-rw-r--r--. 1 root root 1.1K 1月  13 22:23 db.sql
➜  mysql-init cat db.sql 
create database if not exists demo;

use demo;

drop table if exists user;
create table user (
    id bigint primary key auto_increment comment '自增主键id',
    username varchar(20) not null unique comment '用户名',
    password varchar(20) not null comment '密码',
    create_time datetime default now() comment '创建时间',
    update_time datetime default now() comment '修改时间'
);

drop table if exists blog;
create table blog (
    id bigint primary key auto_increment comment '自增主键',
    userId bigint not null comment '用户id',
    title varchar(32) not null comment '标题',
    content varchar(256) not null comment '正文',
    read_count bigint default 0 comment '阅读量',
    create_time datetime default now() comment '创建时间',
    update_time datetime default now() comment '修改时间'
);

insert into user(username, password) values('cyk', '1111');
insert into blog(userId ,title, content) values(1, '今天真开心', '今天真开行啊,我要好好学习,然后晚上出去玩!');

1.3、pom.xml 插件

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

插件如下:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

1.4、测试工作

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

1.5、编写 Dockerflie 文件

a)user 微服务

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

b)blog 微服务

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

c)gateway 微服务

FROM openjdk:17
# 指定容器工作目录为 apps
WORKDIR /apps
# 将宿主机上的 ./gateway-1.0-SNAPSHOT.jar 文件拷贝到容器的工作目录下,并改名为 gateway.jar
COPY ./gateway-1.0-SNAPSHOT.jar ./gateway.jar
EXPOSE 10010
# --spring.profiles.active=prod 表示按照 application-prod.yml 配置文件加载
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 文件如下:

version: "3"

networks:
  blog_net:

volumes:
  data:
  init:

services:

  nacos:
    image: nacos/nacos-server:1.4.2
    ports:
      - "8848:8848"
    environment:
      - "MODE=standalone"
    restart: always
    networks:
      - blog_net


  mysql:
    image: mysql:5.7
    ports:
      - "3306:3306"
    environment:
      - "MYSQL_ROOT_PASSWORD=1111"
    volumes:
      - /root/cyk/cloud_blog/mysql/data:/var/lib/mysql # 映射数据,防止容器重启丢失数据
      - /root/cyk/cloud_blog/mysql/init:/docker-entrypoint-initdb.d
    restart: always
    networks:
      - 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 文件如下:

version: "3"


networks:
  blog_net:

services:

  gateway: # 网关
    build:
      context: ./gateway
      dockerfile: Dockerfile
    ports:
      - "10010:10010"
    networks:
      - blog_net

  blog: # 博客服务
    build:
      context: ./blog
      dockerfile: Dockerfile
    ports:
      - "9091:9091"
    networks:
      - blog_net

  user: # 用户服务
    build:
      context: ./user
      dockerfile: Dockerfile
    ports:
      - "9090:9090"
    networks:
      - blog_net

1.7、修改 application.yml 文件

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

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

开发环境如下

server:
  port: 9090

spring:
  application:
    name: user-server
  cloud:
    nacos:
      server-addr: localhost:8848
  datasource:
    url: jdbc:mysql://localhost:3306/demo?characterEncoding=utf8&useSSL=false
    username: root
    password: 1111
    driver-class-name: com.mysql.jdbc.Driver
    # 时间处理
  jackson:
    date-format: yyyy-MM-dd
    time-zone: GMT+8

  # mybatis xml save path
mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

logging:
  pattern:
    dateformat: HH:mm:ss
  level:
    com:
      cyk: debug

生产环境如下

server:
  port: 9090

spring:
  application:
    name: user-server
  cloud:
    nacos:
      server-addr: nacos:8848
  datasource:
    url: jdbc:mysql://mysql:3306/demo?characterEncoding=utf8&useSSL=false
    username: root
    password: 1111
    driver-class-name: com.mysql.jdbc.Driver
    # 时间处理
  jackson:
    date-format: yyyy-MM-dd
    time-zone: GMT+8

  # mybatis xml save path
mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

logging:
  pattern:
    dateformat: HH:mm:ss
  level:
    com:
      cyk: debug

1.8、打包上传服务器

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

b)打包

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

1.9、微服务,启动!

a)先启动 env 环境容器.

➜  cloud_blog docker-compose -f docker-compose.env.yml up -d
[+] Running 24/24
 ⠿ mysql Pulled                                                                                                                            57.7s
   ⠿ 72a69066d2fe Pull complete                                                                                                            31.9s
   ⠿ 93619dbc5b36 Pull complete                                                                                                            31.9s
   ⠿ 99da31dd6142 Pull complete                                                                                                            32.1s
   ⠿ 626033c43d70 Pull complete                                                                                                            32.2s
   ⠿ 37d5d7efb64e Pull complete                                                                                                            32.2s
   ⠿ ac563158d721 Pull complete                                                                                                            36.7s
   ⠿ d2ba16033dad Pull complete                                                                                                            36.7s
   ⠿ 0ceb82207cd7 Pull complete                                                                                                            36.7s
   ⠿ 37f2405cae96 Pull complete                                                                                                            56.7s
   ⠿ e2482e017e53 Pull complete                                                                                                            56.7s
   ⠿ 70deed891d42 Pull complete                                                                                                            56.7s
 ⠿ nacos Pulled                                                                                                                            64.8s
   ⠿ 5ad559c5ae16 Pull complete                                                                                                            23.7s
   ⠿ aa9bf71274b4 Pull complete                                                                                                            23.7s
   ⠿ 039d8b3d6a90 Pull complete                                                                                                            62.4s
   ⠿ c96722e52477 Pull complete                                                                                                            62.8s
   ⠿ 93185cc2628e Pull complete                                                                                                            63.6s
   ⠿ 6ddaf1829637 Pull complete                                                                                                            63.8s
   ⠿ af68d9507f36 Pull complete                                                                                                            63.9s
   ⠿ 2684f86bd7ff Pull complete                                                                                                            63.9s
   ⠿ b3c841104577 Pull complete                                                                                                            63.9s
   ⠿ a0643cc92b59 Pull complete                                                                                                            63.9s
   ⠿ a6a1256662e3 Pull complete                                                                                                            63.9s
[+] Running 5/5
 ⠿ Network cloud_blog_blog_net     Created                                                                                                  0.1s
 ⠿ Volume "cloud_blog_mysqlData"   Created                                                                                                  0.0s
 ⠿ Volume "cloud_blog_mysql-init"  Created                                                                                                  0.0s
 ⠿ Container cloud_blog-mysql-1    Started                                                                                                  1.3s
 ⠿ Container cloud_blog-nacos-1    Started                                                                                                  1.2s

b)启动 service 服务容器

➜  cloud_blog docker-compose -f docker-compose.service.yml up -d
[+] Building 44.8s (18/18) FINISHED                                                                                                              
 => [cloud_blog_user internal] load .dockerignore                                                                                           0.0s
 => => transferring context: 2B                                                                                                             0.0s
 => [cloud_blog_blog internal] load .dockerignore                                                                                           0.0s
 => => transferring context: 2B                                                                                                             0.0s
 => [cloud_blog_gateway internal] load build definition from Dockerfile                                                                     0.0s
 => => transferring dockerfile: 511B                                                                                                        0.0s
 => [cloud_blog_gateway internal] load .dockerignore                                                                                        0.0s
 => => transferring context: 2B                                                                                                             0.0s
 => [cloud_blog_user internal] load build definition from Dockerfile                                                                        0.0s
 => => transferring dockerfile: 491B                                                                                                        0.0s
 => [cloud_blog_blog internal] load build definition from Dockerfile                                                                        0.0s
 => => transferring dockerfile: 499B                                                                                                        0.0s
 => [cloud_blog_blog internal] load metadata for docker.io/library/openjdk:17                                                              16.3s
 => [cloud_blog_blog 1/3] FROM docker.io/library/openjdk:17@sha256:74bad65c9e59d6410bdd67d71a14e14175ddd33d654419ecfabf03ddbe70fff4        27.6s
 => => resolve docker.io/library/openjdk:17@sha256:74bad65c9e59d6410bdd67d71a14e14175ddd33d654419ecfabf03ddbe70fff4                         0.0s
 => => sha256:74bad65c9e59d6410bdd67d71a14e14175ddd33d654419ecfabf03ddbe70fff4 1.29kB / 1.29kB                                              0.0s
 => => sha256:ab43cabb2140ecf2fc1b32b4981ead56960a59e5b64f742ad30ada7e47bb8870 954B / 954B                                                  0.0s
 => => sha256:5f94f53bbced4225dbe770cd98834716ed540315bf131b38a648378c418a6012 4.45kB / 4.45kB                                              0.0s
 => => sha256:155aced2666332ddff5a741b0236f360820e7aa3fc3dde2224fc17a91fc48db6 42.11MB / 42.11MB                                           15.0s
 => => sha256:ac5901c58ecb29b61159b5e3a63dfbb0fb520b2de1d33c9fb038d9b697e3fcd4 13.52MB / 13.52MB                                            7.6s
 => => sha256:6b1076e441ffb58eee60f1bab40db6ca69a01e33346eff212eac1191e6b754bd 187.17MB / 187.17MB                                         23.7s
 => => extracting sha256:155aced2666332ddff5a741b0236f360820e7aa3fc3dde2224fc17a91fc48db6                                                   2.4s
 => => extracting sha256:ac5901c58ecb29b61159b5e3a63dfbb0fb520b2de1d33c9fb038d9b697e3fcd4                                                   0.6s
 => => extracting sha256:6b1076e441ffb58eee60f1bab40db6ca69a01e33346eff212eac1191e6b754bd                                                   3.9s
 => [cloud_blog_gateway internal] load build context                                                                                        1.0s
 => => transferring context: 37.22MB                                                                                                        1.0s
 => [cloud_blog_blog internal] load build context                                                                                           1.1s
 => => transferring context: 42.58MB                                                                                                        1.1s
 => [cloud_blog_user internal] load build context                                                                                           0.9s
 => => transferring context: 42.58MB                                                                                                        0.9s
 => [cloud_blog_gateway 2/3] WORKDIR /apps                                                                                                  0.2s
 => [cloud_blog_blog 3/3] COPY blog-1.0-SNAPSHOT.jar blog.jar                                                                               0.5s
 => [cloud_blog_gateway 3/3] COPY ./gateway-1.0-SNAPSHOT.jar ./gateway.jar                                                                  0.5s
 => [cloud_blog_user 3/3] COPY ./user-1.0-SNAPSHOT.jar ./user.jar                                                                           0.5s
 => [cloud_blog_user] exporting to image                                                                                                    0.1s
 => => exporting layers                                                                                                                     0.1s
 => => writing image sha256:c339d5ec9b3dc9cb81d033b31eafab456e534527923f5df7c479e4e383d19c28                                                0.0s
 => => naming to docker.io/library/cloud_blog_user                                                                                          0.0s
 => [cloud_blog_gateway] exporting to image                                                                                                 0.1s
 => => exporting layers                                                                                                                     0.1s
 => => writing image sha256:b06ecc27be3690c5d345bd042143ca7d72cf1e55f165e46678f92ea2bc39914b                                                0.0s
 => => naming to docker.io/library/cloud_blog_gateway                                                                                       0.0s
 => [cloud_blog_blog] exporting to image                                                                                                    0.1s
 => => exporting layers                                                                                                                     0.1s
 => => writing image sha256:75d36043551d0200ab71694078530806f3b5846e03551f06042771597bb07179                                                0.0s
 => => naming to docker.io/library/cloud_blog_blog                                                                                          0.0s
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. 
[+] Running 3/3
 ⠿ Container cloud_blog-blog-1     Started                                                                                                  0.9s
 ⠿ Container cloud_blog-user-1     Started                                                                                                  0.8s
 ⠿ Container cloud_blog-gateway-1  Started                                                                                                  0.8s
➜  cloud_blog docker ps -a                                      
CONTAINER ID   IMAGE                      COMMAND                   CREATED              STATUS              PORTS                                                  NAMES
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
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
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
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
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 重新上传了,那么就执行以下指令重新构建,之后再运行即可.

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

1.10、测试结果

通过网关访问以下:

;