Skip to content

Commit 479e64d

Browse files
committed
add prod deploy files
1 parent 44b7110 commit 479e64d

File tree

14 files changed

+366
-5
lines changed

14 files changed

+366
-5
lines changed

.env/.prod-sample

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
DEBUG=0
2+
SECRET_KEY=dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m
3+
DJANGO_ALLOWED_HOSTS=*
4+
5+
SQL_ENGINE=django.db.backends.postgresql
6+
SQL_DATABASE=hello_django_dev
7+
SQL_USER=hello_django
8+
SQL_PASSWORD=hello_django
9+
SQL_HOST=db
10+
SQL_PORT=5432
11+
12+
RABBITMQ_DEFAULT_USER=admin
13+
RABBITMQ_DEFAULT_PASS=admin
14+
15+
CELERY_BROKER=amqp://admin:admin@rabbitmq:5672/
16+
CELERY_BACKEND=redis://redis:6379/0
17+
18+
CELERY_FLOWER_USER=admin
19+
CELERY_FLOWER_PASSWORD=admin
20+
21+
CHANNELS_REDIS=redis://redis:6379/0

compose/auto_deploy_do.sh

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

compose/production/django/Dockerfile

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
FROM python:3.9-slim-buster
2+
3+
ENV PYTHONUNBUFFERED 1
4+
5+
RUN apt-get update \
6+
# dependencies for building Python packages
7+
&& apt-get install -y build-essential netcat \
8+
# psycopg2 dependencies
9+
&& apt-get install -y libpq-dev \
10+
# Translations dependencies
11+
&& apt-get install -y gettext \
12+
# cleaning up unused files
13+
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
14+
&& rm -rf /var/lib/apt/lists/*
15+
16+
RUN addgroup --system django \
17+
&& adduser --system --ingroup django django
18+
19+
# Requirements are installed here to ensure they will be cached.
20+
COPY ./requirements.txt /requirements.txt
21+
RUN pip install -r /requirements.txt
22+
23+
COPY ./compose/production/django/entrypoint /entrypoint
24+
RUN sed -i 's/\r$//g' /entrypoint
25+
RUN chmod +x /entrypoint
26+
RUN chown django /entrypoint
27+
28+
COPY ./compose/production/django/start /start
29+
RUN sed -i 's/\r$//g' /start
30+
RUN chmod +x /start
31+
RUN chown django /start
32+
33+
COPY ./compose/production/django/celery/worker/start /start-celeryworker
34+
RUN sed -i 's/\r$//g' /start-celeryworker
35+
RUN chmod +x /start-celeryworker
36+
RUN chown django /start-celeryworker
37+
38+
COPY ./compose/production/django/celery/beat/start /start-celerybeat
39+
RUN sed -i 's/\r$//g' /start-celerybeat
40+
RUN chmod +x /start-celerybeat
41+
RUN chown django /start-celerybeat
42+
43+
COPY ./compose/production/django/celery/flower/start /start-flower
44+
RUN sed -i 's/\r$//g' /start-flower
45+
RUN chmod +x /start-flower
46+
47+
RUN mkdir /app
48+
RUN mkdir /app/staticfiles
49+
RUN mkdir /app/mediafiles
50+
WORKDIR /app
51+
52+
# copy project code
53+
COPY . .
54+
55+
RUN chown -R django:django /app
56+
57+
USER django
58+
59+
ENTRYPOINT ["/entrypoint"]
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+
8+
celery -A django_celery_example beat -l INFO
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o nounset
5+
6+
worker_ready() {
7+
celery -A django_celery_example 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=django_celery_example \
18+
--broker="${CELERY_BROKER}" \
19+
--basic_auth="${CELERY_FLOWER_USER}:${CELERY_FLOWER_PASSWORD}"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o pipefail
5+
set -o nounset
6+
7+
celery -A django_celery_example worker -l INFO

compose/production/django/entrypoint

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o pipefail
5+
set -o nounset
6+
7+
postgres_ready() {
8+
python << END
9+
import sys
10+
11+
import psycopg2
12+
13+
try:
14+
psycopg2.connect(
15+
dbname="${SQL_DATABASE}",
16+
user="${SQL_USER}",
17+
password="${SQL_PASSWORD}",
18+
host="${SQL_HOST}",
19+
port="${SQL_PORT}",
20+
)
21+
except psycopg2.OperationalError:
22+
sys.exit(-1)
23+
sys.exit(0)
24+
25+
END
26+
}
27+
until postgres_ready; do
28+
>&2 echo 'Waiting for PostgreSQL to become available...'
29+
sleep 1
30+
done
31+
>&2 echo 'PostgreSQL is available'
32+
33+
34+
rabbitmq_ready() {
35+
echo "Waiting for rabbitmq..."
36+
37+
while ! nc -z rabbitmq 5672; do
38+
sleep 1
39+
done
40+
41+
echo "rabbitmq started"
42+
}
43+
44+
rabbitmq_ready
45+
46+
exec "$@"

compose/production/django/start

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o pipefail
5+
set -o nounset
6+
7+
python /app/manage.py collectstatic --noinput
8+
python /app/manage.py migrate
9+
10+
/usr/local/bin/gunicorn django_celery_example.asgi:application -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 --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

compose/production/nginx/nginx.conf

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
upstream hello_django {
2+
server web:8000;
3+
}
4+
5+
upstream celery_flower {
6+
server flower:5555;
7+
}
8+
9+
upstream rabbitmq {
10+
server rabbitmq:15672;
11+
}
12+
13+
server {
14+
listen 80;
15+
location / {
16+
proxy_pass http://hello_django;
17+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
18+
proxy_set_header Host $host;
19+
proxy_redirect off;
20+
client_max_body_size 20M;
21+
}
22+
location /static/ {
23+
alias /app/staticfiles/;
24+
}
25+
location /media/ {
26+
alias /app/mediafiles/;
27+
}
28+
29+
location /ws {
30+
proxy_pass http://hello_django;
31+
proxy_http_version 1.1;
32+
proxy_set_header Upgrade $http_upgrade;
33+
proxy_set_header Connection "upgrade";
34+
proxy_set_header Host $http_host;
35+
proxy_set_header X-Real-IP $remote_addr;
36+
}
37+
}
38+
39+
server {
40+
listen 5555;
41+
location / {
42+
proxy_pass http://celery_flower;
43+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
44+
proxy_set_header Host $host;
45+
proxy_redirect off;
46+
}
47+
}
48+
49+
50+
server {
51+
listen 15672;
52+
location / {
53+
proxy_pass http://rabbitmq;
54+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
55+
proxy_set_header Host $host;
56+
proxy_redirect off;
57+
}
58+
}

django_celery_example/asgi.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
import os
22

3+
import django
4+
from asgiref.compatibility import guarantee_single_callable
35
from channels.routing import ProtocolTypeRouter, URLRouter
4-
from django.core.asgi import get_asgi_application
6+
from django.conf import settings
57

68
from polls import routing
79

10+
811
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_celery_example.settings')
12+
django.setup()
913

1014
application = ProtocolTypeRouter({
11-
"http": get_asgi_application(),
1215
'websocket': URLRouter(
1316
routing.urlpatterns
1417
)
1518
})
19+
20+
if not settings.DEBUG:
21+
# https://github.com/django/channels/issues/1319
22+
application = guarantee_single_callable(application)

django_celery_example/settings.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@
2323
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
2424

2525
# SECURITY WARNING: keep the secret key used in production secret!
26-
SECRET_KEY = '7vu00+58u%2xj&67%pkymsm1s@im&80ixkmkidfn-iqz!9dy8&'
26+
SECRET_KEY = os.environ.get("SECRET_KEY", "&nl8s430j^j8l*je+m&ys5dv#zoy)0a2+x1!m8hx290_sx&0gh")
2727

2828
# SECURITY WARNING: don't run with debug turned on in production!
29-
DEBUG = True
29+
DEBUG = int(os.environ.get("DEBUG", default=1))
3030

31-
ALLOWED_HOSTS = []
31+
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "127.0.0.1").split(" ")
3232

3333

3434
# Application definition
@@ -130,6 +130,10 @@
130130
# https://docs.djangoproject.com/en/3.1/howto/static-files/
131131

132132
STATIC_URL = '/static/'
133+
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
134+
135+
MEDIA_URL = '/media/'
136+
MEDIA_ROOT = os.path.join(BASE_DIR, 'mediafiles')
133137

134138
CELERY_BROKER_URL = os.environ.get("CELERY_BROKER", "redis://127.0.0.1:6379/0")
135139
CELERY_RESULT_BACKEND = os.environ.get("CELERY_BACKEND", "redis://127.0.0.1:6379/0")

0 commit comments

Comments
 (0)