本文主要是介绍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.2ports:- "8848:8848"environment:- "MODE=standalone"restart: alwaysnetworks:- blog_netmysql:image: mysql:5.7ports:- "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.drestart: alwaysnetworks:- blog_net
Ps:docker-retrypoint-initdb.d 是 Docker 官方 MySQL 镜像的目录,用于初始化数据库和表,因此通过映射我们配置好的初始化文件 mysql-init,就可以实现自定义初始化数据库和表.
如果需要执行多个脚本文件(sql 文件)来初始化数据库,可以使用以下方法:
- 将 sql 文件以数字开头命名,例如 001_create_table.sql、002_insert_data.sql.
- 数字小的优先执行.
c)docker-compose.service.yml 文件如下:
version: "3"networks:blog_net:services:gateway: # 网关build:context: ./gatewaydockerfile: Dockerfileports:- "10010:10010"networks:- blog_netblog: # 博客服务build:context: ./blogdockerfile: Dockerfileports:- "9091:9091"networks:- blog_netuser: # 用户服务build:context: ./userdockerfile: Dockerfileports:- "9090:9090"networks:- blog_net
1.7、修改 application.yml 文件
a)强烈建议:提供两个配置文件,一个处理开发环境,另一个处理生产环境(线上环境). 这样本地测试和线上测试就不用老去修改配置文件,关键不小心还容易改错~
b)例如 user 微服务,当前项目需要修改的就是 nacos 和 mysql 连接地址,都修改为 docker-compose 文件中配置的服务Id 名称即可(前提是配置了 networks 在同一网络下):
开发环境如下
server:port: 9090spring:application:name: user-servercloud:nacos:server-addr: localhost:8848datasource:url: jdbc:mysql://localhost:3306/demo?characterEncoding=utf8&useSSL=falseusername: rootpassword: 1111driver-class-name: com.mysql.jdbc.Driver# 时间处理jackson:date-format: yyyy-MM-ddtime-zone: GMT+8# mybatis xml save path
mybatis:mapper-locations: classpath:mapper/*Mapper.xmlconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpllogging:pattern:dateformat: HH:mm:sslevel:com:cyk: debug
生产环境如下
server:port: 9090spring:application:name: user-servercloud:nacos:server-addr: nacos:8848datasource:url: jdbc:mysql://mysql:3306/demo?characterEncoding=utf8&useSSL=falseusername: rootpassword: 1111driver-class-name: com.mysql.jdbc.Driver# 时间处理jackson:date-format: yyyy-MM-ddtime-zone: GMT+8# mybatis xml save path
mybatis:mapper-locations: classpath:mapper/*Mapper.xmlconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpllogging:pattern:dateformat: HH:mm:sslevel: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、测试结果
通过网关访问以下:
这篇关于DockerCompose - 微服务项目部署全过程(最佳实践)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!