This is the last project for "Full Stack Web Developer Nanodegree" on Udacity.
In this project, we will dockerize a simple Python Flask App and deploy it on AWS Lightsail.
Public IP: 52.57.9.218
URL: www.amanuelg.me
Port: 2200
Launch a LightSail instance with Ubuntu and connect to it using SSH. You need to download the default private key from the LightSail website. Don't forget to set the proper permissions for that file.
$ sudo apt-get update
$ sudo apt-get upgrade
How To Install and Use Docker on Ubuntu 16.04
How To Install Docker Compose on Ubuntu 16.04
$ sudo adduser grader
$ sudo visudo
In your Visudo File look for this line:
root ALL=(ALL:ALL) ALL
Then add this line to grant user grader sudo privileges:
grader ALL=(ALL:ALL) ALL
$ mkdir .ssh
$ sudo touch .ssh/authorized_keys
Copy public key into this file, save it and set proper permissions:
$ sudo nano .ssh/authorized_keys
$ chmod 700 .ssh
$ chmod 644 .ssh/authorized_keys
- Add Port 2200 through Lightsail web interface
- Open sshd config file:
sudo nano /etc/ssh/sshd_config
- Change
Port:20
toPort:2200
- Change
PermitRootLogin prohibit-password
toPermitRootLogin no
- Save changes and then restart sshd service
sudo /etc/init.d/ssh restart
- Configure the time zone
sudo dpkg-reconfigure tzdata
- Set it to
UTC
Configure firewall rules using UFW. Check to see if ufw is active: sudo ufw status
. If not active, lets add some rules
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2200/tcp
sudo ufw allow 80/tcp or sudo ufw allow www (either one of these commands will work)
sudo ufw allow 123/udp
Now, enable the rules: sudo ufw enable
To suit my needs, i made the extra effort to learn the ins and outs of Docker.
For this task, we will spin up two containers: one named web
to run our python app with uWSGI
and Nginx
. The other named postgres
to run a PostgresSQL
database server.
- Replace/Copy app content in folder
app
- In
__init__.py
change the config object topostgres
- In
config.py
set database name, user, password and URLs
POSTGRES_USER = 'foo'
POSTGRES_PASSWORD = 'foobar'
POSTGRES_DB = 'prod'
UPLOADS_DEFAULT_URL = '<YOUR_URL>/static/img/'
UPLOADED_IMAGES_URL = '<YOUR_URL>/static/img/'
- Build our own Docker Image via a Dockerfile
FROM tiangolo/uwsgi-nginx:python2.7
MAINTAINER Amanuel Ghebreweldi
RUN pip install --upgrade pip
# Install all necessary Python dependencies
COPY ./app/requirements.txt /app/requirements.txt
RUN pip install --requirement /app/requirements.txt
# This is needed for PostgreSQL
RUN pip install psycopg2
# Copy Nginx config
COPY nginx.conf /etc/nginx/conf.d/
# Copy Python app content
COPY ./app /app
- Create Nginx Config file called
nginx-conf
server {
location / {
try_files $uri @app;
}
location @app {
include uwsgi_params;
uwsgi_pass unix:///tmp/uwsgi.sock;
}
location /static {
alias /app/bookshelf/static; ## serve static files from app
}
}
Keep in mind to follow the same folder structure like the repo
- Create a
docker-compose.yml
file
version: '2'
services:
web:
container_name: 'web'
# point to Dockerfile to build an image and use it afterwards
build: .
ports:
# map ports from HOST:CONTAINER
- "80:80"
volumes:
- ./app:/app
# link to other container postgres and its service
depends_on:
- postgres
postgres:
container_name: 'postgres'
image: postgres:latest
environment:
# set the same ENV variables specified in config.py
POSTGRES_USER : foo
POSTGRES_PASSWORD : foobar
POSTGRES_DB : prod
volumes:
- pgdata:/var/lib/postgresql/data/
ports:
- "5432:5432"
volumes:
pgdata:
- Clone your repo into your AWS Lightsail instance
- Go to your repo directory and build your image:
$ docker-compose build
- Run your Docker Containers
$ docker-compose up`
- Init Database with some sample data
$ docker-compose run web /usr/local/bin/python /app/db_setup.py
- Bookshelf is using Google for login authentification. Public IPs are not allowed to handle responses from Google's authorization server. You need a public top-level domain. Luckily if you are a student, you can get one for free at Namescheap