Docker and flask
This is my first real blog post. I swear it is real, if you don't believe me, continue reading for some super boring stuff!
First, docker is a containerization program that is useful in deploying specific apps or services. It is similar to a virtual machine, but it's lightweight. It also isolated things for added security and reliability. I am not a docker expert, but I know enough to run about 5 containers in my home. This website is inside a docker container!
Flask is a web framework in python that is the glue for web services. I like it for it's simplicity and relative ease-of-use. I am able to use HTML, CSS, Javascript and Mongodb to run this website all within flask.
When I first started using docker and flask, I didn't have much of a plan. I had learned python and javascript along with HTML and CSS, dabbled with Mongodb, but had no idea how to bring these things together. A couple google searches had me writing basic flask apps, then I started on this website, slowing adding features and styling.
As much as I like programming, general information technology like networking, security, and general computer hardware has always interested me. I took a cloud computing course and learned some very basic containerization concepts and started researching. Eventually I came across docker and it looked fun. I started learning the basics and saw how awesome it was to spin up a container, then realize I made a mistake somewhere, fix those mistakes, then quickly start the container again. It's amazing!
So what is the point of this post? I'm essentially just taking notes.
With my back story out of the way...
I finally figured out how to run my flask app in a container with a WSGI server. It was a giant pain in the ass, but I'm starting to test it out. I'm using waitress in my flask app as my WSGI because I can use it in windows, and in docker. In order to use waitress, all you do in your virtual environment is:
pip3 install waitress
Since I am also running it in docker:
pip3 freeze > requirements.txt
So now all my dependencies are in that file so I can tell docker what to include.
To use waitress, I activate my virtual environment, then in the same folder as my app.py, I run:
waitress-serve --listen 127.0.0.1 app:app
I believe waitress listens on default port 8080 (need to verify this). So now on my local machine, I go to 127.0.0.1:8080, and I'm greeted with my flask app. WSGI production ready!
But...I run this site in docker. So how do I use waitress in docker? It's actually quite easy, but took me a while and some trail and errors to figure out. Google was helpful, but didn't give me a clear answer, so I had to learn and piece things together.
Docker is running my server, not on my local machine, so first I have to make sure my files are uploaded there. I already have a test folder there, so I remote in through VS Code so I can edit files a lot easier. In my Dockerfile, I have all my commands for creating a docker image. I won't post it all here, but there is one line I want to take note of.
CMD ["waitress-serve", "--listen=*:5556", "app:app"]
This is the last command given, and the one that gave me the hardest time. It's an easy command, but I had a hard time finding the information. I didn't know I had to use quotes, and separate things with commas, so I was doing some trial and error at that point, but eventually it worked. That's the beauty of docker, I can quickly try things out and if they don't work I go back to the drawing board. And it doesn't take me hours to do!
I was doing things the hard way, but now it is much easier. I can develop on my computer, then secure copy my files to my server, spin up a container, and there we go! Or I can just develop remotely. I have options, which is really cool!
Finding a script to build and start a container was a life saver.
#!/bin/bash
app="flask-test.test"
docker build -t ${app} .
docker run -d -p 7777:5556 \
--name=${app} \
-v $PWD:/app ${app}
This helps so much!
Anyways, I told you it was super boring, but I want to get my thoughts down, and why not use my website! I created it for a purpose, so I'm going to use it!
That's it for now.