# rbac课堂demo **Repository Path**: sspku_admin/rbac-classroom-demo ## Basic Information - **Project Name**: rbac课堂demo - **Description**: No description available - **Primary Language**: Unknown - **License**: GPL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 6 - **Forks**: 1 - **Created**: 2023-11-26 - **Last Updated**: 2024-11-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # RBAC后台管理 ## **一、数据库表结构设计** 一个基于RBAC的后台管理系统中通常包括以下几张表: - **用户表 (Users):** 存储用户的基本信息,如用户名、密码、邮箱等。 - **角色表 (Roles):** 存储角色的信息,角色是权限的集合。 - **权限表 (Permissions):** 存储系统中所有的权限信息,权限通常是对特定操作的授权,如访问某页面、修改某信息等。 - **用户-角色关联表 (User_Roles):** 表示用户和角色之间的关系,一个用户可以有多个角色。 - **角色-权限关联表 (Role_Permissions):** 表示角色和权限之间的关系,一个角色可以有多个权限。 - **菜单表**和**菜单-权限关联表**,可以根据用户的权限动态生成对应的菜单,使得不同角色的用户看到的菜单项是不同的,同时还可以处理菜单的层级关系和显示顺序。此外,通过与权限表的关联,还可以处理菜单的访问控制问题,使得系统的访问控制更加丰富和灵活。 ## **二、构建后端SpringBoot应用** ### **0. 检查后端开发环境** **检查开发环境:** ```bash PS C:\Users\38470> java -version java version "1.8.0_351" Java(TM) SE Runtime Environment (build 1.8.0_351-b10) Java HotSpot(TM) 64-Bit Server VM (build 25.351-b10, mixed mode) PS C:\Users\38470> git --version git version 2.38.1.windows.1 ``` **创建一个Git仓库:** 创建git仓库,以便管理前后端的源代码,,我的地址为 ```bash git config --global user.name "your user name" ``` ```bash git config --global user.email "your email address" ``` ```bash git config --global --list ``` ```bash ssh-keygen -t rsa -C "xxxxxx@xxx" ``` SSH 密钥将被生成,并存储在你的用户目录下的 `.ssh` 文件夹内(通常路径是 `C:\Users\用户名\.ssh`)。将公钥加入到你的git服务器中。 ```bash PS C:\Users\38470> cd PS C:\Users\38470> cat .\.ssh\id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAA****************0@hang ``` ```bash mkdir rbac-classroom-demo cd rbac-classroom-demo git init touch README.md //windows下无此命令 git add README.md git commit -m "first commit" git remote add origin git@gitee.com:sspku_admin/rbac-classroom-demo.git git push -u origin "master" ``` 新建`.gitignore`文件 ```conf # Prerequisites *.d ### IntelliJ IDEA ### .idea *.iws *.iml *.ipr # Compiled Object files *.slo *.lo *.o *.obj # Precompiled Headers *.gch *.pch # Compiled Dynamic libraries *.so *.dylib *.dll # Fortran module files *.mod *.smod # Compiled Static libraries *.lai *.la *.a *.lib # Executables *.exe *.out *.app # build site/ *.zip .DS_Store node_modules/ dist/ npm-debug.log* yarn-debug.log* yarn-error.log* **/*.log tests/**/coverage/ tests/e2e/reports selenium-debug.log # Editor directories and files .idea .vscode *.suo *.ntvs* *.njsproj *.sln *.local package-lock.json ``` ### **1. Spring Boot 开发** **创建一个新项目:** 打开 Spring Initializr 网址: ,然后创建一个新项目: **springboot2.7.16_jdk8:** - Project(Maven) - 编程语言(Java 8) - Spring Boot 版本(2.7.16) - Packaging(Jar) 下载地址:[demo_springboot2.7.16_jdk8.zip](demo_springboot2.7.16_jdk8.zip) **springboot3.2.0_jdk17:** - Project(Maven) - 编程语言(Java 17) - Spring Boot 版本(3.2.0) - Packaging(Jar) 注意:包名不要使用纯数字,尽量规范,否则会出现奇怪的问题 下载地址:[demo_springboot3.2.0_jdk17.zip](demo_springboot3.2.0_jdk17.zip) 解压后,拷贝到本地git仓库目录中。 **在pom.xml文件中添加Web依赖:** ```xml org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-devtools runtime ``` **创建一个新的 Java 类:** ```java @RestController public class HelloController { @RequestMapping("/") public String index() { return "Hello, World!"; } } ``` **在 application.yml 文件中添加以下内容:** `resources/application.yml`文件 ```xml server: port: your_port ``` 将 `your_port` 替换为你希望应用程序使用的端口号,如`28080`。 **运行后端项目:** 可以在IDE工具下运行,也可以在命令行中进入项目目录,然后运行以下命令: ```bash mvn spring-boot:run ``` 或 ```bash mvnw spring-boot:run ``` ### **2. MySQL使用** **创建数据库表:** 在MySQL数据库中创建一张表`user`,并插入测试数据。 ```sql CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `age` int(11) NOT NULL, PRIMARY KEY (`id`) ); INSERT INTO `user` (`name`, `age`) VALUES ('Tom', 20); INSERT INTO `user` (`name`, `age`) VALUES ('Jerry', 25); ``` **配置MySQL和MyBatis:** `pom.xml`文件添加相关依赖。(如果Spring Boot 版本(3.2.0),需要修改依赖的版本) ```xml org.projectlombok lombok 1.18.20 provided mysql mysql-connector-java 8.0.27 org.mybatis.spring.boot mybatis-spring-boot-starter 2.2.0 ``` `resources/application.yml`文件添加数据源等配置 ```xml spring: datasource: url: jdbc:mysql://localhost:3306/yourdb username: username password: yourpassword mybatis: mapper-locations: classpath:mapper/*.xml ``` **创建实体类 (Model):** 使用 Lombok 简化实体类的定义: ```java import lombok.Data; @Data public class User { private Long id; private String name; private String email; } ``` **创建Mapper接口:** ```java import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper public interface UserMapper { User getUserById(Long id); } ``` **创建Mapper XML:** 在 `src/main/resources/mapper` 下,创建 `UserMapper.xml`: ```xml ``` - `com.yourpackage.UserMapper` 改为实际的内容。 - `com.yourpackage.User` 改为实际的内容。 **实现Service:** ```java import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class UserService { private final UserMapper userMapper; public User getUserById(Long id) { return userMapper.getUserById(id); } } ``` **实现Controller:** ```java import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/users") @RequiredArgsConstructor public class UserController { private final UserService userService; @GetMapping("/{id}") public User getUserById(@PathVariable Long id) { return userService.getUserById(id); } } ``` **验证接口:** 在浏览器中访问地址: `http://127.0.0.1:28080/users/1` 页面返回: `{"id":1,"name":"Tom","email":null}` ### **3. Redis使用** **添加依赖:** `pom.xml`中添加Spring Data Redis和Jedis客户端的依赖 ```xml org.springframework.boot spring-boot-starter-data-redis redis.clients jedis ``` **配置Redis:** 在`application.yml`文件中配置Redis服务器的连接信息。 ```yaml spring: redis: host: localhost # Redis服务器地址 port: 6379 # Redis服务器端口 password: # Redis服务器密码,如果有的话 jedis: pool: max-active: 10 # 连接池最大连接数 max-idle: 5 # 连接池中的最大空闲连接 min-idle: 1 # 连接池中的最小空闲连接 max-wait: 10000ms # 连接池最大阻塞等待时间 ``` **实现Controller:** 编写单元测试来验证Redis操作是否正确。 ```java import org.springframework.data.redis.core.StringRedisTemplate; @RestController public class HelloController { @Autowired private StringRedisTemplate redisTemplate; @RequestMapping("/redis") public String testRedis() { redisTemplate.opsForValue().set("testKey", "123"); return redisTemplate.opsForValue().get("testKey"); } } ``` **验证接口:** 在浏览器中访问地址:`http://127.0.0.1:28080/redis` 页面返回: `123` 至此,后端Springboot操作Mysql,Redis已经调试完成。 ## **三、构建前端Vue2应用** ### **0. 检查Vue开发环境** ```bash PS C:\Users\38470> nvm --version 1.1.10 PS C:\Users\38470> nvm ls 18.12.1 * 16.14.2 (Currently using 64-bit executable) PS C:\Users\38470> node --version v16.14.2 PS C:\Users\38470> npm --version 8.5.0 PS C:\Users\38470> vue --version @vue/cli 5.0.8 PS C:\Users\38470> yarn --version 1.22.19 ``` ### **1. 设置 Vue 项目** 使用以下命令来创建: ```bash vue create my-admin-project ``` 选择`Babel`,`Router`,`Vuex`和`Css Pre-processors`组件。 然后,进入你的项目目录: ```bash cd my-admin-project ``` **源码目录结构:** - components:包含了项目中所有的公共组件,例如表格、树形菜单、图表等组件。 - api: 包含了项目中所有的后端接口相关的文件,包括接口的封装和请求方式的定义等。 - router:包含了项目中的前端路由配置文件,用于定义前端路由规则。 - store:包含了项目中的 Vuex 状态管理模块,用于管理应用程序的状态和数据流。 - views:包含了项目中所有的业务组件,例如系统管理、任务调度等组件,每个组件对应一个页面。 - utils:包含了项目中的工具类文件,例如日期处理、字符串处理、请求(axios)封装等工具类文件。 - layout:用于存放系统的基本布局模板。该目录下的文件通常包括顶部导航栏、左侧菜单栏、底部版权信息等。 这些目录和文件的划分和设计,让项目的代码结构更加清晰、模块化、易于扩展和维护。 ### **2. 安装 Element-UI和 axios** 在项目中安装 Element-UI: ```bash npm install element-ui --save npm install axios --save ``` 或 ```bash yarn add element-ui --save yarn add axios --save ``` ### **3. 配置 Element-UI** 在 `main.js` 中导入 Element-UI 和它的样式: ```javascript import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI); ``` 完整代码如下: ```javascript import Vue from 'vue' import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import App from './App.vue' import router from './router' import store from './store' Vue.config.productionTip = false Vue.use(ElementUI); new Vue({ router, store, render: h => h(App) }).$mount('#app') ``` ### **4. 创建Layout通用布局** - `layout` 目录:用于存放系统的基本布局模板。该目录下的文件通常包括顶部导航栏、左侧菜单栏、底部版权信息等。 **layout/index.vue**: ```vue ``` ### **5. 配置路由** **router/index.js**: ```javascript import Vue from 'vue' import VueRouter from 'vue-router' /* Layout */ import Layout from '@/layout' Vue.use(VueRouter) const routes = [ { path: '/', component: Layout, // 修改为 Layout 组件 children: [ { path: '', component: () => import( '../views/HomeView.vue'), name: 'home' } ] }, ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router ``` **App.vue**: ```vue ``` **views/HomeView.vue**: ```vue ``` ### **6. 实现用户管理页面** **views/User/List.vue**: ```vue ``` **views/User/Add.vue**: ```vue ``` **router/index.js**: ```javascript { path: '/rbac', component: Layout, children: [{ path: 'user/list', component:() => import( '../views/User/List.vue') }, { path: 'user/add', component:() => import( '../views/User/Add.vue') } ] }, ``` **防止连续点击多次路由报错:** ```javascript // 防止连续点击多次路由报错 let routerPush = VueRouter.prototype.push; VueRouter.prototype.push = function push(location) { return routerPush.call(this, location).catch(err => err) } ``` ### **7. 运行项目** ```bash npm run serve ``` 或者 ```bash yarn serve ``` ### **8. 封装axios请求** **utils/request.js**: ```javascript import axios from 'axios'; const service = axios.create({ baseURL: '/api', timeout: 5000 }); service.interceptors.request.use( config => { // 在请求发送之前对请求数据进行处理 // ... return config; }, error => { // 对请求错误做些什么 console.log(error); return Promise.reject(error); } ); service.interceptors.response.use( response => { // 对响应数据进行处理 // ... return response.data; }, error => { // 对响应错误做些什么 console.log(error); return Promise.reject(error); } ); export default service; ``` ### **9. 封装 demo api请求** **api/demo.js**: ```javascript import request from '@/utils/request' // 用户登录 export function getMysqlDemo() { return request({ url: '/users/1', method: 'get' }) } // 获取用户信息 export function getRedisDemo() { return request({ url: '/redis', method: 'get' }) } ``` ### **10. 访问后端Demo接口数据** **views/HomeView.vue**: ```vue ``` ### **11. 设置dev proxy** 跨域问题,是因为浏览器的同源策略限制了不同源的站点之间的请求。 **Axios 的基础 URL**: ```javascript axios.defaults.baseURL = '/api' ``` 这里,`axios.defaults.baseURL = '/api'` 是将 Axios 的基础 URL 设置为 '/api'。这意味着所有的 Axios 请求都会自动在 URL 前面加上 '/api' 前缀。 **配置 devServer**: 在 `vue.config.js` 文件中配置 `devServer` 属性: ```javascript //其他配置 devServer: { proxy: { "/api": { target: "[实际请求的目标地址]", changeOrigin: true, pathRewrite: { "^/api": "" } } } } ``` - `devServer.proxy` 是一个代理配置,所有的 API 请求都会通过这个代理。 - `"/api"` 指的是当请求 URL 前缀为 '/api' 的时候,代理就会生效。 - `target` 是实际 API 服务器的地址。 - `changeOrigin` 是一个选项,将其设置为 `true` 来代理目标的主机源。 - `pathRewrite` 是一个选项,可以重写请求的路径。`"^/api": ""` 将 URL 中 '/api' 的部分移除。 **重启服务**: 重启server才能使配置生效。 **实际执行过程**: 1. 首先,你的 Axios 请求的 URL 会自动加上 '/api' 前缀。 2. 然后,当你发送一个请求时,devServer 代理会拦截以 '/api' 开头的请求,并将其代理到你在 `target` 中配置的实际 API 服务器。 3. `pathRewrite` 会去除 URL 中的 '/api' 前缀,因为实际的 API 服务器可能不识别这个前缀。 代理配置可以在本地开发环境中解决跨域问题,但需要注意的是,这种配置只在开发环境中有效。在生产环境中,你可能需要在服务器(如Nginx反向代理)处理跨域问题。 至此,开发环境的前后端均已经调试完成。 ## **四、项目部署** - 服务器对外只开放了`80`端口。 - Docker 提供了一个轻量级且高效的容器化环境。 - Docker Compose 为管理复杂的多容器应用提供了方便的工具。 ### **0. 检查Linux服务器运行环境** ```bash [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker --version Docker version 20.10.6, build 370c289 [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker-compose --version docker-compose version 1.29.1, build c34c88b2 [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@iZuf64pjiv0x3xokoi7y32Z ~]# ``` **卸载宝塔:** ```bash wget http://download.bt.cn/install/bt-uninstall.sh sh bt-uninstall.sh ``` **如果想下载一个镜像,可以使用以下命令:** ```bash [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker pull nginx Using default tag: latest latest: Pulling from library/nginx a2abf6c4d29d: Pull complete a9edb18cadd1: Pull complete 589b7251471a: Pull complete 186b1aaa4aa6: Pull complete b4df32aa5a72: Pull complete a0bcbecc962e: Pull complete Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31 Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 605c77e624dd 23 months ago 141MB ``` **如果想启动一个容器,可以使用以下命令:** 如果镜像在本地不存在,会自动先下载后,在启动容器。 ```bash [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker run -d -p 80:80 --name nginx nginx 12ceb282cd1c73b8c09548419fb18733f028c234cd3ca004740d40e92371aea6 [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 12ceb282cd1c nginx "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp nginx ``` **如果想查看容器运行中的日志,可以使用以下命令:** `docker logs 容器名称或ID` ```bash [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker logs nginx /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh /docker-entrypoint.sh: Configuration complete; ready for start up 2023/11/26 07:21:31 [notice] 1#1: using the "epoll" event method 2023/11/26 07:21:31 [notice] 1#1: nginx/1.21.5 2023/11/26 07:21:31 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6) 2023/11/26 07:21:31 [notice] 1#1: OS: Linux 4.18.0-193.28.1.el8_2.x86_64 2023/11/26 07:21:31 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576 2023/11/26 07:21:31 [notice] 1#1: start worker processes 2023/11/26 07:21:31 [notice] 1#1: start worker process 32 2023/11/26 07:21:31 [notice] 1#1: start worker process 33 124.205.76.33 - - [26/Nov/2023:07:22:21 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" "-" 124.205.76.33 - - [26/Nov/2023:07:22:22 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://139.196.19.49/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" "-" 2023/11/26 07:22:22 [error] 33#33: *2 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 124.205.76.33, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "139.196.19.49", referrer: "http://139.196.19.49/" ``` **如果想进入到运行的容器中查看容器内部信息,可以使用以下命令:** - 进入容器:`docker exec -it 容器名称或ID /bin/sh` - 退出:`exit` ```bash [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker exec -it nginx /bin/sh # ls bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var # cat /etc/nginx/nginx.conf user nginx; worker_processes auto; error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; } # cd /etc/nginx/conf.d/ # ls default.conf # cat default.conf server { listen 80; listen [::]:80; server_name localhost; #access_log /var/log/nginx/host.access.log main; location / { root /usr/share/nginx/html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } # ``` **如果想删除运行中的容器,可以使用下面命令:** - 停止容器:docker stop 容器名称或ID - 删除容器:docker rm 容器名称或ID ```bash [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 12ceb282cd1c nginx "/docker-entrypoint.…" 7 minutes ago Up 6 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp nginx [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker stop nginx nginx [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 12ceb282cd1c nginx "/docker-entrypoint.…" 7 minutes ago Exited (0) 2 seconds ago nginx [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker rm nginx nginx [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ``` **如果想删除镜像,可以使用下面命令:** - `docker rmi 镜像名称或ID` ```bash [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest ad4c705f24d3 2 years ago 133MB [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker rmi nginx Untagged: nginx:latest Untagged: nginx@sha256:853b221d3341add7aaadf5f81dd088ea943ab9c918766e295321294b035f3f3e Deleted: sha256:ad4c705f24d392b982b2f0747704b1c5162e45674294d5640cca7076eba2865d Deleted: sha256:cf45bd1acd3159a35178bfe8a63f910f010990175050ea6c8c333ba3afaf5123 Deleted: sha256:a9e7419d7f7c4fe55c85ce08c4f0a8b45abe9b714aa19880f553859797e0332c Deleted: sha256:13184aa93ccd585fade03704e048828c29eed86090e7399b208edbe022aaf563 Deleted: sha256:3161f310d154031dbd57f90c07715335a25a31bcf20a4abf3e040ab86bcac633 Deleted: sha256:88f95677408c5f02b15064ad1f41a2c74e40e1800cd3536f8fb45b9e6939704b Deleted: sha256:d000633a56813933cb0ac5ee3246cf7a4c0205db6290018a169d7cb096581046 ``` ### **1. 下载前后端项目源码** ```bash git clone https://gitee.com/sspku_admin/rbac-classroom-demo.git ``` ### **2. 通过Docker Compose部署MySQL和Redis** **docker-compose.yml 文件 :** ```yml version: "3.4" services: mysql: container_name: ssadmin-mysql image: mysql:8 restart: unless-stopped tty: true ports: - "3306:3306" environment: MYSQL_DATABASE: ${MYSQL_DATABASE:-root} MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-123456} volumes: - mysql:/var/lib/mysql/ - ./sql/ssadmin_init.sql:/docker-entrypoint-initdb.d/ssadmin_init.sql:ro networks: - my_network volumes: mysql: driver: local networks: my_network: driver: bridge ``` 这段代码是一个 Docker Compose 文件的内容,用于定义和运行多容器 Docker 应用程序。它的版本是 3.4,这指定了文件格式的版本。这个文件定义了一个服务:`mysql`,并提供了相关的配置细节。下面是该文件内容的逐行解释: 1. **`version: "3.4"`**:这一行指定了 Docker Compose 文件的版本号为 3.4。不同版本的 Docker Compose 支持不同的功能。 2. **`services:`**:这个部分定义了你要运行的服务。在这个例子中,只定义了一个服务:`mysql`。 3. **`mysql:`**:这里开始定义名为 `mysql` 的服务。 4. **`container_name: ssadmin-mysql`**:这一行指定了容器的名称为 `ssadmin-mysql`。 5. **`image: mysql:8`**:这里指定使用的 Docker 镜像是 `mysql` 的版本 8。 6. **`restart: unless-stopped`**:这个选项配置容器的重启策略。在这里,除非明确停止,否则如果容器退出,它会自动重启。 7. **`tty: true`**:这行代码分配一个伪 TTY 终端,通常用于保持容器运行。 8. **`ports:`**: - **`- "3306:3306"`**:这里将容器内的 3306 端口映射到宿主机的 3306 端口,使得可以通过宿主机的 3306 端口访问 MySQL。 9. **`environment:`**:这一部分定义了环境变量。 - **`MYSQL_DATABASE: ${MYSQL_DATABASE:-root}`**:设置 MySQL 数据库的名称。如果环境变量 `MYSQL_DATABASE` 未设置,则默认为 `root`。 - **`MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-123456}`**:设置 MySQL root 用户的密码。如果环境变量 `MYSQL_ROOT_PASSWORD` 未设置,则默认为 `123456`。 10. **`volumes:`**:这部分用于数据持久化和数据初始化。 - **`- mysql:/var/lib/mysql/`**:将名为 `mysql` 的卷挂载到容器的 `/var/lib/mysql/` 目录,用于持久化 MySQL 数据。 - **`- ./sql/ssadmin_init.sql:/docker-entrypoint-initdb.d/ssadmin_init.sql:ro`**:将宿主机上的 `sql/ssadmin_init.sql` 文件以只读方式挂载到容器的 `/docker-entrypoint-initdb.d` 目录。MySQL 容器会在首次初始化时执行这个目录下的 SQL 脚本。 11. **`networks:`**: 这部分用于容器网络。 - **`- my_network`** 将 `phpmyadmin` 服务加入到 `my_network` 网络。 12. **`volumes:`**(顶级):定义了卷的具体配置。 - **`mysql:`**:定义了一个名为 `mysql` 的卷。 - **`driver: local`**:指定使用本地驱动来创建卷。 13. **`networks:`**(顶级):定义了网络的具体配置。 - **`my_network:`**:定义了一个名为 `my_network` 的网络。 - **`driver: bridge`**:指定使用桥接模式来创建网络。 这个 Docker Compose 文件配置了一个单独的 MySQL 服务,包括了端口映射、环境变量设置、数据持久化以及数据库初始化脚本的配置。 **设置数据库初始化脚本:** `sql/ssadmin_init.sql`文件: ```sql CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `age` int(11) NOT NULL, PRIMARY KEY (`id`) ); INSERT INTO `user` (`name`, `age`) VALUES ('Tom', 20); INSERT INTO `user` (`name`, `age`) VALUES ('Jerry', 25); ``` **定义phpmyadmin服务(临时验证):** `docker-compose.yml 文件中添加如下内容 :` ```bash phpmyadmin: container_name: test-phpmyadmin image: phpmyadmin/phpmyadmin:4.9 restart: always ports: - "80:80" environment: PMA_HOST: ssadmin-mysql networks: - my_network ``` **开始部署服务:** - `docker-compose up -d` ```bash [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker-compose up -d Starting test-phpmyadmin ... done Starting ssadmin-mysql ... done ``` **查看容器信息:** - `docker volume ls` - `docker network ls` - `docker-compose logs` ```bash [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker volume ls DRIVER VOLUME NAME local root_mysql [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 69af5d6d835f bridge bridge local 7c049655a03b host host local 5c7ae788ddea none null local eb85c31ba62e root_my_network bridge local [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker-compose logs Attaching to test-phpmyadmin, ssadmin-mysql test-phpmyadmin | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.2. Set the 'ServerName' directive globally to suppress this message test-phpmyadmin | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.2. Set the 'ServerName' directive globally to suppress this message test-phpmyadmin | [Sun Nov 26 08:21:50.367368 2023] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.38 (Debian) PHP/7.4.11 configured -- resuming normal operations test-phpmyadmin | [Sun Nov 26 08:21:50.367438 2023] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND' test-phpmyadmin | 124.205.76.33 - - [26/Nov/2023:08:24:29 +0000] "GET / HTTP/1.1" 200 5409 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" test-phpmyadmin | 124.205.76.33 - - [26/Nov/2023:08:24:29 +0000] "GET /js/vendor/codemirror/lib/codemirror.css?v=4.9.7 HTTP/1.1" 200 2880 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" test-phpmyadmin | 124.205.76.33 - - [26/Nov/2023:08:24:29 +0000] "GET /themes/pmahomme/jquery/jquery-ui.css HTTP/1.1" 200 8823 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" test-phpmyadmin | 124.205.76.33 - - [26/Nov/2023:08:24:29 +0000] "GET /js/vendor/codemirror/addon/hint/show-hint.css?v=4.9.7 HTTP/1.1" 200 660 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" test-phpmyadmin | 124.205.76.33 - - [26/Nov/2023:08:24:29 +0000] "GET /js/vendor/codemirror/addon/lint/lint.css?v=4.9.7 HTTP/1.1" 200 1604 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" test-phpmyadmin | 124.205.76.33 - - [26/Nov/2023:08:24:29 +0000] "GET /js/vendor/jquery/jquery.min.js?v=4.9.7 HTTP/1.1" 200 31030 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" test-phpmyadmin | 124.205.76.33 - - [26/Nov/2023:08:24:29 +0000] "GET /phpmyadmin.css.php?nocache=4808377795ltr&server=1 HTTP/1.1" 200 21500 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" test-phpmyadmin | 124.205.76.33 - - [26/Nov/2023:08:24:29 +0000] "GET /js/whitelist.php?v=4.9.7&lang=zh_CN HTTP/1.1" 200 1156 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" test-phpmyadmin | 124.205.76.33 - - [26/Nov/2023:08:24:29 +0000] "GET /js/vendor/sprintf.js?v=4.9.7 HTTP/1.1" 200 2900 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" test-phpmyadmin | 124.205.76.33 - - [26/Nov/2023:08:24:29 +0000] "GET /js/ajax.js?v=4.9.7 HTTP/1.1" 200 8002 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" test-phpmyadmin | 124.205.76.33 - - [26/Nov/2023:08:24:29 +0000] "GET /js/keyhandler.js?v=4.9.7 HTTP/1.1" 200 1421 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" ``` **查看phpmyadmin服务:** ```code http://IP/ 用户名 root 密码 123456 ``` **停止服务:** - `docker-compose down` ```bash [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker-compose down Stopping test-phpmyadmin ... done Stopping ssadmin-mysql ... done Removing test-phpmyadmin ... done Removing ssadmin-mysql ... done Removing network root_my_network [root@iZuf64pjiv0x3xokoi7y32Z ~]# [root@iZuf64pjiv0x3xokoi7y32Z ~]# [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 69af5d6d835f bridge bridge local 7c049655a03b host host local 5c7ae788ddea none null local [root@iZuf64pjiv0x3xokoi7y32Z ~]# docker volume ls DRIVER VOLUME NAME local root_mysql [root@iZuf64pjiv0x3xokoi7y32Z ~]# ``` **通过Docker Compose部署Redis:** 更新Docker Compose 文件,包括Redis 服务,`docker-compose.yml` 文件中添加如下内容 : ```yaml redis: container_name: ssadmin-redis image: redis:6-alpine restart: unless-stopped ports: - "6379:6379" volumes: - redis:/data networks: - my_network volumes: redis: driver: local ``` - 在这个配置中: - **`redis:`** 定义了一个名为 `redis` 的新服务。 - **`container_name: ssadmin-redis`** 设置容器名称为 `ssadmin-redis`。 - **`image: redis:6-alpine`** 使用 Redis 官方的 `6-alpine` 版本镜像。 - **`restart: unless-stopped`** 设置容器除非被手动停止,否则总是重新启动。 - **`ports: - "6379:6379"`** 将容器的 6379 端口映射到宿主机的同一端口。 - **`volumes: - redis:/data`** 将名为 `redis` 的卷挂载到容器的 `/data` 目录,用于持久化 Redis 数据。 - **`networks: - my_network`** 将 Redis 服务加入到 `my_network` 网络。 ### **3. 部署验证MySQL和Redis可用性的测试服务** 创建测试服务的 Dockerfile (test-service/Dockerfile) ```Dockerfile FROM ubuntu:20.04 # 替换为阿里云的 Ubuntu 镜像源 RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list RUN sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list # 安装所需的包和 MySQL 客户端 RUN apt-get update && \ apt-get install -y mysql-client redis-tools curl wget net-tools iputils-ping && \ rm -rf /var/lib/apt/lists/* ``` `docker-compose.yml` 文件中添加如下内容 : ```yaml test-service: container_name: ssadmin-test-service build: ./test-service/ restart: unless-stopped environment: MYSQL_HOST: ssadmin-mysql MYSQL_PORT: 3306 MYSQL_USER: root MYSQL_PASSWORD: 123456 REDIS_HOST: ssadmin-redis REDIS_PORT: 6379 command: tail -f /dev/null networks: - my_network ``` **开始部署服务:** ```bash # 单独构建 test-service docker-compose build test-service # 启动所有服务 docker-compose up -d ``` ```bash docker exec -it ssadmin-test-service sh ``` ```bash mysql -h $MYSQL_HOST -P $MYSQL_PORT -u $MYSQL_USER -p$MYSQL_PASSWORD ``` ```bash redis-cli -h $REDIS_HOST -p $REDIS_PORT PING ``` ```bash [root@iZuf687i72t3i3hqja640lZ rbac-classroom-demo]# docker exec -it ssadmin-test-service sh # mysql -h $MYSQL_HOST -P $MYSQL_PORT -u $MYSQL_USER -p$MYSQL_PASSWORD mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 9 Server version: 8.0.27 MySQL Community Server - GPL Copyright (c) 2000, 2023, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | root | | sys | +--------------------+ 5 rows in set (0.00 sec) mysql> use root; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +----------------+ | Tables_in_root | +----------------+ | user | +----------------+ 1 row in set (0.00 sec) mysql> exit Bye # redis-cli -h $REDIS_HOST -p $REDIS_PORT PING PONG # # # echo $REDIS_HOST ssadmin-redis # exit [root@iZuf687i72t3i3hqja640lZ rbac-classroom-demo]# ``` ### **4. 通过Docker Compose部署SpringBoot** #### **构建Jar包文件** 创建一个存放`Maven仓库`的卷,使得Maven的依赖被缓存,可加快构建速度。 ```bash docker volume create --name ssadmin-maven-repo ``` 使用 Maven Docker 镜像来编译和打包 Spring Boot(demo_springboot2.7.16_jdk8) 应用。 `pom.xml`文件中增加镜像地址 ```xml huaweicloud huawei https://mirrors.huaweicloud.com/repository/maven/ aliyunmaven aliyun https://maven.aliyun.com/repository/public public aliyun nexus https://maven.aliyun.com/nexus/content/groups/public/ true false ``` ```bash docker run -it --rm --name ssadmin-maven \ -v ssadmin-maven-repo:/root/.m2 \ -v "$PWD/demo_springboot2.7.16_jdk8":/usr/src/mymaven \ -w /usr/src/mymaven \ maven:3.8.4-jdk-8 mvn clean install package -e -Dmaven.test.skip=true ``` 1. **`docker run`**:这是用来运行一个新的 Docker 容器的命令。 2. **`-it`**:这个选项组合用于运行容器并提供交互式 shell。`-i` 代表交互模式,保持标准输入打开;`-t` 分配一个伪终端或终端。 3. **`--rm`**:这个选项表示容器在退出时自动删除。也就是说,当 Maven 构建完成后,这个容器将被自动清理。 4. **`--name ssadmin-maven`**:这个选项为即将创建的容器指定了一个名称(在这个例子中是 `ssadmin-maven`)。 5. **`-v ssadmin-maven-repo:/root/.m2`**:这个选项挂载了一个名为 `ssadmin-maven-repo` 的卷到容器内的 `/root/.m2` 目录。这样,所有的 Maven 依赖和插件都会被缓存到这个卷中,以加快未来构建的速度。 6. **`-v "$PWD/demo_springboot2.7.16_jdk8":/usr/src/mymaven`**:这将宿主机的当前目录下的 `demo_springboot2.7.16_jdk8` 子目录挂载到容器的 `/usr/src/mymaven`。这意味着SpringBoot的后端项目源代码被挂载到容器内,供 Maven 构建使用。 7. **`-w /usr/src/mymaven`**:设置容器的工作目录为 `/usr/src/mymaven`。这是 Maven 构建的工作目录。 8. **`maven:3.8.4-jdk-8`**:这指定了要使用的 Docker 镜像,即 Maven 3.8.4 版本,运行在 Java 8 JDK 上。 9. **`mvn clean install package -e '-Dmaven.test.skip=true'`**:这是在容器内运行的实际命令。它执行 Maven 的 `clean`、`install` 和 `package` 生命周期,同时通过 `-Dmaven.test.skip=true` 跳过测试。`-e` 选项用于在构建过程中提供详细的错误信息。 这个命令在一个临时的 Maven Docker 容器内构建了一个 Java 项目。它利用 Docker 卷来缓存依赖,加快后续构建速度,并在完成后自动清理容器。这种方式在持续集成/持续部署(CI/CD)流程中非常有用。 ```bash [INFO] Installing /usr/src/mymaven/pom.xml to /root/.m2/repository/com/example/demo20230927/0.0.1-SNAPSHOT/demo20230927-0.0.1-SNAPSHOT.pom [INFO] [INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ demo20230927 --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Using 'UTF-8' encoding to copy filtered properties files. [INFO] Copying 2 resources [INFO] Copying 1 resource [INFO] [INFO] --- maven-compiler-plugin:3.10.1:compile (default-compile) @ demo20230927 --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 6 source files to /usr/src/mymaven/target/classes [INFO] [INFO] --- maven-resources-plugin:3.2.0:testResources (default-testResources) @ demo20230927 --- [INFO] Not copying test resources [INFO] [INFO] --- maven-compiler-plugin:3.10.1:testCompile (default-testCompile) @ demo20230927 --- [INFO] Not compiling test sources [INFO] [INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ demo20230927 --- [INFO] Tests are skipped. [INFO] [INFO] --- maven-jar-plugin:3.2.2:jar (default-jar) @ demo20230927 --- [INFO] Building jar: /usr/src/mymaven/target/demo20230927-0.0.1-SNAPSHOT.jar [INFO] [INFO] --- spring-boot-maven-plugin:2.7.16:repackage (repackage) @ demo20230927 --- [INFO] Replacing main artifact with repackaged archive [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 01:42 min [INFO] Finished at: 2023-11-28T02:08:38Z [INFO] ------------------------------------------------------------------------ ``` #### **编写 Dockerfile** Dockerfile 用于构建包含 Spring Boot 应用的 Docker 镜像。 ```Dockerfile FROM eclipse-temurin:8-jre RUN mkdir -p /ssadmin-server WORKDIR /ssadmin-server COPY ./target/demo20230927-0.0.1-SNAPSHOT.jar app.jar ENV TZ=Asia/Shanghai ENV JAVA_OPTS="-Xms512m -Xmx512m -Djava.security.egd=file:/dev/./urandom" ENV ARGS="" EXPOSE 28080 CMD java ${JAVA_OPTS} -jar app.jar $ARGS ``` Dockerfile 用于构建一个包含 Spring Boot 应用的 Docker 镜像。 1. **`FROM eclipse-temurin:8-jre`**: - 这行指定了基础镜像,即在哪个镜像的基础上构建镜像。这里使用的是 `eclipse-temurin` 镜像的 8 版本,带有 Java 运行时环境(JRE)。这意味着这个镜像包含了运行 Java 应用所需的环境。 2. **`RUN mkdir -p /ssadmin-server`**: - 这条指令在镜像中创建一个名为 `/ssadmin-server` 的目录。`mkdir -p` 保证了即使这个目录已经存在,命令也不会失败。 3. **`WORKDIR /ssadmin-server`**: - 设置工作目录为 `/ssadmin-server`。后续的 `COPY` 和 `CMD` 指令都将在这个目录下执行。 4. **`COPY ./target/demo20230927-0.0.1-SNAPSHOT.jar app.jar`**: - 将宿主机当前目录下的 `./target/demo20230927-0.0.1-SNAPSHOT.jar` 文件复制到镜像的工作目录中,并重命名为 `app.jar`。这个 JAR 文件是我们前面构建生成的 Spring Boot 应用程序。 5. **`ENV TZ=Asia/Shanghai`**: - 设置环境变量 `TZ`(时区)为 `Asia/Shanghai`。这确保了容器内的时间与中国时区同步。 6. **`ENV JAVA_OPTS="-Xms512m -Xmx512m -Djava.security.egd=file:/dev/./urandom"`**: - 设置 Java 虚拟机的启动参数。`-Xms512m` 和 `-Xmx512m` 分别设置了 JVM 的初始堆大小和最大堆大小为 512MB。`-Djava.security.egd=file:/dev/./urandom` 用于加快随机数生成器的初始化速度。 7. **`ENV ARGS=""`**: - 设置一个名为 `ARGS` 的环境变量,其值为空。这个变量可以用来传递给 Spring Boot 应用的额外参数。 8. **`EXPOSE 28080`**: - 指明容器在运行时将监听 28080 端口。这应与我们的 Spring Boot 应用配置中的端口**一致**。 9. **`CMD java ${JAVA_OPTS} -jar app.jar $ARGS`**: - 容器启动时运行的命令。这个命令将启动我们的 Spring Boot 应用,使用 `JAVA_OPTS` 中定义的 JVM 参数。 这个 Dockerfile 创建了一个 Docker 镜像,其中包含了 Spring Boot 应用程序。当容器启动时,它将运行我们的应用程序,并且可以通过暴露的端口访问。 #### **更新 Docker Compose 文件** 在 Docker Compose 文件中,添加一个 `server` 服务,用于运行 Spring Boot 应用。 ```yaml server: container_name: ssadmin-server build: context: ./demo_springboot2.7.16_jdk8/ image: ssadmin-server restart: unless-stopped ports: - "28080:28080" networks: - my_network environment: SPRING_PROFILES_ACTIVE: local JAVA_OPTS: ${JAVA_OPTS:- -Xms512m -Xmx512m -Djava.security.egd=file:/dev/./urandom} ARGS: --spring.datasource.url=${DATASOURCE_URL:-jdbc:mysql://ssadmin-mysql:3306/ssadmin?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true} --spring.datasource.username=${DATASOURCE_USERNAME:-root} --spring.datasource.password=${DATASOURCE_PASSWORD:-123456} --spring.redis.host=${REDIS_HOST:-ssadmin-redis} depends_on: - mysql - redis ``` 这段 Docker Compose 文件定义了一个名为 `server` 的服务,用于构建和运行一个 Spring Boot 应用。 1. **`server:`** - 定义了一个名为 `server` 的服务。 2. **`container_name: ssadmin-server`** - 为创建的容器指定了一个名称,即 `ssadmin-server`。 3. **`build:`** - 指定了构建 Docker 镜像的配置。 - **`context: ./demo_springboot2.7.16_jdk8/`**:设置 Dockerfile 的路径为当前目录下的 `./demo_springboot2.7.16_jdk8/` 文件夹。 4. **`image: ssadmin-server`** - 定义构建出的 Docker 镜像的名称为 `ssadmin-server`。 5. **`restart: unless-stopped`** - 设置容器的重启策略。这意味着,除非容器被显式停止,否则在容器退出时它会自动重启。 6. **`ports:`** - **`- "28080:28080"`**:将容器的 28080 端口映射到宿主机的 28080 端口。这允许从宿主机访问运行在容器内的 Spring Boot 应用。 7. **`networks:`** - **`- my_network`**:将此服务连接到名为 `my_network` 的网络。这确保了服务可以与同一 Docker 网络中的其他服务通信。 8. **`environment:`** - 设置环境变量,这些变量将在容器运行时传递给 Spring Boot 应用。 - **`SPRING_PROFILES_ACTIVE: local`**:设置 Spring 的活跃配置文件为 `local`。 - **`JAVA_OPTS: ${JAVA_OPTS:- -Xms512m -Xmx512m -Djava.security.egd=file:/dev/./urandom}`**:设置 JVM 选项,如果没有指定 `JAVA_OPTS` 环境变量,则使用默认值。 - **`ARGS:`**:提供 Spring Boot 应用的参数。包括数据库连接和 Redis 主机配置。这些值可以通过环境变量提供或使用默认值。 - **`--spring.datasource.url=${DATASOURCE_URL:-jdbc:mysql://ssadmin-mysql:3306/ssadmin?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true}`**:设置数据库连接 URL。如果没有设置 `DATASOURCE_URL` 环境变量,则使用默认的 MySQL 连接字符串。 - **`--spring.datasource.username=${DATASOURCE_USERNAME:-root}`** 和 **`--spring.datasource.password=${DATASOURCE_PASSWORD:-123456}`**:分别设置数据库的用户名和密码,默认值分别是 `root` 和 `123456`。 - **`--spring.redis.host=${REDIS_HOST:-ssadmin-redis}`**:设置 Redis 服务器的主机名,如果没有设置 `REDIS_HOST` 环境变量,则默认为 `ssadmin-redis`。 9. **`depends_on:`** - **`- mysql - redis`**:表明 `server` 服务依赖于 `mysql` 和 `redis` 服务。这意味着 Docker Compose 会先启动 `mysql` 和 `redis` 服务,然后再启动 `server` 服务。 ```bash # 单独构建 server docker-compose build server # 启动所有服务 docker-compose up -d ``` **测试后端:** ```bash docker exec -it ssadmin-test-service sh ``` ```bash [root@iZuf687i72t3i3hqja640lZ rbac-classroom-demo]# docker exec -it ssadmin-test-service sh # curl http://ssadmin-server:28080 Hello, World!# # # # curl http://ssadmin-server:28080/redis 123# # ``` **DockerCompose文件中的环境变量与 Dockerfile 中的环境参数的关系:** - 在 Dockerfile 中设置的环境变量是在构建镜像时定义的,一旦镜像构建完成,这些变量的值就固定了。 - Docker Compose 文件中的 `environment` 部分则是在容器运行时定义环境变量。这意味着你可以在不重新构建镜像的情况下更改这些变量的值。 - 对于 Spring Boot 应用来说,这些环境变量通常用于控制应用的配置和行为,如数据库连接信息、JVM 设置等。 - 通过 Docker Compose 设置的环境变量在**容器启动时会覆盖** Dockerfile 中设置的同名变量。 通过在 Docker Compose 文件中配置环境变量,可以灵活地管理和调整容器化应用的运行时配置,而无需更改 Dockerfile 或重新构建镜像。 **关于在 Docker Compose 文件中使用的环境变量的说明:** 在 Docker Compose 文件中使用的环境变量(如 `DATASOURCE_URL`)可以通过几种不同的方式设置。以下是几种常见的方法: ##### **1. 在 Docker Compose 文件中直接设置** 可以直接在 Docker Compose 文件的 `environment` 部分为每个服务设置环境变量。例如: ```yaml services: server: environment: DATASOURCE_URL: "jdbc:mysql://ssadmin-mysql:3306/ssadmin?useSSL=false&serverTimezone=Asia/Shanghai" ``` ##### **2. 使用 `.env` 文件** 通常,将配置放在 `.env` 文件中是一种更好的实践,这样可以避免将敏感信息直接写入 Docker Compose 文件。创建一个 `.env` 文件,然后在其中设置环境变量: ```env DATASOURCE_URL=jdbc:mysql://ssadmin-mysql:3306/ssadmin?useSSL=false&serverTimezone=Asia/Shanghai ``` Docker Compose 会自动从同目录下的 `.env` 文件读取环境变量。 ##### **3. 在命令行中设置** 还可以在运行 `docker-compose up` 命令时直接在命令行中设置环境变量: ```bash DATASOURCE_URL=jdbc:mysql://ssadmin-mysql:3306/ssadmin?useSSL=false&serverTimezone=Asia/Shanghai docker-compose up ``` 这种方法对临时更改或测试非常有用,但不适合长期存储配置。 ##### **4. 在宿主机的环境中设置** 也可以在运行 Docker Compose 命令的宿主机上设置环境变量。这在某些自动化部署或 CI/CD 管道中很有用: ```bash export DATASOURCE_URL=jdbc:mysql://ssadmin-mysql:3306/ssadmin?useSSL=false&serverTimezone=Asia/Shanghai docker-compose up ``` 对于持久化配置和避免硬编码敏感信息,使用 `.env` 文件通常是推荐的做法。 ### **5. 通过Docker Compose部署Vue** 要在 Docker 环境中部署 Vue 应用程序,通常包括两个步骤:首先是构建 Vue 应用的生产版本,然后是使用一个轻量级的 Nginx 镜像来提供静态文件服务。 #### **编写Dockerfile:** ```Dockerfile # Stage 1: Build FROM node:16-alpine as build-stage WORKDIR /admim COPY .npmrc package.json ./ RUN yarn install --frozen-lockfile COPY . . # 构建命令 ARG NODE_ENV RUN if [ "$NODE_ENV" = "production" ]; then \ yarn build:prod; \ else \ yarn build; \ fi # Stage 2: Run FROM nginx:alpine ENV TZ=Asia/Shanghai COPY ./nginx.conf /etc/nginx/conf.d/default.conf COPY --from=build-stage /admim/dist /usr/share/nginx/html EXPOSE 80 ``` ##### **Stage 1: Build:** 1. **`FROM node:16-alpine as build-stage`**: - 这行指定了基础镜像为 `node:16-alpine`,使用的是 Node.js 16 的 Alpine Linux 版本。`as build-stage` 给这个构建阶段命名为 `build-stage`,以便在后面的阶段引用。 2. **`WORKDIR /admin`**: - 设置 `/admin` 为容器内的工作目录。后续命令将在这个目录中执行。 3. **`COPY .npmrc package.json yarn.lock ./`**: - 将当前目录(Dockerfile 所在目录)下的 `.npmrc`、`package.json` 和 `yarn.lock` 文件复制到工作目录中。 4. **`RUN yarn install --frozen-lockfile`**: - 运行 `yarn install` 命令来安装依赖。`--frozen-lockfile` 参数确保 `yarn.lock` 文件中锁定的依赖版本被精确安装。 5. **`COPY . .`**: - 将所有其他文件从当前目录复制到容器的工作目录。 6. **`ARG NODE_ENV`**: - 定义一个构建参数 `NODE_ENV`。这个参数可以在构建时通过 `--build-arg` 选项传递给 Docker。 7. **`RUN if [ "$NODE_ENV" = "production" ]; then yarn build:prod; else yarn build; fi`**: - 根据 `NODE_ENV` 的值决定运行哪个构建命令。如果是生产环境,则运行 `yarn build:prod`,否则运行 `yarn build`。 ##### **Stage 2: Run:** 1. **`FROM nginx:alpine`**: - 开始第二阶段,使用 `nginx:alpine` 镜像作为基础。Alpine 版本的 Nginx 非常轻量级。 2. **`ENV TZ=Asia/Shanghai`**: - 设置环境变量 `TZ`(时区)为 `Asia/Shanghai`。 3. **`COPY ./nginx.conf /etc/nginx/conf.d/default.conf`**: - 将本地的 `nginx.conf` 配置文件复制到容器中的 Nginx 配置目录。 4. **`COPY --from=build-stage /admin/dist /usr/share/nginx/html`**: - 从构建阶段 `build-stage` 中复制 `/admin/dist` 目录到 Nginx 的静态文件目录。这里的 `/admin/dist` 是 Vue 应用构建后的输出目录。 5. **`EXPOSE 80`**: - 声明容器在运行时将暴露 80 端口,这是 Nginx 的默认端口。 #### **编写.npmrc文件:** 项目根目录的 .npmrc 的配置,优先级最高,且随着项目一起,可以免去因不同开发者的电脑的环境配置不同而导致的依赖下载异常的问题;实际开发中也推荐在根目录下配置一份,可以给每个项目配置不同的镜像,项目之间的配置互不影响。 ```conf phantomjs_cdnurl=http://cnpmjs.org/downloads chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver sass_binary_site=https://npm.taobao.org/mirrors/node-sass/ registry=https://registry.npmmirror.com ``` #### **编写Nginx配置文件:** ```conf server { listen 80 default_server; server_name _; gzip on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.1; gzip_comp_level 2; gzip_types text/plain application/x-javascript text/css application/xml application/javascript; gzip_proxied any; location / { root /usr/share/nginx/html/; index index.html index.htm; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://ssadmin-server:28080/; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ``` 这个 Nginx 配置文件定义了一个简单的 web 服务器,用于服务 Vue 应用程序并代理到后端 API。 1. **`server {`** - 开始一个 `server` 块,这是 Nginx 用于定义服务器的基本单元。 2. **`listen 80 default_server;`** - 指定 Nginx 监听端口 80(HTTP 的标准端口)。`default_server` 表明这个服务器将被视为默认服务器。 3. **`server_name _;`** - 设置服务器的名称。在这里,下划线 (`_`) 是一个通配符,表示这个服务器将接受所有没有匹配到其他 `server_name` 的请求。 4. **Gzip 压缩配置**: - `gzip on;`:开启 gzip 压缩。 - `gzip_min_length 1k;`:只压缩大于或等于 1KB 的响应。 - `gzip_buffers 4 16k;`:设置压缩所需的缓冲区大小。 - `gzip_http_version 1.1;`:仅对 HTTP 1.1 请求启用压缩。 - `gzip_comp_level 2;`:设置压缩级别。 - `gzip_types`:指定哪些类型的响应需要被压缩。 - `gzip_proxied any;`:允许压缩所有代理请求的响应。 5. **`location / {`** - 定义一个 `location` 块,用于处理根 URL(`/`)的请求。 - `root /usr/share/nginx/html/;`:设置根目录为 `/usr/share/nginx/html/`,这是静态文件的位置。 - `index index.html index.htm;`:设置默认的索引文件。 - `try_files $uri $uri/ /index.html;`:尝试提供请求的文件,如果找不到,则转到 `index.html`。这对于单页面应用(SPA)非常有用,因为它允许 Vue 路由器处理前端路由。 6. **`location /api/ {`** - 定义另一个 `location` 块,专门用于处理以 `/api/` 开头的 URL。 - `proxy_pass http://ssadmin-server:28080/;`:将请求代理到另一个服务器。这里将请求转发到名为 `ssadmin-server` 的服务器,该服务器监听在 28080 端口上。 - `proxy_set_header` 指令用于设置传递给代理服务器的 HTTP 头部。 - `Host` 设置为原始请求的 `Host`。 - `X-Real-IP` 和 `REMOTE-HOST` 设置为客户端的 IP 地址。 - `X-Forwarded-For` 添加了代理服务器的 IP 地址。 7. **`}`** - 结束 `server` 块。 这个配置文件既为前端 Vue 应用提供了静态文件服务,又为后端 API 请求提供了代理功能。这是一个典型的前端后端分离部署的 Nginx 配置示例。 #### **更新 Docker Compose 文件:** ```yaml web: container_name: ssadmin-web build: context: ./ssadmin-web args: NODE_ENV: ENV=${NODE_ENV:-production} VUE_APP_TITLE=${VUE_APP_TITLE:-我的管理系统} image: ssadmin-web restart: unless-stopped ports: - "80:80" networks: - my_network depends_on: - server ``` 这段 Docker Compose 文件定义了名为 `web` 的服务,它用于构建和运行一个 Vue 应用程序,该应用程序使用 Nginx 作为 web 服务器。 1. **`web:`** - 定义了一个名为 `web` 的服务。 2. **`container_name: ssadmin-web`** - 为创建的容器指定了一个名称,即 `ssadmin-web`。 3. **`build:`** - 指定了构建 Docker 镜像的配置。 - **`context: ./ssadmin-web`**:设置 Dockerfile 的路径为当前目录下的 `./ssadmin-web` 文件夹。 - **`args:`**:定义了构建过程中使用的参数。 - **`NODE_ENV:`**:设置一个构建参数 `NODE_ENV`,其值默认为 `production`。如果在运行 Docker Compose 命令时设置了环境变量 `NODE_ENV`,则会使用该值。 - **`VUE_APP_TITLE:`**:设置一个构建参数 `VUE_APP_TITLE`,其值默认为 “我的管理系统”。同样,如果设置了该环境变量,则会使用该值。 4. **`image: ssadmin-web`** - 定义构建出的 Docker 镜像的名称为 `ssadmin-web`。 5. **`restart: unless-stopped`** - 设置容器的重启策略。这意味着,除非容器被显式停止,否则在容器退出时它会自动重启。 6. **`ports:`** - **`- "80:80"`**:将容器的 80 端口映射到宿主机的 80 端口。这允许从宿主机访问运行在容器内的 Nginx 服务器。 7. **`networks:`** - **`- my_network`**:将此服务连接到名为 `my_network` 的网络。这确保了服务可以与同一 Docker 网络中的其他服务通信。 8. **`depends_on:`** - **`- server`**:表明 `web` 服务依赖于 `server` 服务。这意味着 Docker Compose 会先启动 `server` 服务,然后再启动 `web` 服务。