From b887fcd2a115db8812257a5ab526e2a3dde1064f Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 5 Mar 2025 13:09:31 -0500 Subject: [PATCH 01/16] Add Dockerfile --- Dockerfile | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ea2c8fd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM python:3.10 + +WORKDIR /app + +COPY requirements/ requirements/ +COPY requirements.txt . +RUN pip install -r requirements.txt + +COPY . . + +ENV NUM_WORKERS=4 + +ARG SOCKFILE + +CMD ["sh", "-c", "gunicorn config.asgi:application \ + --name django-backend \ + --workers $NUM_WORKERS \ + -k uvicorn.workers.UvicornWorker \ + --bind unix:$SOCKFILE \ + --log-llevel=debug \ + --log-file=/app/logs/gunicorn.log"] From 10a39d94b81bfae640d74ba84497d88a09dc4207 Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 5 Mar 2025 13:13:58 -0500 Subject: [PATCH 02/16] Dockerfile typo --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ea2c8fd..364d6a3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,5 +17,5 @@ CMD ["sh", "-c", "gunicorn config.asgi:application \ --workers $NUM_WORKERS \ -k uvicorn.workers.UvicornWorker \ --bind unix:$SOCKFILE \ - --log-llevel=debug \ + --log-level=debug \ --log-file=/app/logs/gunicorn.log"] From 9e173695f85e96235048c9c27ebad318aa2a1786 Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 5 Mar 2025 13:24:39 -0500 Subject: [PATCH 03/16] Dockerfile update --- Dockerfile | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index 364d6a3..a276b5a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,14 +8,6 @@ RUN pip install -r requirements.txt COPY . . -ENV NUM_WORKERS=4 +RUN mkdir -p /app/asgi.sock -ARG SOCKFILE - -CMD ["sh", "-c", "gunicorn config.asgi:application \ - --name django-backend \ - --workers $NUM_WORKERS \ - -k uvicorn.workers.UvicornWorker \ - --bind unix:$SOCKFILE \ - --log-level=debug \ - --log-file=/app/logs/gunicorn.log"] +CMD ["gunicorn", "--workers", "4", "--bind", "unix:/app/asgi.sock", "config.asgi:application"] From 2a2c13c05f4d4f739a48e048d02b69bee3488a88 Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 5 Mar 2025 18:05:33 -0500 Subject: [PATCH 04/16] Change container internal socket creation --- Dockerfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index a276b5a..29e83a4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,4 @@ RUN pip install -r requirements.txt COPY . . -RUN mkdir -p /app/asgi.sock - CMD ["gunicorn", "--workers", "4", "--bind", "unix:/app/asgi.sock", "config.asgi:application"] From 0e746ecabd3f70873c520aa9886ebc6946e5d36c Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 5 Mar 2025 18:32:43 -0500 Subject: [PATCH 05/16] New Dockerfile --- .dockerignore | 15 +++++++++++++++ Dockerfile | 36 ++++++++++++++++++++++++++++++------ entrypoint.prod.sh | 3 +++ 3 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 .dockerignore create mode 100644 entrypoint.prod.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e1b48ba --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +__pycache__/ + + +# Django stuff +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +static + +# Environment +.env +.env* +.venv +venv/ diff --git a/Dockerfile b/Dockerfile index 29e83a4..1df4c7b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,35 @@ -FROM python:3.10 +FROM python:3.13-slim AS builder + +RUN mkdir /app + +WORKDIR /app + +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +RUN pip install --upgrade pip +COPY requirements.txt /app/ +COPY requirements/ /app/ +RUN pip install --no-cache-dir -r requirements.txt + +FROM python:3.13-slim + +RUN useradd -m -r appuser && \ + mkdir /app && \ + chown -R appuser /app + +COPY --from=builder /usr/local/lib/python3.13/site-packages/ /usr/local/lib/python3.13/site-packages/ +COPY --from=builder /usr/local/bin/ /usr/local/bin WORKDIR /app -COPY requirements/ requirements/ -COPY requirements.txt . -RUN pip install -r requirements.txt +COPY --chown=appuser:appuser . . + +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +RUN chmod +x /app/entrypoint.prod.sh -COPY . . +EXPOSE 8000 -CMD ["gunicorn", "--workers", "4", "--bind", "unix:/app/asgi.sock", "config.asgi:application"] +CMD ["/app/entrypoint.prod.sh"] diff --git a/entrypoint.prod.sh b/entrypoint.prod.sh new file mode 100644 index 0000000..9a57ee4 --- /dev/null +++ b/entrypoint.prod.sh @@ -0,0 +1,3 @@ +python manage.py collectstatic --noinput +python manage.py migrate --noinput +python -m gunicorn --bind 0.0.0.0:8000 --workers 4 config.asgi:application From c67361b8df2b9dd7b168e7439659e6d894e00cf2 Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 5 Mar 2025 18:34:55 -0500 Subject: [PATCH 06/16] Fix copying requirements --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1df4c7b..259f4b8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ ENV PYTHONUNBUFFERED=1 RUN pip install --upgrade pip COPY requirements.txt /app/ -COPY requirements/ /app/ +COPY requirements/ /app/requirements/ RUN pip install --no-cache-dir -r requirements.txt FROM python:3.13-slim From 30b9fb9b201c96e436383e83afea83503b3c0215 Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 5 Mar 2025 18:40:09 -0500 Subject: [PATCH 07/16] 3.13 was not happy with current requirements --- Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 259f4b8..e5bd23a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.13-slim AS builder +FROM python:3.10-slim AS builder RUN mkdir /app @@ -12,13 +12,13 @@ COPY requirements.txt /app/ COPY requirements/ /app/requirements/ RUN pip install --no-cache-dir -r requirements.txt -FROM python:3.13-slim +FROM python:3.10-slim RUN useradd -m -r appuser && \ mkdir /app && \ chown -R appuser /app -COPY --from=builder /usr/local/lib/python3.13/site-packages/ /usr/local/lib/python3.13/site-packages/ +COPY --from=builder /usr/local/lib/python3.10/site-packages/ /usr/local/lib/python3.10/site-packages/ COPY --from=builder /usr/local/bin/ /usr/local/bin WORKDIR /app From 0d7f8a0f9d7fa78b5f77a94570dbb8b27fe610cb Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 19 Mar 2025 13:54:31 -0400 Subject: [PATCH 08/16] Install production requirements in container --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e5bd23a..af6b772 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,10 +7,10 @@ WORKDIR /app ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 -RUN pip install --upgrade pip COPY requirements.txt /app/ COPY requirements/ /app/requirements/ RUN pip install --no-cache-dir -r requirements.txt +RUN pip install --no-cache-dir -r /app/requirements/production.txt FROM python:3.10-slim From 60e377c7c3afdb685984af8dd8ec3acd38b24f0c Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 19 Mar 2025 13:57:18 -0400 Subject: [PATCH 09/16] Specify which settings to use to django --- entrypoint.prod.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/entrypoint.prod.sh b/entrypoint.prod.sh index 9a57ee4..79f1f58 100644 --- a/entrypoint.prod.sh +++ b/entrypoint.prod.sh @@ -1,3 +1,11 @@ +#!/bin/sh + +export DJANGO_READ_DOT_ENV_FILE=True +export DJANGO_SETTINGS_MODULE=config.settings.production + python manage.py collectstatic --noinput python manage.py migrate --noinput -python -m gunicorn --bind 0.0.0.0:8000 --workers 4 config.asgi:application +python -m gunicorn config.asgi:application \ + --bind 0.0.0.0:8000 \ + --workers 4 \ + -k uvicorn.workers.UvicornWorker From c7b6c51492651557b02584b618e827aa04cba7b4 Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 19 Mar 2025 13:58:51 -0400 Subject: [PATCH 10/16] Add dev-api.musiccpr.org to allowed hosts --- config/settings/local.py | 2 +- config/settings/production.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/settings/local.py b/config/settings/local.py index 297c550..4d37575 100644 --- a/config/settings/local.py +++ b/config/settings/local.py @@ -14,7 +14,7 @@ "default": env.db("DATABASE_URL", default="sqlite:///db.sqlite"), } # https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts -ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", default=["localhost", "0.0.0.0", "127.0.0.1"]) +ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", default=["localhost", "0.0.0.0", "127.0.0.1", "dev-api.musiccpr.org"]) # CACHES # ------------------------------------------------------------------------------ diff --git a/config/settings/production.py b/config/settings/production.py index ccdac18..7618c32 100644 --- a/config/settings/production.py +++ b/config/settings/production.py @@ -7,7 +7,7 @@ # https://docs.djangoproject.com/en/dev/ref/settings/#secret-key SECRET_KEY = env("DJANGO_SECRET_KEY") # https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts -ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=["https://tele.band"]) +ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=["https://tele.band", "dev-api.musiccpr.org"]) # DATABASES # ------------------------------------------------------------------------------ From 55cd18d3feb7a2c5994a1b342f0631ba21ae0bae Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 19 Mar 2025 14:11:01 -0400 Subject: [PATCH 11/16] Add deployment workflow --- .github/workflows/deploy.yaml | 62 +++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/workflows/deploy.yaml diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml new file mode 100644 index 0000000..f9bec78 --- /dev/null +++ b/.github/workflows/deploy.yaml @@ -0,0 +1,62 @@ +name: Deploy to EC2 + +on: + push: + branches: + - dev + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set environment variables + run: | + if [[ "${{ github.ref }}" == "refs/head/main" ]]; then + echo "DEPLOY_DIR=/data/MusicCPRProd" >> $GITHUB_ENV + echo "IMAGE_NAME=backend:prod" >> $GITHUB_ENV + echo "CONTAINER_NAME=backend-prod" >> $GITHUB_ENV + echo "HOST_POST=8001" >> $GITHUB_ENV + else + echo "DEPLOY_DIR=/data/MusicCPRDev" >> $GITHUB_ENV + echo "IMAGE_NAME=backend:dev" >> $GITHUB_ENV + echo "CONTAINER_NAME=backend-dev" >> $GITHUB_ENV + echo "HOST_POST=8000" >> $GITHUB_ENV + fi + - name: Set up SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.EC2_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H ${{ secrets.EC2_HOST }} >> ~/.ssh/known_hosts + + - name: Deploy to EC2 + run: | + ssh ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }} << 'EOF' + set -e + echo "Deploying to ${{ env.DEPLOY_DIR }}" + + cd ${{ env.DEPLOY_DIR }} + + echo "Pulling latest changes..." + git pull origin ${{ github.ref_name }} + + echo "Stopping and removing old container" + docker stop ${{ env.CONTAINER_NAME }} || true + docker rm ${{ env.CONTAINER_NAME }} || true + + echo "Removing old image" + docker rmi ${{ env.IMAGE_NAME }} || true + + echo "Building new image..." + docker build -t ${{ env.IMAGE_NAME }} . + + echo "Starting new container..." + docker run -d --name ${{ env.CONTAINER_NAME }} \ + -p ${{ env.HOST_PORT }}:8000 \ + -v ./.env:/app/.env \ + ${{ env.IMAGE_NAME }} + From 004f63db0670c03df34610ec92c01d29d74bab78 Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 19 Mar 2025 14:15:16 -0400 Subject: [PATCH 12/16] Test commit --- .github/workflows/deploy.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index f9bec78..bcf3392 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -59,4 +59,3 @@ jobs: -p ${{ env.HOST_PORT }}:8000 \ -v ./.env:/app/.env \ ${{ env.IMAGE_NAME }} - From db1f297c11de40860cb27a964b89e6ca19ac3489 Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 19 Mar 2025 14:18:33 -0400 Subject: [PATCH 13/16] Fix indent --- .github/workflows/deploy.yaml | 100 +++++++++++++++++----------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index bcf3392..4d48e1e 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -9,53 +9,53 @@ jobs: deploy: runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set environment variables - run: | - if [[ "${{ github.ref }}" == "refs/head/main" ]]; then - echo "DEPLOY_DIR=/data/MusicCPRProd" >> $GITHUB_ENV - echo "IMAGE_NAME=backend:prod" >> $GITHUB_ENV - echo "CONTAINER_NAME=backend-prod" >> $GITHUB_ENV - echo "HOST_POST=8001" >> $GITHUB_ENV - else - echo "DEPLOY_DIR=/data/MusicCPRDev" >> $GITHUB_ENV - echo "IMAGE_NAME=backend:dev" >> $GITHUB_ENV - echo "CONTAINER_NAME=backend-dev" >> $GITHUB_ENV - echo "HOST_POST=8000" >> $GITHUB_ENV - fi - - name: Set up SSH - run: | - mkdir -p ~/.ssh - echo "${{ secrets.EC2_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - ssh-keyscan -H ${{ secrets.EC2_HOST }} >> ~/.ssh/known_hosts - - - name: Deploy to EC2 - run: | - ssh ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }} << 'EOF' - set -e - echo "Deploying to ${{ env.DEPLOY_DIR }}" - - cd ${{ env.DEPLOY_DIR }} - - echo "Pulling latest changes..." - git pull origin ${{ github.ref_name }} - - echo "Stopping and removing old container" - docker stop ${{ env.CONTAINER_NAME }} || true - docker rm ${{ env.CONTAINER_NAME }} || true - - echo "Removing old image" - docker rmi ${{ env.IMAGE_NAME }} || true - - echo "Building new image..." - docker build -t ${{ env.IMAGE_NAME }} . - - echo "Starting new container..." - docker run -d --name ${{ env.CONTAINER_NAME }} \ - -p ${{ env.HOST_PORT }}:8000 \ - -v ./.env:/app/.env \ - ${{ env.IMAGE_NAME }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set environment variables + run: | + if [[ "${{ github.ref }}" == "refs/head/main" ]]; then + echo "DEPLOY_DIR=/data/MusicCPRProd" >> $GITHUB_ENV + echo "IMAGE_NAME=backend:prod" >> $GITHUB_ENV + echo "CONTAINER_NAME=backend-prod" >> $GITHUB_ENV + echo "HOST_POST=8001" >> $GITHUB_ENV + else + echo "DEPLOY_DIR=/data/MusicCPRDev" >> $GITHUB_ENV + echo "IMAGE_NAME=backend:dev" >> $GITHUB_ENV + echo "CONTAINER_NAME=backend-dev" >> $GITHUB_ENV + echo "HOST_POST=8000" >> $GITHUB_ENV + fi + - name: Set up SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.EC2_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H ${{ secrets.EC2_HOST }} >> ~/.ssh/known_hosts + + - name: Deploy to EC2 + run: | + ssh ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }} << 'EOF' + set -e + echo "Deploying to ${{ env.DEPLOY_DIR }}" + + cd ${{ env.DEPLOY_DIR }} + + echo "Pulling latest changes..." + git pull origin ${{ github.ref_name }} + + echo "Stopping and removing old container" + docker stop ${{ env.CONTAINER_NAME }} || true + docker rm ${{ env.CONTAINER_NAME }} || true + + echo "Removing old image" + docker rmi ${{ env.IMAGE_NAME }} || true + + echo "Building new image..." + docker build -t ${{ env.IMAGE_NAME }} . + + echo "Starting new container..." + docker run -d --name ${{ env.CONTAINER_NAME }} \ + -p ${{ env.HOST_PORT }}:8000 \ + -v ./.env:/app/.env \ + ${{ env.IMAGE_NAME }} From 6730ddee50b6810a73ff7df5ce7ad12edf7fca59 Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 19 Mar 2025 14:23:24 -0400 Subject: [PATCH 14/16] Debug port --- .github/workflows/deploy.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 4d48e1e..b997b4f 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -55,6 +55,7 @@ jobs: docker build -t ${{ env.IMAGE_NAME }} . echo "Starting new container..." + echo "Listening on port ${{ env.HOST_PORT }}" docker run -d --name ${{ env.CONTAINER_NAME }} \ -p ${{ env.HOST_PORT }}:8000 \ -v ./.env:/app/.env \ From e060f37a323fca4161c4715cd1ede4c8c0703060 Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 19 Mar 2025 14:25:09 -0400 Subject: [PATCH 15/16] Fix typo in port var --- .github/workflows/deploy.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index b997b4f..aef1590 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -19,12 +19,12 @@ jobs: echo "DEPLOY_DIR=/data/MusicCPRProd" >> $GITHUB_ENV echo "IMAGE_NAME=backend:prod" >> $GITHUB_ENV echo "CONTAINER_NAME=backend-prod" >> $GITHUB_ENV - echo "HOST_POST=8001" >> $GITHUB_ENV + echo "HOST_PORT=8001" >> $GITHUB_ENV else echo "DEPLOY_DIR=/data/MusicCPRDev" >> $GITHUB_ENV echo "IMAGE_NAME=backend:dev" >> $GITHUB_ENV echo "CONTAINER_NAME=backend-dev" >> $GITHUB_ENV - echo "HOST_POST=8000" >> $GITHUB_ENV + echo "HOST_PORT=8000" >> $GITHUB_ENV fi - name: Set up SSH run: | @@ -60,3 +60,4 @@ jobs: -p ${{ env.HOST_PORT }}:8000 \ -v ./.env:/app/.env \ ${{ env.IMAGE_NAME }} + EOF From 2cb08a6340a51fbfffd79e609f083cf7a0f558d8 Mon Sep 17 00:00:00 2001 From: Adam Vinch Date: Wed, 19 Mar 2025 14:26:11 -0400 Subject: [PATCH 16/16] Unindent EOF --- .github/workflows/deploy.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index aef1590..c0898ea 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -55,9 +55,8 @@ jobs: docker build -t ${{ env.IMAGE_NAME }} . echo "Starting new container..." - echo "Listening on port ${{ env.HOST_PORT }}" docker run -d --name ${{ env.CONTAINER_NAME }} \ -p ${{ env.HOST_PORT }}:8000 \ -v ./.env:/app/.env \ ${{ env.IMAGE_NAME }} - EOF + EOF