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/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml new file mode 100644 index 0000000..c0898ea --- /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_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_PORT=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 }} + EOF diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..af6b772 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,35 @@ +FROM python:3.10-slim AS builder + +RUN mkdir /app + +WORKDIR /app + +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +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 + +RUN useradd -m -r appuser && \ + mkdir /app && \ + chown -R appuser /app + +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 + +COPY --chown=appuser:appuser . . + +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +RUN chmod +x /app/entrypoint.prod.sh + +EXPOSE 8000 + +CMD ["/app/entrypoint.prod.sh"] 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 # ------------------------------------------------------------------------------ diff --git a/entrypoint.prod.sh b/entrypoint.prod.sh new file mode 100644 index 0000000..79f1f58 --- /dev/null +++ b/entrypoint.prod.sh @@ -0,0 +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 config.asgi:application \ + --bind 0.0.0.0:8000 \ + --workers 4 \ + -k uvicorn.workers.UvicornWorker