Skip to content

Commit b81e4ce

Browse files
committed
new project
1 parent b27090b commit b81e4ce

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+2188
-0
lines changed

.env/.dev-sample

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FLASK_ENV=development
2+
FLASK_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
8+

.env/.prod-sample

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FLASK_ENV=production
2+
FLASK_CONFIG=production
3+
DATABASE_URL=postgresql://flask_celery:flask_celery@db/flask_celery
4+
SECRET_KEY=my_precious
5+
CELERY_BROKER_URL=amqp://admin:admin@rabbitmq:5672/
6+
CELERY_RESULT_BACKEND=redis://redis:6379/0
7+
SOCKETIO_MESSAGE_QUEUE=redis://redis:6379/0
8+
9+
RABBITMQ_DEFAULT_USER=admin
10+
RABBITMQ_DEFAULT_PASS=admin
11+
12+
CELERY_FLOWER_USER=admin
13+
CELERY_FLOWER_PASSWORD=admin

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
upload
2+

app.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import eventlet # new
2+
eventlet.monkey_patch() # new
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', '-A', 'celery_app.celery', 'worker', '--loglevel=info', '-Q', 'high_priority,default'] # new
16+
)
17+
18+
run_process('./project', run_worker)

compose/auto_deploy_do.sh

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#! /bin/bash
2+
3+
# This shell script quickly deploys your project to your
4+
# DigitalOcean Droplet
5+
6+
if [ -z "$DIGITAL_OCEAN_IP_ADDRESS" ]
7+
then
8+
echo "DIGITAL_OCEAN_IP_ADDRESS not defined"
9+
exit 0
10+
fi
11+
12+
# generate TAR file from git
13+
git archive --format tar --output ./project.tar master
14+
15+
echo 'Uploading project...'
16+
rsync ./project.tar root@$DIGITAL_OCEAN_IP_ADDRESS:/tmp/project.tar
17+
echo 'Uploaded complete.'
18+
19+
echo 'Building image...'
20+
ssh -o StrictHostKeyChecking=no root@$DIGITAL_OCEAN_IP_ADDRESS << 'ENDSSH'
21+
mkdir -p /app
22+
rm -rf /app/* && tar -xf /tmp/project.tar -C /app
23+
docker-compose -f /app/docker-compose.prod.yml build
24+
supervisorctl restart flask-celery-app
25+
ENDSSH
26+
echo 'Build complete.'

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 -A celery_app.celery beat -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+
celery -A celery_app.celery \
17+
--broker="${CELERY_BROKER_URL}" \
18+
flower
+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 -A app.celery worker --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

compose/production/flask/Dockerfile

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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+
RUN addgroup --system flask \
18+
&& adduser --system --ingroup flask flask
19+
20+
# Requirements are installed here to ensure they will be cached.
21+
COPY ./requirements.txt /requirements.txt
22+
RUN pip install -r /requirements.txt
23+
24+
COPY ./compose/production/flask/entrypoint /entrypoint
25+
RUN sed -i 's/\r$//g' /entrypoint
26+
RUN chmod +x /entrypoint
27+
RUN chown flask /entrypoint
28+
29+
COPY ./compose/production/flask/start /start
30+
RUN sed -i 's/\r$//g' /start
31+
RUN chmod +x /start
32+
RUN chown flask /start
33+
34+
COPY ./compose/production/flask/celery/worker/start /start-celeryworker
35+
RUN sed -i 's/\r$//g' /start-celeryworker
36+
RUN chmod +x /start-celeryworker
37+
RUN chown flask /start-celeryworker
38+
39+
COPY ./compose/production/flask/celery/beat/start /start-celerybeat
40+
RUN sed -i 's/\r$//g' /start-celerybeat
41+
RUN chmod +x /start-celerybeat
42+
RUN chown flask /start-celerybeat
43+
44+
COPY ./compose/production/flask/celery/flower/start /start-flower
45+
RUN sed -i 's/\r$//g' /start-flower
46+
RUN chmod +x /start-flower
47+
48+
RUN mkdir /app
49+
RUN mkdir /app/upload
50+
RUN mkdir /app/flower_db
51+
WORKDIR /app
52+
53+
# copy project code
54+
COPY . .
55+
56+
RUN chown -R flask:flask /app
57+
58+
USER flask
59+
60+
ENTRYPOINT ["/entrypoint"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o nounset
5+
6+
celery -A celery_app.celery beat -l info
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o nounset
5+
6+
worker_ready() {
7+
celery -A project.wsgi.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+
celery -A celery_app.celery \
17+
--broker="${CELERY_BROKER_URL}" \
18+
flower \
19+
--basic_auth="${CELERY_FLOWER_USER}:${CELERY_FLOWER_PASSWORD}" \
20+
--persistent=1 --db=/app/flower_db/flower.db --state_save_interval=5000
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o nounset
5+
6+
celery -A project.wsgi.celery worker --loglevel=info

compose/production/flask/entrypoint

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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+
rabbitmq_ready() {
46+
echo "Waiting for rabbitmq..."
47+
48+
while ! nc -z rabbitmq 5672; do
49+
sleep 1
50+
done
51+
52+
echo "rabbitmq started"
53+
}
54+
55+
rabbitmq_ready
56+
57+
exec "$@"

compose/production/flask/start

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o pipefail
5+
set -o nounset
6+
7+
flask db upgrade
8+
gunicorn project.wsgi:app -k eventlet -w 1 --bind 0.0.0.0:5000 --chdir=/app

compose/production/nginx/Dockerfile

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
FROM nginx:1.19-alpine
2+
3+
RUN rm /etc/nginx/conf.d/default.conf
4+
COPY nginx.conf /etc/nginx/conf.d

0 commit comments

Comments
 (0)