我编写了以下 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。
这是预期的输出:
使用 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
我注意到您的应用程序可能会在两个地方引发错误。
首先,您的上传文件夹未按预期创建。
您正在尝试创建路径为
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
进行上述更改后,应用程序应该可以正常运行。