要么改变世界,要么适应世界

docker-compose部署博客系统(nginx+MySQL+Nuxt+Java)

2023-09-29 16:18:44
167
目录

前言

之前博客系统是直接部署在云服务器物理机上的(严格意义上来说不算是物理机,毕竟是云服务器,哪有运行商那么好直接给你物理机?更多的可能是在物理机的基础上加了他们自己的虚拟服务),奈何家境贫寒的我,买的服务器只有2g内存,运行过程node线程占用内存会越来越大,排查了很久也没有找到是哪个地方存在内存泄漏,或许是框架的问题?

等内存占用快爆满的时候,Java进程总是会被迫下线,虽然我加了个crontab任务,每天重启PM2任务,但是如果某天博客系统被访问多了,node进程老早就把内存吃满了,Java线程可能很快就被下线了。

所以之前,平均每两三天我就得手动访问一下博客系统,看看是否一切都正常,作为计算机专业学生实在受不了了,好笨的方法😭。

干脆使用docker-compose吧,让各个容器都可以遇到错误的时候自动重启,弄个自动化部署的脚本,这样子还方便下次迁移。

docker安装

docker-compose安装

编排文件

www目录下创建文件夹blogSystem

cd /www
mkdir blogSystem

再在blogSystem中创建相应的文件夹:

.
├── api
│   ├── config
│   │   └── application.yml
│   ├── Dockerfile
│   ├── link
│   ├── log
│   └── rblog-0.0.1-SNAPSHOT.jar
├── compose
│   ├── mysql
│   │   ├── conf
│   │   │   └── my.cnf
│   │   └── init
│   │       └── blog-2023-09-23.sql
│   └── nginx
│       ├── cert
│       ├── conf
│       │   ├── nginx.conf
│       ├── conf.d
│       ├── html
│       └── logs
├── docker-compose.yml
└── front
    ├── Dockerfile
    ├── nuxt.config.js
    ├── package.json
    ├── package-lock.json
    └── static

相关文件夹作用如下:

后端

后端主要在api文件夹下,后端容器对应的Dockerfile如下:

FROM openjdk:8-jre-alpine
# 容器内创建项目目录
RUN mkdir -p /opt/blog
WORKDIR /opt/blog
# 将当前目录下文件 放入容器指定目录
ADD . /opt/blog
# 按照日期分割日志
ENTRYPOINT ["java", "-jar", "rblog-0.0.1-SNAPSHOT.jar", ">>", "./log/nohup`date +%Y-%m-%d`.out", "2>&1"]

由于后端打包后是一个可执行jar包,因此相对而言Dockerfile比较简单。

configSpring Boot的配置文件,其中有一个很重要的地方需要更改:

spring:
  datasource:
    url: jdbc:mysql://db:3306/blog?serverTimezone=UTC&characterEncoding=UTF-8&useSSL=false&useJDBCCompliantTimezoneShift=true&useUnicode=true
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
  jackson:
    time-zone: GMT+8

因为数据库和Java应用在不同的容器中,因此数据库连接不能使用localhost或者127.0.0.1,要用容器名字(这里用的是db)。

link放的是博客系统中的业务需求,与部署不太相关。

数据库

数据库相关的在compose/mysql文件夹下,其中conf文件夹下放配置文件my.cnf,内容如下:

# compose/mysql/conf/my.cnf
[mysqld]
user=mysql
default-storage-engine=INNODB
character-set-server=utf8
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

port            = 3306 # 这里端口于docker-compose里映射端口保持一致
#bind-address= localhost

basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
skip-name-resolve # 这个参数是禁止域名解析的,远程访问推荐开启skip_name_resolve。
character_set_server=utf8mb4
[client]
port = 3306
default-character-set=utf8mb4

[mysql]
no-auto-rehash
default-character-set=utf8mb4

init文件夹下放的是初始数据库,即博客系统的数据。

前端

前端相关的在front文件夹下,其中有一个Dockerfile,内容如下:

# 使用 Node.js 18 作为基础镜像
FROM node:12.16.1

MAINTAINER yalexin


# 设置工作目录
WORKDIR /app
ENV NODE_ENV=production

ENV HOST 0.0.0.0

# 复制项目文件到容器中
COPY . .

# 安装项目依赖
RUN npm install



# 构建 Nuxt.js 应用
#RUN npm run build

# 暴露应用所使用的端口(默认为 3000)
EXPOSE 3000

# 启动 Nuxt.js 应用
CMD ["npm", "run", "start" ]

nuxt.config.js中,代理需要更改:

  proxy: {
    '/api': {
        // target要更改为服务器真实IP
        target: 'http://182.43.75.61:8080/api/',
        ws: false,
        changeOrigin: true,
        pathRewrite: {
            '^/api': '',
        }
    }
  }

