diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..016fce7d7 --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +# Remove the variable and all commands in Makefile will use docker +USE_LOCAL=1 +# If you want deploy app on heroku makefile have "h-deploy" goal, set app name here +HEROKU_APP_NAME= diff --git a/.gitignore b/.gitignore index 251669fad..d39b0b69a 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ frontend/node_modules/* frontend/dist/* frontend/manifest.json .coverage +staticroot diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..c644153d1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +# A single container to publish/run your app on a server + +FROM node:15-alpine AS frontend +WORKDIR /app +ADD ./frontend /app +RUN yarn install && yarn build + +FROM python:3-alpine +WORKDIR /app +ADD . /app +RUN apk update \ + && pip install gunicorn \ + && pip install -r requirements/base.txt \ + && rm -rf /var/cache/apk/* +COPY --from=frontend /app ./frontend +RUN python manage.py collectstatic --noinput + +CMD docker/backend-cmd.sh diff --git a/Makefile b/Makefile index fc1d850ae..4585077b2 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,25 @@ -# Dev servers -CMD_PREFIX=./docker/compose.sh -MANAGE=$(CMD_PREFIX) run backend python manage.py +ifneq (,$(wildcard ./.env)) + include .env + export +endif + +DOCKER_CMD_PREFIX=./docker/compose.sh +ifeq (,$(USE_LOCAL)) + MANAGE=$(DOCKER_CMD_PREFIX) run --rm backend python manage.py +else + MANAGE=python manage.py +endif TEST_SETTINGS=fortytwo.test_settings TEST_APP=apps/ +# Dev servers run: @echo Starting http://127.0.0.1:8000 - $(CMD_PREFIX) up - -build: - $(CMD_PREFIX) build +ifeq (,$(USE_LOCAL)) + $(DOCKER_CMD_PREFIX) up +else + (trap 'kill 0' SIGINT; $(MANAGE) runserver & yarn --cwd frontend serve) +endif # Database migrate: @@ -29,8 +39,13 @@ shell: @echo Starting shell... $(MANAGE) shell +cmd=black apps && flake8 apps lint: - $(CMD_PREFIX) run backend sh -c "black apps && flake8 apps" +ifeq (,$(USE_LOCAL)) + $(DOCKER_CMD_PREFIX) run backend sh -c "$(cmd)" +else + $(cmd) +endif djangotest: $(MANAGE) test --settings=$(TEST_SETTINGS) $(TEST_APP) --noinput @@ -45,4 +60,35 @@ collectstatic: $(MANAGE) collectstatic --noinput eslint: - $(CMD_PREFIX) run frontend sh -c "cd frontend && yarn lint src --fix" +ifeq (,$(USE_LOCAL)) + $(DOCKER_CMD_PREFIX) run frontend sh -c "yarn --cwd /app/frontend lint src --fix" +else + yarn --cwd frontend lint src --fix +endif + +# Deploy +DEPLOY_CONT_ID=fortytwotesttask +build: +ifeq (,$(USE_LOCAL)) + docker build --tag=$(DEPLOY_CONT_ID):latest . +else + yarn --cwd frontend install + yarn --cwd frontend build + $(MAKE) collectstatic +endif + +server: +ifeq (,$(USE_LOCAL)) + docker run -p=8000:8000 --rm --name $(DEPLOY_CONT_ID) $(DEPLOY_CONT_ID):latest +else + ./docker/backend-cmd.sh +endif + +h-deploy: +ifeq (,$(HEROKU_APP_NAME)) + @echo Missing HEROKU_APP_NAME env var +else + @echo Deploying on heroku + heroku container:push web --app $(HEROKU_APP_NAME) + heroku container:release web --app $(HEROKU_APP_NAME) +endif diff --git a/README.md b/README.md index 93dae2c97..f7e9f851d 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,13 @@ A Django 3+ project template -### Requirements -* SPA -* global: `yarn`, `node` (tested on v15), `python>=3.7` (tested on 3.9) +### System requirements +* global: yarn, node (tested on v15), python>=3.7 (tested on 3.9) *OR* docker + +### Code/deployment requirements * management commands should be proxied to single word make commands, e.g make test +* app should be deployed on a server of your choice (heroku, pythonanywhere, aws, etc.) + +### Initial setup +You can develop app in docker container or directly on host, check `.env.example` +Most usable commands are proxied in the `Makefile` diff --git a/docker-compose.yaml b/docker-compose.yaml index e3608f43a..3cfb11bdd 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -7,7 +7,6 @@ services: dockerfile: docker/backend.Dockerfile container_name: backend restart: always - # mount the volumes so we can change code and hot reload volumes: - .:/app ports: diff --git a/docker/backend-cmd.sh b/docker/backend-cmd.sh index 45b3a4a4d..1ce238aff 100755 --- a/docker/backend-cmd.sh +++ b/docker/backend-cmd.sh @@ -1,3 +1,3 @@ python manage.py migrate --noinput python manage.py createcachetable -supervisord -c /etc/supervisord.conf +gunicorn fortytwo.wsgi -b 0.0.0.0:"${PORT:-8000}" --reload diff --git a/docker/backend.Dockerfile b/docker/backend.Dockerfile index 4f9f35444..4bca3cefe 100644 --- a/docker/backend.Dockerfile +++ b/docker/backend.Dockerfile @@ -1,15 +1,12 @@ FROM python:3-alpine WORKDIR /app -ADD . /app +COPY . /app # gcc, libc-dev are flake8 (typed-ast) deps RUN apk update \ - && apk add make supervisor gcc libc-dev \ - && pip install gunicorn \ - && pip install -r requirements/base.txt \ + && apk add make gcc libc-dev \ && pip install -r requirements/dev.txt \ - && echo "files = /app/docker/conf/supervisor.ini" >> /etc/supervisord.conf \ && rm -rf /var/cache/apk/* CMD docker/backend-cmd.sh diff --git a/docker/conf/supervisor.ini b/docker/conf/supervisor.ini deleted file mode 100644 index e81b78359..000000000 --- a/docker/conf/supervisor.ini +++ /dev/null @@ -1,13 +0,0 @@ -[supervisord] -nodaemon=true -pidfile=/tmp/fttt_docker_backend_supervisord.pid - -[program:web] -command=gunicorn fortytwo.wsgi -b 0.0.0.0:8000 --reload -directory=/app -autostart=true -autorestart=true -startsecs=10 -startretries=3 -stdout_logfile=/var/log/webout.log -stderr_logfile=/var/log/weberr.log diff --git a/docker/frontend-cmd.sh b/docker/frontend-cmd.sh index 6da2a0f2b..7d55f9e0b 100755 --- a/docker/frontend-cmd.sh +++ b/docker/frontend-cmd.sh @@ -1,3 +1 @@ -cd /app/frontend -yarn -yarn serve +yarn --cwd /app/frontend serve diff --git a/docker/frontend.Dockerfile b/docker/frontend.Dockerfile index bdcf5ecab..cc6355bd6 100644 --- a/docker/frontend.Dockerfile +++ b/docker/frontend.Dockerfile @@ -1,6 +1,7 @@ FROM node:15-alpine WORKDIR /app -ADD . /app +COPY . /app +RUN yarn --cwd /app/frontend install CMD docker/frontend-cmd.sh diff --git a/requirements/base.txt b/requirements/base.txt index d40927a14..019e0782f 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,3 +1,4 @@ Django==3.0.8 djangorestframework==3.12.2 django-webpack4-loader==0.0.5 +gunicorn==20.1.0 diff --git a/requirements/dev.txt b/requirements/dev.txt index bc91f21b9..2d4fae458 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,3 +1,5 @@ +-r base.txt + 42cc-pystyle black==20.8b1 flake8==3.8.3