{"id":21017412,"url":"https://github.com/mkader/python_web_docker_container","last_synced_at":"2026-01-30T14:35:24.266Z","repository":{"id":164207083,"uuid":"639629215","full_name":"mkader/python_web_docker_container","owner":"mkader","description":null,"archived":false,"fork":false,"pushed_at":"2023-05-12T19:14:59.000Z","size":573,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-20T12:24:56.894Z","etag":null,"topics":["leaerning","mslearning"],"latest_commit_sha":null,"homepage":"","language":"Bicep","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mkader.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-11T21:44:46.000Z","updated_at":"2023-12-28T21:26:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"f72e3db4-3b1f-447b-bb41-54a4c99025f3","html_url":"https://github.com/mkader/python_web_docker_container","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkader%2Fpython_web_docker_container","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkader%2Fpython_web_docker_container/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkader%2Fpython_web_docker_container/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkader%2Fpython_web_docker_container/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mkader","download_url":"https://codeload.github.com/mkader/python_web_docker_container/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243447635,"owners_count":20292452,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["leaerning","mslearning"],"created_at":"2024-11-19T10:19:22.464Z","updated_at":"2026-01-30T14:35:24.253Z","avatar_url":"https://github.com/mkader.png","language":"Bicep","funding_links":[],"categories":[],"sub_categories":[],"readme":"Containerizing Python Web Apps with Docker\n    \n    aka.ms/pyday-containers\n\n    A container is a standard way to package an application with all of its dependencies, so that it can be run anywhere.\n\n    Docker overview\n\n        The Docker engine runs multiple Docker containers, where each container is an isolated environment.\n![alt img](docker_overview.PNG)\n\n        Each container can be a very different environment, with binaries and libraries dependent on the application.\n![alt img](docker_overview_example.PNG)\n\n    Container benefits\n        \n        Environment consistency: Ensure that the dev, test, prod environment are the same.\n\n        Application portability: Easy to run the application on new hardware if old hardware fails or if application needs to scale.\n\n        Efficient hardware use: A machine can run multiple containers to make optimal use of its resources.\n\n    Docker images\n        \n        A container image is a software package that includes everything needed to run an application.\n        \n        A container is a running instance of a container image.\n![alt img](docker_images.PNG)    \n\n        Multiple containers can be run from the same image.\n![alt img](docker_images_same.PNG)\n\n    Image registries: A registry is a place to store and share images.\n        Docker Hub: contains many images, including official images for python, postgres, Unix systems, etc.\n        GitHub, Azurem AWS, Google Cloud container registry\n        Private (Proget, JFrog)\n    \n    Image layers: A container image often starts off with a base image, and then adds layers on top of it.\n        For example:\n            Base image: Ubuntu 20.04\n            Layer 1: Python 3.9\n            Layer 2: Flask 2.0\n            Layer 3: Your app\n        \n        Docker can cache each layer, which improves performance.\n\nProductionizing Flask apps    \n\n    Sample Flask app: github.com/pamelafox/simple-flask-server-container-starter\n        from flask import Flask, render_template, request\n\n        app = Flask(__name__, template_folder='templates', static_folder='static')\n\n        @app.route('/')\n        def index():\n            return render_template('index.html')\n\n        @app.route('/hello')\n        def hello():\n            return render_template('hello.html', name=request.args.get('name'))\n\n    pip install -r requirements.txt\n    \n    Running Flask app locally, Using the built-in Flask server:\n        python3 -m flask run --port 50505 --debug\n\n    Running Flask with gunicorn\n        Gunicorn is a production-level server that can run multiple worker processes.\n        \n        Add gunicorn to requirements.txt:\n            Flask==2.2.3\n            gunicorn==20.1.0\n        \n        Use gunicorn to run Flask app with multiple workers:\n            python3 -m gunicorn app:app --workers 4 --bind 0.0.0.0:50505\n    \n    Configuring gunicorn, Gunicorn can be configured with a gunicorn.conf.py file:\n        import multiprocessing\n            \n        max_requests = 1000\n        max_requests_jitter = 50\n        log_file = \"-\"\n        bind = \"0.0.0.0:50505\"\n\n        workers = (multiprocessing.cpu_count() * 2) + 1\n        threads = workers\n        timeout = 120\n\n    The run command can be simplified to: python3 -m gunicorn app:app\n\nContainerizing Flask apps\n\n    Containerization steps\n        Write a Dockerfile\n        Build image from Dockerfile\n        Run container using built image\n\n    Dockerfile format, A Dockerfile includes:\n        The base or parent image*\t            FROM python:3.11\n        Additional software\t                    RUN pip3 install Flask gunicorn\n        Application code\t                    WORKDIR /code\n                                                COPY . .\n        Services to expose (storage/network)\tEXPOSE 50505\n        Command to run upon launching container\tENTRYPOINT [\"gunicorn\", \"-c\", \"gunicorn.conf.py\", \"app:app\"]\n        \n    Dockerfile for Flask, A complete file:\n        FROM python:3.11\n        WORKDIR /code\n        COPY requirements.txt .\n        RUN pip3 install -r requirements.txt\n        COPY . .\n        EXPOSE 50505\n        ENTRYPOINT [\"gunicorn\", \"-c\", \"gunicorn.conf.py\", \"app:app\"]\n\n    Add a dockerignore file, Prevent unnecessary files from being copied to the image:\n        .git*\n        .venv/\n        **/*.pyc\n        __pycache__/\n\nBuilding the image, Using the docker build command:\n    docker build --tag flaskapp .\n\n    Using the VS Code Docker extension\n![alt img](vsc-docker.png)    \n\nRunning the container, Using the docker run command:\n    docker run --publish 50505:50505 flaskapp\n\n    Using VS Code Docker extension or Docker Desktop\n![alt img](screenshot_vscode_run.png)\n\nHosting containers on Azure\n\n    Azure hosting options\n        For hosting containers, Kubernetes Service, Container Apps, and App Service (BYOC) are all good options.\n![alt img](azure_hosting_options.PNG)\n\n    Hosting on Azure Container Apps\n        A Container Apps Environment manages a Container App.\n![alt img](diagram_azurecontainerapp.png)    \n\n        Flask container architecture diagram: Azure Container Apps Environment, Azure Container App, Azure Container Registry, Container, and PostgreSQL Server\n        \n        The Container App pulls its image from an Azure Container Registry. (Other registries are also possible)\n\n    Deploying to ACA with Azure CLI\n        Install the Azure Developer CLI (already installed in Dev Container).\n        \n        Login to your Azure account: az login or az login --use-device-code\n        \n        Create a resource group: az group create --name flaskapp-rg --location eastus\n        \n        Create resources and deploy the app:\n            az containerapp up --resource-group flaskapp-rg --name flaskapp-aca \\\n                --ingress external --target-port 50505 --source .\n        \n    Deploying to ACA with AZD\n        Using this repo (with Bicep files in infra folder): github.com/pamelafox/simple-flask-server-container\n        \n        Install the Azure Developer CLI (already installed in Dev Container).\n        \n        Login to your Azure account: azd auth login\n        \n        Create resources and deploy the app: azd up\n    \n    Clean up the resources, through portal or azd down\n    \n    Accessing databases from containers\n\n        Sample Flask app with DB: github.com/pamelafox/flask-surveys-container-app    \n            @app.route('/surveys', methods=['GET'])\n            def surveys_list_page():\n                return render_template('surveys_list.html', surveys=Survey.query.all())\n\n            @app.route('/surveys/', methods=['GET'])\n            def survey_page(survey_id):\n                survey = Survey.query.where(Survey.id == survey_id).first()\n                answers = Survey.query.where(Answer.survey==survey_id)\n                return render_template('survey_details.html', survey=survey, answers=answers, already_voted='survey_id' in request.cookies)\n    \n    Data persistence in containers\n        Data can be written to a container's file system, but:\n            Removing a container removes the data\n            Container data is difficult to move between environments\n            Container storage drives are less performant\n            If you need to persist data, you should store it outside the container.\n\n    Docker volumes - A volume is a directory on the host machine that is mapped to a directory in the container.\n        \n        Diagram of Docker container and Docker volumes inside the File System\n![alt img](docker_volumn.PNG)            \n        \n        When developing with databases locally, use a volume to store the data for the database.        \n\n    Running PostgreSQL with Docker\n        Create a volume: docker volume create postgres-data\n\n        Create a network for the containers to communicate over: docker network create postgres-net\n\n        Run a PostgreSQL container with the volume and network:\n            docker run --rm -d --name db --network postgres-net \\\n                -v postgres-data:/var/lib/postgresql/data \\\n                -e POSTGRES_USER=app_user -e POSTGRES_PASSWORD=app_password \\\n                postgres\n\n    Connecting the app to the DB\n        Set environment variables for the database connection:\n            DBHOST=db\n            DBNAME=postgres\n            DBUSER=app_user\n            DBPASS=app_password\n\n        Build the container: docker build --tag flasksurveyscontainerapp src/\n\n        Run the app container over the same network:\n            docker run --rm --name flask-db-app --network postgres-net \\\n                --env-file .env -p 50505:50505 \\\n                flasksurveyscontainerapp            \n\n        Error: docker: Error response from daemon: failed to create shim task: OCI runtime create failed: \n               runc create failed: unable to start container process: \n               exec: \"/code/entrypoint.sh\": permission denied: unknown.\n\n            RUN chmod +x /code/entrypoint.sh       \n\n            re built: docker build -t flasksurveyscontainerapp .\n\nDocker compose\n    Docker compose is a tool for multi-container Docker apps.\n    docker-compose.yaml defines the services that make up your app:\n\n        services:\n            db:\n                image: postgres\n                restart: always\n                environment:\n                    POSTGRES_PASSWORD: ${DBPASS:?database password not set}\n                    POSTGRES_USER: ${DBUSER:?database user not set}\n                    POSTGRES_DB: ${DBNAME:?database name not set}\n                volumes:\n                    - postgres-data:/var/lib/postgresql/data\n                healthcheck:\n                    test: [\"CMD-SHELL\", \"pg_isready -U ${DBUSER} -d ${DBNAME}\"]\n                    interval: 5s\n                    timeout: 5s\n                    retries: 5\n            app:\n                build:\n                    context: .\n                ports:\n                    - 5000:5000\n                depends_on:\n                    db:\n                        condition: service_healthy\n            volumes:\n                postgres-data:            \n\n    Run multiple containers, Run the app and database containers (remove web app container ): docker-compose up   \n        \n        Error: ERROR: for app  Cannot start service app: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: \"/code/entrypoint-dev.sh\": permission denied: unknown\n\n        add dockercompose : \n            entrypoint: sh /code/entrypoint-dev.sh\n            command: sh -c \"chmod +x /code/entrypoint-dev.sh \u0026\u0026 /code/entrypoint-dev.sh\"\n   \n   Remove all: docker-compose down   \n\n\nHosting containers with databases on Azure\n    \n    Storage in container apps\n\n        For temporary storage, you can write to file system or have an ephemeral volume in a container app.\n    \n        For permanent storage, you can mount Azure Files but performance is too limited to be useful for a database.\n\n        Best approach for Azure: Use a managed database service outside the container.\n    \n    Azure managed databases services, These are just some of the options:\n        Option\t                        Description\n        Azure CosmosDB\t                Distributed database with multiple APIs, including MongoDB and Cassandra.\n        Azure Cosmos DB for PostgreSQL\tDistributed database using PostgreSQL and the Citus extension. \n                                        Can scale vertically and horizontally.\n        Azure Database for PostgreSQL   Fully managed service \n        – Flexible Server\t\n\n    Containerized App with PostgreSQL access\n![alt img](azurecontainerapp_postgres.png)        \n\n    Deploying to ACA + PG with AZD using Azure\n        Create azure.yaml, add infr folder for bicep files\n\n        Login to your Azure account: azd auth login\n        \n        Create resources and deploy the app: azd up\n            ? Please enter a new environment name: [? for help] \n\n    Clean up the resources, through portal or azd down.    \n\nMore containerized Python templates\n    \n    Find lots of examples in the AZD templates gallery:\n        https://azure.github.io/awesome-azd/?operator=AND\u0026tags=python\u0026tags=aca","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkader%2Fpython_web_docker_container","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmkader%2Fpython_web_docker_container","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkader%2Fpython_web_docker_container/lists"}