Skip to content

Commit e6a6489

Browse files
committed
part 1
0 parents  commit e6a6489

29 files changed

+1048
-0
lines changed

.env/.dev-sample

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FLASK_ENV=development
2+
FLACK_CONFIG=development
3+
DATABASE_URL=postgresql://flask_celery:flask_celery@db/flask_celery
4+
SECRET_KEY=my_precious
5+
CELERY_BROKER_URL=redis://redis:6379/0
6+
CELERY_RESULT_BACKEND=redis://redis:6379/0
7+
SOCKETIO_MESSAGE_QUEUE=redis://redis:6379/0

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
celerybeat.pid
2+
.DS_Store
3+
__pycache__

app.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import eventlet
2+
eventlet.monkey_patch()
3+
4+
from project import create_app, ext_celery, socketio
5+
6+
app = create_app()
7+
8+
9+
@app.route("/")
10+
def hello_world():
11+
return "Hello, World!"
12+
13+
14+
if __name__ == '__main__':
15+
socketio.run(
16+
app,
17+
debug=True,
18+
use_reloader=True,
19+
host='0.0.0.0'
20+
)

celery_app.py

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from project import create_app, ext_celery
2+
3+
4+
app = create_app()
5+
celery = ext_celery.celery
6+
7+
8+
@app.cli.command("celery_worker")
9+
def celery_worker():
10+
from watchgod import run_process
11+
import subprocess
12+
13+
def run_worker():
14+
subprocess.call(
15+
['celery', 'worker', '-A', 'celery_app.celery', '--loglevel=info', '-Q', 'high_priority,default']
16+
)
17+
18+
run_process('./project', run_worker)

celerybeat-schedule

16 KB
Binary file not shown.

