当前位置: 首页 > article >正文

docker搭建云盘

使用minio搭建自己的文件存储服务(新版和旧版)

一开始使用了上述教程,可以迅速搭建好云盘,但是这个云盘会自动重定向,这就导致我没办法设置反向代理,于是考虑新的办法

之后使用docker部署flask,部署过程为

一.搭建后端

1.创建 app.py 和 requirements.txt 文件

app.py 文件
此文件为 Flask 应用的主程序,简单示例如下:

from flask import Flask, request, send_file, jsonify
import os
from datetime import datetime

app = Flask(__name__)
UPLOAD_FOLDER = '/app/data'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 * 1024  # 100MB
# 配置日志
#logging.basicConfig(level=logging.DEBUG)

@app.route('/api/upload', methods=['POST'])
def upload():
    """文件上传接口"""
    if 'file' not in request.files:
        return jsonify({"error": "No file part"}), 400
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({"error": "No selected file"}), 400
    
    # 保存文件
    filename = f"{datetime.now().timestamp()}_{file.filename}"
    save_path = os.path.join(UPLOAD_FOLDER, filename)
    file.save(save_path)
    
    return jsonify({
        "filename": filename,
        "size": os.path.getsize(save_path),
        "upload_time": datetime.now().isoformat()
    })

@app.route('/api/download/<filename>')
def download(filename):
    """文件下载接口"""
    file_path = os.path.join(UPLOAD_FOLDER, filename)
    if not os.path.exists(file_path):
        return jsonify({"error": "File not found"}), 404
    return send_file(file_path, as_attachment=True)

@app.route('/api/files')
def list_files():
    """文件列表接口"""
    files = []
    for f in os.listdir(UPLOAD_FOLDER):
        path = os.path.join(UPLOAD_FOLDER, f)
        files.append({
            "filename": f,
            "size": os.path.getsize(path),
            "upload_time": datetime.fromtimestamp(os.path.getctime(path)).isoformat()
        })
    return jsonify(files)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

requirements.txt 文件
该文件用于列出项目所需的 Python 依赖,这里仅需要 Flask:

flask

2.创建 Dockerfile

# 使用轻量级Python镜像
FROM python:3.11-alpine

# 设置工作目录
WORKDIR /app

# 复制依赖清单并安装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 复制代码
COPY app.py .

# 创建数据目录
RUN mkdir -p /app/data

# 暴露端口
EXPOSE 6000

# 启动命令
CMD ["python", "app.py"]

3.构建 Docker 镜像

在包含 Dockerfile 的目录下执行以下命令来构建镜像:

docker build -t file-server .

4.运行 Docker 容器

构建好镜像后,使用以下命令运行容器:

sudo docker run -d   -p 5000:5000   -v $(pwd)/data:/app/data   --name my-file-server   file-server

5.验证

打开浏览器,访问 http://localhost:5000/api/files,若有输出,则表明 Flask 应用在 Docker 容器中成功运行。

但我在测试时总是有问题,浏览器显示
在这里插入图片描述
终端显示
在这里插入图片描述
之后一直找不到问题,但是豆包说可以先获得容器的IP,在宿主机中执行以下命令获取容器 IP:

docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' sweet_johnson

然后通过容器 IP 和端口访问:

curl http://<容器IP>:6000

居然就成功了!!!
在这里插入图片描述
在这里插入图片描述
豆包说,如果成功,说明是宿主机 localhost 解析问题(可能与 Docker 网络配置冲突)。

二、搭建前端

在Nginx的html目录下,添加index.html文件和script.js文件

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>文件管理</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container mt-5">
    <!-- 上传区域 -->
    <div class="card mb-4 shadow">
        <div class="card-header bg-primary text-white">
            <h5 class="mb-0">文件上传</h5>
        </div>
        <div class="card-body">
            <div class="mb-3">
                <input type="file" class="form-control" id="fileInput" multiple>
            </div>
            <button class="btn btn-success" onclick="uploadFile()">开始上传</button>
            <div class="progress mt-3" style="height: 25px;">
                <div id="uploadProgress" class="progress-bar progress-bar-striped"
                     style="width: 0%"></div>
            </div>
            <div id="uploadStatus" class="mt-2 text-muted small"></div>
        </div>
    </div>

    <!-- 文件列表 -->
    <div class="card shadow">
        <div class="card-header bg-info text-white">
            <h5 class="mb-0">已上传文件</h5>
        </div>
        <div class="card-body">
            <table class="table table-hover">
                <thead>
                <tr>
                    <th>文件名</th>
                    <th>大小</th>
                    <th>上传时间</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody id="fileList">
                <!-- 动态加载 -->
                </tbody>
            </table>
            <button class="btn btn-sm btn-outline-secondary" onclick="loadFiles()">
                刷新列表
            </button>
        </div>
    </div>
