VIT Students: Building a Demo-Ready Python Backend Internship Project with Docker and Tests

Facebook
Twitter
LinkedIn
WhatsApp
Email

A demo-ready Python backend project is one that a reviewer can start with a single command, see pass its tests, and exercise through a prepared Postman collection in under ten minutes. For VIT students, the way to get there is a small API with a clear scope, a Dockerfile and Compose file, an automated test suite, a seeded database, and a rehearsed walkthrough script.

This guide covers each of those pieces with illustrative code and a scorecard you can use to grade your own project before you present it.

What “demo-ready” actually means

Many student backends work on the author’s laptop and nowhere else. A demo-ready project removes that risk. Judge it by five questions:

  1. Does it start cleanly? A fresh clone should run with one documented command, with no manual database setup and no hidden environment variables.
  2. Does it have data? An empty API makes a dull demo. Seed data lets you show lists, filters, errors and relationships immediately.
  3. Is it verifiable? Automated tests show that behaviour is checked, not just claimed.
  4. Is it explorable by a non-author? A Postman collection lets a reviewer call endpoints without reading your code.
  5. Can you explain it in five minutes? A written walkthrough script keeps you on the path that works.

Scope matters as much as tooling. Two or three related resources, implemented well, impress more than ten half-working ones.

Step 1: Choose a small, demonstrable scope

Pick a domain you can describe in one sentence and that needs at least one relationship between tables. Good examples include a club event registration API, a lab equipment booking service, a bookstore inventory service, or a task tracker with users and projects. Avoid anything that needs paid third-party services, because a demo that depends on an external key can fail on the day.

Aim for this minimum feature set:

  • Two or three resources, for example users, events and registrations.
  • Create, read, update and delete for the main resource.
  • One business rule that can be rejected, such as “an event cannot exceed its capacity”.
  • Input validation with clear error messages.
  • Token or API-key authentication on write endpoints, if time allows.
  • A health-check endpoint, which Docker and reviewers can both use.

Free 2-Week CareerSwami Internship

Online, 14 days, with a free offer letter and a free completion certificate once you finish the work. Check with your college that it fits your requirement before you enrol.

Apply for the free internship

Step 2: Lay out the repository

A predictable structure tells a reviewer where to look. The layout below is illustrative, using FastAPI, SQLAlchemy and PostgreSQL. Flask or Django would work equally well.

event-api/
  app/
    main.py
    models.py
    schemas.py
    crud.py
    database.py
    seed.py
  tests/
    conftest.py
    test_events.py
    test_registrations.py
  postman/
    event-api.postman_collection.json
    local.postman_environment.json
  Dockerfile
  docker-compose.yml
  requirements.txt
  .env.example
  .dockerignore
  README.md
  DEMO.md

Commit .env.example with dummy values and keep real secrets out of version control. A reviewer should be able to copy the file and run the project.

Step 3: Write the Dockerfile

The goal is a small, reproducible image that runs as a non-root user. This is an illustrative Dockerfile for a FastAPI app. It has not been executed here, so build it yourself and fix anything your own setup needs.

FROM python:3.12-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1

WORKDIR /code

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY app ./app

RUN useradd --create-home appuser
USER appuser

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

Points worth being able to explain in a viva or review:

  • Dependencies are copied before the code. Docker caches layers, so editing a source file does not reinstall every package.
  • Versions are pinned in requirements.txt. This stops a new library release from breaking the demo.
  • The host is 0.0.0.0. Binding to localhost inside a container makes the app unreachable from outside it.
  • A .dockerignore file should exclude .git, __pycache__, virtual environments and .env.

Step 4: Add Docker Compose for the database

Compose runs the API and the database together. Add a health check on the database so the API does not start before it is ready.

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: ${DB_NAME}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
      interval: 5s
      timeout: 3s
      retries: 10
    volumes:
      - pgdata:/var/lib/postgresql/data

  api:
    build: .
    env_file: .env
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "8000:8000"

volumes:
  pgdata:

Inside Compose, the database host is the service name, db, not localhost. This is the most common reason a containerised API fails to connect. Your DATABASE_URL should therefore look like postgresql://user:password@db:5432/dbname.

Step 5: Seed the database deliberately

Seed data is part of the demo script. Design it to show something, not just to fill rows.

  • Include one event that is almost full, so you can demonstrate the capacity rule triggering.
  • Include one event that is already past, to show filtering.
  • Include a user with several registrations and a user with none.
  • Use obviously fake names and emails. Do not load real student data.
  • Make the seed script idempotent, so running it twice does not create duplicates.
def seed(db):
    if db.query(User).count() > 0:
        return
    users = [User(name="Demo Admin", email="admin@example.com"),
             User(name="Demo Student", email="student@example.com")]
    db.add_all(users)
    db.flush()
    db.add(Event(title="Almost Full Workshop", capacity=2, owner_id=users[0].id))
    db.commit()

Run seeding on startup in demo mode, controlled by an environment flag such as SEED_ON_START=true. Also provide a documented command to reset the database, for example docker compose down -v followed by docker compose up --build.

Step 6: Build a test suite that earns trust

Use pytest with the framework’s test client. Test against a separate test database or an in-memory SQLite database. Never test against the database you demo with.

Cover these categories:

  • Happy path: create, fetch, update and delete the main resource.
  • Validation: a missing field or malformed email returns a 422 or 400 response, not a 500.
  • Business rule: registering for a full event is rejected with a clear message.
  • Not found: requesting a missing id returns 404.
  • Authorisation: a write request without a token is rejected.
  • Idempotence or duplicates: registering the same user twice is handled.

An illustrative test for the capacity rule:

def test_registration_rejected_when_event_full(client, full_event, new_user):
    response = client.post(
        f"/events/{full_event.id}/registrations",
        json={"user_id": new_user.id},
    )
    assert response.status_code == 409
    assert "capacity" in response.json()["detail"].lower()

Fixtures in conftest.py should create a fresh database for each test, so tests do not depend on run order. Add a one-line command to your README, such as docker compose run --rm api pytest, so tests run in the same environment as the app. Run this yourself before presenting and quote the real result. Do not state a pass count you have not seen.

Step 7: Prepare the Postman collection

Postman turns your API into something a reviewer can click through. Build the collection in the order of your walkthrough, not alphabetically.

  • Use a collection or environment variable such as {{base_url}} so the host can change without editing requests.
  • Name requests as actions: “1. Health check”, “2. List events”, “3. Register (success)”, “4. Register (full event, expect 409)”.
  • Add short Tests scripts to check status codes, so a green tick appears during the demo.
  • Store the login token in a variable automatically after the login request.
  • Add a description to the collection with the run order and the seeded credentials.
  • Export the collection and environment JSON files into the postman/ folder and commit them.

Also expose the framework’s interactive documentation page (FastAPI provides /docs by default) as a backup if Postman fails to open.

Step 8: Write the walkthrough script

A walkthrough script is a numbered list in DEMO.md. It keeps the presentation controlled and gives you a recovery path if something breaks. A five-to-seven-minute structure works well:

  1. Problem (30 seconds): one sentence on what the API does and who would use it.
  2. Start (45 seconds): run docker compose up --build and show the containers healthy.
  3. Explore (90 seconds): open Postman, call health and list endpoints, and point out the seeded data.
  4. Write path (90 seconds): log in, create a registration, and fetch it back.
  5. Failure path (60 seconds): trigger the full-event rule and show the 409 with its message.
  6. Tests (60 seconds): run the test command and show the output.
  7. Design notes (60 seconds): explain two decisions, for example why a unique constraint backs the duplicate check, and what you would add next.

Rehearse with a stopwatch, and rehearse once on a different machine or after a clean reset. Build the images before the session, because a first-time image download over a slow network is a common cause of demo delays.

Demo-readiness scorecard

Grade each item from 0 to 2: 0 for missing, 1 for partial, 2 for complete. A total of 24 is the maximum. Fix any zero before polishing a two.

Area What a 2 looks like Your score (0-2)
One-command start A fresh clone runs with docker compose up --build and nothing else
Image quality Slim base image, pinned dependencies, non-root user, .dockerignore present
Configuration All settings come from environment variables, with .env.example committed
Database readiness Health check or retry logic, so the API never starts before the database
Seed data Idempotent seed with deliberate edge cases and a documented reset
Test coverage of behaviour Happy path, validation, business rule, 404 and auth cases are all tested
Test isolation Separate test database, fresh state per test, one documented command
Error handling Consistent JSON errors with correct status codes, no stack traces exposed
Postman collection Ordered requests, variables, status-code checks, exported to the repo
API documentation Interactive docs or README endpoint table, with example requests
README and DEMO.md Prerequisites, run, test, reset and demo steps all written and checked
Rehearsal Timed run completed from a clean reset, with a fallback if Postman fails

Interpret the total as follows: 20 to 24 is ready to present, 14 to 19 needs a focused fix day, and below 14 means reduce scope before adding features.

Worked example (illustrative): grading a first draft

The following is an invented scenario to show how the scorecard works. It is not a real student’s project.

A student builds a lab equipment booking API with endpoints for equipment, users and bookings. The first draft runs locally with a virtual environment, uses SQLite, has no tests and has a Postman collection with requests in random order. Scoring it honestly might give: one-command start 0, image quality 0, configuration 1, database readiness 1 (SQLite needs none), seed data 0, test coverage 0, test isolation 0, error handling 1, Postman 1, documentation 1, README 1, rehearsal 0. The total is 6 out of 24.

The student then works through the zeros in a sensible order:

  1. Write the Dockerfile and Compose file, and move to PostgreSQL. This lifts the start, image and database rows.
  2. Write a seed script with one booking that already conflicts with a time slot.
  3. Add six tests: create booking, list bookings, overlapping booking rejected, invalid time range, unknown equipment id, and missing token.
  4. Reorder the Postman requests to match a seven-step script, and add status checks.
  5. Write DEMO.md and rehearse twice from a clean reset.

The overlapping-booking rule becomes the centrepiece of the demo. The student shows the conflict being rejected in Postman, then shows the same rule covered by an automated test. That pairing communicates engineering judgement better than a long feature list.

Common failure points and fixes

  • “Connection refused” to the database: the host is set to localhost instead of db, or the API started before the database was ready.
  • Port already in use: a local server or old container is holding port 8000 or 5432. Stop it or remap the port in Compose.
  • Stale data after changes: the volume kept the old schema. Reset with docker compose down -v.
  • Tests pass locally but fail in the container: an undeclared dependency is missing from requirements.txt. Add a separate requirements-dev.txt for pytest and install it in the test run.
  • Secrets in the repository: rotate anything committed by mistake and add the file to .gitignore.
  • Slow first start: pre-pull images and pre-build before the session begins.

VIT and the Docker-and-tests backend demo: what to settle before review day

VIT is a large university with several campuses and many programmes. Internship, project and presentation requirements can differ by programme, school, batch and campus, so a rule heard from a senior in another branch or campus may not apply. The Docker, test and Postman work in this guide is technical and stays the same everywhere. How it is assessed is what varies.

Four practical points follow for a student building a Python backend project:

  • Submission format. Some evaluations expect a report, slides or a logbook alongside the working project. Keep the repository README and any written summary consistent, and be ready to explain every file, including the Dockerfile and the seed script.
  • Demo environment. Lab machines or evaluation rooms may not have Docker installed, or may restrict it. Prepare a fallback: a screen recording of the Compose run, plus a plain virtual-environment command in the README that starts the API against a local database.
  • Individual contribution. In a team project, keep a clear commit history and a short note on who built which endpoints, tests and containers, so each person’s part is visible.
  • Time slots. Review slots are often short. The seven-minute walkthrough script can be cut to three minutes by dropping the design notes and shortening the Postman exploration.

