docker-compose部署博客系统(nginx+MySQL+Nuxt+Java)
前言
之前博客系统是直接部署在云服务器物理机上的(严格意义上来说不算是物理机,毕竟是云服务器,哪有运行商那么好直接给你物理机?更多的可能是在物理机的基础上加了他们自己的虚拟服务),奈何家境贫寒的我,买的服务器只有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
比较简单。
config
放Spring 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
最后
人生,重在折腾!
最后,祝大家中秋国庆快乐!😘
本文由「黄阿信」创作,创作不易,请多支持。
如果您觉得本文写得不错,那就点一下「赞赏」请我喝杯咖啡~
商业转载请联系作者获得授权,非商业转载请附上原文出处及本链接。
关注公众号,获取最新动态!