In your terminal:
> django-admin startproject projectName
> cd projectname
> touch .gitignore or nul> .gitignore (PCs)
In your .gitignore
file, add *.pyc
and venv/
Now back in your terminal:
> git init
> git add .
> git commit -m "my first commit"
Now build the rest of your project, committing to your local repo as necessary.
###Important!
Note where the
git init
command occurred: At the same level as your Django project'smanage.py
file
- Go to GitHub
- Create a repository (don't initialize with a README.md file)
Time to connect our local repository with the GitHub repo. Return to your terminal and paste the code generated by GitHub to your terminal. Those ones might look something like this:
> git remote add origin https://github.com/MikeHannon/myRepoName.git
> git push -u origin master
When finished with your project (with your Django virtual environment active), let's create a text file that lists our dependencies. This will make it easier to install those dependencies later. In your terminal:
(djangoEnv)> pip freeze > requirements.txt
edit this requirements.txt file removing pygraphviz, pydot, mysql and other similar 'tricky' to install pieces.
Make sure to add
, commit
and push
your final changes to GitHub. Once you login to AWS and set up a cloud server, you'll be pulling code from your GitHub (or Bitbucket) repository.
> git add .
> git commit -m "add python dependencies"
> git push origin master
Note: You'll need an AWS account, which you can sign up for here. It's free for a year, so long as you don't have more than 1 (free-tier) instance up at a time!
- Login to AWS Console
- Launch a new instance from the EC2 Dashboard (top left of main console leads to a page with a blue button)
- Select Ubuntu Server 14.04 option
- Select t2.micro option and click Review and Launch
###Time to set up security settings
- Click the Edit security groups link in the left hand column, choose the security group, (e.g. launch-wizard-1) and edit/add the following Inbound rules
- SSH type should be sourced to MyIP (this has to be updated everytime you change IP addresses. It adds a level of security, but can be annoying to maintain.)
- HTTP and HTTPS types should be sourced to Anywhere
##Click Review and Launch
You'll be asked to create a key file. This is what will let us connect and control the server from our local machine. Download the file to a place you'll remember (probably a good idea is to have a keys
folder to house this types of files). Do NOT put this folder in your project or ANYWHERE that gets pushed to GitHub.
##Click Launch You should see a launched instance in your dashboard. A blue button at the top saying connect will show up. Eventually we'll click that and select Connect. But first:
Back in your terminal, navigate to the folder that holds the key file you just downloaded.
> cd My/Keys/Folder
Mac users: Run a chmod
command to alter the permissioning of your key file.
> chmod 400 my-key-pair.pem
Now we're ready to use that file to connect to the AWS instance! That means, in your AWS console, click the Connect button to get instructions to connect to your instance and use the supplied code in your terminal (PC users: use a bash terminal or putty to do this). Or shortcut to this:
> ssh -i name_of_pem_file.pem [email protected]_address.here
If all goes well, you should be in your Ubuntu cloud server! Yay you! Your terminal should show something like this in the far left of your prompt:
ubuntu@ip-my-ip:~$ #Commands you write appear here
Now we are going to set up our Linux box for deployment.
In the terminal:
ubuntu@ip-my-ip:~$ sudo apt-get update
ubuntu@ip-my-ip:~$ sudo apt-get install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx git
You just installed pip
and some other python libraries, a postGRES
database, ngnix
(we'll talk about that shortly) and git
, which you already know and love.
ubuntu@ip-my-ip:~$ sudo apt-get update
ubuntu@ip-my-ip:~$ sudo pip install virtualenv
Time to clone your project from GitHub.
ubuntu@ip-my-ip:~$ git clone https://github.com/MikeHannon/myRepoName.git
At the moment your current folder directory should looks something like this.
- ubuntu
- myRepoName
- apps
- projectName
- ... # other files/folders
Navigate into this project and run ls
in your terminal. If you don't see manage.py
as one of the files, STOP. Review the setting up GitHub/Git pieces from earlier.
If everything looks good, let's make a virtual environment in our cloud server!
ubuntu@ip-my-ip:~/myRepoName$ virtualenv venv
ubuntu@ip-my-ip:~/myRepoName$ source venv/bin/activate
ubuntu@ip-my-ip:~/myRepoName$ pip install -r requirements.txt
(venv) ubuntu@ip-my-ip:~/myRepoName$ pip install django bcrypt django-extensions
(venv) ubuntu@ip-my-ip:~/myRepoName$ pip install gunicorn
(venv) ubuntu@ip-my-ip:~/myRepoName$ pip install psycopg2
Anywhere you see {{myRepoName}} -- replace that whole thing INCLUDING the {{}} with your outer folder name.
Anywhere you see {{projectName}} -- replace that whole thing INCLUDING the {{}} with the project folder name.
Navigate into your main project directory (where settings.py
lives). We're going to use a built-in text editor in the terminal to update the code in settings.py
. For example:
(venv) ubuntu@ip-my-ip:~/myRepoName$ cd {{projectName}}
(venv) ubuntu@ip-my-ip:~/myRepoName/projectName$ sudo nano settings.py
settings.py
is now open for editing. Change the following:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'anyname', # This name must be lowercase but can be anything!
'USER': 'mikehannon', # you can put whatever you want here
'PASSWORD': 'passwordYO', # you can put whatever you want here
'HOST': 'localhost',
'PORT': '',
}
}
And add the following (this will allow you to serve static content):
#Inside settings.py
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
Now just ctrl-X
and save! We just set up our settings.py
for a postgres database and added a place for all of our static files.
Let's actually set up the database. Note that all of the commands in the Postgres shell must end with a semicolon.
(venv) ubuntu@ip-my-ip:~$ sudo su - postgres
postgres_prompt1:~$ psql
postgres=# CREATE DATABASE anyname; #matches the anyname in the DATABASES and is all lower case!
postgres=# CREATE USER mikehannon WITH PASSWORD 'passwordYO'; #username is not in quotes, but password is, and both should match what you put into settings.py.
postgres=# GRANT ALL PRIVILEGES ON DATABASE anyname TO mikehannon;
postgres=# \q #quits this prompt
postgres_prompt1:~$ exit
Navigate back to the folder that holds manage.py
. Make sure your virtual environment is on!
(venv) ubuntu@ip-my-ip:~myRepoName$ python manage.py collectstatic #say yes
(venv) ubuntu@ip-my-ip:~myRepoName$ python manage.py makemigrations
(venv) ubuntu@ip-my-ip:~myRepoName$ python manage.py migrate
Migrations made. Now let's run the following:
(venv) ubuntu@ip-my-ip:~myRepoName$ gunicorn --bind 0.0.0.0:8000 projectName.wsgi:application
Run ctrl-c
and deactivate
your virtual environment.
Next, we're going to tell this green unicorn (gunicorn
) service to start a virtualenv, navigate to and start our project, all behind the scenes!
ubuntu@ip-my-ip:~$ sudo nano /etc/init/gunicorn.conf
Add the following to this empty file, updating the code that's in between curly braces {{}} (this assumes the name of your virtual environment is venv
):
description "Gunicorn application server handling our project"
start on runlevel [2345]
stop on runlevel [!2345]
respawn
setuid ubuntu
setgid www-data
chdir /home/ubuntu/{{myRepoName}}
exec venv/bin/gunicorn --workers 3 --bind unix:/home/ubuntu/{{myRepoName}}/{{projectName}}.sock {{projectName}}.wsgi:application
REMINDER: myRepoName is the name of the repo you cloned in, projectName is the name of the folder that was used when you ran the django-admin startproject command. This folder is sibling to your apps folder.
Here's what's actually happening:
runlevel
s are system configuration bytes (just use 2,3,4,5 as stated on the start, stop)respawn
-- if the project stops, restart itsetuid
-- ubuntu can use this projectsetgid
-- establishes a groupchdir
-- go to the /home/ubuntu/{yourProject} #This needs to be updated to have your project's nameexec venv/bin/gunicorn
... -- executegunicorn
in yourvirtualenv
where you pip installed it. Futhermore, bind some workers to it and activate thewsgi
file in your main project folder. Look at these names carefully!
To turn on or off this process:
ubuntu@ip-my-ip:~$ sudo service gunicorn start
#OR
ubuntu@ip-my-ip:~$ sudo service gunicorn stop
##Turn it on!
One final file to edit. From your terminal:
ubuntu@ip-my-ip:~$ sudo nano /etc/nginx/sites-available/{{projectName}}
Add this to the following, editing what's inside curly brackets {{}}:
server {
listen 80;
server_name {{yourEC2.public.ip.here}}; # This should be just the digits from AWS public ip!
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/ubuntu/{{myRepoName}};
}
location / {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/{{myRepoName}}/{{projectName}}.sock;
}
}
Remove the # This should be just the digits from AWS public ip! statement
Run ctrl-x
and save.
Now in terminal, run the following (taking note of the space after {{projectName}}):
ubuntu@ip-my-ip:~$ sudo ln -s /etc/nginx/sites-available/{{projectName}} /etc/nginx/sites-enabled
ubuntu@ip-my-ip:~$ sudo nginx -t
Take a careful look at everything that's in that file. Compare these names to the gunicorn
names, and what you actually are using!
##Finally:
ubuntu@ip-my-ip:~$ sudo service nginx restart
If you get an OK, hopefully you are rockin and rollin' and your app is deployed! Go to the public domain and bask in its brilliance! ##Also: if you are receiving a 502 or DisallowedHost error, add 'localhost', '127.0.0.1', '{{your.aws.public.address}}' to ALLOWED_HOSTS