One free option for practising this kind of work is the CareerSwami free two-week online internship, a 14-day programme across 26 tracks that includes a free offer letter and a free completion certificate after successful completion. It is an independent programme with no connection to VIT. Whether any external internship counts toward a requirement at your university is a question for your own department.

Questions to put to your VIT coordinator before building the demo

  • Ask your faculty guide or project coordinator for the written marking rubric, and check whether it rewards running software, a report, or both.
  • Ask your school’s coordinator or the training and placement office whether a self-arranged or online internship needs prior approval, a form or a letter, and by what date. Request the answer by email.
  • Ask what proof is accepted for an online internship (offer letter, certificate, report, supervisor sign-off) and whether it counts toward your programme’s requirement.
  • Ask about the presentation format and time limit, and whether you may use your own laptop, internet access and Docker in the evaluation room.
  • Ask whether code must be submitted as a repository link, a zip file or both, and whether a report template is mandatory.
  • Read the academic integrity policy on open-source code and generative tools, and note what must be cited in the README.

Final pre-demo checklist

  • Clone the repository into a new folder and run it from scratch.
  • Run the full test command and note the actual output.
  • Reset the database and confirm the seed data appears.
  • Run the Postman collection top to bottom.
  • Check that no secrets, personal data or debug output appear in the repository or on screen.
  • Close unrelated browser tabs, notifications and terminals.
  • Keep a backup: a screen recording, screenshots, and the repository on a second device or cloud link.

Frequently Asked Questions

Do I need Docker for a Python backend project to be taken seriously?

Not always, but it removes the “works on my machine” problem and makes your setup reproducible. If your evaluation environment cannot run Docker, keep clear non-Docker instructions in the README as well.

Which framework suits a Docker-and-tests internship demo: Flask, FastAPI or Django?

Any of them is fine. FastAPI gives automatic interactive documentation and type-based validation with little code. Flask is minimal and flexible, and Django includes an ORM, admin and authentication. Choose the one you can explain confidently.

How many tests are enough for a student project?

Aim for meaningful coverage of behaviour, not a number. Between 10 and 20 well-chosen tests across happy paths, validation errors, the main business rule and authorisation usually tell a reviewer more than a high percentage reached with trivial tests.

Is SQLite acceptable instead of PostgreSQL?

For tests, yes. For the demo, PostgreSQL in Compose shows that you can work with a real database service, but SQLite is acceptable when scope or time is tight. Say which you chose and why.

How do I handle secrets in a demo project?

Keep real credentials out of Git, commit a .env.example with placeholder values, and read configuration from environment variables. Use throwaway passwords for the demo database.

What if Postman or Docker fails during the presentation?

Have a fallback ready: the framework’s built-in docs page for calling endpoints, curl commands in DEMO.md, and a short screen recording of a successful run. Mention calmly what failed and carry on with the backup.

Can I put this project on my resume or GitHub?

Yes. A clean README, a test command, a Postman collection and a short architecture note make a repository easy for others to evaluate. Describe what you built accurately, and do not claim features that are not in the code.

Will a CareerSwami internship certificate count for my VIT requirements?

That cannot be assumed. CareerSwami offers a free completion certificate after successful completion, but acceptance for any university requirement is decided by your department, so ask your coordinator in writing before relying on it.

Related Python & Backend Engineering guides

Ready to put this into practice?

Join the free two-week CareerSwami online internship in Python & Backend Engineering. The internship, the offer letter and the completion certificate are free.

Start your free 2-week internship

Web Stories

Scroll to Top