Skip to content

Commit

Permalink
Feat: Dockerizing using nginx reverse proxy (makeplane#280)
Browse files Browse the repository at this point in the history
* minor docker fixes

* eslint config changes

* dockerfile changes to backend and frontend

* oauth enabled env flag

* sentry enabled env flag

* build: get alternatives for environment variables and static file storage

* build: automatically generate random secret key if not provided

* build: update docker compose for next url env add channels to requirements for asgi server and save files in local machine for docker environment

* build: update nginx conf for backend base url update backend dockerfile to make way for static file uploads

* feat: create a default user with given values else default values

* chore: update docker python version and other dependency version in docker

* build: update local settings file to run it in docker

* fix: update script to run in default production setting

* fix: env variable changes and env setup shell script added

* Added Single Dockerfile to run the Entire plane application

* docs build fixes

---------

Co-authored-by: Narayana <[email protected]>
Co-authored-by: pablohashescobar <[email protected]>
  • Loading branch information
3 people authored Feb 21, 2023
1 parent 33e2986 commit bdca84b
Show file tree
Hide file tree
Showing 47 changed files with 9,614 additions and 11,019 deletions.
6 changes: 3 additions & 3 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
module.exports = {
root: true,
// This tells ESLint to load the config from the package `config`
// extends: ["custom"],
// This tells ESLint to load the config from the package `eslint-config-custom`
extends: ["custom"],
settings: {
next: {
rootDir: ["apps/*/"],
rootDir: ["apps/*"],
},
},
};
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,9 @@ package-lock.json
.vscode

# Sentry
.sentryclirc
.sentryclirc

# lock files
package-lock.json
pnpm-lock.yaml
pnpm-workspace.yaml
116 changes: 116 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
FROM node:18-alpine AS builder
RUN apk add --no-cache libc6-compat
RUN apk update
# Set working directory
WORKDIR /app

RUN yarn global add turbo
COPY . .

RUN turbo prune --scope=app --docker

# Add lockfile and package.json's of isolated subworkspace
FROM node:18-alpine AS installer


RUN apk add --no-cache libc6-compat
RUN apk update
WORKDIR /app

# First install the dependencies (as they change less often)
COPY .gitignore .gitignore
COPY --from=builder /app/out/json/ .
COPY --from=builder /app/out/yarn.lock ./yarn.lock
RUN yarn install

# Build the project
COPY --from=builder /app/out/full/ .
COPY turbo.json turbo.json

RUN yarn turbo run build --filter=app


FROM python:3.11.1-alpine3.17 AS backend

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV PIP_DISABLE_PIP_VERSION_CHECK=1

WORKDIR /code

RUN apk --update --no-cache add \
"libpq~=15" \
"libxslt~=1.1" \
"nodejs-current~=19" \
"xmlsec~=1.2" \
"nginx" \
"nodejs" \
"npm" \
"supervisor"

COPY apiserver/requirements.txt ./
COPY apiserver/requirements ./requirements
RUN apk add libffi-dev
RUN apk --update --no-cache --virtual .build-deps add \
"bash~=5.2" \
"g++~=12.2" \
"gcc~=12.2" \
"cargo~=1.64" \
"git~=2" \
"make~=4.3" \
"postgresql13-dev~=13" \
"libc-dev" \
"linux-headers" \
&& \
pip install -r requirements.txt --compile --no-cache-dir \
&& \
apk del .build-deps

# Add in Django deps and generate Django's static files
COPY apiserver/manage.py manage.py
COPY apiserver/plane plane/
COPY apiserver/templates templates/

COPY apiserver/gunicorn.config.py ./
RUN apk --update --no-cache add "bash~=5.2"
COPY apiserver/bin ./bin/

RUN chmod +x ./bin/takeoff ./bin/worker
RUN chmod -R 777 /code

# Expose container port and run entry point script
EXPOSE 8000
EXPOSE 3000
EXPOSE 80



WORKDIR /app

# Don't run production as root
RUN addgroup --system --gid 1001 plane
RUN adduser --system --uid 1001 captain

COPY --from=installer /app/apps/app/next.config.js .
COPY --from=installer /app/apps/app/package.json .

COPY --from=installer --chown=captain:plane /app/apps/app/.next/standalone ./

COPY --from=installer --chown=captain:plane /app/apps/app/.next/static ./apps/app/.next/static

ENV NEXT_TELEMETRY_DISABLED 1

# RUN rm /etc/nginx/conf.d/default.conf
#######################################################################
COPY nginx/nginx-single-docker-image.conf /etc/nginx/http.d/default.conf
#######################################################################

COPY nginx/supervisor.conf /code/supervisor.conf


CMD ["supervisord","-c","/code/supervisor.conf"]




20 changes: 12 additions & 8 deletions apiserver/.env.example
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
# Backend
SECRET_KEY="<-- django secret -->"
DJANGO_SETTINGS_MODULE="plane.settings.production"
# Database
DATABASE_URL=postgres://plane:plane@plane-db-1:5432/plane
# Cache
REDIS_URL=redis://redis:6379/
# SMPT
EMAIL_HOST="<-- email smtp -->"
EMAIL_HOST_USER="<-- email host user -->"
EMAIL_HOST_PASSWORD="<-- email host password -->"

# AWS
AWS_REGION="<-- aws region -->"
AWS_ACCESS_KEY_ID="<-- aws access key -->"
AWS_SECRET_ACCESS_KEY="<-- aws secret acess key -->"
AWS_S3_BUCKET_NAME="<-- aws s3 bucket name -->"

SENTRY_DSN="<-- sentry dsn -->"
WEB_URL="<-- frontend web url -->"

# FE
WEB_URL="localhost/"
# OAUTH
GITHUB_CLIENT_SECRET="<-- github secret -->"

# Flags
DISABLE_COLLECTSTATIC=1
DOCKERIZED=0 //True if running docker compose else 0
DOCKERIZED=1
19 changes: 10 additions & 9 deletions apiserver/Dockerfile.api
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.8.14-alpine3.16 AS backend
FROM python:3.11.1-alpine3.17 AS backend

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
Expand All @@ -8,19 +8,19 @@ ENV PIP_DISABLE_PIP_VERSION_CHECK=1
WORKDIR /code

RUN apk --update --no-cache add \
"libpq~=14" \
"libpq~=15" \
"libxslt~=1.1" \
"nodejs-current~=18" \
"nodejs-current~=19" \
"xmlsec~=1.2"

COPY requirements.txt ./
COPY requirements ./requirements
RUN apk add libffi-dev
RUN apk --update --no-cache --virtual .build-deps add \
"bash~=5.1" \
"g++~=11.2" \
"gcc~=11.2" \
"cargo~=1.60" \
"bash~=5.2" \
"g++~=12.2" \
"gcc~=12.2" \
"cargo~=1.64" \
"git~=2" \
"make~=4.3" \
"postgresql13-dev~=13" \
Expand All @@ -46,15 +46,16 @@ COPY templates templates/

COPY gunicorn.config.py ./
USER root
RUN apk --update --no-cache add "bash~=5.1"
RUN apk --update --no-cache add "bash~=5.2"
COPY ./bin ./bin/

RUN chmod +x ./bin/takeoff ./bin/worker
RUN chmod -R 777 /code

USER captain

# Expose container port and run entry point script
EXPOSE 8000

CMD [ "./bin/takeoff" ]
# CMD [ "./bin/takeoff" ]

4 changes: 4 additions & 0 deletions apiserver/bin/takeoff
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@
set -e
python manage.py wait_for_db
python manage.py migrate

# Create a Default User
python bin/user_script.py

exec gunicorn -w 8 -k uvicorn.workers.UvicornWorker plane.asgi:application --bind 0.0.0.0:8000 --config gunicorn.config.py --max-requests 1200 --max-requests-jitter 1000 --access-logfile -
28 changes: 28 additions & 0 deletions apiserver/bin/user_script.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import os, sys
import uuid

sys.path.append("/code")

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "plane.settings.production")
import django

