Sunday, October 30, 2022
HomeWordPress DevelopmentPython Flask: Interacts with Docker Containers

Python Flask: Interacts with Docker Containers


Python3 Flask: Interacts with Docker Containers

Final Friday, I used to be speaking with my co-worker at my work. Nearly work, you already know. He informed me he needed to implement a server for serving his options. Though I did not perceive what he was going to do precisely, it sounded actually fascinating and I needed to attempt. Since I acquired numerous work that make many pages, I had written a bunch of HTML issues with React. It wasn’t technically fascinating in the intervening time(I really like React however the work was nearly the identical in any respect). I acquired bored with that. Whereas I used to be in there, the coworker mentioned me what he was doing.

He needed to do

  • Make an API server that will get a picture file
  • Execute a docker container and go the picture file to the container and the container will create the textual content file that’s generated from the picture file
  • Execute one other docker container and go the textual content
  • The API Server is aware of that the container has performed with its work and notify to a different server(The backend that servers the information to customers).

It sounds fascinating, ha?, I made a decision to implement the system on the weekend. I assumed it was going to be enjoyable. However it’s been actually a very long time since I coded with python. So, I needed to be taught numerous stuff. Throughout the weekends, I could not be taught all of the issues, so, I might use the minimal abilities for implementing the system. In case you’re a python developer or working with the docker, it is perhaps not in your thoughts at some factors.

Anyhow, Let’s get began!




Prerequisite

Pipenv is a software that goals to convey one of the best of all packaging worlds (bundler, composer, npm, cargo, yarn, and so on.) to the Python world. Home windows is a first-class citizen, in our world.
After I first use python, it was about 5 years in the past, I used conda or venv for managing packages. Whereas I used to be looking for package deal administration, I discovered this. It looks as if npm, I am undecided that is one of the best answer, however in my view, it have to be price it to attempt.

Docker is a platform designed to assist builders construct, share, and run trendy purposes. We deal with the tedious setup, so you’ll be able to deal with the code.
As I launched at first, that is the primary subject on this submit

Flask is an online software framework written in Python. It was developed by Armin Ronacher, who led a group of worldwide Python fans referred to as Poocco.
To implement a easy API internet server, I used Flask. there have been different libraries like Quick API. For lowering my hours, I went with Flask.


Process

That is the method that I’ll implement.

  1. The API server receives a file from the consumer

  2. Container A processes A file then saves it to the B File

  3. Container B processes the B File then saves it to the C File

  4. Customers can see the consequence by way of API




Python Apps and Docker Photos

I made two photos and uploaded to my them repository in docker-hub.

A tokenizer and word-counting app.

[Tokenizer]

import sys, json, os, requests
from textblob import TextBlob


def extract_nouns(textual content):
    blob = TextBlob(textual content)
    filtered_tags = checklist(filter(lambda tag: tag[1] == "NN", blob.tags))
    nouns = checklist(map(lambda tag: tag[0], filtered_tags))
    return nouns


def read_file(path):
    with open(path) as f:
        contents = f.learn()
    return contents


def save_data(path, information):
    with open(path, "w") as f:
        json.dump(information, f)


def get_filename_from_path(path):
    return os.path.splitext(os.path.basename(path))[0]


def notify_done(url, file_name):
    requests.get(f"{url}/docker/tokenizer_done?file_name={file_name}")


if __name__ == "__main__":
    if len(sys.argv) < 4:
        print("You have to go file path as an argument")
        print("python3 major.py [file path to read] [dir to save] [notification api]")
        print("Instance) python3 major.py ./take a look at.txt ./ http://host.docker.inner:20000")
        sys.exit()

    api_url = sys.argv[3]
    file_path = sys.argv[1]
    file_name = get_filename_from_path(file_path)
    target_path = os.path.be part of(sys.argv[2], file_name + ".json") 

    textual content = read_file(file_path)
    nouns = extract_nouns(textual content)

    save_data(target_path, {"nouns": nouns})
    notify_done(api_url, file_name)

    print("Executed")
Enter fullscreen mode

Exit fullscreen mode

[word-counting]

import sys, json, os, requests


def count_word(nouns_list):
    count_dict = dict()

    for noun in nouns_list:
        if noun in count_dict:
            count_dict[noun] += 1
        else:
            count_dict[noun] = 1

    return count_dict


def load_data(path):
    with open(path) as f:
        json_data = json.load(f)
    return json_data


def save_data(path, information):
    with open(path, "w") as f:
        json.dump(information, f)


def get_filename_from_path(path):
    return os.path.splitext(os.path.basename(path))[0]


def notify_done(url, file_name):
    requests.get(f"{url}/docker/word_count_done?file_name={file_name}")


if __name__ == "__main__":
    if len(sys.argv) < 4:
        print("You have to go file path as an argument")
        print("python3 major.py [file path to read] [dir to save] [notification api]")
        print("Instance) python3 major.py ./take a look at.txt ./ http://host.docker.inner:20000")
        sys.exit()

    api_url = sys.argv[3]
    file_path = sys.argv[1]
    file_name = get_filename_from_path(file_path)
    target_path = os.path.be part of(sys.argv[2], file_name + ".json") 

    json_data = load_data(file_path)
    count_dict = count_word(json_data["nouns"])

    save_data(target_path, {"consequence": count_dict})
    notify_done(api_url, file_name)
    print("Executed")
Enter fullscreen mode

Exit fullscreen mode

For operating the apps from the API server, I constructed each python recordsdata with beneath Dockerfiles.

[Tokenizer]

FROM python:3.9

WORKDIR /app
COPY . .

