Introduction to Containerizing a Flask App
Hey there everyone, Hitesh here back again with another video. And in this video, we're going to see that how we can convert a Flask app, which is made in Python, in a Docker image. Now, this is a really basic Flask app that we have created, which obviously runs on a web and just give us a 'hey' message, 'Hey Python'.
Now, Flask is one of the most easiest way of how you can build a simple Python application on the web, or maybe just APIs. And yes, there are other ways like FastAPI and Django, and a lot of database could be involved. But slowly, baby steps, we're moving through the journey of going through with the Docker. So this is the most easiest one. The whole idea behind creating these kinds of videos is so that you understand a little bit journey about the DevOps. And sometimes you even want to know that I don't really understand what is the business logic in these applications that developers has coded. I just need the bare minimum information, and via that information, I can make a container or I can make an image out of any application, whether that's coded in JavaScript or in Python.
Let's just assume I don't know Python. Let's just assume I don't know even a tiny bit of Java, and still I'll be able to host these application. The today's turn in this specific video is for a Python Flask application. Let's go ahead and see how we can do that.
Authoring the Dockerfile
This is one of the most easiest one that you can do. So I don't even need to check what's there inside the index.py. The first thing that is important for me is the requirement. What are the requirement for these application? Now, this is where you actually go ahead and interact with your developer. He says, hey, this is a basic Flask app which needs to run on the port 3000. That's all I care, and that's all I really want to know. I don't know what it produces as an output, what's success and all of that. That's the developer role. We just want to put this application as an image, and obviously, we want to push it onto the Docker Hub, just for fun. All right.
So first thing we're going to do is simply go ahead and say, uh, Dockerfile. So that's what we want. Now, in this case, this is a Python image, so we want to take a base image which is going to be a Python image. Now, there are a lot of python images available, both for version 2 and 3, but obviously this is a Python 3 version that we want to call up. So really simple, we start with the base image, always and always with the base image. So the base image in this case we are going to go ahead with python. I'm going to hit control space and it can give me a lot of suggestions. So I'm going to go ahead, put colon, then again hit Ctrl+space and it gives me a lot of versions of these images. In a minute, there we go, we have a lot of version of Python 2. I'm not interested in that, I'm version 3, that is where I'm interested. And you can see from 3.16 to 3.15, a lot of version. 3.16 seems a little bit too much updated for me, so I'm gonna go with alpine 3.15. Alpine is nothing, just a stripped-down version, a little bit lower in the size, but again depends on what kind of Python is being used in your application. You really want to consult with your developer a little bit on that.
All right. So this is the basic. Then what we do is really the basic, uh, this remains common in most of the applications. So we find the working directory. You can put it just in the slash, but it is not a good idea. So you always want to have a directory because this is like an operating system, almost like, and in that, the slash is very sensitive directory. So you want to create a new directory, just like you have a desktop, something like that is there. So we do just the app, and it doesn't need to be always like app, it could be just hitesh, but hitesh doesn't seem great. The app is actually much better.
Then we go ahead and simply say that, hey, we want to copy, and copy some information. Uh, there are ways how you can copy then run the command then can copy rest over the files. These are caching and all these optimization. We don't want to go into that as of now. We simply want to say, hey, copy everything that you have and just go ahead and put it into /app. That's it. We defined a working directory, we move all of our files into that working directory. That's what the basic of this image does.
Installing Dependencies and Finalizing the Dockerfile
Then, obviously, we need to run some command because when you take an image which is based on Python, it is based on Python, the Python is installed in that, but all the requirements like Flask, maybe Django or something else, is not present in that. So we need to install that. So we go ahead and run the command. In case your company or you deal with a lot of Python command, uh, you should run these few of these commands. The first one is actually pip install and then we pass on a flag of -r which gives all the requirement in a file, which is going to be requirements.txt. And make sure you don't do typo because I do a lot. requirements should be the exact same file, requirements.txt, so make sure you take care of that.
Once this is done, that means in a new image which is based out of Python, all the files have been copied, all the requirements are also done. The only thing which for this basic Flask app remains is exposing the port, and then finally running the app. So let's go ahead and see that. We have seen that in the last video as well. We can go ahead and say hey EXPOSE 3000. It always doesn't need to be 3000, it could be 5000, 8000, whatever the port makes sense you want to expose out of that machine or an image, you can go ahead and do that.
And finally, you have to fire up a command. We'll talk more about these in the series itself for the Docker. By the way, I do already have an existing series, but I want to freshen it up. So we're going to go ahead and have some command. And the command is really simple. It's just a Python file which we want to run in the same directory. Remember, we have already mentioned our working directory, that's where all the things happen. We'll say ./index.py. So we want to run this base file. And based on that, there could be 100 other files and dependencies, all that. This is the entry point we want to mention.
Once you do this, that's it. That's your basic Dockerfile. Not too much of the command. Obviously, as the complexity begins to increase, uh, maybe that's a Django file, just basic SQLite or maybe Postgres is involved, maybe MongoDB is involved, there's a lot of things that can come up again. And based on that, we have other files, even spoiler alert, Docker Compose is there. But we don't want to track them right now, at least in this video. But this is all what you have to do.
Building and Tagging the Docker Image
This is a great exercise to build up a lot of images. And all of this, by the way... in case you want to go for that, here's a basic python file, or you can just go for... here's the basic Python file. You can pause and write that, but I don't recommend this. I recommend you to go onto the Flask documentation. Let me just show you that. Actually, it's super easy. Let me just go ahead and open this up. So if you go ahead onto Google and just say 'Flask Hello World,' you can just go up into the... a lot of files are there, even the Flask quickstart documentation. A lot of great websites are there which actually helps you out there. We'll go on to the Flask, a Flask getting started, and there it will give you the documentation of how you can get started with the basic application.
So notice here, this is all you need to copy. This is the root slash on which 'Hello World' is being defined and you are just running it. And that's basically it. It can do all the job for you. Uh, there is additionally a couple of more lines that you can write, but this is all, this is all you need in case you are not able to find or don't want to write it. Just go get it up here. That's all. That's all you need for the practice purpose. In case you are seasoned in Python, you want to write a couple of more lines of code, like if and all of that, that's fine. If you don't write it, that is also fine. Flask actually works without this as well.
All right. So we got this one. Now, let's go ahead and try to build this as an image. In case you have followed the last video where I showed you how you can build images using the Node.js, this is almost going to be similar that with that. But I'll show you that again. The requirement is you should have Docker installed on your machine, at least.
So the way how we do it is simply say docker, we pass on a command to build, and then we pass on a -t. The -t is to give you a tag, and I always, always prefer that my tag should be something which comes up from hub.docker.com and your username. In my case, I've already logged in into this so I can check my profile and this gives me my username. So this is 'hey-nodejs' we pushed it in the last video, and this is my username. So I go up here and I say that hey, I want to tag it first with my username, then whatever the name you want to probably define here. So in this case I would like to say hey-python-flask would be better because I do have a plan to push up more Python projects and show you more example with the Django and a couple of others as well, but no promises on that. And this is the basics hey-python-flask. So this is the app.
Now again, we'll talk about these tags. You can go ahead and say latest. This is the default tag that when you pull the image it pulls up. But if you don't want to pass it on because we'll be incrementally updating it, you can go ahead and say classic, 0.0.1.release. Again, if you don't pass on anything, pass on latest, that's a default tag, but you can go ahead and pass on this as well. Once you have done this, the most important part is put up a dot. This dot defines that the Dockerfile based on which this image should be created is available in the current directory, which is Dockerfile.
Now if I go ahead and show you my dashboard on the Docker Desktop, in the image, we have just the 'hey-nodejs' with the tag itself. We'll be creating another one. I can go ahead and show you by refreshing it, nothing is there. And we can go ahead, hit run this, and this is going to take just a few seconds because it's not a big image on that. Depends on your internet speed as well, but I think it should be fairly easy. And now we have got this basics up here copied and all of that, so I should have another image in theory at least. So there we go, 'hey-python-flask' and we've got the same tags and release and all of that.
Running the Container and Mapping Ports
So now what I want to do is I want to run this image first, because before pushing it to Hub, I obviously want to check out whether this actually works or not. So to run that, all I can say is docker container and then I can run this app with a -d which stands for detach mode. Hey, don't keep my terminal busy, give me my terminal back and you keep it running in the background. And then we obviously need to expose the port because it's a web application, runs on a certain port. And I would say, hey, in the Docker, the 3000 ports were running and on my main machine, I can be saying 4000 or I can say 3000, wherever you want to map those ports together. And then obviously, I have to mention these name which says hey-python-flask and I have to give it the version because otherwise it pulls up as this default I don't... I haven't given that. So I'll say 0. oops my bad, accidentally hit enter. Okay, we're gonna say 0.0.1.release, that's a long one, and then all I have to do is hit enter after that. So I'm gonna hit enter and this is supposedly, in theory, if it is all correct, it's gonna run a container behind the scene for me and we'll be exposing a port on my main machine. It's taking a little bit while. Probably did I hit enter something wrong? Let's try to find out where it is going wrong. Right now nothing and the image is there. All right, let's wait for a couple of seconds. Did I accidentally run some command wrong?
All right, let's, let's actually close this and let me open it up as a full screen so that we can actually borrow this name. Maybe I did accidentally type something wrong. Okay, all right, one more time. This happens to every one of us. docker container, we want to run the container. We are saying hey, run it in detach mode with a port exposed of 3000 and we'll map 3000 on our real machine as well. And then I'll paste this one as it is, and after a space, I'll hit enter. And there we go. This time it works. Probably I mistyped something, I'm sure here or probably here, I don't know where.
Okay, so this is now running. And I can verify that by saying docker container ls small for listing down. So there we go, container is running. Now let's quickly check on port 3000 whether we are getting 'Hey Python' this time. Ah, great. But what if I want to stop this? So I'm going to go ahead and say docker container stop, and I want to stop 076F. So I want to stop that. I want to run this command again, but this time I don't want it to run on my main machine for 3000.
All right, a small glitch and now it's recording back. So okay, so what we're trying to do is we were trying to, uh, just change the port here. So let's go ahead and say we're gonna go ahead and run this Docker container and we want to just click LS, nothing so far. And we want to run this. So we're going to say docker container run and what we want to do is run in the detach mode with a -p option, and we initially went through with the 3000, but on my main machine now I want to expose 4000 port. But on the container it's always 3000, that's what we mapped while building this image, so that should be fine. And now we simply go ahead and mention that hey, this is the image that we want to run, and that's it. So it gives us a 97c.
So let's go back up here. So if I go ahead and check it out, this is where recording stopped, 3000, nothing is there. And if I go ahead and say 4000, there we go. So you got the idea, this first one is my machine port. This is the image Port. I cannot change it once the image is being built. But yeah, I got the idea that how this is being done.
Pushing the Image to Docker Hub
So let's go ahead and say docker container stop and I want to stop 9D... 9 and I can just run... no such container 9D or 97? My bad. 97. Okay, all right. So now all the containers should be freed up. Uh, this means I can push this particular image onto the Docker Hub so that anybody can use it.
I'm going to go ahead and say docker push and I'll name this one same. I'll say that 'hitesh', my username, and then all I have to do is, actually I can copy and paste this one. I've already got this as my clipboard. So there we go. So this is my username, and this is what I want to call my image. And of course you have to pull in the tag with this exact release. Otherwise, if I just say it :latest, then it will pull the latest, but this incremental update will help us later on as we'll be studying the Docker. So this is the basics. Let's try hit that, and obviously it will take a little bit time, not much, but a little bit. Can we do a fast forwarding in the editing? I think yes.
All right so finally it's being pushed.
Final Verification and Key Takeaways
And let's go back and see on to the Docker Hub whether we got Python as Flask... and there we go. All right. We can see that 'hey-python-flask' is now available and we can see that... there we go. Anybody can use this one. Of course they also have to use the tag, this tag exactly, and this will help to get them this file.
All right. So again, you noticed here that as a Docker or as a DevOps engineer, you don't have to too much worry about what's happening, what is the business logic and all that. You were just responsible for creating the image. And as you will move forward, you will realize that this is the image that somebody needs to give you and you can run as many containers as you like of this exact image without worrying about what's the business logic, what's this. But again, yeah, this much of the piece you need to write. And this is mostly available on the internet, on the documentation, or through such YouTube videos, which I'm pretty sure you're gonna subscribe as well. That's it for this one. Let's go ahead and catch up in the next video.