Docker 构建Node后端项目,拉取MySQL、Redis、MongoDB镜像,然后全部部署到腾讯云服务器

149 阅读9分钟

后端项目示例

  • file-server(后端文件服务)
    • 技术栈:Node.js 18 + Express.js 4 + TypeScript + MongoDB + Multer
  • node-project(后端Node.js服务)
    • 技术栈:Node.js 18 + Express.js 4 + TypeScript + MySQL + Redis + Sequelize + jsonwebtoken

1. 本地电脑环境准备

  • 根据电脑类型下载安装对应的 docker image.png

  • 各个项目配置好打包命令
    例如file-server项目package.json文件的scripts内容如下:

    "scripts": {
        "dev": "nodemon src/app.ts --exec ts-node",
        "build": "tsc && ts-node copyStatic.ts",
        "start": "node dist/app.js"
    },
    
  • 提前选择配置好各个项目 Docker 容器之间的访问方式
    比如file-server怎么访问MongoDB的容器:

    • 使用ip和端口访问,访问的url如下:
      mongodbUrl: 'mongodb://用户名:密码@ip地址:27017'
      
    • 使用Docker创建自定义网络(docker network create),访问的url如下:
      mongodbUrl: 'mongodb://用户名:密码@mongodb:27017' // mongodb为运行的容器名称
      
  • 配置好各个项目的Dockerfile文件
    例如file-serverDockerfile文件内容如下:

    FROM node:18.18.0 AS builder
    WORKDIR /app
    COPY package*.json ./
    RUN yarn
    COPY . .
    RUN npm run build  # 生成 /app/dist
    
    FROM node:18.18.0
    WORKDIR /app
    COPY --from=builder /app/dist ./dist
    COPY --from=builder /app/package*.json ./
    RUN yarn --production
    EXPOSE 8001
    CMD ["node", "dist/app.js"]
    

2. 腾讯云服务器环境准备

首先,你得拿点💰买个云服务器,我是蹲的双十一便宜买的腾讯云轻量云应用服务器,以下流程都按照腾讯云轻量云应用服务器的页面和操作方式编写:

  • 服务器买好以后先在服务器上安装Docker,我是在服务器装系统的时候就选了一个 Docker 应用模板的系统。

  • 在腾讯云控制台上方搜索容器镜像服务,开通腾讯云镜像仓库个人版,然后按照要部署的项目名称新建仓库

3. 本地使用Docker构建镜像并推送到腾讯云服务器镜像仓库

  • 在所有要放到服务器的项目目录下执行docker build命令构建镜像(不包含数据库)
    例如在file-server项目下面执行:
    docker build \
        --platform linux/amd64 \ # 打包 linux/amd64(操作系统/架构)的镜像
        -t ccr.ccs.tencentyun.com/my-namespace/file-server:[tag] . \  
    
    # my-namespace 云服务器容器镜像服务命名空间名称;# [tag] 是变量,你定义的版本号;
    # 不要忘记命令最后有一个 .(点),是为了指明 Dockerfile 文件的位置
    
  • 登录腾讯云容器镜像服务
    直接在镜像仓库里面可以看到每个仓库的操作列里面有个【快捷指令】,点开复制登录命令即可
    docker login ccr.ccs.tencentyun.com --username=你的用户名
    # 然后输入密码
    
  • 将所有镜像推送到腾讯云服务器镜像仓库中
    例如file-server项目下面执行:
    # 镜像仓库 操作列 快捷指令可看到推送命令,可直接复制
    docker push ccr.ccs.tencentyun.com/my-namespace/file-server:[tag] # [tag] 是变量,你定义的版本号
    

4. 在腾讯云服务器拉取file-server镜像并运行

  • 拉取file-server镜像

    # 镜像仓库 操作列 快捷指令可看到拉取命令,可直接复制
    docker pull ccr.ccs.tencentyun.com/my-namespace/file-server:[tag] # [tag] 是变量,你定义的版本号
    
  • 运行file-server镜像

    • 通过ip和端口访问MongoDB容器,直接运行并做好端口映射即可
      docker run \
        --name file-server \
        --env-file /secrets/test.env \ # 加载当前部署环境的环境变量文件内容
        -p 8000:8000 \ # 将云服务器的端口与容器内部端口绑定,实现外部访问
        ccr.ccs.tencentyun.com/my-namespace/file-server:[tag] # [tag] 是变量,你定义的版本号
      
      注意: -p 8000:8000实现外部访问时,要注意打开云服务器防火墙的端口访问限制,允许外部访问。
    • 通过Docker创建自定义网络访问MongoDB容器
      • 先创建自定义网络
        docker network create file-net
        
      • 然后运行容器并加入网络
        docker run \
          --name file-server \
          --network file-net \ # 加入自定义网络
          -p 8000:8000 \  
          -e NODE_ENV=test \
          ccr.ccs.tencentyun.com/my-namespace/file-server:[tag]
        