RUN pip set up pipenv
RUN pipenv set up
RUN pipenv run python3 -m textblob.download_corpora

ENTRYPOINT ["pipenv", "run", "python3", "./main.py"]
Enter fullscreen mode

Exit fullscreen mode

[word-counting]

FROM python:3.9

WORKDIR /app
COPY . .

RUN pip set up pipenv
RUN pipenv set up

ENTRYPOINT ["pipenv", "run", "python3", "./main.py"]
Enter fullscreen mode

Exit fullscreen mode




API Server

That is the primary code and it is type of easy.

from flask import Flask
from dotenv import load_dotenv

load_dotenv()

app = Flask(__name__)

import routes
Enter fullscreen mode

Exit fullscreen mode



Routes

[routes/docker.py]

import os
from flask import jsonify, request
from server import app
from lib import docker, json


consequence = []


@app.route('/docker/tokenizer_done')
def get_tokenizer_done():
    file_name = request.args.get("file_name")
    docker.run_word_count_container(file_name)
    return "run a word_count container"


@app.route('/docker/word_count_done')
def get_word_count_done():
    file_name = request.args.get("file_name")

    json_data = json.load_data(
        os.path.be part of(os.getenv("SHARED_VOLUME_PATH"),
        "word_count_output",
        f"{file_name}.json"
    ))
    consequence.append(json_data)

    return "all works performed"


@app.route('/docker/consequence')
def get_result():
    file_name = request.args.get("file_name")
    return jsonify({
        "consequence": consequence
    })
Enter fullscreen mode

Exit fullscreen mode

[routes/upload.py]

import os
from flask import jsonify, request
from werkzeug.utils import secure_filename
from server import app
from lib import docker


@app.route("/add", strategies=["POST"])
def upload_file():
    f = request.recordsdata["file"]

    file_name = secure_filename(f.filename)
    f.save(os.path.be part of(os.getenv("SHARED_VOLUME_PATH"), "enter", file_name))

    docker.run_tokenizer_container(file_name)

    return "succeed to add"
Enter fullscreen mode

Exit fullscreen mode

[routes/__init__.py]

from routes import docker, add
Enter fullscreen mode

Exit fullscreen mode

[lib/docker.py]

import os

API_URL = os.getenv("API_URL")
VOLUME_ROOT_PATH = os.getenv("SHARED_VOLUME_PATH")
RUN_TOKENIZER_CONTAINER = 'docker run -it --add-host=host.docker.inner:host-gateway -v "' + VOLUME_ROOT_PATH + ':/shared_volume" hskcoder/tokenizer:0.2 /shared_volume/enter/{FILE_NAME_WITH_EXTENSION} /shared_volume/tokenizer_output ' + API_URL
RUN_WORD_COUNT_CONTAINER = 'docker run -it --add-host=host.docker.inner:host-gateway -v "' + VOLUME_ROOT_PATH + ':/shared_volume" hskcoder/word_count:0.2 /shared_volume/tokenizer_output/{FILE_NAME_WITHOUT_EXTENSION}.json /shared_volume/word_count_output ' + API_URL


def run_tokenizer_container(file_name):
    print(RUN_TOKENIZER_CONTAINER.format(
        FILE_NAME_WITH_EXTENSION = file_name
    ))
    os.popen(RUN_TOKENIZER_CONTAINER.format(
        FILE_NAME_WITH_EXTENSION = file_name
    ))



def run_word_count_container(file_name):
    os.popen(RUN_WORD_COUNT_CONTAINER.format(
        FILE_NAME_WITHOUT_EXTENSION = file_name
    ))
Enter fullscreen mode

Exit fullscreen mode

[iib/json.py]

import json


def load_data(path):
    with open(path) as f:
        json_data = json.load(f)
    return json_data
Enter fullscreen mode

Exit fullscreen mode

This app learn surroundings variables from .env file, so it is advisable to arrange like this.
The beneath variables simply match my system.

API_URL=http://host.docker.inner:20000
ROOT_PATH=C:UsershskcoOneDrive바탕 화면stuffdockerapi
SHARED_VOLUME_PATH=C:UsershskcoOneDrive바탕 화면stuffdockerapishared_volume
Enter fullscreen mode

Exit fullscreen mode


You’ll be able to run the server with this script

python3 -m pipenv run flask run -h 0.0.0.0 --port 20000
Enter fullscreen mode

Exit fullscreen mode

Earlier than operating this command, it is advisable to set an surroundings variable FLASK_APP.
Since I used to be growing in Home windows, I ran this command in api dir.

$env:FLASK_APP = './server.py'
Enter fullscreen mode

Exit fullscreen mode

In case you enter http://127.0.0.1/docker/consequence it’s essential to see this web page.

Empty Result

Let’s ship a file to the API server and see the consequence.

[1]
step one

[2]
step two

[3]
result




Conclusion

It was actually enjoyable. I’ve discovered numerous issues.
No matter your place, I feel It might be actually good to attempt something you are all in favour of.

This instance is basically fundamental, I imply.
It ought to’ve thought-about like

  • Authorization
  • Communication between containers (On this instance, the API server exposes all routes to the general public)
  • Administration containers (Containers which have performed have to be deleted)
  • Deployment the API server

With out these, there have to be many issues that it is advisable to contemplate. (I respect for backend builders) I used to be simply specializing in implementing the system, Truthfully, I did not care a lot about others. If I did, I could not write this text. I’ll be again to work tomorrow.

Anyhow, it was enjoyable, it is true 🙂 I hope it’s going to be useful for somebody.




References



Github Supply Code

Github Supply Code



Python


Pipenv


Flask


Docker

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments