docker搭建云盘

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

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

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

一.搭建后端

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

app.py 文件

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

python 复制代码
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:

python 复制代码
flask

2.创建 Dockerfile

python 复制代码
# 使用轻量级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 的目录下执行以下命令来构建镜像:

haskell 复制代码
docker build -t file-server .

4.运行 Docker 容器

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

haskell 复制代码
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:

haskell 复制代码
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' sweet_johnson

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

haskell 复制代码
curl http://<容器IP>:6000

居然就成功了!!!

豆包说,如果成功,说明是宿主机 localhost 解析问题(可能与 Docker 网络配置冲突)。

二、搭建前端

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

bash 复制代码
<!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>
bash 复制代码
// 初始化加载文件列表
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配置文件

bash 复制代码
    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;
        }
相关推荐
摸鱼仙人~2 分钟前
大模型文章生成的风格个性化与多文体写作:一套可落地的方法论
linux·运维·服务器
xybDIY5 分钟前
亚马逊云 Organizations 组织 Link 账号关联与解绑自动化解决方案
运维·自动化·云计算·aws
慕容雪_13 分钟前
运维笔记-网络【属性】-【共享】中没有【家庭网络连接(H)】的选项
运维·网络·共享
AC赳赳老秦41 分钟前
Shell 脚本批量生成:DeepSeek 辅助编写服务器运维自动化指令
运维·服务器·前端·vue.js·数据分析·自动化·deepseek
菜鸟思维1 小时前
优化NextJs 项目的Docker 镜像 从3.62G 优化到 296.85M
docker
学Linux的语莫1 小时前
linux的root目录缓存清理
linux·运维·服务器
oMcLin1 小时前
如何在 SUSE Linux Enterprise Server 15 上部署并优化 K3s 集群,提升轻量级容器化应用的资源利用率?
linux·运维·服务器
怣疯knight1 小时前
Docker Desktop 4.55.0版本安装成功教程
windows·docker
Run Out Of Brain1 小时前
解决nginx代理配置下wordpress的 /wp-admin/返回 302 重定向到登录页问题
运维·nginx
Ghost Face...2 小时前
深入解析YT6801驱动模块架构
linux·运维·服务器