From b8e6ec97bf3dcb3a500885e27e71885f28a05e6f Mon Sep 17 00:00:00 2001 From: filipopo Date: Tue, 26 Nov 2024 21:26:50 +0100 Subject: [PATCH] Improve docker compose --- Dockerfile | 31 ++++++++++++++++++++++++++----- README.md | 18 ++++++++++-------- app/requirements-mssql.txt | 1 + app/requirements.txt | 1 - app/urlshortener/settings.py | 12 ++++++------ {infra => cdk}/Pipfile | 0 {infra => cdk}/Pipfile.lock | 0 {infra => cdk}/cdktf.json | 0 {infra => cdk}/help | 0 {infra => cdk}/main-test.py | 0 {infra => cdk}/main.py | 0 compose.yml | 23 ++++++++++++++++------- compose/entrypoint.sh | 14 ++++++++++++++ compose/init.sql | 5 +++++ compose/nginx.conf | 21 +++++++++++++++++++++ nginx.conf | 18 ------------------ 16 files changed, 99 insertions(+), 45 deletions(-) create mode 100644 app/requirements-mssql.txt rename {infra => cdk}/Pipfile (100%) rename {infra => cdk}/Pipfile.lock (100%) rename {infra => cdk}/cdktf.json (100%) rename {infra => cdk}/help (100%) rename {infra => cdk}/main-test.py (100%) rename {infra => cdk}/main.py (100%) create mode 100644 compose/entrypoint.sh create mode 100644 compose/init.sql create mode 100644 compose/nginx.conf delete mode 100644 nginx.conf diff --git a/Dockerfile b/Dockerfile index e2f7674..300f205 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,32 @@ -ARG PY_VER="3.12" +ARG PY_VER=3.12 +ARG BUILD=default # Build stage FROM python:${PY_VER}-slim AS base +ARG BUILD WORKDIR /app -COPY app/requirements.txt . +COPY app/requirements.txt app/requirements-mssql.txt . -RUN pip install --no-cache-dir --upgrade -r requirements.txt +RUN pip install --no-cache-dir --upgrade -r requirements.txt && \ + if [ "$BUILD" = "mssql" ]; then \ + pip install --no-cache-dir --upgrade -r requirements-mssql.txt && \ + apt update && apt install -y curl gpg && \ + apt clean && rm -rf /var/lib/apt/lists/* && \ + VER=$(cut -d. -f1 /etc/debian_version) && \ + curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg && \ + curl https://packages.microsoft.com/config/debian/${VER}/prod.list > /etc/apt/sources.list.d/mssql-release.list; \ + fi COPY app . RUN echo "python manage.py migrate --noinput && gunicorn --bind 0.0.0.0:8000 urlshortener.wsgi" > start.sh && \ python manage.py collectstatic --noinput && \ - rm -rf webapp/static requirements.txt + rm -rf webapp/static requirements.txt requirements-mssql.txt # Deploy stage -FROM python:${PY_VER}-slim +FROM python:${PY_VER}-slim AS build_default ARG PY_VER WORKDIR /app @@ -25,6 +35,17 @@ COPY --from=base /usr/local/bin/gunicorn /usr/local/bin/gunicorn COPY --from=base /usr/local/lib/python${PY_VER}/site-packages/ /usr/local/lib/python${PY_VER}/site-packages/ +FROM build_default AS build_mssql + +ONBUILD COPY --from=base /usr/share/keyrings/microsoft-prod.gpg /usr/share/keyrings/microsoft-prod.gpg + +ONBUILD COPY --from=base /etc/apt/sources.list.d/mssql-release.list /etc/apt/sources.list.d/mssql-release.list + +ONBUILD RUN apt update && ACCEPT_EULA=y apt install -y unixodbc msodbcsql17 && \ + apt clean && rm -rf /var/lib/apt/lists/* + +FROM build_$BUILD + COPY --from=base /app . EXPOSE 8000 diff --git a/README.md b/README.md index 71de4e3..5c34698 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ cd urlshortener python manage.py startapp webapp ``` -and the infra folder which was created using this cdktf template: +and the cdk folder which was created using this cdktf template: `cdktf init --template=typescript --providers=azurerm --local` @@ -67,7 +67,7 @@ This application comes with an API which it interally uses, the available routes curl -b "csrftoken=${csrf}" -H "X-CSRFToken: ${csrf}" -d "url=https://example.com" http://127.0.0.1:8000/url ``` ``` - {"message": "http://127.0.0.1:8000/u/filip", "url": true} + {"message": "http://127.0.0.1:8000/u/A", "url": true} ``` @@ -92,9 +92,9 @@ Regardless of how you deploy this app, there are some environment variables that ``` DB_ENGINE=mssql - DB_NAME=database - DB_USER=root - DB_PASSWORD=password + DB_NAME=urlshortener + DB_USER=sa + DB_PASSWORD=P@ssw0rd! DB_HOST=example.database.windows.net DB_PORT=1433 ``` @@ -123,7 +123,7 @@ There are several options for installing the app, here is a non exhaustive list: For this approach you will need Docker: https://www.docker.com - Running `docker compose up` will build the Dockerfile in the current directory and start 3 containers, the python app, a mssql database and an nginx static file server. Consider using an .env file with the env-file option + Running `docker compose up` will build the Dockerfile in the current directory and start 3 containers, the python app, a mssql database and an nginx static file server Alternatively, you can run just the python app like this: @@ -133,6 +133,8 @@ There are several options for installing the app, here is a non exhaustive list: ``` If you're deploying to the cloud, make sure you build for the right platform e.g `--platform linux/amd64` + + If you're going to use the mssql database, build with `--build-arg BUILD=mssql`
@@ -144,9 +146,9 @@ There are several options for installing the app, here is a non exhaustive list: the VE can be activated: `source venv/bin/activate` and deactivated: `deactivate` - To get started install the dependencies + To get started install the dependencies, you may skip mssql if you don't plan on using it - `pip install -r requirements.txt` + `pip install -r requirements.txt requirements-mssql.txt` Then this command to apply the database migrations diff --git a/app/requirements-mssql.txt b/app/requirements-mssql.txt new file mode 100644 index 0000000..4eff2ec --- /dev/null +++ b/app/requirements-mssql.txt @@ -0,0 +1 @@ +mssql-django==1.5 \ No newline at end of file diff --git a/app/requirements.txt b/app/requirements.txt index 86dc4cc..1068069 100644 --- a/app/requirements.txt +++ b/app/requirements.txt @@ -1,3 +1,2 @@ django==5.0.9 -mssql-django==1.5 gunicorn==23.0.0 \ No newline at end of file diff --git a/app/urlshortener/settings.py b/app/urlshortener/settings.py index 66ecc23..7df179d 100644 --- a/app/urlshortener/settings.py +++ b/app/urlshortener/settings.py @@ -69,9 +69,9 @@ DATABASES = { 'default': { 'ENGINE': os.getenv('DB_ENGINE', 'mssql'), - 'NAME': os.getenv('DB_NAME', 'database'), - 'USER': os.getenv('DB_USER', 'root'), - 'PASSWORD': os.getenv('DB_PASSWORD', 'password'), + 'NAME': os.getenv('DB_NAME', 'urlshortener'), + 'USER': os.getenv('DB_USER', 'sa'), + 'PASSWORD': os.getenv('DB_PASSWORD', 'P@ssw0rd!'), 'HOST': os.getenv('DB_HOST', 'example.database.windows.net'), 'PORT': os.getenv('DB_PORT', '1433'), } @@ -128,11 +128,11 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' -CSRF_TRUSTED_ORIGINS = os.getenv('DJANGO_CSRF', 'https://example.com').split(',') +CSRF_TRUSTED_ORIGINS = os.getenv('DJANGO_CSRF', 'http://127.0.0.1,http://127.0.0.1:8000').split(',') -CSRF_COOKIE_SECURE = True +CSRF_COOKIE_SECURE = os.getenv('DJANGO_CSRF') != None -SESSION_COOKIE_SECURE = True +SESSION_COOKIE_SECURE = os.getenv('DJANGO_CSRF') != None # Redirect to home URL after login and logout LOGIN_REDIRECT_URL = '/' diff --git a/infra/Pipfile b/cdk/Pipfile similarity index 100% rename from infra/Pipfile rename to cdk/Pipfile diff --git a/infra/Pipfile.lock b/cdk/Pipfile.lock similarity index 100% rename from infra/Pipfile.lock rename to cdk/Pipfile.lock diff --git a/infra/cdktf.json b/cdk/cdktf.json similarity index 100% rename from infra/cdktf.json rename to cdk/cdktf.json diff --git a/infra/help b/cdk/help similarity index 100% rename from infra/help rename to cdk/help diff --git a/infra/main-test.py b/cdk/main-test.py similarity index 100% rename from infra/main-test.py rename to cdk/main-test.py diff --git a/infra/main.py b/cdk/main.py similarity index 100% rename from infra/main.py rename to cdk/main.py diff --git a/compose.yml b/compose.yml index 065bf94..5e0f8b6 100644 --- a/compose.yml +++ b/compose.yml @@ -1,7 +1,13 @@ services: web: - build: . + build: + context: . + args: + BUILD: mssql restart: unless-stopped + environment: + - DB_EXTERNAL=true + - DB_HOST=db depends_on: db: condition: service_healthy @@ -13,17 +19,20 @@ services: restart: unless-stopped environment: MSSQL_PID: "Express" - MSSQL_SA_PASSWORD: "${DB_PASSWORD:-P@ssw0rd}" + MSSQL_SA_PASSWORD: "${DB_PASSWORD:-P@ssw0rd!}" ACCEPT_EULA: "Y" - SQLCMDPASSWORD: "${DB_PASSWORD:-P@ssw0rd}" + SQLCMDPASSWORD: "${DB_PASSWORD:-P@ssw0rd!}" healthcheck: test: /opt/mssql-tools*/bin/sqlcmd -C -S localhost -U sa -Q "SELECT 1" -b -o /dev/null interval: 10s retries: 10 timeout: 3s - start_period: 10s - #volumes: - # - /var/opt/mssql:/var/opt/mssql + start_period: 20s + volumes: + - ./compose/init.sql:/init/init.sql + - ./compose/entrypoint.sh:/usr/local/bin/entrypoint.sh + #- /var/opt/mssql:/var/opt/mssql + entrypoint: ["sh", "/usr/local/bin/entrypoint.sh"] nginx: image: nginx @@ -34,7 +43,7 @@ services: - web volumes: - static:/app/prod_static - - ./nginx.conf:/etc/nginx/conf.d/default.conf + - ./compose/nginx.conf:/etc/nginx/conf.d/default.conf volumes: static: diff --git a/compose/entrypoint.sh b/compose/entrypoint.sh new file mode 100644 index 0000000..01c92a3 --- /dev/null +++ b/compose/entrypoint.sh @@ -0,0 +1,14 @@ +#!/bin/sh +set -e + +# Start SQL Server in the background +/opt/mssql/bin/sqlservr & + +# Give SQL Server time to start +sleep 10 + +# Run SQL script +/opt/mssql-tools*/bin/sqlcmd -C -S localhost -U sa -i /init/init.sql -b + +# Wait for SQL Server to exit +wait \ No newline at end of file diff --git a/compose/init.sql b/compose/init.sql new file mode 100644 index 0000000..08b6025 --- /dev/null +++ b/compose/init.sql @@ -0,0 +1,5 @@ +IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = 'urlshortener') +BEGIN + CREATE DATABASE urlshortener; +END; +GO \ No newline at end of file diff --git a/compose/nginx.conf b/compose/nginx.conf new file mode 100644 index 0000000..3443a96 --- /dev/null +++ b/compose/nginx.conf @@ -0,0 +1,21 @@ +server { + listen 80; + + location /favicon.ico { + alias /app/prod_static/favicon.ico; + } + + location /static { + alias /app/prod_static; + } + + location / { + proxy_pass http://web:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_redirect off; + } +} \ No newline at end of file diff --git a/nginx.conf b/nginx.conf deleted file mode 100644 index 597860a..0000000 --- a/nginx.conf +++ /dev/null @@ -1,18 +0,0 @@ -server { - listen 80; - - location /favicon.ico/ { - alias /app/prod_static/favicon.ico/; - } - - location /static/ { - alias /app/prod_static/; - } - - location / { - proxy_pass http://web:8000; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_redirect off; - } -} \ No newline at end of file