在 Docker 中运行的 Flask 应用程序用于文件上传

问题描述 投票:0回答:1

我编写了以下 Flask 应用程序,它将收集选定的文件,然后将其上传到在 sql lite 中运行的数据库。如果我在本地运行该应用程序,它可以很好地处理数据库中创建的表以及上传的所有数据。但是,如果我使用 docker 运行应用程序,文件上传时会收到 200 错误,但看不到数据库中创建的表以及所有数据。

这是代码:

import os
import sqlite3
from flask import Flask, flash, jsonify, request, redirect, render_template
from werkzeug.utils import secure_filename

app = Flask(__name__)
app.secret_key = "secret key"
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024

path = os.getcwd()
uploadFolder = 'app/uploads'
if not os.path.isdir(uploadFolder):
    os.mkdir(uploadFolder)
app.config['UPLOAD_FOLDER'] = uploadFolder

allowedExtensions = set(['txt'])

# Initialize SQLite database
#database = os.path.join(path, 'file_uploads.db')
database = 'app/uploads/file_uploads.db'

# Health check to see if the service is active
@app.route('/healthCheck', methods=['GET'])
def checkStatus():
    response = {
        'healthCheck': 'Flask service is up and running!'
    }
    return jsonify(response), 200

def createTable():
    conn = sqlite3.connect(database)
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS words
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                 word TEXT NOT NULL,
                 filename TEXT NOT NULL,
                 filepath TEXT NOT NULL)''')
    conn.commit()
    conn.close()

createTable()

def allowedFile(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in allowedExtensions

@app.route('/')
def uploadForm():
    return render_template('upload.html')

@app.route('/', methods=['POST'])
def uploadFile():
    if request.method == 'POST':
        if 'file' not in request.files:
            flash('No file part')
            return redirect(request.url)
        
        file = request.files['file']
        if file.filename == '':
            flash('No file selected for uploading')
            return redirect(request.url)
        
        if file and allowedFile(file.filename):
            filename = secure_filename(file.filename)
            filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            file.save(filepath)
            
            # Read content of the file and split into words
            with open(filepath, 'r') as f:
                content = f.read()
                words = content.split()
            
            # Insert each word into the SQLite database
            conn = sqlite3.connect(database)
            c = conn.cursor()
            for word in words:
                c.execute("INSERT INTO words (word, filename, filepath) VALUES (?, ?, ?)", (word, filename, filepath))
            conn.commit()
            conn.close()
            
            flash('File successfully uploaded and words saved to database')
            return render_template('upload.html')
        else:
            flash('Allowed file types are txt')
            return redirect(request.url)

# Route to get word by ID
@app.route('/word/<int:id>', methods=['GET'])
def getWordById(id):
    conn = sqlite3.connect(database)
    c = conn.cursor()
    c.execute("SELECT word FROM words WHERE id=?", (id,))
    word = c.fetchone()
    conn.close()
    if word:
        return jsonify({'id': id, 'word': word[0]}), 200
    else:
        return jsonify({'error': 'Word not found'}), 404

if __name__ == "__main__":
    app.run(host="127.0.0.1", port=5000)

有人可以帮我弄清楚为什么该表在 sql lite 中不可见,即使文件上传日志中出现 200。

这是预期的输出:

enter image description here

enter image description here

enter image description here

enter image description here

使用 Docker 运行应用程序时,我无法在 SQLLite 中实现预期输出。我做错了什么?

以下是docker文件的内容:

# Use an official Python runtime as a parent image
FROM python:3.8-slim

# Set the working directory in the container
WORKDIR /app

# Copy the Flask application directory into the container at /app
COPY . /app

# Install any needed dependencies specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

# Make port 5000 available to the world outside this container
EXPOSE 5000

# Set the upload folder as a volume
VOLUME /app/uploads

# Define environment variable
ENV FLASK_APP=test.py

# Run the Flask application when the container launches
CMD ["flask", "run", "--host=0.0.0.0"]

Makefile代码:

# Variables
DOCKER_IMAGE_NAME = my-flask-app
DOCKER_CONTAINER_NAME = my-flask-container
TEST_FILE = upload/word.txt

# Targets
build:
    docker build -t $(DOCKER_IMAGE_NAME) .

run:
    docker run -d -p 5000:5000 --name $(DOCKER_CONTAINER_NAME) $(DOCKER_IMAGE_NAME)

test: build
    docker run  $(DOCKER_IMAGE_NAME) python -u test.py

upload:
    curl -X POST -F "file=@$(TEST_FILE)" http://127.0.0.1:5000/

stop:
    docker stop $(DOCKER_CONTAINER_NAME)
    docker rm $(DOCKER_CONTAINER_NAME)

.PHONY: build run stop test upload
python docker sqlite flask makefile
1个回答
0
投票

我注意到您的应用程序可能会在两个地方引发错误。

首先,您的上传文件夹未按预期创建。
您正在尝试创建路径为

app/uploads
的文件夹。因此,在您的项目目录中,有一个文件夹
app
和一个子文件夹
uploads

要创建完整的文件夹结构,我建议

os.makedirs(path, exist_ok=True)
。这也消除了检查文件夹是否已存在的需要。

# ...

uploadFolder = 'app/uploads'
os.makedirs(uploadFolder, exist_ok=True)
app.config['UPLOAD_FOLDER'] = uploadFolder

# ...

其次,这会导致 docker 文件中卷的路径规范不同,因为您创建了工作目录中提到的目录结构

app/uploads
/app

进行上述更改后,应用程序应该可以正常运行。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.