From 927329de79257d272947e3f883ad574261ff8060 Mon Sep 17 00:00:00 2001 From: pacien Date: Fri, 30 Jul 2021 01:13:20 +0200 Subject: docs: add container-based cloud deployment to Heroku --- flake.nix | 15 ++++++++++++++- readme.md | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index b8616f8..5f63359 100644 --- a/flake.nix +++ b/flake.nix @@ -31,6 +31,9 @@ develPackagesAndScripts = [ postgresql_13 # PostgreSQL server with the standard admin tools. python.pkgs.ipython # Interactive Python REPL for experimenting. + heroku # CLI for the Heroku hosting platform. + skopeo # Docker container upload utility. + pwgen # Simple random token generator. # More pleasant alternative to psql, with colours and auto-completion. # Custom configuration to suppress irrelevant warnings and messages. @@ -92,7 +95,7 @@ in { - packages = { + packages = rec { # Minimal production server. # This includes only application files tracked by git. # Using `gunicorn` on top of `uvicorn` is recommended for bigger loads. @@ -100,6 +103,16 @@ cd ${./.} ${pythonWithDependencies}/bin/uvicorn --app-dir app app:main "$@" ''; + + # Minimal docker image. + # The Heroku hosting service assigns the `$PORT` dynamically. + docker = dockerTools.streamLayeredImage { + maxLayers = 2; + name = "app-docker"; + config.EntryPoint = writeShellScript "run.sh" '' + ${server} --host 0.0.0.0 --port $PORT + ''; + }; }; devShell = mkShell rec { diff --git a/readme.md b/readme.md index 569b173..7a16b0d 100644 --- a/readme.md +++ b/readme.md @@ -349,6 +349,8 @@ course, asking students to deploy their application on the Internet could be a motivational factor. It would also facilitate evaluating and grading projects, avoiding deployment and testing hassles to the teaching staff. +#### Standard daemon + The Nix Flake provides a Nix package which can be used to run the web application in a production context as a [daemon], managed by a standard [init] system. @@ -356,6 +358,69 @@ system. [daemon]: https://en.wikipedia.org/wiki/Daemon_(computing) [init]: https://en.wikipedia.org/wiki/Init +#### Docker container + +A [Docker] container can also be derived from this package to be deployed on +popular cloud hosting services. + +[Docker]: https://www.docker.com/resources/what-container + +##### Example of container deployment + +An example of deployment procedure using the free tier provided by the [Heroku] +hosting service is given below. This makes use of the [skopeo] tool to upload +the Docker container to the service. + +[Heroku]: https://www.heroku.com/ +[skopeo]: https://github.com/containers/skopeo + +```sh +# Log in to an Heroku account. +heroku login + +# Create a new project with a random name, hosted somewhere in Europe. +heroku create --region eu + +# Set a local environment variable with the assigned name of the project so +# that the next commands operate on it. +set --export HEROKU_APP 'name of the created app' + +# Set a randomly-generated signed cookie secret key for our application. +heroku config:set COOKIE_SECRET_KEY=$(pwgen --secure 128 1) + +# Attach a PostgreSQL database to the newly created app. +# This sets a connection URL in "DATABASE_URL" in the server's environment, +# containing the confidential database username and password. +heroku addons:create heroku-postgresql:hobby-dev --version=13 + +# Create the tables in the database. +heroku psql < ./sql/tables.sql + +# Prepare a Docker container. +# This creates a Docker archive streaming script as `./result`. +nix build .#docker + +# Log in to the Heroku container registry to upload our container. +skopeo login --username _ --password $(heroku auth:token) registry.heroku.com + +# Upload the Docker image to Heroku (uploading about ~200MB). +./result \ +| gzip --fast \ +| skopeo --insecure-policy copy \ + docker-archive:/dev/stdin \ + docker://registry.heroku.com/$HEROKU_APP/web + +# Deploy and launch the uploaded container. +heroku container:release web + +# If all went well, the app should now be deployed and accessible on +# https://$HEROKU_APP.herokuapp.com +heroku open + +# If not, logs can be remotely inspected for debugging. +heroku logs --tail +``` + ## Copyright and licensing -- cgit v1.2.3