Deployment¶
Deployment Process¶
The following should be read as more of a reference than a guide. To deploy Rocket 2, you must follow the steps as if you were building it for local use, except some tweaks in regards to where it goes and more tooling-specific details mentioned below.
Hosting¶
Rocket 2 is currently hosted by an AWS EC2 t2.micro instance. Since this is a single-threaded application with a single worker thread, there is not much of a reason to go for anything more. Note: Adding more worker threads may cause “minor” issues such as the scheduler running more than once, weird exceptions, and may prevent the server from running in some cases, which is why increasing the number of worker threads beyond 1 is not recommended.
If need-be, Inertia can help provision an instance for you.
Should you wish to set up your own Rocket 2 instance for deployment, you should
first be able to set up a Rocket 2 instance for testing on a local computer
with ngrok
forwarding. If you have successfully set up an instance on a remote
computer, you may still want to have a look.
For those of you who don’t want too much of a hassle, hosting via Heroku is also a valid option, as Heroku does continuous deployment without the need of setting up Inertia, and also has built-in SSL so you don’t need to set anything up. Be wary, however, that Heroku is almost twice as expensive as an AWS EC2 t2.micro instance.
Do note that you must set the environmental variables in the provided settings
page if you are to host via Heroku. For details regarding how you would input
the GITHUB_KEY
, please see below.
SSL¶
Before deploying for the first time, you must set up SSL and configuration for
Nginx, which we are using as a proxy server. This can be done by running the
scripts/setup_deploy.sh
script. This runs the official
Let’s Encrypt container to request SSL certificates,
sets up a cronjob to periodically re-validate them, and copies
nginx.conf
to the correct location. Do note that the Let’s
Encrypt container needs to use port 443, so if you have another process or
container using that port, you will need to kill it before running the
set up script.
Inertia¶
For UBC Launch Pad, we continuously deploy off the ec2-release
branch on
Github using UBC Launch Pad’s
Inertia. This will pull the repo when
changes are merged, rebuild the containers from docker-compose.yml
, and
redeploy.
When deploying with Inertia, make sure that you are using a stable version of Inertia.
Since we have changed from using .toml
configuration files to using
environmental variables for configuration, you must inject them using inertia
{some name} env set AWS_LOCAL False
and the like. If you already have all your
environmental variables set up in your .env
file, you can send the entire file
over with inertia {some name} send .env
.
GITHUB_KEY¶
The GITHUB_KEY
is merely the GPG private key used to sign Github API requests.
We simply shove the entire file into a string and use it in the environmental
variable. Do note that doing this on the command line is somewhat difficult
because inertia
would treat the dashes --
in the string as flags and get
confused. Another thing to watch out for is that the command line ignores the
new lines in the string. The current working method of doing this is to pass in
the entire string with a single quote (which means that every symbol is taken
literally), then for every dash in the string, we add a forward slash \
in
front. We then replace all new lines with the literal \n
.
Our configuration code replaces these instances of \-
and \n
with actual
dashes and new lines.
Note that these replacements are not necessary on Heroku and you can simply copy and paste the contents of the key file directly into the box provided.
If you are using the .env
file approach, you only need to replace the new
lines and not the dashes.
Docker Compose¶
Our main deployment configuration is contained in
docker-compose.yml
. We deploy an Nginx container
to serve as a proxy, as well as building and running a Rocket 2 container.
The Nginx proxy exposes ports 80 and 443, for HTTP/S, which must also be
accessible from the outside world. The Rocket 2 container exposes port 5000,
as Gunicorn is listening on this port; this should not be accessible to
the outside world.
Note that Docker Compose has a rather complex networking utility. In particular,
note that to access HTTP endpoints in other composed containers, you must
reference them by their service name in docker-compose.yml
, not via
localhost. This is already handled in nginx.conf
.
Other Build Tools¶
Github Actions CI¶
Github Actions CI is a continuous
integration service that is used to build and test software projects hosted on
Github. To configure Github CI, a file pythonpackage.yml
needs to be added
to .github/workflows/
. This YAML file will contain the commands for
the automated tests that needs to run.
Every time a branch gets pushed into github, Github CI starts a job. A job is where Github clones the GitHub repository into a new virtual environment to test the code.
Docker¶
Docker is a program that run software packages called containers. Every container is isolated from each other and is a bundle (also known as image) of their own tools, applications, libraries and configuration files. However, containers are able to also communicate with each other through channels, and all containers are run by a single OS kernel. We use Docker in Rocket2 to make deployment to the server easier.
Docker is composed of 3 parts: Container, Services, and Stack.
Dockerfile
defines the container. Inside Dockerfile
is the environment that
would be set up. Inside the container for Rocket2, we have a copy of our app,
and all the dependencies and the virtual environment installed.
docker-compose.yml
defines the services that allow multiple containers to run
together.
Docker is different than virtual machines because it can run multiple containers using only one kernel which makes it more lightweight.