From 7f96b2a9eaf2d1680d0f4744f9ff61a92b1bb6fe Mon Sep 17 00:00:00 2001 From: Sarah Aligbe <37581442+Sarahligbe@users.noreply.github.com> Date: Thu, 8 Aug 2024 11:33:42 +0100 Subject: [PATCH] updated the dockerfile, docker compose and cd files to reflect the docker changes --- .github/workflows/cd.dev.yml | 45 +++++++++++--------- .github/workflows/cd.dev.yml.bac | 35 ++++++++++++++++ .github/workflows/cd.prod.yml | 44 +++++++++++--------- .github/workflows/cd.prod.yml.bac | 35 ++++++++++++++++ .github/workflows/cd.staging.yml | 42 ++++++++++--------- .github/workflows/cd.staging.yml.bac | 35 ++++++++++++++++ .github/workflows/{ci.yml => ci.yml.bac} | 0 .github/workflows/pr-deploy.yml | 6 ++- .github/workflows/test.yml | 50 +++++++++++++++++++++++ Dockerfile | 16 ++++---- docker/prod/Dockerfile | 25 ++++++++++++ docker/prod/docker-compose.prod.yml | 36 ++++++++++++++++ docker/staging/Dockerfile | 25 ++++++++++++ docker/staging/docker-compose.staging.yml | 36 ++++++++++++++++ 14 files changed, 360 insertions(+), 70 deletions(-) create mode 100644 .github/workflows/cd.dev.yml.bac create mode 100644 .github/workflows/cd.prod.yml.bac create mode 100644 .github/workflows/cd.staging.yml.bac rename .github/workflows/{ci.yml => ci.yml.bac} (100%) create mode 100644 .github/workflows/test.yml create mode 100644 docker/prod/Dockerfile create mode 100644 docker/prod/docker-compose.prod.yml create mode 100644 docker/staging/Dockerfile create mode 100644 docker/staging/docker-compose.staging.yml diff --git a/.github/workflows/cd.dev.yml b/.github/workflows/cd.dev.yml index fcb167d96..2b19b2354 100644 --- a/.github/workflows/cd.dev.yml +++ b/.github/workflows/cd.dev.yml @@ -1,35 +1,40 @@ -name: Dev Branch Deployment - +name: Dev cd pipeline on: - workflow_run: - workflows: ["CI"] - types: - - completed - branches: [dev] + push: + branches: [devops] jobs: - on-success: + build-and-deploy: runs-on: ubuntu-latest - if: ${{ github.event.workflow_run.conclusion == 'success' }} steps: - name: Checkout code uses: actions/checkout@v3 - - name: Use SSH Action + - name: Build image + run: docker build -t anchor-python-bp-dev:latest -f Dockerfile . + + - name: Save image + run: docker save anchor-python-bp-dev:latest | gzip > dev.tar.gz + + - name: Copy image to server + uses: appleboy/scp-action@v0.1.7 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + source: "dev.tar.gz" + target: "/home/${{ secrets.USERNAME }}/boilerplate-python/dev_source_code" + + - name: Deploy image on server uses: appleboy/ssh-action@v0.1.8 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} password: ${{ secrets.PASSWORD }} script: | - cd python/dev_source_code/ - git pull origin dev - source .venv/bin/activate - pip install -r requirements.txt - alembic upgrade head + cd /home/${{ secrets.USERNAME }}/boilerplate-python/dev_source_code + git pull origin devops + docker load --input dev.tar.gz + docker compose -f docker-compose.yml up -d + rm -f dev.tar.gz - on-failure: - runs-on: ubuntu-latest - if: ${{ github.event.workflow_run.conclusion == 'failure' }} - steps: - - run: echo 'The triggering workflow failed' diff --git a/.github/workflows/cd.dev.yml.bac b/.github/workflows/cd.dev.yml.bac new file mode 100644 index 000000000..fcb167d96 --- /dev/null +++ b/.github/workflows/cd.dev.yml.bac @@ -0,0 +1,35 @@ +name: Dev Branch Deployment + +on: + workflow_run: + workflows: ["CI"] + types: + - completed + branches: [dev] + +jobs: + on-success: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Use SSH Action + uses: appleboy/ssh-action@v0.1.8 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + script: | + cd python/dev_source_code/ + git pull origin dev + source .venv/bin/activate + pip install -r requirements.txt + alembic upgrade head + + on-failure: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'failure' }} + steps: + - run: echo 'The triggering workflow failed' diff --git a/.github/workflows/cd.prod.yml b/.github/workflows/cd.prod.yml index 23217d2e5..b3b1c5d45 100644 --- a/.github/workflows/cd.prod.yml +++ b/.github/workflows/cd.prod.yml @@ -1,35 +1,39 @@ -name: Prod Branch Deployment - +name: Prod cd pipeline on: - workflow_run: - workflows: ["CI"] - types: - - completed - branches: [main] + push: + branches: [dev] jobs: - on-success: + build-and-deploy: runs-on: ubuntu-latest - if: ${{ github.event.workflow_run.conclusion == 'success' }} steps: - name: Checkout code uses: actions/checkout@v3 - - name: Use SSH Action + - name: Build image + run: docker build -t anchor-python-bp-prod:latest -f docker/prod/Dockerfile . + + - name: Save image + run: docker save anchor-python-bp-prod:latest | gzip > prod.tar.gz + + - name: Copy image to server + uses: appleboy/scp-action@v0.1.7 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + source: "prod.tar.gz" + target: "/home/${{ secrets.USERNAME }}/boilerplate-python/prod_source_code/docker/prod" + + - name: Deploy image on server uses: appleboy/ssh-action@v0.1.8 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} password: ${{ secrets.PASSWORD }} script: | - cd python/prod_source_code/ + cd /home/${{ secrets.USERNAME }}/boilerplate-python/prod_source_code/docker/prod git pull origin main - source .venv/bin/activate - pip install -r requirements.txt - alembic upgrade head - - on-failure: - runs-on: ubuntu-latest - if: ${{ github.event.workflow_run.conclusion == 'failure' }} - steps: - - run: echo 'The triggering workflow failed' + docker load --input prod.tar.gz + docker compose -f docker-compose.yml up -d + rm -f prod.tar.gz \ No newline at end of file diff --git a/.github/workflows/cd.prod.yml.bac b/.github/workflows/cd.prod.yml.bac new file mode 100644 index 000000000..23217d2e5 --- /dev/null +++ b/.github/workflows/cd.prod.yml.bac @@ -0,0 +1,35 @@ +name: Prod Branch Deployment + +on: + workflow_run: + workflows: ["CI"] + types: + - completed + branches: [main] + +jobs: + on-success: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Use SSH Action + uses: appleboy/ssh-action@v0.1.8 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + script: | + cd python/prod_source_code/ + git pull origin main + source .venv/bin/activate + pip install -r requirements.txt + alembic upgrade head + + on-failure: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'failure' }} + steps: + - run: echo 'The triggering workflow failed' diff --git a/.github/workflows/cd.staging.yml b/.github/workflows/cd.staging.yml index 7de13a1b6..c3b4be4a2 100644 --- a/.github/workflows/cd.staging.yml +++ b/.github/workflows/cd.staging.yml @@ -1,35 +1,39 @@ -name: Staging Branch Deployment - +name: Staging cd pipeline on: - workflow_run: - workflows: ["CI"] - types: - - completed + push: branches: [staging] jobs: - on-success: + build-and-deploy: runs-on: ubuntu-latest - if: ${{ github.event.workflow_run.conclusion == 'success' }} steps: - name: Checkout code uses: actions/checkout@v3 - - name: Use SSH Action + - name: Build image + run: docker build -t anchor-python-bp-staging:latest -f docker/staging/Dockerfile . + + - name: Save image + run: docker save anchor-python-bp-staging:latest | gzip > staging.tar.gz + + - name: Copy image to server + uses: appleboy/scp-action@v0.1.7 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + source: "staging.tar.gz" + target: "/home/${{ secrets.USERNAME }}/boilerplate-python/staging_source_code/docker/staging" + + - name: Deploy image on server uses: appleboy/ssh-action@v0.1.8 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} password: ${{ secrets.PASSWORD }} script: | - cd python/staging_source_code/ + cd /home/${{ secrets.USERNAME }}/boilerplate-python/staging_source_code/docker/staging git pull origin staging - source .venv/bin/activate - pip install -r requirements.txt - alembic upgrade head - - on-failure: - runs-on: ubuntu-latest - if: ${{ github.event.workflow_run.conclusion == 'failure' }} - steps: - - run: echo 'The triggering workflow failed' + docker load --input staging.tar.gz + docker compose -f docker-compose.yml up -d + rm -f staging.tar.gz \ No newline at end of file diff --git a/.github/workflows/cd.staging.yml.bac b/.github/workflows/cd.staging.yml.bac new file mode 100644 index 000000000..7de13a1b6 --- /dev/null +++ b/.github/workflows/cd.staging.yml.bac @@ -0,0 +1,35 @@ +name: Staging Branch Deployment + +on: + workflow_run: + workflows: ["CI"] + types: + - completed + branches: [staging] + +jobs: + on-success: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Use SSH Action + uses: appleboy/ssh-action@v0.1.8 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + script: | + cd python/staging_source_code/ + git pull origin staging + source .venv/bin/activate + pip install -r requirements.txt + alembic upgrade head + + on-failure: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'failure' }} + steps: + - run: echo 'The triggering workflow failed' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml.bac similarity index 100% rename from .github/workflows/ci.yml rename to .github/workflows/ci.yml.bac diff --git a/.github/workflows/pr-deploy.yml b/.github/workflows/pr-deploy.yml index 7ede1e307..a0a0b2e7d 100644 --- a/.github/workflows/pr-deploy.yml +++ b/.github/workflows/pr-deploy.yml @@ -12,6 +12,8 @@ jobs: steps: - name: Checkout to branch uses: actions/checkout@v4 + - name: Copy .env.sample to .env + run: cp .env.sample .env - id: deploy name: Pull Request Deploy uses: hngprojects/pr-deploy@dev @@ -22,8 +24,8 @@ jobs: comment: true context: '.' dockerfile: 'Dockerfile' - exposed_port: '8000' + exposed_port: '7001' github_token: ${{ secrets.GITHUB_TOKEN }} - name: Print Preview Url run: | - echo "Preview Url: ${{ steps.deploy.outputs.preview-url }}" + echo "Preview Url: ${{ steps.deploy.outputs.preview-url }}" \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..f1eb8c436 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,50 @@ +name: Test +on: + pull_request: + types: [opened, synchronize, reopened, closed] + +jobs: + test: + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: "username" + POSTGRES_PASSWORD: "password" + POSTGRES_DB: "test" + ports: + - 5432:5432 + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.12" + + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install dependencies + run: | + pip install -r requirements.txt + + - name: Copy env file + run: cp .env.sample .env + + - name: Run migrations + run: | + alembic upgrade head + + - name: Run tests + run: | + PYTHONPATH=. pytest \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index bac36d7f2..0a84aa847 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Use an official Python runtime as the base image -FROM python:3.11.9-alpine +FROM python:3.12-alpine # Set environment variables ENV PYTHONDONTWRITEBYTECODE=1 @@ -11,17 +11,15 @@ WORKDIR /app # Install system dependencies RUN apk add --no-cache curl +#copy the requirements.txt file and install with pip +COPY ./requirements.txt /app/requirements.txt +RUN pip install --no-cache-dir --upgrade -r requirements.txt + # Copy the rest of the backend files COPY . /app/ -# Copy the .env.sample to .env -COPY .env.sample /app/.env - -# Install dependencies -RUN pip install --no-cache-dir --upgrade -r requirements.txt - # Expose the port the app runs on -EXPOSE 8000 +EXPOSE 7001 # Command to run the application -CMD ["/bin/sh", "-c", "uvicorn main:app --host 0.0.0.0 --port 8000 --reload"] +CMD ["/bin/sh", "-c", "uvicorn main:app --host 0.0.0.0 --port 7001 --reload"] \ No newline at end of file diff --git a/docker/prod/Dockerfile b/docker/prod/Dockerfile new file mode 100644 index 000000000..0a84aa847 --- /dev/null +++ b/docker/prod/Dockerfile @@ -0,0 +1,25 @@ +# Use an official Python runtime as the base image +FROM python:3.12-alpine + +# Set environment variables +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 +ENV PYTHONPATH=/app +# Set the working directory in the container +WORKDIR /app + +# Install system dependencies +RUN apk add --no-cache curl + +#copy the requirements.txt file and install with pip +COPY ./requirements.txt /app/requirements.txt +RUN pip install --no-cache-dir --upgrade -r requirements.txt + +# Copy the rest of the backend files +COPY . /app/ + +# Expose the port the app runs on +EXPOSE 7001 + +# Command to run the application +CMD ["/bin/sh", "-c", "uvicorn main:app --host 0.0.0.0 --port 7001 --reload"] \ No newline at end of file diff --git a/docker/prod/docker-compose.prod.yml b/docker/prod/docker-compose.prod.yml new file mode 100644 index 000000000..cb8fbe15b --- /dev/null +++ b/docker/prod/docker-compose.prod.yml @@ -0,0 +1,36 @@ +services: + app_prod: + image: anchor-python-bp-prod:latest + command: ["sh", "-c", "alembic upgrade head && uvicorn main:app --host 0.0.0.0 --port 7001 --reload"] + container_name: app_prod + networks: + - hng-network + restart: unless-stopped + ports: + - 7007:7001 + working_dir: /app + volumes: + - .env:/app/.env + depends_on: + - prod_db + + prod_db: + image: postgres:14.12 + container_name: prod_db + restart: always + volumes: + - prod_db:/var/lib/postgresql/data + - .env:/app/.env + environment: + - POSTGRES_PASSWORD=${DB_PASSWORD?Variable not set} + - POSTGRES_USER=${DB_USER?Variable not set} + - POSTGRES_DB=${DB_NAME?Variable not set} + networks: + - hng-network + +volumes: + prod_db: + +networks: + hng-network: + driver: bridge \ No newline at end of file diff --git a/docker/staging/Dockerfile b/docker/staging/Dockerfile new file mode 100644 index 000000000..0a84aa847 --- /dev/null +++ b/docker/staging/Dockerfile @@ -0,0 +1,25 @@ +# Use an official Python runtime as the base image +FROM python:3.12-alpine + +# Set environment variables +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 +ENV PYTHONPATH=/app +# Set the working directory in the container +WORKDIR /app + +# Install system dependencies +RUN apk add --no-cache curl + +#copy the requirements.txt file and install with pip +COPY ./requirements.txt /app/requirements.txt +RUN pip install --no-cache-dir --upgrade -r requirements.txt + +# Copy the rest of the backend files +COPY . /app/ + +# Expose the port the app runs on +EXPOSE 7001 + +# Command to run the application +CMD ["/bin/sh", "-c", "uvicorn main:app --host 0.0.0.0 --port 7001 --reload"] \ No newline at end of file diff --git a/docker/staging/docker-compose.staging.yml b/docker/staging/docker-compose.staging.yml new file mode 100644 index 000000000..8c2a062a2 --- /dev/null +++ b/docker/staging/docker-compose.staging.yml @@ -0,0 +1,36 @@ +services: + app_staging: + image: anchor-python-bp-staging:latest + command: ["sh", "-c", "alembic upgrade head && uvicorn main:app --host 0.0.0.0 --port 7001 --reload"] + container_name: app_staging + networks: + - hng-network + restart: unless-stopped + ports: + - 7008:7001 + working_dir: /app + volumes: + - .env:/app/.env + depends_on: + - staging_db + + staging_db: + image: postgres:14.12 + container_name: staging_db + restart: always + volumes: + - staging_db:/var/lib/postgresql/data + - .env:/app/.env + environment: + - POSTGRES_PASSWORD=${DB_PASSWORD?Variable not set} + - POSTGRES_USER=${DB_USER?Variable not set} + - POSTGRES_DB=${DB_NAME?Variable not set} + networks: + - hng-network + +volumes: + staging_db: + +networks: + hng-network: + driver: bridge