Home > Mobile >  How to run two flask servers on different ports at the same time using bash script
How to run two flask servers on different ports at the same time using bash script

Time:04-23

I have two python files.

server1.py

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return "Hello world from server 1."


if __name__ == "__main__":
    app.run(port=3000)

server2.py

from flask import Flask

app = Flask(__name__)


@app.route('/')
def home():
    return "Hello from server 2."


if __name__ == "__main__":
    app.run(port=4000)

Now, I need to run these two servers at the same time using a bash script.

I have tried this in my bash script.

python3 server1.py && python3 server2.py

When I run this bash script, it runs the server1.py file only when I quit server 1 it runs the server2.py

Output of my bash script:

* Serving Flask app 'server1' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:3000 (Press CTRL C to quit)
^C * Serving Flask app 'server2' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:4000 (Press CTRL C to quit)

I think its not possible to run two flask servers same time in a single terminal. Is there any way using bash we can open a new terminal and run the server2.py file on that terminal? for some reasons, I need to run both flask servers same time.

CodePudding user response:

hope you are doing well,

Thank you for providing the scripts and servers configuration. With these I was able to reproduce what you got.

So

I think there is multiple solutions but I will give you two of them:

  • The first is to deploy your servers into docker containers and run them either with a bash script or with docker-compose or in other container platforms.

  • the second is, instead of using "&&" at the end of the command "python3 server1.py" that means "execute what comes after this only if what is before is executed and successful, you can just use "&" that means "execute what is before in the background and execute what is next in the same time. here is the bash script:

script.sh:

#/bin/bash
python3 server1.py &
python3 server2.py

it worked well for me but the problem with this is that even when you "ctrl-c" on your bash script output, the server2 will stop but not the server1:

❯ ps -aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
...
bguess     21149  0.0  0.2 178708 26480 pts/3    S    00:48   0:00 python3 server1.py
...

you will have to kill it manually with kill "PID_HERE" (kill 21149 in my example.)

Instead here is the solution with docker: First lets modify your servers to listen on all host on port 4000 (since server1 and server2 will be isolated in 2 differents containers there will be no conflicts)

server1.py:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return "Hello world from server 1."


if __name__ == "__main__":
    app.run(port=4000, debug=True, host='0.0.0.0')

server2.py:

from flask import Flask

app = Flask(__name__)


@app.route('/')
def home():
    return "Hello from server 2."


if __name__ == "__main__":
    app.run(port=4000, debug=True, host='0.0.0.0')

Next, lets write down the two dockerfiles needed to build your containers images:

but first here is the requirements.txt file we will copy into our docker images:

requirements.txt:

flask

dockerfile1:

FROM python:3.8-slim-buster

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt

COPY server1.py .

CMD [ "python3", "-m" , "server1", "run", "--host=0.0.0.0:4000"]

EXPOSE 4000

dockerfile2:

FROM python:3.8-slim-buster

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt

COPY server1.py .

CMD [ "python3", "-m" , "server1", "run", "--host=0.0.0.0:4000"]

EXPOSE 4000

Now lets build the docker images from this 2 dockerfiles:

docker build -t so-flask-s1 -f dockerfile1 .
docker build -t so-flask-s2 -f dockerfile2 .

Now lets run our containers:

❯ docker run --rm -d -p 8081:4000 --name server1 so-flask-s1
7cfb16a63cd6de6ff2ecb9d728302a9f9ef0a848ab81a5cedf6ce9f60eaa66ae


❯ docker run --rm -d -p 8082:4000 --name server2 so-flask-s2
209013ba82f8c701ba46fd67675b9151056921a5a8b5a916e7f29b9014e7c9a1

Lets check if they are both running:

❯ docker ps
CONTAINER ID   IMAGE                                COMMAND                  CREATED          STATUS             PORTS
            NAMES
209013ba82f8   so-flask-s2                          "python3 -m server2 …"   3 seconds ago    Up 2 seconds       0.0.0.0:8082->4000/tcp      server2
7cfb16a63cd6   so-flask-s1                          "python3 -m server1 …"   10 seconds ago   Up 9 seconds       0.0.0.0:8081->4000/tcp      server1

Now, lets check our browser:

enter image description here

enter image description here

enter image description here

Hope this has helped you.

delete the images with: docker rmi #exemple: docker rmi so-flask-s2

kill the containers with: docker kill #example: docker kill server2

here is a little cheat sheet (but you can find plenty of them on the internet): https://www.docker.com/wp-content/uploads/2022/03/docker-cheat-sheet.pdf

bguess

CodePudding user response:

I agree with @gordon-davisson, about the connector. But, if you are looking for a bash script to run your server, with different port configuration, it's better to use the flask run command line utility provided with the flask package.

Also, you don't need to change the port manually in the script, in case you again want to change the port, or the configuration i.e debug=True/False or the hostname=0.0.0.0 or 127.0.0.1

Some basics of it are (from it's help description):

flask run --help
Usage: flask run [OPTIONS]

  Run a local development server.

  This server is for development purposes only. It does not provide the
  stability, security, or performance of production WSGI servers.

  The reloader and debugger are enabled by default if FLASK_ENV=development
  or FLASK_DEBUG=1.

Options:
  -h, --host TEXT                 The interface to bind to.
  -p, --port INTEGER              The port to bind to.
  --cert PATH                     Specify a certificate file to use HTTPS.
  --key FILE                      The key file to use when specifying a
                                  certificate.
  --reload / --no-reload          Enable or disable the reloader. By default
                                  the reloader is active if debug is enabled.
  --debugger / --no-debugger      Enable or disable the debugger. By default
                                  the debugger is active if debug is enabled.
  --eager-loading / --lazy-loader
                                  Enable or disable eager loading. By default
                                  eager loading is enabled if the reloader is
                                  disabled.
  --with-threads / --without-threads
                                  Enable or disable multithreading.
  --extra-files PATH              Extra files that trigger a reload on change.
                                  Multiple paths are separated by ':'.
  --help                          Show this message and exit.

You can find great info on this topic at flask run command

  • Related