django.setup()

from plane.db.models import User


def populate():
default_email = os.environ.get("DEFAULT_EMAIL", "[email protected]")
default_password = os.environ.get("DEFAULT_PASSWORD", "password123")

if not User.objects.filter(email=default_email).exists():
user = User.objects.create(email=default_email, username=uuid.uuid4().hex)
user.set_password(default_password)
user.save()
print("User created")

print("Success")


if __name__ == "__main__":
populate()
3 changes: 2 additions & 1 deletion apiserver/plane/settings/common.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import os
import datetime
from datetime import timedelta
from django.core.management.utils import get_random_secret_key


BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


SECRET_KEY = os.environ.get("SECRET_KEY")
SECRET_KEY = os.environ.get("SECRET_KEY", get_random_secret_key())

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
Expand Down
31 changes: 21 additions & 10 deletions apiserver/plane/settings/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import absolute_import

import dj_database_url
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.redis import RedisIntegration
Expand All @@ -24,6 +25,10 @@
}
}

DOCKERIZED = os.environ.get("DOCKERIZED", False)

if DOCKERIZED:
DATABASES["default"] = dj_database_url.config()

CACHES = {
"default": {
Expand All @@ -41,15 +46,16 @@

CORS_ORIGIN_ALLOW_ALL = True

sentry_sdk.init(
dsn=os.environ.get("SENTRY_DSN"),
integrations=[DjangoIntegration(), RedisIntegration()],
# If you wish to associate users to errors (assuming you are using
# django.contrib.auth) you may enable sending PII data.
send_default_pii=True,
environment="local",
traces_sample_rate=0.7,
)
if os.environ.get("SENTRY_DSN", False):
sentry_sdk.init(
dsn=os.environ.get("SENTRY_DSN"),
integrations=[DjangoIntegration(), RedisIntegration()],
# If you wish to associate users to errors (assuming you are using
# django.contrib.auth) you may enable sending PII data.
send_default_pii=True,
environment="local",
traces_sample_rate=0.7,
)

REDIS_HOST = "localhost"
REDIS_PORT = 6379
Expand All @@ -64,5 +70,10 @@
},
}

WEB_URL = "http://localhost:3000"
MEDIA_URL = "/uploads/"
MEDIA_ROOT = os.path.join(BASE_DIR, "uploads")

if DOCKERIZED:
REDIS_URL = os.environ.get("REDIS_URL")

WEB_URL = os.environ.get("WEB_URL", "localhost:3000")
Loading

0 comments on commit bdca84b

Please sign in to comment.