Spaces:
Sleeping
Sleeping
Dockerize the api rest app
Browse filesAdd dockerfile docker-compose file and conf files
- api_rest/Dockerfile +33 -0
- api_rest/api.py +16 -2
- api_rest/config.py +3 -0
- api_rest/docker-compose.yml +18 -0
- api_rest/gunicorn.py +13 -0
- requirements.txt +11 -7
api_rest/Dockerfile
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.10
|
2 |
+
|
3 |
+
WORKDIR /wordle_app
|
4 |
+
|
5 |
+
ARG UID=1000
|
6 |
+
ARG GID=1000
|
7 |
+
|
8 |
+
RUN groupadd -g "${GID}" python \
|
9 |
+
&& useradd --create-home --no-log-init -u "${UID}" -g "${GID}" python \
|
10 |
+
&& chown python:python -R /wordle_app
|
11 |
+
|
12 |
+
USER python
|
13 |
+
|
14 |
+
COPY --chown=python:python ./requirements.txt ./
|
15 |
+
RUN pip install --no-cache-dir --user -r requirements.txt
|
16 |
+
|
17 |
+
ARG FLASK_DEBUG="false"
|
18 |
+
ENV FLASK_DEBUG="${FLASK_DEBUG}" \
|
19 |
+
FLASK_APP="api_rest.api" \
|
20 |
+
FLASK_SKIP_DOTENV="true" \
|
21 |
+
PYTHONUNBUFFERED="true" \
|
22 |
+
PYTHONPATH="." \
|
23 |
+
PATH="${PATH}:/home/python/.local/bin" \
|
24 |
+
USER="python"
|
25 |
+
|
26 |
+
COPY --chown=python:python . .
|
27 |
+
|
28 |
+
RUN if [ "${FLASK_DEBUG}" != "true" ]; then \
|
29 |
+
flask digest compile; fi
|
30 |
+
|
31 |
+
EXPOSE 8000
|
32 |
+
|
33 |
+
CMD ["gunicorn", "-c", "python:api_rest.gunicorn", "api_rest.api:create_app()"]
|
api_rest/api.py
CHANGED
@@ -29,7 +29,7 @@ def get_play():
|
|
29 |
word = word.upper()
|
30 |
env = get_env()
|
31 |
model_path = get_play_model_path()
|
32 |
-
# Call the
|
33 |
won, attempts = play(env, model_path, word)
|
34 |
return jsonify({'attempts': attempts, 'won': won})
|
35 |
|
@@ -37,11 +37,25 @@ def get_play():
|
|
37 |
@app.route('/word', methods=['GET'])
|
38 |
@cross_origin(origin='*', headers=['Content-Type', 'Authorization'])
|
39 |
def get_word():
|
40 |
-
# Get
|
41 |
word = random.choice(target_vocabulary)
|
42 |
word = word.upper()
|
43 |
return jsonify({'word': word})
|
44 |
|
45 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
if __name__ == '__main__':
|
47 |
app.run(debug=True)
|
|
|
29 |
word = word.upper()
|
30 |
env = get_env()
|
31 |
model_path = get_play_model_path()
|
32 |
+
# Call the play function with the goal word and return the attempts and the result
|
33 |
won, attempts = play(env, model_path, word)
|
34 |
return jsonify({'attempts': attempts, 'won': won})
|
35 |
|
|
|
37 |
@app.route('/word', methods=['GET'])
|
38 |
@cross_origin(origin='*', headers=['Content-Type', 'Authorization'])
|
39 |
def get_word():
|
40 |
+
# Get a random word from the target vocabulary used to train the model
|
41 |
word = random.choice(target_vocabulary)
|
42 |
word = word.upper()
|
43 |
return jsonify({'word': word})
|
44 |
|
45 |
|
46 |
+
def create_app(settings_override=None):
|
47 |
+
"""
|
48 |
+
Create a Flask application using the app factory pattern.
|
49 |
+
:param settings_override: Override settings
|
50 |
+
:return: Flask app
|
51 |
+
"""
|
52 |
+
# app.config.from_object("config.settings")
|
53 |
+
|
54 |
+
if settings_override:
|
55 |
+
app.config.update(settings_override)
|
56 |
+
|
57 |
+
return app
|
58 |
+
|
59 |
+
|
60 |
if __name__ == '__main__':
|
61 |
app.run(debug=True)
|
api_rest/config.py
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
SECRET_KEY = os.getenv("SECRET_KEY", None)
|
api_rest/docker-compose.yml
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
services:
|
2 |
+
web:
|
3 |
+
build:
|
4 |
+
context: "../"
|
5 |
+
dockerfile: './api_rest/Dockerfile'
|
6 |
+
args:
|
7 |
+
- "UID=${UID:-1000}"
|
8 |
+
- "GID=${GID:-1000}"
|
9 |
+
- "FLASK_DEBUG=${FLASK_DEBUG:-false}"
|
10 |
+
env_file:
|
11 |
+
- "../.env"
|
12 |
+
restart: unless-stopped
|
13 |
+
stop_grace_period: "3s"
|
14 |
+
tty: true
|
15 |
+
ports:
|
16 |
+
- 8000:8000
|
17 |
+
expose:
|
18 |
+
- 8000
|
api_rest/gunicorn.py
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
+
import multiprocessing
|
3 |
+
import os
|
4 |
+
from distutils.util import strtobool
|
5 |
+
|
6 |
+
bind = f"0.0.0.0:{os.getenv('PORT', '8000')}"
|
7 |
+
accesslog = "-"
|
8 |
+
access_log_format = "%(h)s %(l)s %(u)s %(t)s '%(r)s' %(s)s %(b)s '%(f)s' '%(a)s' in %(D)sµs" # noqa: E501
|
9 |
+
|
10 |
+
workers = int(os.getenv("WEB_CONCURRENCY", multiprocessing.cpu_count() * 2))
|
11 |
+
threads = int(os.getenv("PYTHON_MAX_THREADS", 1))
|
12 |
+
|
13 |
+
reload = bool(strtobool(os.getenv("WEB_RELOAD", "false")))
|
requirements.txt
CHANGED
@@ -1,7 +1,11 @@
|
|
1 |
-
|
2 |
-
firebase-admin
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
|
|
|
|
|
|
|
|
|
1 |
+
autopep8==2.0.1
|
2 |
+
firebase-admin==6.1.0
|
3 |
+
Flask==2.2.3
|
4 |
+
Flask-Cors==3.0.10
|
5 |
+
Flask-Static-Digest==0.2.1
|
6 |
+
gunicorn==20.1.0
|
7 |
+
gym==0.21.0
|
8 |
+
matplotlib==3.6.3
|
9 |
+
python-dotenv==1.0.0
|
10 |
+
selenium==4.8.2
|
11 |
+
torch==1.13.1
|