5. 在腾讯云服务器拉取node-project镜像并运行

  • 拉取node-project镜像
    # 镜像仓库 操作列 快捷指令可看到拉取命令,可直接复制
    docker pull ccr.ccs.tencentyun.com/my-namespace/node-project:[tag] # [tag] 是变量,你定义的版本号
    
  • 运行node-project镜像
    • 通过ip和端口访问MySQLRedis容器,直接运行并做好端口映射即可
      docker run \
        --name node-project \
        --env-file /secrets/test.env \ # 加载当前部署环境的环境变量文件内容
        -p 8088:8088 \ # 将云服务器的端口与容器内部端口绑定,实现外部访问
        ccr.ccs.tencentyun.com/my-namespace/node-project:[tag] # [tag] 是变量,你定义的版本号
      
      注意: -p 8001:8001实现外部访问时,要注意打开云服务器防火墙的端口访问限制,允许外部访问。
    • 通过前面用Docker创建的自定义网络file-net访问MySQLRedis容器
      docker run \
        --name node-project \
        --network file-net \ # 加入自定义网络
        -p 8088:8088 \  
        -e NODE_ENV=test  \
        ccr.ccs.tencentyun.com/my-namespace/node-project:[tag]
      

6. 在腾讯云服务器拉取MongoDB镜像并运行

  • 拉取MongoDB镜像
    docker pull mongo:latest  # 拉取最新版
    docker pull mongo:5.0 # 或指定版本(如 5.0)
    
  • 运行MongoDB镜像
    # 创建数据持久目录并授权
    sudo mkdir -p /data/mongo/db && sudo chmod 755 /data/mongo/db
    
    # 运行镜像
    docker run \
      --name mongodb \ # 设置运行的容器名称为 mongodb
      --network file-net \ # 加入前面创建的自定义网络,实现同一个网络下的容器可直接通过容器名称访问
      -p 27017:27017 \ # 将云服务器的端口与容器内部端口绑定,实现外部访问
      -v /data/mongo/db:/data/db \ # 数据持久化,不持久化容器停止或删除后,内部文件系统会被清除
      -e MONGO_INITDB_ROOT_USERNAME=用户名 \ # 设置用户名
      -e MONGO_INITDB_ROOT_PASSWORD=密码 \ # 设置密码
      mongo # 选择要运行的镜像名称
    
    注意: -p 27017:27017 实现外部访问时,要注意打开云服务器防火墙的端口访问限制,允许外部访问。

7. 在腾讯云服务器拉取MySQL镜像并运行

  • 拉取MySQL镜像

    docker pull mysql:8.0
    
  • 创建数据持久目录并授权

    sudo mkdir -p /data/mysql/{data,conf.d} && sudo chmod 755 /data/mysql/{data,conf.d}
    
  • 创建配置文件my.cnf

    touch /data/mysql/conf.d/my.cnf  # 创建配置文件
    
  • 编辑配置文件my.cnf,输入以下内容

    [client]
    default-character-set = utf8mb4  # 客户端连接默认字符集
    
    [mysql]
    default-character-set = utf8mb4  # MySQL 命令行工具字符集
    
    [mysqld]
    character-set-server = utf8mb4    # 服务端默认字符集
    collation-server = utf8mb4_unicode_ci  # 服务端校对规则
    init_connect = 'SET NAMES utf8mb4'     # 每个新连接自动执行SET NAMES
    skip-character-set-client-handshake = ON  # 强制客户端使用服务端字符集
    
  • 运行MySQL镜像

    # 运行镜像
    docker run \
      --name mysql \
      --network file-net \ # 加入前面创建的自定义网络,实现同一个网络下的容器可直接通过容器名称访问
      -p 3306:3306 \
      -e MYSQL_ROOT_PASSWORD=密码 \
      -v /data/mysql/data:/var/lib/mysql \ # 挂载数据目录(数据持久化)
      -v /data/mysql/conf.d:/etc/mysql/conf.d \ # 挂载配置目录
      mysql:8.0
    
  • 安全加固(关键步骤)
    进入容器修改密码策略,兼容旧版客户端:

    # 进入容器终端
    docker exec -it mysql bash
    
    # 登录MySQL
    mysql -u root -p
    
    # 修改密码加密方式(解决低版本客户端连接问题)
    ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的新密码';
    FLUSH PRIVILEGES;
    
  • 从本地MySQL导出SQL文件,使用MySQL Workbench导出完整数据库
    导出步骤:

    1. 在Workbench中选择 ServerData Export
    2. 勾选目标数据库,选择 Dump Structure and Data(导出结构和数据)
    3. 勾选 Export to Self-Contained File(生成单一SQL文件)
    4. 指定文件路径(如 dump.sql)并点击 Start Export
  • SQL文件上传到服务器MySQL容器中,然后导入

    # 先将文件上传到服务器 /home/ubuntu 文件夹下
    
    # 然后执行下面的命令复制到 mysql容器内
    docker cp /home/ubuntu/you.sql mysql:/tmp/you.sql
    
    # 进入容器终端
    docker exec -it mysql bash
    
    # 登录MySQL
    mysql -u root -p
    
    # 创建数据库
    CREATE DATABASE db_name;
    
    # 检查是否创建成功,表格中显示有 db_name 则表示成功
    SHOW DATABASES;
    
    # 使用创建的数据库
    USE db_name;
    
    # 导入SQL文件到数据库中
    SOURCE /tmp/you.sql;
    
    # 检查表结构
    SHOW TABLES;
    
    # 随机抽取表数据检查
    SELECT * FROM 表名 LIMIT 10;
    

