基于docker-compose.yml配置vue+nest+mysql+redis网站


一、整体架构设计

1.多容器协作模式

Docker 部署 Vue(前端)和 Node.js(后端)的 Web 服务,通常采用 多容器协作模式

  1. 前端容器:基于 Nginx 镜像托管 Vue 构建产物(如 dist 目录)。

  2. 后端容器:基于 Node.js 镜像运行 API 服务,处理数据库 MySQL 交互和业务逻辑。

  3. 数据库容器:如 MySQLRedis,通过数据卷持久化存储数据。

  4. Jenkins 容器:自动化构建与部署流水线控制中心。

  5. Nginx 容器:反向代理前端请求,支持多域名配置。

  6. 网络与通信

  • 使用 Docker 自定义网络(如 my-network)确保容器间通过服务名互通。
  • Nginx 通过 proxy_passAPI 请求转发至后端容器(如 http://backend:3000)。

2.整体架构


+----------+----------+

+---------------------+

|    Nginx     | # 反向代理/静态资源/多站点

+----------+----------+

     |

+----------v----------+  +------------------+

|   Vue Frontend   |  |  Node.js Backend|

+----------+----------+  +--------+---------+

     |            |

+----------v------------------------v---------+

|        Docker Network        |

+----------+------------------+--------------+

     |         |

+----------v----------+ +-----v--------------+

|  MySQL Container  | |  Redis Container  |

+---------------------+ +--------------------+

3.分步部署指南


project/

├── frontend/      # Vue项目

│  ├── Dockerfile

│  ├── jenkinsfile

│  └── Vue项目文件

├── backend/       # Node.js项目

│  ├── Dockerfile

│  ├── jenkinsfile

│  └── Node.js项目文件

├── nginx/

│  ├── conf.d/

│  │  ├── site1.conf  # 站点配置

│  │  └── site2.conf

│  └── nginx.conf

├── docker-compose.yml

└── jenkins/

  └── jenkinsfile   # 主部署脚本

二、分步部署指南

1. 前端 Vue 项目容器化

步骤 1:编写 Dockerfile

在 Vue 项目根目录创建 Dockerfile,采用 多阶段构建 优化镜像体积:

# 第一阶段:构建项目
FROM node:latest AS build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install --registry=https://registry.npmmirror.com
COPY . .
RUN npm run build


# 第二阶段:生产环境 部署到 Nginx
# nginx:latest 是基于 Debian 或 Ubuntu 的完整 Nginx 镜像,包含了所有 Nginx 的功能和模块。

FROM nginx:latest
COPY --from=build-stage /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

关键点

  • 使用 node:latest 安装依赖并构建,减少镜像层大小。
  • 使用 .dockerignore 忽略 node_modules.env 敏感文件。
  • 通过 nginx.conf 配置反向代理(如后端 API 地址)。

步骤 2:构建并运行前端容器

docker build -t vue-app . # 使用 Dockerfile 从当前目录构建一个名为 vue-app 的 Docker 镜像
docker run -d -p 80:80 --name vue-container vue-app #运行一个基于 vue-app 镜像的容器,将其命名为 vue-container,并且将容器的 80 端口映射到主机的 80 端口。

2. 后端 Node.js 项目容器化

步骤 1:编写 Dockerfile

在 Node.js 项目根目录创建 Dockerfile

FROM node:latest
WORKDIR /app
COPY package*.json ./
RUN npm install --production --registry=https://registry.npmmirror.com
COPY . .
ENV MYSQL_HOST=mysql REDIS_HOST=redis
EXPOSE 3000
CMD ["npm", "start"]

关键点

  • 使用 npm install --production 仅安装生产依赖。
  • 通过环境变量(如 .env)配置数据库连接信息。
  • 通过环境变量注入 MySQLRedis 连接信息。
  • backend 容器内使用 ping mysqltelnet redis 6379 验证连通性。

步骤 2:构建并运行后端容器

docker build -t node-api . # 使用 Dockerfile 从当前目录构建一个名为 node-api 的 Docker 镜像
docker run -d -p 3000:3000 --name api-container node-api #运行一个基于 node-api 镜像的容器,将其命名为 api-container,并且将容器的 3000 端口映射到主机的 3000 端口。

3. 数据库容器与数据持久化

使用 MySQL 容器

docker run -d \
--name mysql-container \
--env-file .env \  # 加载 .env 文件中的所有变量
-v mysql-data:/var/lib/mysql \
# -e MYSQL_ROOT_PASSWORD=your_password \
# -e MYSQL_DATABASE=your_db \
-p 3306:3306 \
--network my-network \
mysql:latest

关键点

  • -v mysql-data:/var/lib/mysql 通过数据卷持久化数据库。
  • Node.js 代码中通过 process.env.MYSQL_HOST 读取环境变量。
  • 通过数据卷 mysql-data 持久化数据,避免容器重启后数据丢失。

4. Nginx 多站点配置

示例 nginx/conf.d/site1.conf

server {
    listen 80;
    server_name example.com;

    # 前端
    location / {
        proxy_pass http://frontend;
        proxy_set_header Host $host;
    }

    # 后端API
    location /api/ {
        proxy_pass http://backend:3000;
        proxy_set_header Host $host;
    }
}

关键点

  • 每个域名对应独立的 server 块,支持 SSL 证书挂载(需 Certbot 自动化)。

  • 前端静态文件路径与容器内目录映射一致。

docker-compose.yml 片段

services:
    nginx:
        image: nginx:latest
        volumes:
            - ./nginx/site1.conf:/etc/nginx/conf.d/site1.conf
            - ./nginx/site2.conf:/etc/nginx/conf.d/site2.conf
        ports:
            - "80:80"
            - "443:443"
        networks:
            - my-network

5.Redis 容器

docker run -d \
--name redis \
-v redis-data:/data \
-v ./redis.conf:/usr/local/etc/redis/redis.conf \
--network my-network \
redis redis-server /usr/local/etc/redis/redis.conf

关键点

  • 挂载自定义配置文件 redis.conf,设置密码和内存限制(如 requirepass your_redis_passmaxmemory 512mb)。

6. Jenkins 自动化部署

Jenkins 容器启动

docker run -d \
--name jenkins \
-p 8080:8080 -p 50000:50000 \
-v jenkins-data:/var/jenkins_home \
--network my-network \
jenkins/jenkins:lts

关键点

  • 挂载 jenkins-data 卷保存配置,安装插件(Git、Publish Over SSH、Pipeline)。

Pipeline 脚本示例(jenkins/jenkinsfile

pipeline {
    agent any
    stages {
        stage('Checkout') {
            steps {
                git branch: 'main', url: 'https://github.com/your-repo.git'
            }
        }

        stage('Build Frontend') {
            steps {
                    dir('frontend') {
                    sh 'docker build -t vue-app .'
                }
            }
        }

        stage('Build Backend') {
            steps {
                    dir('backend') {
                    sh 'docker build -t node-api .'
                }
            }
        }

        stage('Deploy') {
            steps {
                sh 'docker-compose down && docker-compose up -d'
            }
        }
   }
    post {
        success {
            slackSend(color: '#00FF00', message: 'Deployment succeeded')
        }

        failure {
            slackSend(color: '#FF0000', message: 'Deployment failed')
        }

    }
}

关键点

  • 通过 docker-compose.yml 统一管理服务启动顺序和依赖。

三、整合服务Docker Compose 编排

在项目根目录创建 docker-compose.yml,统一管理多服务:

# version: "3.8" # Docker Compose V2+ 版本移除了对 version 字段的支持,继续保留该字段会导致警告(但不会影响运行)。
name: vue_project # 定义项目名称

services:
    # 前端服务
    frontend:
        build:
            context: ./vue-app
            dockerfile: Dockerfile
        container_name: vue-container
        restart: always
        ports:
            - "8080:80"
        depends_on:
            - backend
        networks:
            - app-network

    # Node.js后端服务
    backend:
        build:
            context: ./node-api
            # args:
            #     # 构建时传参
            #     NPM_REGISTRY: "https://registry.npmmirror.com"
            dockerfile: Dockerfile
        container_name: api-container
        restart: always
        env_file: .env # 直接指向文件
        # command: npm run dev  # 开发模式启用热重载
        environment:
            # npm 镜像源
            - NPM_CONFIG_REGISTRY="https://registry.npmmirror.com"
            - NODE_ENV=production
            - DB_HOST=mysql
            - DB_USER=root
            - DB_PASSWORD=${MYSQL_ROOT_PASSWORD} #your_mysql_root_password
            - DB_NAME=${MYSQL_DATABASE} #your_database_name
            - REDIS_HOST=redis
            - REDIS_PORT=6379
        ports:
            - "3000:3000"
        volumes:
            # 持久化 npm 缓存(加速后续构建)
            - ./npm_cache:/root/.npm
        depends_on:
            mysql:
                condition: service_healthy
            redis:
                condition: service_healthy
        networks:
            - app-network

    #Nginx反向代理
    nginx:
        image: nginx:latest
        container_name: nginx-proxy
        restart: always
        volumes:
            - ./nginx/conf.d:/etc/nginx/conf.d
            - ./nginx/nginx.conf:/etc/nginx/nginx.conf
        ports:
            - "80:80"
            - "443:443"
        depends_on:
            - frontend
            - backend
        networks:
            - app-network

    #MySQL数据库
    mysql:
        image: mysql:latest
        container_name: mysql-container
        restart: always
        env_file: .env # 直接指向文件
        environment:
            # 🌟 基础配置(必须项) 🌟
            MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} #your_password 设置 root 用户的密码
            MYSQL_DATABASE: ${MYSQL_DATABASE} #your_database 创建的数据库名称(可选)

            # 🔒 高级安全配置(新增部分) 🔒
            MYSQL_ROOT_HOST: "%" # '%' 允许 root 用户从任意 IP 访问,​生产环境强烈建议关闭;'localhost' 仅允许本机访问
            # MYSQL_USER_HOST: "%" # 允许普通用户从任意 IP 访问,生产环境强烈建议关闭
            # MYSQL_SSL_MODE: "REQUIRED" # 强制SSL连接
            # MYSQL_SSL_CA: "/etc/ssl/certs/ca-certificates.crt" # SSL证书路径
            # 🔐 其他配置(可选) 🔐
            TZ: "Asia/Shanghai" # 设置容器时区为上海时间
        volumes:
            - mysql_data:/var/lib/mysql
            # - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql # 自定义初始化脚本目录
        ports:
            - "3306:3306"
        # 明确启动命令
        command: ["mysqld", "--character-set-server=utf8mb4"]
        networks:
            - app-network
        healthcheck:
            test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
            interval: 5s
            timeout: 10s
            retries: 10
        logging: # Docker 的日志配置
            driver: "json-file" # 使用文件日志
            options:
                max-size: "200m"
                max-file: "10"

    #Redis缓存
    redis:
        image: redis:latest
        container_name: redis-cache
        restart: always
        ports:
            - "6379:6379"
        volumes:
            - redis_data:/data
        networks:
            - app-network
        healthcheck:
            test: ["CMD", "redis-cli", "ping"]
            interval: 5s
            timeout: 10s
            retries: 10

    #Jenkins自动化部署
    jenkins:
        image: jenkins/jenkins:lts
        container_name: jenkins-cli
        restart: unless-stopped
        user: root
        ports:
            - "8081:8080"
            - "50000:50000"
        volumes:
            - jenkins_data:/var/jenkins_home
            - /var/run/docker.sock:/var/run/docker.sock
            - ./:/var/jenkins_workspace
        networks:
            - app-network

    # kuma 网络监听
    uptime-kuma:
        image: louislam/uptime-kuma:1
        container_name: uptime-kuma
        restart: always
        volumes:
            - ./uptime-kuma:/var/lib/kuma/data
        ports:
            - 30001:30001
        networks:
            - app-network

#数据卷定义
volumes:
    mysql_data:
    redis_data:
    jenkins_data:
    kuma_data:

#网络定义
networks:
    app-network:
        driver: bridge
# .env 文件
MYSQL_ROOT_PASSWORD=my-secret-pw
MYSQL_DATABASE=appdb
MYSQL_USER=appuser
MYSQL_PASSWORD=apppw
# 环境变量
ENVIRONMENT=dev

关键点

  • 通过 depends_on 控制服务启动顺序。
  • 使用共享网络确保容器间通过服务名通信(如 backend 访问 mysql)。

总结

通过 Docker Compose 编排,我们可以将多个容器组合成一个应用,实现服务的统一管理和部署。同时,通过 docker-compose.yml 配置文件,我们可以定义服务的依赖关系、网络配置和数据卷挂载,简化了容器的启动和管理过程。

1.部署流程说明:

  • Jenkins 配置流水线任务,监听代码仓库变更
  • 触发构建时自动执行:
    • 前端:npm install && npm run build
    • 后端:npm install && 运行测试
  • 通过 Docker 命令重新构建镜像并重启容器
  • 使用 Webhook 通知部署状态

2.使用前需要:

  • 替换所有密码(your_mysql_root_password)
  • 配置 Nginx 的域名和 SSL 证书
  • 根据项目需求调整端口和路径
  • 配置 Jenkins 流水线脚本
  • 添加.env 文件管理敏感信息(推荐)

3.建议的安全增强措施:

  1. 为 MySQL 创建专用用户代替 root
  2. 使用 Docker secrets 管理敏感信息
  3. 添加适当的容器资源限制
  4. 配置 Redis 密码保护
  5. 启用 Nginx 的 HTTPS 配置
  6. 设置防火墙规则限制外部访问

四、 初始化及启动


# 创建网络
docker network create app-network

# 启动所有服务
docker-compose up -d --build

# 查看日志
docker-compose logs -f

针对项目中的容器名(根据 docker-compose.yml 定义)

容器名 服务用途 推荐进入命令
mysql-container MySQL 数据库 docker exec -it mysql-container mysql -u root -p
api-container Node.js 后端 docker exec -it api-container sh
vue-container Vue 前端 docker exec -it vue-container sh
redis-cache Redis 缓存 docker exec -it redis-cache redis-cli
nginx-proxy Nginx 反向代理 docker exec -it nginx-proxy nginx -t

五、关键注意事项及优化建议

1.注意事项

  1. 环境变量管理
  • 使用 .env 文件管理敏感信息
  • 在 Docker Compose 中使用 env_file 配置
  1. 数据持久化
volumes:
    - ./mysql/data:/var/lib/mysql

    - ./redis/data:/data
  1. 集群扩展
docker-compose scale backend=3
  1. 健康检查
healthcheck:

test: ["CMD", "curl", "-f", "http://localhost:3000/health"]

interval: 30s

timeout: 10s

retries: 3

2.优化与扩展

  1. 镜像加速:在 Dockerfile 中配置国内镜像源(如 npmmirror.com)提升构建速度。

  2. 负载均衡:通过 pm2 启动 Node.js 服务,支持多进程和自动重启。

  3. 安全与性能

  • 使用 .dockerignore 忽略 node_modules 和敏感文件。
  • 通过 nginx.conf 配置 HTTPSGzip 压缩。
  • HTTPS 配置:在 Nginx 配置中添加 SSL 证书,使用 Let's Encrypt 自动更新 SSL 证书。
  • Redis 优化:启用 AOF 持久化,设置内存淘汰策略(如 maxmemory-policy allkeys-lru)。
  • MySQL 备份:通过 Cron 定时任务导出数据库至宿主机。
  1. 自动化流程整合
  • 配置 GitLab Webhook:代码提交后触发 Jenkins Pipeline
  • 钉钉通知插件:部署结果实时推送至团队群。
  1. 横向扩展
  • 负载均衡Nginx 配置 upstream 实现后端多容器负载。
  • Redis 集群:使用 Docker SwarmKubernetes 扩展 Redis 节点。

六、常见问题排查

  • 环境变量未生效:确认 Dockerfile 或 docker-compose.yml 中变量传递正确。

  • 容器网络不通

    • 检查 docker-compose.yml 中的服务名和端口映射。
    • 检查 Docker 网络配置,确保 depends_on 和自定义网络正确
  • 依赖安装失败:确认 package.json 中依赖版本与 Node.js 镜像版本兼容。

  • 数据库连接超时:确保 MySQL 容器已启动且环境变量正确。

  • Nginx 403 错误:检查静态文件目录权限(如 chown -R www-data:www-data /var/www)。

  • 无权限进入容器:添加 --user root 参数

  • 容器未运行:先执行 docker start [容器名]

  • 命令不存在:改用镜像内置的命令(如 Redis 用 redis-cli

超时报错

安装 docker 镜像时,抛出Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

解决方法:

sudo vi /etc/resolv.conf

#删掉默认的nameserver地址在后面增加
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 114.114.114.114

#从新加载
systemctl restart systemd-resolved.service

七、常用运维命令

# 进入正在运行的容器
docker exec -it [容器名或ID] [执行的命令]

# 进入容器默认 shell(适用于大多数镜像)
docker exec -it mysql-container sh       # Alpine 系镜像用 sh
docker exec -it api-container bash     # Debian/Ubuntu 系镜像用 bash

# 直接运行特定命令(不进入交互模式)
# 在 MySQL 容器中执行查询
docker exec -it mysql-container mysql -u root -p -e "SHOW DATABASES;"
# 查看 Nginx 容器配置
docker exec -it nginx-proxy cat /etc/nginx/nginx.conf

# 检查容器是否能访问其他服务
docker exec -it api-container ping redis

# 进入正在运行的 MySQL 容器 第一个mysql是容器的名字
docker exec -it mysql mysql -u root -p

# 执行数据库备份
docker exec -i mysql sh -c 'mysqldump -u root -prootpass appdb' > backup.sql

# 进入Redis CLI
docker exec -it redis redis-cli

# 运行 Docker Compose
docker-compose up -d
# 查看容器状态
docker-compose ps
# 停止所有容器
docker-compose stop

# 启动所有容器
docker-compose start

# 查看容器日志
docker-compose logs -f --tail=100

# 停止旧服务(如果已运行)
docker-compose down

# 查看compose是否成功执行
docker compose ls

# 查看卷是否创建
docker volume ls

# 查看网络是否创建
docker network ls

# 重新启动(建议指定项目名,避免目录名不合法)
docker-compose -p my_project up -d

# 查看运行状态
docker-compose -p my_project ps

# 查看 MySQL 日志
docker-compose -p my_project logs mysql

# 查看 Redis 日志
docker-compose -p my_project logs redis

文章作者: 弈心
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 弈心 !
评论
  目录