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.toml
andpoetry.lock
conda install some_package=version
conda env export --from-history > environment.yml
conda-lock -f environment.yml --lockfile conda-lock.yml
Always run the image update script after changes:
./src/docker-python-env/create_docker_image.sh
Path:
./src/docker-python-env/create_docker_image.sh
Logic:
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
fi
This 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.24.4 .
cd geoserver_agora/
chmod +x download_plugins.sh
./download_plugins.sh "2.24.4" "mbstyle vectortiles"
β οΈ Warning:plugins/
will be wiped before downloading.
docker build . -t agora-geoserver:2.24.4
To build and run the full dev environment:
chmod +x build_dev_container.sh
./build_dev_container.sh
Which runs:
docker compose -f docker-compose-dev.yml --env-file src/app/.env up -d --build
If you make any changes to dependencies in the API (pyproject.toml
or environment.yml
), you must run:
./src/docker-python-env/create_docker_image.sh
This ensures the dev image reflects those changes.
docker compose -f docker-compose-dev.yml --env-file src/app/.env up -d
docker compose -f docker-compose-prod.yml --env-file src/app/.env up -d
π Note: The
.env
file must be located at:src/app/.env
This path is used by both
docker-compose-dev.yml
anddocker-compose-prod.yml
. A template is available at:src/app/.env.example
β οΈ GeoServer Notice: Environment variables such asGEOSERVER_ADMIN_USER
andGEOSERVER_ADMIN_PASSWORD
are 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/Dockerfile
and 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=true
app/
βββ 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-api
In 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/dumps
Then 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.tar
inside./database/dumps
on host.
If you do not mount a volume, you must copy the file manually:
docker cp agora-dev-db:/tmp/dump.tar ./dump-202506241446.tar
You 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 header
ERROR: 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/dumps
Then 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"