package-lock.json千万别忘了一起放过来

nginx

nginx相关的文件在文件夹compose/nginx下:

其中cert文件文件夹下放的是ssl证书。

conf文件夹下是配置文件nginx.conf,内容如下:

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
  worker_connections 1024;
}

http {
  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;
  tcp_nodelay         on;
  keepalive_timeout   65;
  types_hash_max_size 4096;

  include /etc/nginx/mime.types;
  default_type        application/octet-stream;

  # Load modular configuration files from the /etc/nginx/conf.d directory.
  # See http://nginx.org/en/docs/ngx_core_module.html#include
  # for more information.
  include /etc/nginx/conf.d/*.conf;

  server {
    listen 80;
    listen       443 ssl;
	# http自动转https
    if ($server_port !~ 443){
        rewrite ^(/.*)$ https://$host$1 permanent;
    }
    # 证书文件
        ssl_certificate "/etc/nginx/cert/www.yalexin.top_bundle.pem";
    ssl_certificate_key "/etc/nginx/cert/www.yalexin.top.key";
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;

    server_name www.yalexin.top;
    root         /usr/share/nginx/html;

    include /etc/nginx/default.d/*.conf;

    error_page 404 /404.html;
    location = /404.html {
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    }
    
    # 将用户请求转发到后台
    location /api/ {
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      real_ip_header    X-Forwarded-For;
      real_ip_recursive  on;
      # 这里用的还是容器名称
      proxy_pass http://blog_api:8080;

    }
    
    #这里是需要部署的二级目录应用配置
    location ^~/blog/ {

      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      real_ip_header    X-Forwarded-For;
      real_ip_recursive  on;
	  # 这里用的还是容器名称
      proxy_pass http://node:3000/blog/;

    }

    # 必应代理
    location /bingProxy/ {
      rewrite ^/bingProxy/(.*)$ /$1 break;  #对加了proxy前缀的请求加以区分,真正访问的时候移除这个前缀,这个前缀需要自定义
      proxy_pass https://cn.bing.com;  #将真正的请求代理到真实的服务器地址
    }
  }
}

html下放的是静态文件,我放的是个人主页相关的内容,里边有地方用到了必应壁纸,因此上面的配置中有相关配置。

logs放的是日志相关

docker-compose.yml

到了最重要的docker-compose.yml了,它描述了各个容器要做的内容:

version: "3"
volumes: # 自定义数据卷,位于宿主机/var/lib/docker/volumes内
  reputation_db_vol: # 定义数据卷同步容器内mysql数据

services:
  node:
    build: ./front # 使用 front 目录下的Dockerfile
    ports:
       - "3000:3000"
    expose:
       - "3000"
    restart: always # always表容器运行发生错误时一直重启
  db:
    image: mysql:5.7
    environment:
       - MYSQL_ROOT_PASSWORD=123456 # 数据库密码
       - MYSQL_DATABASE=blog # 数据库名称
       - MYSQL_USER=yalexin # 数据库用户名
       - MYSQL_PASSWORD=123456 # 用户密码

    volumes:
       - reputation_db_vol:/var/lib/mysql:rw # 挂载数据库数据, 可读可写
       - ./compose/mysql/conf/my.cnf:/etc/mysql/my.cnf # 挂载配置文件
       - ./compose/mysql/init:/docker-entrypoint-initdb.d/ # 挂载数据初始化sql脚本
    ports:
       - "3306:3306" # 与配置文件保持一致,映射端口
    expose:
       - "3306"
    restart: always

  blog_api:
    image: blog_api:2.0.0
    build: ./api # 使用 api 目录下的Dockerfile
    ports:
       - "8080:8080"
    expose:
       - "8080"
    volumes:
       - ./api/log:/opt/blog/log # 挂载后端日志
    restart: always
    tty: true
    stdin_open: true    
  nginx_web:
     #定义主机名
     container_name: nginx_container
     #使用的镜像
     image: nginx:1.16.1
     #容器的映射端口
     ports:
       - 80:80
       - 443:443
     #定义挂载点         
     volumes:
       - ./compose/nginx/html:/usr/share/nginx/html
       - ./compose/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
       - ./compose/nginx/conf.d:/etc/nginx/conf.d
       - ./compose/nginx/logs:/var/log/nginx
       - ./compose/nginx/cert:/etc/nginx/cert

     #docker 重启后,容器自启动
     restart: always
     links:
       - node
       - db
       - blog_api
     depends_on: # 依赖关系
       - node
       - db
       - blog_api

完成后,在blogSystem目录下,构建我们的应用,并运行:

docker-compose build
docker-compose up -d

最后

人生,重在折腾!

最后,祝大家中秋国庆快乐!😘

历史评论
开始评论