Docker#

GeoAssistant-API is packaged as a Docker image and deployed via Docker Hub to Railway. This page covers the full build and deployment process.

Why Docker#

GeoAssistant-API depends on two private GitHub repositories (geoassistant and geogeometry). A Nixpacks-style deployment on Railway would require GitHub access at build time for each deploy, which becomes fragile with chained private dependencies.

Docker solves this by baking all dependencies into the image at build time on your local machine — where you already have GitHub access. Railway then simply runs the pre-built image with no GitHub access needed.

Prerequisites#

  • Docker Desktop installed and running

  • SSH key added to your GitHub account

  • GitHub Personal Access Token (PAT) with repo scope

  • Docker Hub account (username: kamejoin)

Generating a GitHub PAT#

  1. Go to GitHub → Settings → Developer Settings → Personal Access Tokens → Tokens (classic)

  2. Generate a new token with repo scope

  3. Copy the token — GitHub only shows it once

  4. Store it in your .env file:

GITHUB_TOKEN="your_token_here"

Loading the Token into Your Terminal#

Since .env stores the token with quotes, strip them when loading:

$env:GITHUB_TOKEN=(Get-Content .env | Select-String "GITHUB_TOKEN" | ForEach-Object { $_.ToString().Split("=")[1].Trim('"') })

Dockerfile#

FROM python:3.11-slim

ARG GITHUB_TOKEN

WORKDIR /app

RUN apt-get update && apt-get install -y \
    git \
    && rm -rf /var/lib/apt/lists/*

RUN pip install poetry

COPY pyproject.toml poetry.lock ./

RUN poetry config virtualenvs.create false

# Inject GitHub token into git config for private repo access
RUN git config --global url."https://${GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"

RUN poetry install --only main --no-root

# Remove token from git config before copying app code
RUN git config --global --unset url."https://${GITHUB_TOKEN}@github.com/".insteadOf

COPY . .

RUN poetry install --only main

EXPOSE 8000

CMD ["uvicorn", "geoassistant_api.main:app", "--host", "0.0.0.0", "--port", "8000"]

Key decisions in the Dockerfile:

  • ARG GITHUB_TOKEN — passed at build time only, never baked into the final image as a persistent layer.

  • Token is unset after poetry install to avoid leaking it into subsequent layers.

  • poetry config virtualenvs.create false — installs packages directly into the system Python inside the container, cleaner for Docker.

Building the Image#

docker buildx build --build-arg GITHUB_TOKEN=$env:GITHUB_TOKEN -t geoassistant-api .

Testing Locally#

docker run -p 8000:8000 --env-file .env geoassistant-api

Then visit http://localhost:8000/docs to verify FastAPI is running.

Pushing to Docker Hub#

docker tag geoassistant-api kamejoin/geoassistant-api
docker push kamejoin/geoassistant-api

Clearing Build Cache#

Docker caches build layers aggressively. If dependency changes aren’t being picked up:

docker buildx prune -f

Then rebuild from scratch.

Updating Dependencies#

When geoassistant or geogeometry have new commits on master, update the lock file in GeoAssistant before rebuilding:

# In the GeoAssistant repo
poetry update geogeometry

# In GeoAssistant-API repo
poetry update geoassistant

Then rebuild and push the Docker image.