8. 在腾讯云服务器拉取Redis镜像并运行

  • 拉取Redis镜像
    docker pull redis:latest  # 拉取最新版
    
    docker pull redis:5.0.5  # 或指定版本
    
  • 创建创建数据持久目录并授权
    # 创建数据持久目录并授权
    sudo mkdir -p /data/redis/{data,conf} && sudo chmod 755 /data/redis/{data,conf}
    
  • 创建配置文件redis.conf
    touch /data/redis/conf/redis.conf  # 创建配置文件
    
  • 编辑配置文件redis.conf,输入以下内容
    # 允许远程连接
    bind 0.0.0.0
    # 关闭保护模式
    protected-mode no
    # 设置密码
    requirepass 密码
    # 限制内存
    maxmemory 2gb
    # 优先淘汰长期未使用的数据
    maxmemory-policy allkeys-lru
    
  • 运行Redis镜像
    # 运行镜像
    docker run \
      --name redis \
      --network file-net \ # 加入前面创建的自定义网络,实现同一个网络下的容器可直接通过容器名称访问
      -p 6379:6379 \
      -v /data/redis/data:/data \
      -v /data/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf \
      redis \
      redis-server /usr/local/etc/redis/redis.conf \
      --requirepass 123456Aa \ # 设置访问密码,强制客户端连接时进行身份验证
      --appendonly yes # 启用AOF持久化
    
  • 检查redis容器是否正常
    # 确认容器状态,为 UP 为正常
    docker ps | grep redis
    
    # 使用 redis-cli 测试连接与密码
    docker exec -it redis redis-cli
    
    AUTH 你的密码  # 返回 OK 表示密码正确
    SET testkey "hello"  # 测试写入
    GET testkey         # 应返回 "hello"
    

9. 根据不同后端服务的请求前缀配置Nignx转发

不配置Nignx访问不同的后端服务需要加上端口号,配置后直接访问域名或ip就行,Nignx根据不同的前缀进行转发。

  • 云服务器安装Nginx
    sudo apt update && sudo apt install nginx -y  # 更新并安装Nginx
    
    sudo systemctl start nginx && sudo systemctl enable nginx  # 启动并设置开机自启
    
  • 修改Nginx配置文件
    sudo vim /etc/nginx/sites-available/default  # Ubuntu/Debian
    
    修改文件内容为:
    server {
        listen 80;
        server_name _;  # 无需域名,匹配所有请求
    
        # 处理大文件上传(需≥Multer配置)
        client_max_body_size 500M;
    
        location /file-server/ { # 项目接口地址的统一路由前缀,每个项目的前缀应该设置为不同
            proxy_pass http://localhost:8000;  # 指向Docker映射端口
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
            # WebSocket 支持
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }
    
        location /node-project/ {
            proxy_pass http://localhost:8088;  # 指向Docker映射端口
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
            # WebSocket 支持
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }
    }
    
  • 保存文件后重启Nginx服务
    sudo nginx -t          # 检查配置文件语法是否正确
    
    sudo systemctl reload nginx  # 应用新配置