Last active
December 23, 2024 05:57
-
-
Save arifwn/2b9d5eec6c93665f30bfe8b558b8b6bd to your computer and use it in GitHub Desktop.
(Relatively) Simple Dockerfile that bundles Django, Nginx, Gunicorn, Supervisord, Celery, Redis, Memcached, wkhtmltopdf, nodejs and React frontend build in a single container
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
version: '2' # sample docker-compose to bring up the whole thing | |
services: | |
nginx: # the "load balancer" to terminate https connections, configure this to proxy all request to "appserver" | |
image: nginx:1.15-alpine | |
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'" | |
ports: | |
- "80:80" | |
- "443:443" | |
volumes: | |
- ~/tmp/app/conf:/etc/nginx/conf.d:cached | |
depends_on: | |
- mls | |
postgres: | |
image: postgres | |
volumes: | |
- ~/tmp/app/postgres:/var/lib/postgresql/data:cached | |
environment: | |
POSTGRES_DB: postgres | |
POSTGRES_USER: postgres | |
POSTGRES_PASSWORD: replaceme | |
appserver: | |
image: me/myapp | |
volumes: | |
- ~/tmp/app/media:/var/media:cached | |
- ~/tmp/app/logs:/var/logs:cached | |
- ~/tmp/app/build:/var/app/ui/build | |
- ~/tmp/app/node_modules:/var/app/ui/node_modules | |
depends_on: | |
- postgres | |
environment: | |
HOST: app.localhost # make sure to update your settings.py to allow specifying these config via env variables | |
SECRET_KEY: replaceme | |
PRODUCTION: production | |
BUILD_UI: "NO" # set to "YES" to run `yarn run build` on ui directory | |
DATABASE_BACKEND: django.db.backends.postgresql_psycopg2 | |
DATABASE_HOST: postgres | |
DATABASE_PORT: 5432 | |
DATABASE_NAME: postgres | |
DATABASE_USER: postgres | |
DATABASE_PASSWORD: replaceme | |
MEDIA_ROOT: /var/media/media | |
STATIC_ROOT: /var/media/static | |
WORKER_COUNT: 2 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM python:3.8 | |
ENV PYTHONUNBUFFERED 1 | |
# Install node prereqs, nodejs and yarn | |
# Ref: https://deb.nodesource.com/setup_10.x | |
# Ref: https://yarnpkg.com/en/docs/install | |
RUN \ | |
apt-get update && \ | |
apt-get install -yqq apt-transport-https xfonts-base xfonts-75dpi libsasl2-dev | |
RUN \ | |
echo "deb https://deb.nodesource.com/node_10.x stretch main" > /etc/apt/sources.list.d/nodesource.list && \ | |
wget -qO- https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ | |
echo "deb https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list && \ | |
wget -qO- https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ | |
apt-get update && \ | |
apt-get install -yqq nodejs yarn && \ | |
rm -rf /var/lib/apt/lists/* | |
# install redis | |
RUN groupadd -r redis && useradd -r -g redis redis | |
ENV REDIS_VERSION 5.0.4 | |
ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-5.0.4.tar.gz | |
ENV REDIS_DOWNLOAD_SHA 3ce9ceff5a23f60913e1573f6dfcd4aa53b42d4a2789e28fa53ec2bd28c987dd | |
# for redis-sentinel see: http://redis.io/topics/sentinel | |
RUN set -ex; \ | |
wget -O redis.tar.gz "$REDIS_DOWNLOAD_URL"; \ | |
echo "$REDIS_DOWNLOAD_SHA *redis.tar.gz" | sha256sum -c -; \ | |
mkdir -p /usr/src/redis; \ | |
tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1; \ | |
rm redis.tar.gz; \ | |
grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 1$' /usr/src/redis/src/server.h; \ | |
sed -ri 's!^(#define CONFIG_DEFAULT_PROTECTED_MODE) 1$!\1 0!' /usr/src/redis/src/server.h; \ | |
grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 0$' /usr/src/redis/src/server.h; \ | |
make -C /usr/src/redis -j "$(nproc)"; \ | |
make -C /usr/src/redis install; \ | |
rm -r /usr/src/redis; | |
RUN mkdir /var/redis && chown redis:redis /var/redis | |
# install memcached | |
RUN groupadd --system --gid 11211 memcache && useradd --system --gid memcache --uid 11211 memcache | |
ENV MEMCACHED_VERSION 1.5.14 | |
ENV MEMCACHED_SHA1 94592688ae685caf53ab90a821c99f1503bb1018 | |
RUN set -x \ | |
&& wget -O memcached.tar.gz "https://memcached.org/files/memcached-$MEMCACHED_VERSION.tar.gz" \ | |
&& echo "$MEMCACHED_SHA1 memcached.tar.gz" | sha1sum -c - \ | |
&& mkdir -p /usr/src/memcached \ | |
&& tar -xzf memcached.tar.gz -C /usr/src/memcached --strip-components=1 \ | |
&& rm memcached.tar.gz \ | |
&& cd /usr/src/memcached \ | |
&& gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" \ | |
&& ./configure \ | |
--build="$gnuArch" \ | |
--enable-sasl \ | |
&& make -j "$(nproc)" \ | |
&& make install \ | |
&& cd / && rm -rf /usr/src/memcached \ | |
&& memcached -V | |
RUN mkdir /var/memcache && chown memcache:memcache /var/memcache | |
# install nginx | |
ENV NGINX_VERSION 1.15.12-1~stretch | |
ENV NJS_VERSION 1.15.12.0.3.1-1~stretch | |
RUN set -x \ | |
&& \ | |
NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62; \ | |
found=''; \ | |
for server in \ | |
hkp://keyserver.ubuntu.com:80 \ | |
hkp://p80.pool.sks-keyservers.net:80 \ | |
pgp.mit.edu \ | |
; do \ | |
echo "Fetching GPG key $NGINX_GPGKEY from $server"; \ | |
apt-key adv --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" && found=yes && break; \ | |
done; \ | |
test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" && exit 1; \ | |
apt-get remove --purge --auto-remove -y gnupg1 && rm -rf /var/lib/apt/lists/* \ | |
&& dpkgArch="$(dpkg --print-architecture)" \ | |
&& nginxPackages=" \ | |
nginx=${NGINX_VERSION} \ | |
nginx-module-xslt=${NGINX_VERSION} \ | |
nginx-module-geoip=${NGINX_VERSION} \ | |
nginx-module-image-filter=${NGINX_VERSION} \ | |
nginx-module-njs=${NJS_VERSION} \ | |
" \ | |
&& echo "deb https://nginx.org/packages/mainline/debian/ stretch nginx" >> /etc/apt/sources.list.d/nginx.list \ | |
&& apt-get update \ | |
&& apt-get install --no-install-recommends --no-install-suggests -y \ | |
$nginxPackages \ | |
gettext-base \ | |
&& rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list | |
# install wkhtmltopdf | |
RUN \ | |
cd /tmp/ && \ | |
wget --quiet https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.stretch_amd64.deb && \ | |
dpkg -i wkhtmltox_0.12.5-1.stretch_amd64.deb && \ | |
rm wkhtmltox_0.12.5-1.stretch_amd64.deb | |
# install app | |
RUN mkdir /var/app && chown www-data:www-data /var/app | |
WORKDIR /var/app | |
COPY ./requirements.txt /var/app/ | |
RUN pip install -r requirements.txt | |
COPY . /var/app/ | |
COPY ./nginx.conf /etc/nginx/conf.d/default.conf | |
VOLUME /var/media | |
VOLUME /var/app/ui/build | |
VOLUME /var/app/ui/node_modules | |
VOLUME /var/logs | |
RUN chown www-data:www-data /var/media | |
ENTRYPOINT ["./entrypoint.sh"] | |
CMD ["run"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -e | |
if [ "$1" = 'run' ]; then | |
export | sed 's/declare\ \-x\ /export\ /' > env.sh | |
python ./manage.py migrate --noinput | |
if [ "$BUILD_UI" = 'YES' ]; then | |
cd ./ui | |
yarn install | |
yarn build | |
cd ../ | |
fi | |
python ./manage.py collectstatic --noinput | |
exec supervisord -n -c ./supervisord.conf | |
else | |
exec "$@" | |
fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
server { | |
listen 80 default_server; | |
error_log /dev/stdout info; | |
access_log /dev/stdout; | |
client_max_body_size 100M; | |
location /static { | |
root /var/app/ui/build; | |
} | |
location /site-static { | |
root /var; | |
} | |
location /media { | |
root /var; | |
} | |
location / { | |
root /var/app/ui/build; # try react build directory first, if file doesn't exist, route requests to django app | |
try_files $uri $uri/index.html $uri.html @app; | |
} | |
location @app { | |
proxy_set_header Host $host; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |
proxy_set_header X-Forwarded-Proto "https"; # assumes https already terminated by the load balancer in front of us | |
proxy_pass http://127.0.0.1:8000; | |
proxy_read_timeout 300; | |
proxy_buffering off; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
celery==4.4.2 | |
Django==3.0.5 | |
django-celery-beat==2.0.0 | |
gunicorn==20.0.4 | |
psycopg2==2.8.5 | |
python-memcached==1.59 | |
redis==3.4.1 | |
supervisor==4.1.0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[supervisord] | |
loglevel=info | |
logfile=../logs/supervisord.log ; main log file; default $CWD/supervisord.log | |
logfile_maxbytes=50MB ; max main logfile bytes b4 rotation; default 50MB | |
logfile_backups=10 ; # of main logfile backups; 0 means none, default 10 | |
loglevel=info ; log level; default info; others: debug,warn,trace | |
pidfile=../logs/supervisord.pid | |
[supervisorctl] | |
serverurl=unix://./supervisor.sock | |
[program:myapp] | |
user=www-data | |
command=gunicorn --workers=%(ENV_WORKER_COUNT)s --bind 0.0.0.0:8000 myapp_project.wsgi:application | |
directory=./ | |
autostart=true | |
autorestart=true | |
stdout_logfile = ../logs/myapp.log | |
stderr_logfile = ../logs/myapp.err.log | |
[program:celery_worker] | |
user=www-data | |
command=celery -A myapp worker -c2 -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler | |
directory=./ | |
autostart=true | |
autorestart=true | |
stdout_logfile = ../logs/celery-worker.log | |
stderr_logfile = ../logs/celery-worker.err.log | |
[program:celery_beat] | |
user=www-data | |
command=celery -A myapp beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler | |
directory=./ | |
autostart=true | |
autorestart=true | |
stdout_logfile = ../logs/celery-beat.log | |
stderr_logfile = ../logs/celery-beat.err.log | |
[program:redis] | |
user=redis | |
command=/usr/local/bin/redis-server | |
directory=/var/redis/ | |
autostart=true | |
autorestart=true | |
stdout_logfile = ../logs/redis.log | |
stderr_logfile = ../logs/redis.err.log | |
[program:memcache] | |
user=memcache | |
command=/usr/local/bin/memcached | |
directory=/var/memcache | |
autostart=true | |
autorestart=true | |
stdout_logfile = ../logs/memcache.log | |
stderr_logfile = ../logs/memcache.err.log | |
[program:nginx] | |
command=/usr/sbin/nginx -g "daemon off;" | |
directory=/var/app | |
autostart=true | |
autorestart=true | |
stdout_logfile = ../logs/nginx.log | |
stderr_logfile = ../logs/nginx.err.log |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment