How to Deploy Django on Nginx with uWSGI (full tutorial)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone this is tony aces tech i'm tony and i'm super excited to be filming this video today because this is the video that i wish existed three or four years ago when i started working with django and i wanted to build a website with python while that's a fairly easy process as far as development is concerned when it comes time for production and you want to release your website to the public there wasn't a lot of information available it was scattered all over the internet i was looking for a single source of information that could walk you through step by step how to set up your server for production and that's exactly what this video is today i will walk you through the process of setting up django on an ubuntu server with an nginx web server back-end and a web server gateway interface the ultimate goal here is to take the request from the client pass that to nginx nginx will take it and pass it to a unix socket the unix socket is kind of like a shared space between nginx and the web server gateway interface so the web server gateway interface will take that request pass it on to the django backend whoops and then the django backend will ultimately pass it on to python it'll compile the web page and send it right back through that chain back to the client that sounds like a lot it is a lot so i'm going to do my best to walk you through step by step and give you the fundamentals along the way so that you are prepared for down the road if something does happen something comes up with your web server you are at least have a basic understanding of how everything fits together so if that's something you're interested in learning how to do let's go ahead and proceed with the tutorial and just one other thing before we start here i want to give you a little background information about what we're going to be working with and it's specifically a website that i plan to release i'm actually in the process of building it i'm going to be building it with you here today it is called micro domains the domain name is micro dot domains okay it's like dot com or dot net it's micro dot domains and we'll be working with that throughout this tutorial i have already set up my dnsa records from the ip address of my web server to point from the domain name to the ip address so that's already in place and if you want to follow along with whatever setup you got i recommend you go ahead and do that ahead of time and set up your ubuntu server which by the way i have here on my screen so let's go ahead and take a look at that i'm logged into the uh the server via ssh you can see that up here micro dot domains and i am using a user that i created this is basically like a fresh install of ubuntu 20.04 i added a user called udoms he does have sudo access and um i think that's about it as far as the configuration is concerned um i did do the apt-get update in the apt-get upgrade so everything's up to date as you can see here and i think with that said we can get on into the actual tutorial and start executing some commands here so the first thing is i want to check the version of python so we can do that with python 3 dash dash version and we can see that we're working with python 3.8.5 and you know we don't want to use the python version that's installed in user bin which is available to the entire system we want to have a virtual environment for python to run into or run in and that will um be accomplished with v and v e n v the old way of doing this was virtual m i think that's prior to python version 3.3 but since we're working with 3.8 we can use vm so that's the first thing we want to do we want to do we want to get that package so we can do sudo apt to get install python 3-v-e-n-v and i'll type in my password and yes we'll go ahead and install that and this will take just a few seconds here and when we're done we're going to create a directory with make dur called env and right just so you know right now we're working out of the home directory for this user so now we have that m directory so we can place our virtual environment in there and any other virtual environments that we create in the future on the server so um let's go ahead and do that let's make our virtual environment we can do something like python3 v-e-n-v and then we'll give it the absolute path to our virtual environment so home udoms and and then the name of our new virtual environment i'm going to call it md short for micro domains we'll execute that and when that's finished we can do an ls inside of the end directory we'll now see that micro domains md environment and then in there we'll have a bin directory and include directory lib directory et cetera we're interested in what's inside the bin directory we got pip installed here we got python python 3 and the activate command which is what we're going to be using to activate our virtual environment so we can do that with source and we'll use the relative path here and the name of our virtual environment md and then bin activate and that is now activated as you can see on the terminal here it's prefixed by md in parentheses and we can also verify that with which we can type in which python and instead of being located at in the bin directory we're now working out of our virtual environment so that's all set up and ready to go the next thing i'm going to do is install django so we can do that with pip install django and just to be clear we're executing just like the python up here we're executing pip from within the virtual environment so django will be installed for the virtual environment only and not the rest of the system so unless you're working out of that virtual environment this django install won't be available and this looks like it's going to take a little bit so i'll pause the video and when it's finished i'll get back with you all right django has been installed and now since that's installed we can access the django admin command and it should be on your environment um your path so you can just start typing that hit tab to auto complete and then we can do uh start project to start a django project p-r-o-j-e-c-t um and we're going to call for me i'm going to call my project micro domains and what this is going to do is just create a directory here with the basic infrastructure of a django project so we're going to go inside of that directory just to look around there's a manage.pi file and then another micro domains directory in here so let's look in there and we have a settings file urls wsgi.pi file we'll be re we'll be working with a few of these throughout this tutorial the one cool thing about django it's a blessing and a curse kind of like i alluded to in the beginning of the video it comes with a server a built-in web server that you can test out your code changes without you know messing with nginx or apache or any other web server like that so let's test that out first and that's just going to be a demonstration that django's working but this is kind of what we're trying to get away from with this whole tutorial this is not production ready a web server so to do that we can do python manage.pi run server 0.0.0.0 colon 8000 and this is just like a standard way to to set up the server so go ahead and execute that and now the server it's just sitting here waiting for requests to come to in this case micro domains because i already have those dns a record set up so i'm going to bring it over a guest window here and i'm going to type in micro dot domains and that did not work right off the bat let's see if we got any requests coming in here no it didn't so okay sorry about that i just figured out what the issue was i did not put the port on there so let's go to micro dot domains colon eight zero zero zero and now we see um some type of activity here and although this is an era i did this on purpose to show you that this is what a debug environment looks like in django it gives you some helpful information about what's going on behind the scenes and in this case it's telling us that we need to edit our settings.pi file and add the uh add our domain name to the allowed hosts variable so let's go ahead and do that i'll just uh bring our terminal back up here we'll ctrl c to get out of the the test server and then we're going to edit our micro domains settings.pi file and in here you'll see just a few lines down a variable called allowed hosts it's empty by default this is where we want to put our domain name so for me it's going to be micro dot domains and then we can also do the www version so www dot micro dot domains okay so we'll save that spin back up our test server open up our browser refresh the page and we should see the default landing page for django and we do and that's good that means that we have tested out django and it's working and that's kind of how we're going to start out this tutorial just make sure that each individual puzzle piece is working before we connect the dots so let's go back to the terminal window here and we'll get out of our our test server again and the next thing we want to do is start working with our web server gateway interface so in this case we're going to be using and this is a this is a tough acronym um the uw sgi we're going to be using uw sgi for our web server gateway interface and the first thing we need to do is to actually install that so there's some dependencies for this and we want to grab those first you can do that with sudo apt get install python 3.8-dev and if you're using a different version of python then you'll obviously want to specify that instead of 3.8 and then after this we want to also get gcc the gnu c compiler because when we do go ahead and install the uw sgi package in pip it'll have to build that some parts of it at least from source so we'll go ahead and do the same type of thing for gcc and we'll continue with that and um let's just pause the video and i'll come back when this finishes all right like five seconds later we're back and now we want to go ahead and install via pip so we'll do pip um install u w s g i and in some instances this might look like it initially fails you might see some red error text it'll actually say air um but it'll kind of do a second try and hopefully in your case it'll finish and it'll be successful so let's go ahead and again pause the video and i'll get back with you when it finishes okay we're back and just like i anticipated we did see that initial error message but ultimately it successfully installed and that's all we care about so we can continue on with the tutorial here if you have any idea about why that's the case please let me know in the comments below anyway um like we did with django we isolated that we tested it and it works let's go ahead and try this with the web server gateway interface so let's just make a simple python file that's going to serve some some text in a web browser so in this tutorial i'm going to be using vim as my text editor i'll have a tutorial for you about how to do that but you can use whatever text editor you want and what we're going to do is just create a simple python file called test.pi and it's going to have the this three lines of call yeah three lines of code which is basically just going to print out hello world in the web browser when we visit so let's go ahead and save that file and again like i was saying just to test out the web server gateway interface by itself let's go ahead and do that with a very simple command u w s g i http we're going to use port 8000 again and we're going to pass it the wsgi file called test.pi the one that we just created so we'll go ahead and start up that that test server and go back over to our browser and if we refresh the page we do see hello world just like we expected to see so back in our terminal window let's get out of that with ctrl c and let's let's bridge the gap between the the django and web server gateway interface so we can do that kind of like the same command here except instead of a web server gateway interface file let's give it a module and the module in this case is going to be micro domains dot w s g i and you know before we before we execute that let me just explain why this works and it will work but let me just show you what i'm what we're working with here so if we do an ls inside of micro domains directory you will see a file in here called wsgi and that's exactly what we're referring to here the directory micro domains dot syntax and then wsgi we don't need to put the pi dot pi but that's what we're referring to when we pass in this module okay that's like the entry port in entry point into the django server so let's go ahead and do that again we'll type that one more time so dash dash module micro domains.wsgi we'll start up that server and in the background in the browser let's go ahead and refresh the page and this time since we're connecting the web server gateway interface with django we should see the landing page for django and we do so we know that that connection is now working okay so that's all good whoops i didn't mean to open the calculator let's go out of this with ctrl c and now we can start looking at nginx so that's the web server that's going to be like what's receiving the request from the client and we can first install that with sudo apt get install nginx and we'll say yes we want to continue and that'll take not too long and while that's going i'm going to copy our configuration file content so what we're going to do next is create a configuration file for our website for nginx and that's at the vim well it's at the directory etc engine x sites available and we're going to make a file in here called microdomains.com and i'm going to paste in this text and by the way all of this all of these commands all of this all of the content of all the files in this tutorial is going to be linked in the description below on my blog so you don't have to type what you see you can just copy and paste it and change it as you need it i think that'll help you guys out so let me just save this file and i think yep i had i'm gonna have to get out of this we have to use sudo to edit this file so i'm gonna paste that in again i'll save the file real quick open it back up just so we can see some syntax highlighting and here we go this this seems like a lot probably but let me just walk you through it at least some of the lines here so this this main server block here you can see that we're listening on port 80 and that's the default port for http um i'll have another video in the future about how to make this being served over https but for now let's serve it over http the server name is our domain name and our domain name with www we've got some default settings here but the thing i want to draw attention to is these three location blocks okay so we have a location block for media a location block for static and a location block just for slash so these two right here they map to a physical address on the um the system right so this this doesn't exist now but it will exist soon we'll go through the process of setting it up home udoms micro domains which is our django project and then media same thing for static now this whole part of the tutorial we're just trying to test out serving static files which when i say static i mean images css files javascript files any non-html files okay or like php or anything like that excuse me um so that's what this these two blocks do and then this one down here we'll talk a little bit more about this later but this is the the unix socket that i was referring to earlier what you need to know for this is basically that this w or this u w s gi pass references this django you know value but this actually is what's defined up here so upstream django and let's go up here this is a unix socket and this is again another file on our system which doesn't exist yet we will create that later but i just want you to know that this is how that is mapped to the socket okay so um one other thing we'll point out and i know there's a lot going on here but i'll try to make it all make sense we the first thing i want to do is just create this params file because this is just something by default that you need so that's in our django project micro domains we need to make a file called uws gi params so let me copy that let's save the file and let's make that file so vim uw sgi params and let's just get this out of the way this is again just some configuration that you need to do we'll go ahead and type that in without any uh without too much explanation so we'll save that and the other thing i want to do is i want to make sure that we take our nginx configuration file in the site's available directory and sim link it to the site's enabled directory because if you're not familiar you can have a whole bunch of configuration files in the sites available directory but in order to you know make them public or publish them you need to have them sim linked into the site's enabled directory and that will allow nginx to actually serve those those websites so let's go ahead and do that next and we can do that with sudo ln s for sim link basically the same exact path to our configuration file and we're going to sim link that to the from the available directory to the enabled directory okay and um okay so that that is good as far as nginx is concerned for the moment i want to go back to what i was saying about testing out the static files in the media file so we need let's open this up again we need these two directories to exist well this directory the media directory and the static directory okay and we need to tell django that they exist too and the whole reason we're doing this is because nginx does a much better job at serving static files again images javascript css non-php non-html then um django does so we want to make sure nginx handles those files that's why these have separate location blocks so let's go ahead and take care of those one at a time the first thing i'm going to do is to tell django in the settings.pi file that the static directory exists so let's go ahead and go in there and down here i think near the bottom actually at the very bottom you see that we have a static url and that is what's going to be appended to our domain so micro dot domains slash static and then whatever the name of the image file the css file that's how those are going to be served to the public but we need to tell django about where they exist on our file system so we can do that with this line of code it's going to be static root and this is this is like one of those predefined django variables you can see it in the documentation and we're basically going to join our base directory with static so it's going to be let me show you what that is so let's base directory is defined up top okay so there's base directory right here and it's basically taking the current file's parent parent which in our case is home udoms slash micro domains the root of our django project um and then down here we're just going to append on to that static so that maps up perfectly with what we defined in the the static location block in our nginx configuration file one other thing we have to do in here is import os because we're referencing it down below so import os and that is referenced right here okay so let's save that and what's really cool is django makes it really easy to create your static and manage your static files create the directory and manage the files and you can do that with python manage.pi collect static and what this does is it'll not only create the static directory but it'll copy all of the static files into that directory so let's go ahead and execute that and now you see that same exact path that we're working with is here and we can see that directory has been created there okay so that takes care of the static directory what about the media directory this is more for like user uploads this is where those are gonna live those are gonna are supposed to um reside so let's make that directory manually and just to test it out okay just to make sure nginx is properly serving these files we're going to do we're going to use wget to get the image at this url and place it into the media directory and we're going to call it media.gif so let's go ahead and execute that and it is taking it's good old time here um i think i'm gonna break out of that and try it again i don't know why that's not working let me um let me pause the video the bug and i'll be right back with you all right guys so i just think there's like a small issue with the dns settings or something on my server which is not allowing me to get out to the internet um but that's okay i secure copied the file from my local computer and uploaded it to the media directory so you can see that here so let's go ahead and test this out the first thing i want to do is to just restart the the nginx server with sudo etc d nginx restart that'll apply the changes that we made to our configuration file and then back in our web browser instead of going to micro domains colon 8000 if you remember we were working on port 80 with nginx so we don't need to specify a port number anymore and then we can go to slash media slash media.gif which is the name of the the file and we can see that show up that means nginx is properly serving static files from directly from the web server and django has nothing to do with it so that's good that's what we want and by the way if you're curious this is google's first logo from back in i think 1998. okay so let's open up our terminal window again and as you can see we've tested out django we tested out the web server gateway interface and we actually connected them to and then we tested out nginx by itself so um we're working really good here we want to now connect them all we want to make them work together so let's go ahead and do that and we can we're actually in a place where we can test that out right now we have everything in place where it needs to be the command to bring that all together looks something like this okay so we have uwsgi our web server gateway interface we're gonna pass it a unix socket and this is a relative path so this in this directory there is let me just show you that um well there won't there isn't right now but there will be a socket that's going to be used to communicate from the web server gateway interface to nginx this command is going to create that and then continuing on the module like i explained before this is the connection to django so microdomains.wsgi which is the folder micro domains and then there there's a file called wsgi.pi and you might or might not need this if test it out with 666 if it works great test it out with 664 if it works that's even better and test it out without this whole argument and if that works too then just use that going forward just remember that going forward but for me i need to change the permissions to of the socket the socket to 666 okay so let's go ahead and run that we have our our web server gateway interface running and what we can do now is go back here and knock off this from the url just test out micro domains on port 80. let's see what we get here and we get our django our django landing page and that means that our web server gateway interface is connected to our unix socket is connected to our django application and that is working that is pretty much the essence of this video there is more that we have to do though we have to make sure that this starts up when the system runs so we're going to do that there's a couple steps and configuration options that we can do to make everything stable and work the way we want it to so let's continue on here we'll control c out of that and you know instead of passing these arguments and there's more arguments that we want to ultimately add to make this um this stable we want to create a configuration file to hold all of these options and then we'll pass that configuration file into the uw-sdi program so let's go ahead and make that file we're just going to make that in here it's going to be called micro domains underscore u w s g i dot ini and um again you can get this information from the linked blog post down below in the description and let's go through this some of these options we have the the directory that we're working out of which is our django root directory we have our wsgi module you guys should know what that is by this point and then we have our python virtual environment our map we're going to enable the the master process to be true the maximum number of worker processes is 10 in this case the the socket the full path to the socket we have that here and then the permissions the 666 you might or might not need this it could be a 664 you can maybe get rid of this if it works without it um and then we want to clear the environment on exit so we'll set vacuum to true and then we want to have a log file pretty much all that stuff that you saw spit out on the screen to to be logged into a file at this location pretty much in the root of our home directory so let's save that file and now like i said instead of specifying all of those options on the command line we can just specify the ini file that we created so uw sgi dash dash ini micro domains you know the file that we just created go ahead and run that and um this actually takes uh runs it in the background so if you do a ps aux we'll see that we have those 10 worker processes up here running and if we go back to our web server we should be able to refresh and the web server is running as it should so we're making really good progress here the next thing we want to do is to let me just check my cheat sheet here just so i don't miss anything okay we want to work with emperor and um i'm just going to walk you through this here this is like a layer on top of the web server gateway interface that kind of detects changes whenever the configuration file changes and allows those changes to kind of propagate through the system so in order to do that let's go into our home udoms and our um python virtual environment directory and we want to make a directory in here called vassals and this is kind of some funky terminology but what we're doing is basically we're kind of like we did with nginx we're going to make a sim link from the ini file that we just created to the current directory so that is at slash home udoms md vassal so again just assembling from this file to where we are right now uh yep so that looks good and then if you do an ls into the vassal's directory we'll see that simlink file here all right now we want to test out running the web server gateway interface in emperor remote and right now it would be a good idea to reboot the server because these have been backgrounded and this this website is still running so let's reboot the server to kill it and then we'll come back and run the next command so we'll pause it we'll do a pseudo reboot and this will take like a minute so i'll pause the video we'll come back when that's finished all right we're back so let's log back into the server via ssh and i'll go ahead and type my password and now that we're on let's do a ps aux just to show you that there is no website running and actually we can go back to our web browser and refresh and we're not going to see anything um let's paste that command that we were going to do before which is the emperor so uw sgi passing at the emperor to the the vassals directory and we're just specifying a user id and a group id here as www data so um oh whoops that actually did not work because of this here this um uh command so web server gateway interface what happened right i did not do my virtual environment so we have to do source and then end and md bin activate okay so let's try that again again this is coming from our virtual environment that looks good let's go back to our our website here refresh the page and we see the default django landing page which is really good that means everything up until this point is working together including emperor the vassals the web server gateway interface django the socket and python so last step here let's make this startup on boot the best way to do that on ubuntu is with a service file using systemd so let's do that and we can get out of this server here and that'll take a minute to just a couple seconds to stop what we want to do is create a a systemd service file in the directory and this will be sudo vim etc system system d system and then the name of your service so i'm going to call it emperor dot u w s g i dot service and this is kind of like a recommended name for this kind of stack um so let's go ahead and create that and in here we'll paste in the following which is basically a we'll go through line by line description of the process we need the network to be kind of running before executing um for our website to work so that's why we have after network.target here the user we want to run it under is udom's restart always means that if the process is killed for whatever reason if it's an error or somebody manually kills it it's going to automatically restart and the reason we want that is because this is a production web server in like most cases we always want our website to be online 100 of the time so that's why we have that and then the command that we just executed so the the full path to the uw-sgi um binary emperor the vassals and then the user id and group id and then this last part wanted by multi-user target that's just again some some necessary information that you have to have in this configuration file so let's go ahead and save that and the first thing we want to do is enable our new service so we can do that with system ctl enable emperor.uwsdi.service so what the let me type in my my let me type in my password okay like i was saying what the enable option does is allows this to start at boot okay and that's essentially why we created the system service d service to begin with all right so to avoid a reboot right now let's go ahead and start up the process manually we can do that with system ctl and instead of enable we can do start so we'll do that and actually let me just um ju because i know you're just seeing the same thing pop up here the default landing page seems like nothing's happening but right now if you recall nothing's running right if we refresh the page we're going to get a bad gateway error now when we start emperor the emperor service we have to type in our password now that service is running we can check that with psa ux and we see our processes are kind of cut off here running let's refresh the page and we see our django landing page once again and the way i guess to ultimately test this out is to reboot the server one last time and we'll do that with you let's go ahead and do sudo reboot and we'll wait for that to start back up and then we'll test it out one last time okay and just real quick uh while the system is booting up i want to show you that the system's offline nothing's running it's actually probably better for me to not wait until the system boots up you can see it's trying to connect but i don't think that we have let's ping micro dot domains it we might be able to ping it but no we're not even able to ping it so um once as the system boots up you know when the network's ready then this is going to um there we go we can see our network now then the whole systemd service file that we created is going to execute we're going to start up the web server gateway interface with emperor and all that stuff and then we should be able to visit our website in the browser so let's see if we're ready we're ready nothing else we had to do externally this is always going to run and we are pretty much ready for deployment there are a couple other options django options excuse me that you want to set up so i have a video on that right here so definitely check that out and i also have another video about how to set up a free ssl certificate with django right here check that out thank you guys for watching i hope you got some value please give this video a thumbs up subscribe to this channel for more like this and i will see you in the next [Music] video
Info
Channel: Tony Teaches Tech
Views: 30,194
Rating: undefined out of 5
Keywords: django nginx, deploy django uwsgi nginx, django and nginx, django on nginx, nginx serve static files django, django wsgi, wsgi server django, django and wsgi, best wsgi server for django, uwsgi django, django nginx uwsgi ubuntu 20.04, django server, django web server, deploy django app on nginx, django tutorial
Id: ZpR1W-NWnp4
Channel Id: undefined
Length: 37min 56sec (2276 seconds)
Published: Thu Nov 05 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.