Spring Boot+Nginx+MySQL容器化实战

文章目录

  • 一、实现目标
    • [1.1 概述](#1.1 概述)
    • [1.2 表定义](#1.2 表定义)
    • [1.3 spring-boot程序](#1.3 spring-boot程序)
    • [1.4 nginx配置文件](#1.4 nginx配置文件)
  • 二、spring-boot程序打包
    • [2.1 生成jar包](#2.1 生成jar包)
    • [2.2 通过scp命令上传到服务器](#2.2 通过scp命令上传到服务器)
  • 三、创建宿主机依赖路径、文件
    • [3.1 宿主机mysql初始化文件](#3.1 宿主机mysql初始化文件)
    • [3.2 宿主机nginx配置文件](#3.2 宿主机nginx配置文件)
  • 四、定义docker-compose.yml
    • [4.1 nginx容器定义](#4.1 nginx容器定义)
    • [4.2 mysql容器定义](#4.2 mysql容器定义)
    • [4.3 spring-boot容器定义](#4.3 spring-boot容器定义)
    • 4.4容器依赖关系与健康检查
      • [4.4.1 概述](#4.4.1 概述)
      • [4.4.2 健康检查](#4.4.2 健康检查)
      • [4.4.3 容器依赖关系(也叫容器拓扑)](#4.4.3 容器依赖关系(也叫容器拓扑))
    • [4.5 容器网络定义](#4.5 容器网络定义)
  • 五、启动docker-compose.yml

一、实现目标

1.1 概述

编写一个spring-boot程序,返回user表的所有数据,并且通过nginx反向代理实现。

1.2 表定义

sql 复制代码
# 文件名:init.sql 
DROP DATABASE IF EXISTS test;
CREATE DATABASE `test` DEFAULT CHARACTER SET utf8mb4;
USE `test`;

CREATE TABLE `users` (
    `sno` int(11) DEFAULT NULL,
    `sname` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO users (sno, sname) VALUES
    (1, 'hyy'),
    (2, 'blog');

小提示:

init.sql需要存放到容器的docker-entrypoint-initdb.d路径,mysql容器会自动初始化表结构以及一些原始数据!

1.3 spring-boot程序

controller:

java 复制代码
package com.example.docker_compose;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class Controller {

    @Autowired
    JdbcTemplate jdbcTemplate;

    @RequestMapping("/list")
    @ResponseBody
    public Object Users(){
        return jdbcTemplate.queryForList("select * from users");
    }

}

application.properties配置:

bash 复制代码
spring.application.name=docker_compose #项目名
spring.datasource.url=jdbc:mysql://mysql容器名称:3306/数据库名称
spring.datasource.username=root # mysql用户名
spring.datasource.password=1111 # mysql密码

注意:

  1. jdbc的url一定不能错,尤其是容器名称,后面我们定义容器网络,它会根据容器名称寻址(域名解析)。
  2. Docker Compose 未自定义容器名时,容器会生成默认名称,规则为:[项目目录名]-[服务名]-[容器启动序号](例如 p12_spring-mysql-1)
  3. 默认情况下,容器名称会随项目目录、启动次数变化,不建议直接用于 JDBC 配置;可以使用container_name自定义容器名称(后续会讲到)

1.4 nginx配置文件

powershell 复制代码
# 文件名:myapp.conf(只要是.conf后缀都行)
server{ 
  listen 80; #容器内部监听80端口
  access_log off; # 关闭日志记录-减少io
  location / {# /所有请求,转发到user/list路径下
    proxy_pass http://myapp:8080/user/list; 
  }
}

小提示:

myapp.conf文件配置到容器/etc/nginx/conf.d可以实现路径转发

二、spring-boot程序打包

2.1 生成jar包

spring-boot项目编写完后,点击maveclear清理缓存,然后点击package打包:

提示BUILD SUCCESS后,target路径下会有一个编译好的jar包:

2.2 通过scp命令上传到服务器

首先创建好服务器这边的项目路径:

bash 复制代码
pwd
/root/docker_stu/docker_compose/p11_blog

后续docker-compose默认会以p11_blog命名容器

然后直接在控制台(windows终端或者idea的控制台都可以)

执行scp命令:

bash 复制代码
scp jar包路径.jar 用户名(一般都是root)@你的公网IP:你的服务器项目路径

执行完命令会提示输入服务器密码,输入完成后,即可开始传输jar

三、创建宿主机依赖路径、文件

3.1 宿主机mysql初始化文件

bash 复制代码
cd 回到项目路径
mkdir mysqlinit
cd ./mysqlinit
vim init.sql

然后把刚才我们提及到的1.2中的init.sql拷贝到这个路径(宿主机路径)

3.2 宿主机nginx配置文件

bash 复制代码
cd 回到项目路径
mkdir -p ./nginxhome/conf.d 
cd ./nginxhome/conf.d
vim myapp.conf

1.4中的myapp.conf配置文件拷贝过去即可,功能1.4已经讲过,这里不过多赘述

四、定义docker-compose.yml

注意

docker-compose.yml直接放到项目路径,那么其工作目录默认就是项目路径,下面的存储卷路径默认以项目路径为基准;

4.1 nginx容器定义

yml 复制代码
# 文件名:docker-compose.yml
services:
  web:
    image: nginx:latest
      
    volumes:
      - ./nginxhome/conf.d:/etc/nginx/conf.d #简洁写法,定义绑定卷

    ports:
      - 8080:80 #端口映射
    expose:
      - 80 #声明容器内部开放端口

4.2 mysql容器定义

bash 复制代码
# 文件名:docker-compose.yml
services:
  web:
  ...省略
  mysql:
    image: mysql:5.7
    container_name: mysql_container #定义容器名称

    volumes:
      - type: bind #这是完整方式定义绑定卷
        source: ./mysqlinit/
        target: /var/lib/mysql/
        read_only: true
        volume:
          nocopy: false  #若宿主机目录为空,复制容器数据到宿主机目录

4.3 spring-boot容器定义

这里我们使用openjdk镜像去驱动jar包:

bash 复制代码
# 文件名:docker-compose.yml
services:
  web:
  ....省略
  myapp:
    image: openjdk:17 #这里版本,使用和自己java版本一致的就行

    volumes:
      - ./app:/app/ #简洁定义绑定卷

    command: java -jar /app/docker_compose-0.0.1-SNAPSHOT.jar #设置启动命令

4.4容器依赖关系与健康检查

4.4.1 概述

回到第一节的目标上,我们需要启动一个spring-boot程序,查询user表内容,并且通过nginx实现反向代理;这里涉及多个容器:myapp、mysql、nginx;

那么容器之间一定存在这样的依赖关系:

  1. myapp查询user表需要mysql
  2. nginx反向代理myapp,前提是myapp要优先于nginx启动

docker-compose.yml提供了depends_on来实现这种容器之间的依赖需求。

此外这还引入了一个问题:如何判断依赖的容器是否成功启动呢?
docker-compose.yml也很贴心,给我们提供了healthcheck来自定义容器如何算是启动成功;

接下来,我会接着用这个案例来具体显示其用法

4.4.2 健康检查

根据4.4.1的说明myappmysql是被依赖的容器,那么它们两个一定需要健康检查(虽然nginx健康检出是不必须的,但是建议也加上,实现增肌)

bash 复制代码
#文件名:docker-compose.yml
services:
  mysql:
    healthcheck:
      test: mysql -u root -p1111 -e 'select 1;' #mysql自带的健康检查
      interval: 10s
        timeout: 10s
        retries: 5



  myapp:
    healthcheck:
      test: ["CMD", "sh", "-c", "jps -l | grep 'docker_compose-0.0.1-SNAPSHOT.jar' || exit 1"] #该命令openjdk自带的
      interval: 10s #检查间隔时间
      timeout: 5s # 定义超时时间
      retries: 5 # 重试最大次数
      start_period: 30s #给一个启动缓冲时间,30s之后才开始记录重试次数

4.4.3 容器依赖关系(也叫容器拓扑)

以下为省略写法(只含有依赖定义):

yml 复制代码
#文件名:docker-compose.yml
services:
  web:
    depends_on:
      mysql:
        condition: service_healthy #condition不为headlthy则容器编排会报错
      myapp:
        condition: service_healthy
  
  myapp:
    depends_on:
      mysql:
        condition: service_healthy

condition健康类型的选项:

状态值 含义
service_healthy 依赖的服务容器状态为 healthy(健康检查通过)
service_started 依赖的服务容器只是 running(进程启动,不校验健康状态)------ 这是默认值
service_completed_successfully 依赖的服务容器已 exited 且退出码为 0(适用于一次性任务,如初始化脚本)

4.5 容器网络定义

还是回到第一节讲到的目标,配置Spring-boot+Mysql+Nginx容器编排,网络类型毫无疑问,bridge是最合适的;所以我们可以定义一个自定义bridge网络,让三个容器都加入该自定义网络即可:

yml 复制代码
#文件名:docker-compose.yml

services:
  web:
    image: nginx:latest #指定容器的nginx镜像版本

    volumes:
      - ./nginxhome/conf.d:/etc/nginx/conf.d #简洁写法,定义绑定卷

    ports:
      - 8080:80 #端口映射
    expose:
      - 80 #声明容器内部开放端口

    depends_on:
      mysql:
        condition: service_healthy
      myapp:
        condition: service_healthy
    networks:
      - mybridge_network


  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: 1111
    container_name: mysql_container

    volumes:
      - type: bind #这是完整定义方式
        source: ./mysql/mysqllib/
        target: /var/lib/mysql/ #mysql元数据存储在这里
        read_only: false
        volume:
          nocopy: false
      - type: bind
        source: ./mysql/mysqlinit
        target: /docker-entrypoint-initdb.d/ #自动根据ini.sql初始化数据


    healthcheck:        
      test: mysql -u root -p1111 -e 'select 1;'
      interval: 10s
      timeout: 10s
      retries: 5
    networks:
      - mybridge_network


  myapp:
    image: openjdk:17
    
    volumes:
      - ./app:/app/

    command: java -jar /app/docker_compose-0.0.1-SNAPSHOT.jar

    healthcheck:
      test: ["CMD", "sh", "-c", "jps -l | grep 'docker_compose-0.0.1-SNAPSHOT.jar' || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    networks:
      - mybridge_network

networks:
  mybridge_network:
    driver: bridge

五、启动docker-compose.yml

启动所有容器:

bash 复制代码
cd 回到项目路径
docker compose up -d
WARN[0000] mount of type `bind` should not define `volume` option 
[+] Running 3/3
 ✔ Container p11_blog-myapp-1  Healthy                                                                                                                                6.5s 
 ✔ Container mysql_container   Healthy                                                                                                                               11.0s 
 ✔ Container p11_blog-web-1    Started                                                                                                                               13.0s 
root@iZ2ze8ve39i30yl0dhbqneZ:~/docker_stu/docker_compose/p11_blog# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS                    PORTS                                     NAMES
bf059297e184   nginx:latest   "/docker-entrypoint...."   48 seconds ago   Up 37 seconds             0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   p11_blog-web-1
82746d8b74d1   openjdk:17     "java -jar /app/dock..."   48 seconds ago   Up 48 seconds (healthy)                                             p11_blog-myapp-1
a69b1ac6de7d   mysql:5.7      "docker-entrypoint.s..."   48 seconds ago   Up 48 seconds (healthy)   3306/tcp, 33060/tcp                       mysql_container

查看地址:公网IP:8080

成功回显数据:

查看网络创建情况:

bash 复制代码
docker network ls |grep  p11
1de554ab3031   p11_blog_mybridge_network   bridge    local
docker compose down
[+] Running 4/4
 ✔ Container p11_blog-web-1           Removed                                                                                                                         1.3s 
 ✔ Container mysql_container          Removed                                                                                                                         4.6s 
 ✔ Container p11_blog-myapp-1         Removed                                                                                                                         1.3s 
 ✔ Network p11_blog_mybridge_network  Removed                                                                                                                         0.3s 
root@iZ2ze8ve39i30yl0dhbqneZ:~/docker_stu/docker_compose/p11_blog# docker network ls |grep  p11 #停止并且删除容器后,再次查看,网络也已经被删除了

end

相关推荐
人生匆匆2 小时前
配置nginx ssl反向代理tcp端口
tcp/ip·nginx·ssl
召田最帅boy2 小时前
为博客每日一句添加音频播放功能
spring boot·html·音视频
轩情吖2 小时前
MySQL内置函数
android·数据库·c++·后端·mysql·开发·函数
ID_云泽2 小时前
MySQL 备份工具分享(三):定时全量备份
数据库·mysql·数据备份
小邓睡不饱耶2 小时前
实战教程:Python爬取北京新发地农产品价格数据并存储到MySQL
开发语言·python·mysql
小箌2 小时前
springboot_02
java·spring boot·后端
zzh0812 小时前
Nginx性能优化与监控笔记
笔记·nginx·性能优化
moxiaoran57532 小时前
MySQL分库分表的实现(二)--水平分表
数据库·mysql
亚林瓜子2 小时前
AWS RDS创建ReadLatency,WriteLatency,DBLoad,AuroraVolumeBytesLeftTotal四种指标告警
mysql·aws·aurora·alarm·cloudwatch·rds·cw