Develop a Python Flask Application with Docker and Deploy it to AWS – Part 4 Deploy our docker images
Jan 19, 2019VICTORY
Now that our docker-compose.yml file is all ready, we have almost all the pieces we need to deploy our application to AWS. The last thing it so deploy our docker images to some docker storage provider.
I personally like quay.io, but docker hub is an equally excellent choice that is rapidly improving.
Get the Code
If you haven't already, clone the github repo to see the full code.
Upload your docker containers
AWS can't work with containers just hanging out on OS, so you need to upload (or push) them to the cloud.
Create a Docker Account
Create an account on either quay.io or docker hub. It really doesn't matter where. Just pick one and go for it. Quay.io has a nice tutorial to get started pushing (uploading) and pulling (downloading) your docker images.
If you're like me, and you're really terrible at remembering things, you will want to save your password somewhere. Probably in a file. Possibly even in a file that is backed up using Dropbox or some other cloud backup provider. ( I can't even count the number of times git and dropbox have saved myself from my own stupidity.)
Login to your docker account
Ensure you can login to your docker account from the command line like so:
Tag and Upload Your Images
Label your images so that quay or dockerhub knows where to stick them. You need to know the full name, not the shortcut we get to use with docker-compose. You can get this with:
Since my docker-compose working directory is deploy-a-python-flask-app-to-aws, that is the first part of the image name. The second is the service name, separated by an underscore ( _ ).
The Repository name is what we are going for here.
Tag and push your images to the interwebz. This may take awhile. The larger your image the longer the upload size.
Versioning Your Images
Here we used latest as the version, which is a bit of a convention. You can assign a single image to multiple tags, and it does not take up more space on your filesystem, or on the cloud. Simple add another tag, and replace the :latest with your version of choice. Don't forget to push it!
Make sure your image is public!
If you use quay.io it may make the image private by default. I find this annoying and wish it would change, but for now just go into the web UI, find your repository, go to the Settings Cog (at the bottom), and Scroll down to 'Visibility'. Make it public, and you'll be golden.
Finally! Deploy to AWS
For interested parties the AWS documentation is here. We are doing just about the same thing, except with a python application instead of a PHP app.
Full disclaimer, there are about a million gazillion ways to do this. I am going to show you what I think is the easiest method using ElasticBeanStalk, but there are other ways! There are always other ways!
AWS Account
This portion assumes you already have an AWS account, free tier is fine, with an SSH key. If you don't have one already, check out the very robust AWS documentation on setting up your account.
It also assumes you already have at least one SSH key. Set Up AWS EC2 SSH Keys.
Create the AWS Docker Configuration
We are basically going to take our docker-compose file and map it to the configuration format that AWS understands. Yes, this is a pain, but it's very nearly the same thing, so calm down. If you want to know all about the AWS Dockerrun format check out the Container Definition Format Docs.
This is what the file looks like, but for elasticbeanstalk we need to upload it in a zip
Download the zip archive here.
{ | |
"AWSEBDockerrunVersion": 2, | |
"volumes": [ | |
], | |
"containerDefinitions": [ | |
{ | |
"name": "flask-app-server", | |
"image": "quay.io/jerowe/flask-app-server:latest", | |
"update": true, | |
"essential": true, | |
"memory": 400, | |
"environment": [ | |
], | |
"mountPoints": [ | |
], | |
"portMappings": [ | |
{ | |
"hostPort": 80, | |
"containerPort": 5000 | |
} | |
] | |
} | |
] | |
} |
A Note about Ports
The default port open on the AWS web worker port 80. The flask app is running on port 5000, so we tell docker to map from port 5000 in the container to port 80 on the host.
To have multiple servers running on different ports within the same configuration you must either use nginx load balancing or traefik. I recommend traefik, because it's amazing!
Choose MultiContainer Docker Instance
Actually, we are only using one docker container, but whatever. It's the same stuff.
If your name isn't Jillian Rowe, you will probably want to change all this jerowe nonsense. You can also name the environment and create the domain however you want. I like to keep my names basically the same as my github repo because I have the worst memory of all time.
Use the zip archive from the github repo here (if you didn't download previously) . If you have been following along and uploading your own images, you can change the container definition from quay.io/jerowe/flask-app-server:latest to match your image name from the deploy step.
It's not in the image, but scroll down a bit and press next or submit or something of that sort.
On the next screen, after uploading our container definition, scroll waaaaay down, and press 'Create App'. No need to change anything here.
THAT'S IT!
Wait around awhile for your environment to build. Once its up and ready, then type your url address you chose as your domain name into the browser. For me that's http://jerowe-flask-app-server.us-east-2.elasticbeanstalk.com/. You should see a {"status": "ok"}, as I have this setup to be my default route in the flask app. You can also open up Postman or use curl to try out the health endpoint.