Note: The main focus is not about to build the Flask App, but guide you to setup CI/CD into your existing Flask App and some recommendation to deploy it.
I will not bring to much how you build web from Flask. I will give some main aspects from Flask and how we containerize them. Your project may have different structure with me but actually it will not really different. Please see my repo here for the last result.
Feel free to use my repositories or just follow the tutorial from Flask: https://flask.palletsprojects.com/en/1.1.x/tutorial/
We have same structure, which the main project as python package. Keep an eye, I use wsgi to run my app, I use gunicorn. Please see Deployment Options to setup your Flask App to production.
I use multistage and alpine so hopefully the container image will have small size. Please use your own Dockerfile, maybe your Dockerfile will different with me, it will depend what requirement in your Flask App. But I will bring you some guide how to build the Dockerfile.
- Base Image
- Setup binary for install dependencies from pip and download the dependencies
- Setup binary for runtime
- Copy all your code
- Setup entrypoint
- For the base image I usually use python:3.8-alpine, but sometimes I also use python:3.8-slim because some dependencies not compatible with alpine.
- Sometimes you need to setup the binary or install any binaries before install the dependencies, some dependencies maybe will need development tools installed first.
- You need to know any binary that needed at runtime, as example needed the MySQL client or PostgreSQL client. It will depend on your apps.
- After finished download the dependencies, yeah, the last step to copy your code. Why you bring this into last step? So you can use the caching strategy, when you just change the code, sometimes you will not need to run the step from beginning, but it will do the step from cache and build new layer from you updated code.
- Last, you will need to define the Entrypoint, but someone use CMD, it’s ok, just use what you want.
Here is my example
For setup the CI, I use the Github Action to do CI (Continuous Integration). Hemm… Anyway, you required to have any unit test and/or integration test for this. It means nothing to do when you not have one of them. If you check my repository, you will know, my unit test not cover all and very bad condition, but little bit better than nothing. Okay, I will guide you, I will not provide full code, since it will depend on your code too! I have 3 stages for CI/CD, 2 CI & 1 CD. 1 CI for test from python directly, 1 CI for test my build process, 1 CD to build Dockerfile into Github Package.
You can see my example CI/CD
Important step/task at CI
- Install your dependencies
- Do linting, I recommend to do test the lint, so any codes will follow your convention
- Unit test
- Integration test (if you have)
- Docker build
I use coverage (coverage report), pytest (unit test) and flake8 (linter). I use coverage report so I know how much the unit test cover my source code. You can see the cover report example here.
Okay, after you setup the CI correctly, maybe you image how you automate the build process. Anyway, you need to know, for some projects will required you to have multiple environment, in my case, I just have one environment, so it will deploy directly to my main Azure App Service. I will learn more about the multi environment and will share it too.
You can see my process as the image above. I will bring you more detail for how you send Webhook to Azure App Service. The build docker image step maybe will same with my repository.
In this step, assume you already created the Azure App Service with Container services.
Uh, oh, I just notice this will deprecated, so sad actually. But I will bring another step later to adapt new features.
Okay, the key is, you need to setup the server URL. In my case, because I deploy to Github Package, so I will point the URL to github package. Please also fill the Login (your username) and Password. In my experience, it still need this whatever your repositories privacy (private/public). The password field, I recommended you to fill with PAT (Personal Access Token), if you not sure what is that, please see this link: https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token. You can define the permission just to read your package. For full image name and tag, because I just use latest, so I define the tag to latest. You can see the full image name from here. https://github.com/berv-uni-project/tweety/packages/131103
Update: I just found this pages. Seems it will good if they already fully compatible with Github Action, no need my old way to use Webhook. :D
Ok, remember from my previous page, there is Webhook URL, please copy that. It will needed for setup at Github Event.
Navigate to Settings > Webhook > Add Webhook
Please fill the payload URL to previous copy Webhook URL.
For the event, I choose custom event. I select the registry package event.
Done! You can try use your CI/CD, it will send the webhook to Azure so they will pull new image each you push the docker image into Github Package.
Anyway, keep you Webhook URL safe, since it will trigger to start your Azure App Services and pull new images. For multiple environment, I will recommend you to use Deployment Slot, and the CD will have different steps. I will try to document it too.
Feel free to comment this article and have any suggestion to update this article. I’m sorry if not really detail and not really technical. You can ask me directly if you have any questions to setup the Azure App Service and Github Action. The last, Correct Me If I Wrong. :)
Have a nice day!