-
Notifications
You must be signed in to change notification settings - Fork 1
production deployment
Deployment to production environment shall follow a semi-automated process. The initial deployments will require access to the node via SSH - later on we may lift this requirement.
The idea is to use a deployment script, coupled with a suitable configuration file, which takes care of most deployment-related tasks.
The script is located on the backend repo, at the /deployments/deploy.py
relative path.
Deployments work by using suitable docker compose
configuration files. The workflow is automated by the deployment
script and consists of:
- Retrieving the latest version of the deployment-related files from the source code repository
- Standing down the docker compose stack, if it is running
- Updating system docker images by pulling their specified versions from the docker registry
- Standing up the stack again, with the new images
- Updating translations and perform any database migrations
In order to ensure a healthy deployment environment exists we need to perform some bootstrapping steps:
- Have all necessary system packages installed
- Ensure there is a periodic cleaning of unused docker images
- Login to github docker registry
Ensure git
and docker
are installed:
sudo apt-get install --yes \
curl \
git
curl \
-fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg \
--dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
sudo groupadd docker
sudo usermod -aG docker $USER
If installing docker, be sure to log out of the current session and then log back in, which would be necessary for the new group memberships to be loaded.
The backend source code repository contains sample systemd unit files that can be used to set up a periodic
service which cleans up any unused docker images. These sample files are located at the /deployments/systemd-unit-files
path. They consist of two files:
-
clean-docker-images.service
- specifies that the commanddocker system prune --all --force
shall be run -
clean-docker-images.timer
- specifies that the.service
file shall run every sunday at 01h
Copy both of them on to the node's /etc/systemd/system
directory. Modify the .service
file, ensuring that
any {CHANGE_ME}
placeholder values get modified to their correct value.
Finally, enable the timer by running:
sudo systemctl start clean-docker-images.timer
The deployment workflow pulls docker images from the ghcr.io
docker registry. This registry is owned by github and
does not allow anonymous access. Therefore, it is necessary to log in to the registry in order to be able to download
images from it.
Currently, the github registry can only be accessed by registered users and it needs a user to provide either their password or a personal access token (PAT).
Obtain a relevant PAT and then login to the registry:
docker login ghcr.io
# when instructed, provide the user email and PAT
In order for a deployment to be possible we need to perform some preparations:
- Upload docker images to the github docker registry
- Create base deployment directory and copy the relevant files over
- Create or modify the deployment configuration file
Deployments to production use docker images and expect to be able to retrieve them from the github docker registry. Therefore, images for both the backend and the frontend applications must have been previously uploaded to the registry in order to be deployed.
The deployment script can be told which images to use for backend in frontend by one of two ways:
- Passing the
--backend-image
and--frontend-image
parameters when calling the deployment script - Having the
main.backend_image
andmain.frontend_image
parameters properly configured in the deployment configuration file
In either case, the value of both the backend and frontend image parameters must be the full URL of the docker image, including the registry and including the tag name.
Note
In order to make it easy to always know which code is running in the production environment, always use a properly versioned docker tag. This means pushing a git tag to the respective source code repository and using the same name for the docker image tag too. Pushing a git tag and building a docker image with the same tag should optimally be done in sequence, by an automated project, like a CI pipeline.
Both the backend and frontend source code repositories have Continuous Integration (CI) pipelines running on the github actions platform. These CI pipelines will build a new docker image when a new git tag is pushed to the respective source code repository, tag the built docker image with the same tag used in git, and then push the image to the docker registry.
The deployment script must be able to operate on some directory as it needs to fetch files from the source code repository. Create a suitable directory:
DEPLOYMENT_ROOT=/opt/arpav-cline
sudo mkdir ${DEPLOYMENT_ROOT}
sudo chown $(id -u):$(id -g) ${DEPLOYMENT_ROOT}
cd ${DEPLOYMENT_ROOT}
Now clone the backend source code repository and get the initial version of the deployment files:
Note
This is a bootstrap procedure that only needs to be done once. Subsequent deployments will re-download the necessary files automatically.
# clone repo and get initial deployment files
git clone https://github.com/geobeyond/Arpav-PPCV-backend.git
cp Arpav-PPCV-backend/deployments/deploy.py .
cp Arpav-PPCV-backend/deployments/sample-prod-deployment.cfg .
rm -rf Arpav-PPCV-backend
Although not strictly required, you should also copy into this directory:
- TLS-related files
- traefik basic auth users file
- uvicorn log config file
This is just for keeping everything together
The deployment configuration file is required for the deployment script to execute properly. This file must be
in a format suitable for parsing with Python's configparser
library. The backend code repository contains a sample configuration file, which can be copied and used as a base. This
sample file is located at /deployments/sample-prod-deployment.cfg
.
cd ${DEPLOYMENT_ROOT}
mv sample-prod-deployment.cfg prod-deployment.cfg
The file is expected to contain the following entries and all of them are mandatory, with two notable exceptions, as mentioned in the previous section:
section | parameter | description | example |
---|---|---|---|
main | backend_image | full docker registry URL of the backend image | ghcr.io/geobeyond/arpav-ppcv-backend/arpav-ppcv-backend:v1.0.0 |
main | db_image_tag | tag name of the postgis/postgis image to use for various DB containers |
16-3.4 |
main | deployment_root | path to the directory where the deployment files reside | /opt/arpav-cline |
main | frontend_image | full docker registry URL of the frontend image | ghcr.io/geobeyond/arpav-ppcv/arpav-ppcv:v1.0.0 |
main | discord_notification_urls | comma-separated list of discord-webhook URLs which will be notified when a deployment is done | |
main | deployment_files_repo | URL of the git repository where the deployment-related files reside | https://github.com/geobeyond/Arpav-PPCV-backend.git |
main | martin_image_tag | tag name of the ghcr.io/maplibre/martin image to use |
v0.13.0 |
main | prefect_server_image_tag | tag name of the prefecthq/prefect image to use |
3.0.0rc17-python3.10 |
db | name | name of the backend db | arpavppcv |
db | password | password of the backend db. Choose something hard to guess and keep it secret. | |
db | user | username of user that connects to the backend db | arpav |
prefect_db | name | name of the prefect db | prefect |
prefect_db | password | password of the prefect db. Choose something hard to guess and keep it secret. | |
prefect_db | user | username of user that connects to the prefect db | prefect |
reverse_proxy | image_tag | tag name of the traefik image to use |
3.0.2 |
reverse_proxy | tls_cert_path | local path to TLS certificate | /opt/arpav-cline/cert.crt |
reverse_proxy | tls_cert_key_path | local path to TLS certificate key | /opt/arpav-cline/cert.key |
reverse_proxy | traefik_users_file_path | local path to traefik basicauth users file. This contains users that can access the prefect UI section | /opt/arpav-cline/basicauth-users.txt |
tolgee_app | env_tolgee_authentication_initial_password | initial password for the tolgee user | |
tolgee_app | env_tolgee_authentication_jwt_secret | JWT secret key for auth-related tasks | |
tolgee_app | env_tolgee_frontend_url | public URL of the tolgee service | https://tolgee.cline.arpav.it |
tolgee_app | image_tag | tag name of the tolgee/tolgee image to use |
v3.71.4 |
tolgee_db | name | name of the tolgee db | tolgee |
tolgee_db | password | password of the tolgee db. Choose something hard to guess and keep it secret. | |
tolgee_db | user | username of user that connects to the tolgee db | tolgee |
webapp | env_admin_user_password | password for the user that is able to access the admin section | |
webapp | env_admin_user_username | username for the user that is able to access the admin section | admin |
webapp | env_cors_origins | comma-separated list of allowed CORS origins | https://cline.arpav.it |
webapp | env_num_uvicorn_worker_processes | how many worker processes should the uvicorn server use | 4 |
webapp | env_public_url | public URL of the system | https://cline.arpav.it |
webapp | env_session_secret_key | secret key used in sessions | |
webapp | env_thredds_server_base_url | base URL of the THREDDS server | https://thredds.arpav.it/thredds |
webapp | env_uvicorn_log_config_file | local path to the uvicorn log configuration | /opt/arpav-cline/prod-log-config.yaml |
After having gone through the steps mentioned in the previous sections, performing an actual deployment is simple:
just execute the deployment script, passing it the correct configuration file and the --confirm
flag:
cd ${DEPLOYMENT_ROOT}
python3 deploy.py --config-file prod-deployment.cfg --confirm