Ship it and know the bill
Package your assistant so it runs the same anywhere, keep secrets out of the package, and work out what a request costs.
You build: A container image of your assistant with a health check, and a cost per request you measured.
- Docker
- Python 3.11 or newer and uv
- Lab 30 done
-
01Put the harness behind two HTTP routes: /health and /ask
curl -s localhost:8080/healthYou pass when: {"status":"ok"} from the server running on your machine.
-
02Write a Dockerfile and run the image with keys passed in at start
docker build -t parcel-desk . && docker run -d --name pd -p 8080:8080 --env-file .env parcel-desk && sleep 3 && curl -s localhost:8080/healthYou pass when: The same health answer, now from the container.
-
03Check that no key is inside the image
docker history --no-trunc parcel-desk | grep -c -i "api_key"; docker run --rm --entrypoint ls parcel-desk -aYou pass when: The count is 0 and no .env file is listed. Keys arrive when the container starts, never when it is built.
-
04Send 50 requests and work out the cost of one
uv run --with requests load.py --n 50You pass when: Average seconds and average cost per request, and what 1,000 requests a day would cost a month.
-
05Stop everything the course started
Leaving things running is how a free experiment becomes a bill. Make teardown the last step of every delivery.
docker rm -f pd learn-pg learn-qdrant; docker ps --format "{{.Names}}"You pass when: None of the lab containers are listed. Stop Langfuse with docker compose down in its folder.
The check runs on the computer, not on your word: a step passes when its command exits with 0 there.
Computers are not set up on this site yet. Run each command on your own machine and compare with "You pass when".
Commands run in labs/53-deploy and may take up to 60 seconds each. Every command starts a new shell: put keys and settings in a .env file there, it is loaded each time.