</div>

<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
<script src="script.js"></script>
</body>
</html>
// 初始化加载文件列表
document.addEventListener('DOMContentLoaded', loadFiles);

async function loadFiles() {
    try {
        const response = await fetch('/api/files');
        const files = await response.json();
        renderFileList(files);
    } catch (error) {
        showAlert('获取文件列表失败: ' + error.message, 'danger');
    }
}

function renderFileList(files) {
    const tbody = document.getElementById('fileList');
    tbody.innerHTML = files.map(file => `
        <tr>
            <td>${file.filename}</td>
            <td>${formatFileSize(file.size)}</td>
            <td>${new Date(file.upload_time).toLocaleString()}</td>
            <td>
                <button class="btn btn-sm btn-outline-primary" 
                        onclick="downloadFile('${file.filename}')">
                    下载
                </button>
            </td>
        </tr>
    `).join('');
}

async function uploadFile() {
    const fileInput = document.getElementById('fileInput');
    if (fileInput.files.length === 0) {
        showAlert('请先选择文件', 'warning');
        return;
    }

    const file = fileInput.files[0];
    const formData = new FormData();
    formData.append('file', file);

    try {
        const response = await fetch('/api/upload', {
            method: 'POST',
            body: formData
        });

        if (!response.ok) {
            throw new Error(`上传失败: ${response.statusText}`);
        }

        showAlert('上传成功', 'success');
        await loadFiles();  // 刷新列表
        fileInput.value = '';  // 清空选择
    } catch (error) {
        showAlert(error.message, 'danger');
    }
}

function downloadFile(filename) {
    window.open(`/api/download/${encodeURIComponent(filename)}`, '_blank');
}

// 辅助函数
function formatFileSize(bytes) {
    if (bytes === 0) return '0 B';
    const units = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(1024));
    return (bytes / Math.pow(1024, i)).toFixed(2) + ' ' + units[i];
}

function showAlert(message, type = 'info') {
    const alertDiv = document.createElement('div');
    alertDiv.className = `alert alert-${type} alert-dismissible fade show mt-3`;
    alertDiv.innerHTML = `
        ${message}
        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
    `;
    document.querySelector('.container').prepend(alertDiv);

    setTimeout(() => {
        alertDiv.classList.remove('show');
        setTimeout(() => alertDiv.remove(), 150);
    }, 3000);
}

三、部署Nginx代理

修改Nginx配置文件

    server {
        listen       8080;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;
#         location / {
#            proxy_pass   http://172.17.0.1:9000;
#         }
        location / {
            root   html;
            index  index.html index.htm;
        }
    # 代理后端API请求
        location /api {
            proxy_pass http://172.17.0.3:5000;  # Flask后端地址
            proxy_set_header Host $host;
            #proxy_set_header X-Real-IP $remote_addr; #用于传递客户端的真实 IP 地址
            #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;#会将客户端的 IP 地址和之前代理服务器的 IP 地址拼接起来

            # 文件上传需要调整超时时间
            client_max_body_size 100M;
            proxy_read_timeout 300s;
        }

http://www.kler.cn/a/596218.html

相关文章:

  • 说一下yolo的一些概念 和 自己对 置信度阈值 和图像处理模板匹配的理解
  • 如何把全局坐标系转到机器人本体坐标系
  • Android数据加密方案
  • 深入解析计算机组成原理:从硬件架构到程序运行的本质
  • 【access开发】导入excel 并生成表
  • Object 转 JSONObject 并排除null和““字符串
  • SpringSecurity——前后端分离登录认证
  • 工作相关记录
  • 深入了解 C# 中的 LINQ:功能、语法与应用解析
  • 基于深度学习的皮肤癌智能检测与语音提示系统【python源码+Pyqt5界面+数据集+训练代码】
  • 使用ArgoCD管理Kubernetes部署指南
  • php文件包含与伪协议
  • (electron 报错)TypeError: Cannot read property ‘upgrade‘ of undefined
  • MySQL身份验证的auth_socket插件
  • Java基础面试题学习
  • ruoyi-vue部署linux(war包方式)
  • 【DNN量化工具】QKeras 工具简介
  • springmvc中使用interceptor拦截
  • TensorFlow 与 Matplotlib 核心知识点及实战案例
  • 2953. 统计完全子字符串(将题目中给的信息进行分组循环)