compose/local/flask/Dockerfile

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
FROM python:3.9-slim-buster
2+
3+
ENV PYTHONUNBUFFERED 1
4+
ENV PYTHONDONTWRITEBYTECODE 1
5+
6+
RUN apt-get update \
7+
# dependencies for building Python packages
8+
&& apt-get install -y build-essential \
9+
# psycopg2 dependencies
10+
&& apt-get install -y libpq-dev \
11+
# Additional dependencies
12+
&& apt-get install -y telnet netcat \
13+
# cleaning up unused files
14+
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
15+
&& rm -rf /var/lib/apt/lists/*
16+
17+
# Requirements are installed here to ensure they will be cached.
18+
COPY ./requirements.txt /requirements.txt
19+
RUN pip install -r /requirements.txt
20+
21+
COPY ./compose/local/flask/entrypoint /entrypoint
22+
RUN sed -i 's/\r$//g' /entrypoint
23+
RUN chmod +x /entrypoint
24+
25+
COPY ./compose/local/flask/start /start
26+
RUN sed -i 's/\r$//g' /start
27+
RUN chmod +x /start
28+
29+
COPY ./compose/local/flask/celery/worker/start /start-celeryworker
30+
RUN sed -i 's/\r$//g' /start-celeryworker
31+
RUN chmod +x /start-celeryworker
32+
33+
COPY ./compose/local/flask/celery/beat/start /start-celerybeat
34+
RUN sed -i 's/\r$//g' /start-celerybeat
35+
RUN chmod +x /start-celerybeat
36+
37+
COPY ./compose/local/flask/celery/flower/start /start-flower
38+
RUN sed -i 's/\r$//g' /start-flower
39+
RUN chmod +x /start-flower
40+
41+
WORKDIR /app
42+
43+
ENTRYPOINT ["/entrypoint"]

compose/local/flask/celery/beat/start

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o nounset
5+
6+
rm -f './celerybeat.pid'
7+
celery beat -A celery_app.celery -l info
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o nounset
5+
6+
worker_ready() {
7+
celery -A celery_app.celery inspect ping
8+
}
9+
10+
until worker_ready; do
11+
>&2 echo 'Celery workers not available'
12+
sleep 1
13+
done
14+
>&2 echo 'Celery workers is available'
15+
16+
flower \
17+
--app=celery_app.celery \
18+
--broker="${CELERY_BROKER_URL}"
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o nounset
5+
6+
# celery worker -A app.celery --loglevel=info
7+
flask celery_worker

compose/local/flask/entrypoint

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/bin/bash
2+
3+
# if any of the commands in your code fails for any reason, the entire script fails
4+
set -o errexit
5+
# fail exit if one of your pipe command fails
6+
set -o pipefail
7+
# exits if any of your variables is not set
8+
set -o nounset
9+
10+
postgres_ready() {
11+
python << END
12+
import sys
13+
14+
import psycopg2
15+
import urllib.parse as urlparse
16+
import os
17+
18+
url = urlparse.urlparse(os.environ['DATABASE_URL'])
19+
dbname = url.path[1:]
20+
user = url.username
21+
password = url.password
22+
host = url.hostname
23+
port = url.port
24+
25+
try:
26+
psycopg2.connect(
27+
dbname=dbname,
28+
user=user,
29+
password=password,
30+
host=host,
31+
port=port
32+
)
33+
except psycopg2.OperationalError:
34+
sys.exit(-1)
35+
sys.exit(0)
36+
37+
END
38+
}
39+
until postgres_ready; do
40+
>&2 echo 'Waiting for PostgreSQL to become available...'
41+
sleep 1
42+
done
43+
>&2 echo 'PostgreSQL is available'
44+
45+
exec "$@"

compose/local/flask/start

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o pipefail
5+
set -o nounset
6+
7+
flask db upgrade
8+
# flask run --host=0.0.0.0
9+
python app.py

docker-compose.yml

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
version: '3.8'
2+
3+
services:
4+
web:
5+
build:
6+
context: .
7+
dockerfile: ./compose/local/flask/Dockerfile
8+
image: flask_celery_example_web
9+
# '/start' is the shell script used to run the service
10+
command: /start
11+
# this volume is used to map the files and folders on the host to the container
12+
# so if we change code on the host, code in the docker container will also be changed
13+
volumes:
14+
- .:/app
15+
ports:
16+
- 5010:5000
17+
env_file:
18+
- .env/.dev-sample
19+
environment:
20+
- FLASK_APP=app
21+
depends_on:
22+
- redis
23+
- db
24+
25+
db:
26+
image: postgres:13-alpine
27+
volumes:
28+
- postgres_data:/var/lib/postgresql/data/
29+
environment:
30+
- POSTGRES_DB=flask_celery
31+
- POSTGRES_USER=flask_celery
32+
- POSTGRES_PASSWORD=flask_celery
33+
34+
redis:
35+
image: redis:6-alpine
36+
37+
celery_worker:
38+
build:
39+
context: .
40+
dockerfile: ./compose/local/flask/Dockerfile
41+
image: flask_celery_example_celery_worker
42+
command: /start-celeryworker
43+
volumes:
44+
- .:/app
45+
env_file:
46+
- .env/.dev-sample
47+
environment:
48+
- FLASK_APP=celery_app
49+
depends_on:
50+
- redis
51+
- db
52+
53+
celery_beat:
54+
build:
55+
context: .
56+
dockerfile: ./compose/local/flask/Dockerfile
57+
image: flask_celery_example_celery_beat
58+
command: /start-celerybeat
59+
volumes:
60+
- .:/app
61+
env_file:
62+
- .env/.dev-sample
63+
environment:
64+
- FLASK_APP=celery_app
65+
depends_on:
66+
- redis
67+
- db
68+
69+
flower:
70+
build:
71+
context: .
72+
dockerfile: ./compose/local/flask/Dockerfile
73+
image: flask_celery_example_celey_flower
74+
command: /start-flower
75+
volumes:
76+
- .:/app
77+
env_file:
78+
- .env/.dev-sample
79+
environment:
80+
- FLASK_APP=celery_app
81+
ports:
82+
- 5557:5555
83+
depends_on:
84+
- redis
85+
- db
86+
87+
volumes:
88+
postgres_data:

migrations/README

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Generic single-database configuration.

migrations/alembic.ini

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# A generic, single database configuration.
2+
3+
[alembic]
4+
# template used to generate migration files
5+
# file_template = %%(rev)s_%%(slug)s
6+
7+
# set to 'true' to run the environment during
8+
# the 'revision' command, regardless of autogenerate
9+
# revision_environment = false
10+
11+
12+
# Logging configuration
13+
[loggers]
14+
keys = root,sqlalchemy,alembic,flask_migrate
15+
16+
[handlers]
17+
keys = console
18+
19+
[formatters]
20+
keys = generic
21+
22+
[logger_root]
23+
level = WARN
24+
handlers = console
25+
qualname =
26+
27+
[logger_sqlalchemy]
28+
level = WARN
29+
handlers =
30+
qualname = sqlalchemy.engine
31+
32+
[logger_alembic]
33+
level = INFO
34+
handlers =
35+
qualname = alembic
36+
37+
[logger_flask_migrate]
38+
level = INFO
39+
handlers =
40+
qualname = flask_migrate
41+
42+
[handler_console]
43+
class = StreamHandler
44+
args = (sys.stderr,)
45+
level = NOTSET
46+
formatter = generic
47+
48+
[formatter_generic]
49+
format = %(levelname)-5.5s [%(name)s] %(message)s
50+
datefmt = %H:%M:%S

0 commit comments

Comments
 (0)