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
reposcopeDocker Hub account (username:
kamejoin)
Generating a GitHub PAT#
Go to GitHub → Settings → Developer Settings → Personal Access Tokens → Tokens (classic)
Generate a new token with
reposcopeCopy the token — GitHub only shows it once
Store it in your
.envfile:
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 installto 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.