This guide is designed for new developers joining the AGORA project. It covers setting up the Python backend, dependency management, building API and GeoServer containers, and running everything with Docker Compose in both dev and production modes.
AGORA's API is based on Python 3.10 using Poetry and Conda for dependency management.
poetry add --lock package_name
poetry update- Automatically updates
pyproject.tomlandpoetry.lock
conda install some_package=version
conda env export --from-history > environment.yml
conda-lock -f environment.yml --lockfile conda-lock.ymlAlways run the image update script after changes:
./src/docker-python-env/create_docker_image.shPath:
./src/docker-python-env/create_docker_image.shLogic:
if git diff --exit-code pyproject.toml environment.yml; then
echo "No changes in dependencies. Skipping image update."
exit 0
else
docker commit agora-dev-api agora-api-image:latest
fiThis script ensures that the Docker image is updated only when library dependencies change. All developers and CI pipelines should use this.
AGORA uses a modular GeoServer build system with plugin support and custom CORS configuration.
geoserver_agora/
βββ plugins/ # Plugin jars
βββ Dockerfile # Final image using base + plugins
βββ download_plugins.sh
geoserver_base/
βββ Dockerfile # Base image
βββ entrypoint.sh # Startup logic
βββ production_web.xml # CORS etc.
βββ set_geoserver_auth.sh # Admin credentials
βββ tasks.py # (Optional)
cd geoserver_base/
docker build -t dcs-base-geoserver:2.25.6 .cd geoserver_agora/
chmod +x download_plugins.sh
./download_plugins.sh "2.25.6" "mbstyle vectortiles"
β οΈ Warning:plugins/will be wiped before downloading.
docker build . -t agora-geoserver:2.25.6To build and run the full dev environment:
chmod +x build_dev_container.sh
./build_dev_container.shWhich runs:
docker compose -f docker-compose-dev.yml --env-file src/app/.env up -d --buildIf you make any changes to dependencies in the API (pyproject.toml or environment.yml), you must run:
./src/docker-python-env/create_docker_image.shThis ensures the dev image reflects those changes.
docker compose -f docker-compose-dev.yml --env-file src/app/.env up -ddocker compose -f docker-compose-prod.yml --env-file src/app/.env up -dπ Note: The
.envfile must be located at:src/app/.envThis path is used by both
docker-compose-dev.ymlanddocker-compose-prod.yml. A template is available at:src/app/.env.example
β οΈ GeoServer Notice: Environment variables such asGEOSERVER_ADMIN_USERandGEOSERVER_ADMIN_PASSWORDare used by the GeoServer container only if declared in your docker-compose file. However, CORS-related settings (likeGEOSERVER_CORS_ALLOWED_ORIGINS, etc.) must be set manually ingeoserver_base/Dockerfileand rebuilt accordingly.
DATABASE_HOSTNAME=db
DATABASE_PORT=5432
DATABASE_NAME=agora
DATABASE_USERNAME=agora
DATABASE_PASSWORD=agora
SECRET_KEY=your_secret_key
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=760
REFRESH_TOKEN_EXPIRE_MINUTES=1000
GEOSERVER_ADMIN_USER=admin
GEOSERVER_ADMIN_PASSWORD=geoserver2
GEOSERVER_PORT=8383
GEOSERVER_CORS_ENABLED=True
GEOSERVER_CORS_ALLOWED_ORIGINS=*
GEOSERVER_CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE,HEAD,OPTIONS
GEOSERVER_CORS_ALLOWED_HEADERS=*
GEOSERVER_CSRF_DISABLED=trueapp/
βββ auth/ # Login, Register, Token
βββ db/ # SQLAlchemy + GeoAlchemy2 models
βββ geoserver/ # GeoServer REST API integration
βββ ligfinder/ # Spatial analysis module
βββ utils/ # Shared helpers
βββ main.py # FastAPI entry point
- Enter API container:
docker exec -it agora-dev-api bash- Restart only the API:
docker compose restart api- Tail logs:
docker logs -f agora-dev-apiIn production, the API container directly mounts the src/ directory from the main repository.
To reflect new changes, you must log into the production server and run:
git pullThis ensures the latest codebase is updated inside the container. Since the container uses the mounted
src/folder directly, no rebuild is required after pulling updates. Just make sure to test changes in dev before pushing to production.
This section explains how to take backups from production and restore them on development. This is the preferred way to replicate the live environment locally.
If a volume is mounted like:
volumes:
- ./database/dumps:/var/lib/postgresql/dumpsThen simply run:
docker exec -it agora-dev-db bash -c "pg_dump -U agora -F t -f /var/lib/postgresql/dumps/dump-$(date +%Y%m%d%H%M).tar agora"This creates a file like
dump-202506241446.tarinside./database/dumpson host.
If you do not mount a volume, you must copy the file manually:
docker cp agora-dev-db:/tmp/dump.tar ./dump-202506241446.tarYou can use GUI tools like DBeaver for backup and restore only if you also use the same tool for both actions. That means:
- If you export via DBeaver, you must import again via DBeaver GUI.
- Do not mix GUI-generated exports with CLI tools like
pg_restore.
Incompatibilities may otherwise occur, such as:
pg_restore: error: unsupported version (1.16) in file headerERROR: unrecognized configuration parameter "transaction_timeout"
β
Preferred: use pg_dump and pg_restore directly inside containers.
Preferred approach if volume is already mounted:
volumes:
- ./database/dumps:/var/lib/postgresql/dumpsThen place your backup file under ./database/dumps/ and run:
docker exec -it agora-dev-db bash -c "PGPASSWORD='agora' pg_restore -U agora -h localhost -p 5432 -d agora -c -v /var/lib/postgresql/dumps/dump-202506241446.tar"Alternative if no volume is mounted:
docker cp ./dump-202506241446.tar agora-dev-db:/tmp/dump.tar
docker exec -it agora-dev-db bash -c "PGPASSWORD='agora' pg_restore -U agora -h localhost -p 5432 -d agora -c -v /tmp/dump.tar"sh backup_geoserver.sh CONTAINER_NAME(e.g.sh backup_geoserver.sh agora-geoserver-dev-container) to create a backup of the geoserver data. This creates a tar.gz of all relevant geoserver content in the geoserver_backup foldersh restore_geoserver CONTAINER_NAME FILENAME(e.g.sh restore_geoserver agora-geoserver-dev-container geoserver-backup-20251217_143039, filename of bakcup tar without extensions!) to restore the content of the geoserver