diff --git a/.github/workflows/deploy-api.yml b/.github/workflows/deploy-api.yml new file mode 100644 index 0000000..8691d1d --- /dev/null +++ b/.github/workflows/deploy-api.yml @@ -0,0 +1,48 @@ +name: Deploy API + +on: + push: + +jobs: + build: + runs-on: ubuntu-latest + name: build-main-api + steps: + - name: Check out code + uses: actions/checkout@v2 + + - name: Login to Docker Hub + run: echo ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin + + - name: Build, tag, and push image to Docker Hub + run: | + docker build .. --file docker-conf/Dockerfile-django-api --tag ${{ secrets.DOCKER_REGISTRY }}/algova-django-api:${GITHUB_SHA::7} + docker push ${{ secrets.DOCKER_REGISTRY }}/algova-django-api:latest + + deploy: + needs: [build] + runs-on: ubuntu-latest + name: deploy-main-api + steps: + - name: Checkout main + uses: actions/checkout@v2 + + - name: Install doctl + uses: digitalocean/action-doctl@v2 + with: + token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }} + + - name: Deploy to DigitalOcean Kubernetes + run: | + kubectl apply -f kubernetes/api-deployment.yaml --namespace=default + kubectl set image deployment/algova-django-api algova-django-api=${{ secrets.DOCKER_REGISTRY }}/algova-django-api:${GITHUB_SHA::7} --namespace=default + kubectl rollout status deployment/algova-django-api --namespace=default + kubectl wait --for=condition=available --timeout=300s --namespace=default deployment/algova-django-api + kubectl get pods -l app=algova-django-api --namespace=default + sleep 10 # Wait for previous pod to terminate + kubectl exec --namespace=default \ + $(kubectl get pod -l app=algova-django-api --field-selector=status.phase==Running -o jsonpath="{.items[0].metadata.name}" --namespace=default) \ + -- python manage.py makemigrations + kubectl exec --namespace=default \ + $(kubectl get pod -l app=algova-django-api --field-selector=status.phase==Running -o jsonpath="{.items[0].metadata.name}" --namespace=default) \ + -- python manage.py migrate diff --git a/demo/settings.py b/demo/settings.py index f0559e9..2f67583 100644 --- a/demo/settings.py +++ b/demo/settings.py @@ -16,7 +16,7 @@ # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = ["0.0.0.0","127.0.0.1"] # Application definition diff --git a/docker-conf/Dockerfile-django-api b/docker-conf/Dockerfile-django-api new file mode 100644 index 0000000..d90bd31 --- /dev/null +++ b/docker-conf/Dockerfile-django-api @@ -0,0 +1,44 @@ +# Build Stage +FROM python:3.9-slim as builder + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 + +WORKDIR /build + +# Install build dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + git \ + build-essential \ + unixodbc-dev \ + default-libmysqlclient-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +COPY requirements ./requirements + +RUN pip install --no-cache-dir --target=/build/deps -r requirements/prod.txt + + +# Final Stage +FROM python:3.9-slim + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 + +WORKDIR /home/algova + +# Copy installed dependencies from the builder stage +COPY --from=builder /build/deps /usr/local/lib/python3.9/site-packages +COPY --from=builder /build/deps/bin /usr/local/bin + +COPY . . + +# Runtime dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + unixodbc-dev \ + default-libmysqlclient-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +EXPOSE 8000 diff --git a/kubernetes/api-deployment.yaml b/kubernetes/api-deployment.yaml new file mode 100644 index 0000000..8406d60 --- /dev/null +++ b/kubernetes/api-deployment.yaml @@ -0,0 +1,26 @@ +kind: Deployment +apiVersion: apps/v1 +metadata: + namespace: default + name: algova-django-api +spec: + selector: + matchLabels: + app: algova-django-api + template: + metadata: + labels: + app: algova-django-api + spec: + containers: + - name: algova-django-api + image: algova/algova-django-api:latest + imagePullPolicy: Always + command: ['gunicorn', 'config.wsgi', '--bind=0.0.0.0:8000'] + resources: + requests: + memory: "256Mi" + cpu: "250m" + limits: + memory: "512Mi" + cpu: "500m" \ No newline at end of file diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index c5ac02c..0000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -django==4.2 -django-environ==0.10.0 -djangorestframework==3.14.0 \ No newline at end of file diff --git a/requirements/prod.txt b/requirements/prod.txt new file mode 100644 index 0000000..5952874 --- /dev/null +++ b/requirements/prod.txt @@ -0,0 +1,4 @@ +django==4.2 +django-environ==0.10.0 +djangorestframework==3.14.0 +gunicorn \ No newline at end of file