我在 Flask 中实现了一个基本的 REST API。我实现了 Docker 来将其容器化,并且它在本地运行良好。然后我能够将我的项目推送到 VPS 上,因为我希望我的 Flask api 可以在互联网上的任何地方访问。 但我无法这样做,我无法访问主机服务器上的 Flask api。我对 Docker 和 VPS 完全陌生,但根据我在各个论坛上了解到的信息,这就是我所设置的。
Dockerfile
FROM python:3.11
WORKDIR /app
COPY ./requirements.txt /app/requirements.txt
COPY . /app
RUN python3 -m pip install -r /app/requirements.txt
EXPOSE 5000
ENTRYPOINT ["python3"]
CMD ["app.py"]
需求.txt
aiohttp==3.8.6
aiohttp-retry==2.8.3
aiosignal==1.3.1
async-timeout==4.0.3
attrs==23.1.0
blinker==1.6.3
certifi==2023.7.22
charset-normalizer==3.3.1
click==8.1.7
distlib==0.3.7
filelock==3.12.4
Flask==2.3.0
Flask-Cors==4.0.0
flask-marshmallow==0.14.0
Flask-MySQL==1.5.2
Flask-MySQLdb==2.0.0
Flask-SQLAlchemy==3.1.1
frozenlist==1.4.0
idna==3.4
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
marshmallow-sqlalchemy==0.29.0
multidict==6.0.4
mysqlclient==2.2.0
packaging==23.2
platformdirs==3.11.0
PyJWT==2.8.0
PyMySQL==1.1.0
python-dotenv==1.0.0
requests==2.31.0
six==1.16.0
SQLAlchemy==2.0.22
twilio==8.10.0
typing_extensions==4.8.0
urllib3==2.0.7
virtualenv==20.24.5
Werkzeug==3.0.0
yarl==1.9.2
应用程序.py
from flask import Flask, request, jsonify, json
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.event import listens_for
from flaskext.mysql import MySQL
from flask_cors import CORS
from dataclasses import dataclass
from sqlalchemy import text
from urllib.parse import quote
app = Flask(__name__)
CORS(app, origins=["http://localhost:3000", "http://localhost:3000"])
db = SQLAlchemy()
db = SQLAlchemy(engine_options={"pool_size": 10, 'pool_recycle': 280, "poolclass":QueuePool, "pool_pre_ping":True})
mysql =MySQL()
@dataclass
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True)
firstname = db.Column(db.String(46), nullable=False)#1
lastname = db.Column(db.String(46), nullable=False)#1
def __init__(self, firstname, lastname):
self.firstname = firstname
self.lastname = lastname
def as_dict(self):
excluded_fields = ['id']
return {field.name:getattr(self, field.name) for field in self.__table__.c if field.name not in excluded_fields}
@dataclass
class User(db.Model):
__tablename__ = 'user'
__table_args__ = {'extend_existing': True}
id = db.Column(db.Integer, primary_key=True)
firstname = db.Column(db.String(46), nullable=False)#1
lastname = db.Column(db.String(46), nullable=False)#1
def __init__(self, firstname, lastname):
self.firstname = firstname
self.lastname = lastname
def as_dict(self):
excluded_fields = ['id']
return {field.name:getattr(self, field.name) for field in self.__table__.c if field.name not in excluded_fields}
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:[email protected]/test'
db.init_app(app)
with app.app_context():
db.create_all()
@app.route('/users', methods=['GET'])
def get_user():
users = User.query.all()
return jsonify(users)
@app.route('/user/<firstname>', methods=['GET'])
def user_byfirstname(firstname):
user = User.query.filter_by(firstname = firstname).first()
return jsonify(user.as_dict())
if __name__ == '__main__':
app.run(debug=True, host="0.0.0.0")
然后我进入 VPS 终端,并运行
$ docker build -t myapp:latest
。
构建成功,我可以看到我的应用程序列在 Docker VPS 应用程序中
然后我就跑了
$ docker run --rm -it -p 8080:5000 myapp:latest
* Running on http://127.0.0.1:5000
* Running on http://172.17.0.2:5000
Press CTRL+C to quit
* Restarting with stat
/usr/local/lib/python3.11/site-packages/flask_sqlalchemy/model.py:144: SAWarning: This declarative base already contains a class with the same class name and module name as __main__.User, and will be replaced in the string-lookup table.
super().__init__(name, bases, d, **kwargs)
* Debugger is active!
* Debugger PIN: 581-248-767
Docker VPS 显示 myapp 正在使用中。
到目前为止,一切都很好。但这就是我开始遇到问题的地方。
我运行cmd来了解我的vps主机IP:
$ docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ad37e8ffe744 //container Id
它回来了
172.17.0.2
然后我在本地机器上使用Postman进行测试:
172.17.0.2:8080/users
邮递员抛出错误:
Error: Request timed out
我真的不知道该做什么或从这里去哪里,我尝试过的每一个来源都给我带来了与我已经尝试过的略有不同的变化,而且我离让它发挥作用还很远。请帮忙,我如何通过互联网的任何地方访问我的 docker 服务器。谢谢。
看起来你的 Flask 应用程序在容器端绑定到 127.0.0.1:5000,即使你的应用程序说 0.0.0.0 也许 docker 也将主机绑定到 127.0.0.1。 您可以尝试将您的绑定应用程序显式绑定到主机端的 0.0.0.0,如下所示:
$ docker run --rm -it -p 0.0.0.0:8080:5000 myapp:latest
您还可以使用 docker port 命令显示端口映射列表,如https://docs.docker.com/engine/reference/commandline/port/
中所述