Files
Manuel de la Peña 36d384d2da docs(guides): add two testcontainers intro guides (go and python) (#24450)
## Description

Migrate the first two Testcontainers getting-started guides from
[testcontainers.com/guides](https://testcontainers.com/guides/) into the
Docker docs site:

- **Getting started with Testcontainers for Go** — multi-page guide with
4 chapters (create project, write tests, test suites, run tests). Code
updated to testcontainers-go v0.41.0 API (`postgres.Run()`,
`CleanupContainer`, `BasicWaitStrategies()`).
- **Getting started with Testcontainers for Python** — multi-page guide
with 3 chapters (create project, write tests, run tests). Code updated
to testcontainers-python 4.14.2 (fixed `get_exposed_port()` returning
`int`).

Each guide appears as its own entry in the `/guides/` listing with
proper language and tag filters (`testing-with-docker`). Chapters render
with stepper navigation in the sidebar.

Also adds:
- A `testing-with-docker` tag to `data/tags.yaml`
- A Claude skill
(`.claude/skills/testcontainers-guides-migrator/SKILL.md`) that
documents the repeatable migration process for the remaining 19 guides
- Links from `content/manuals/testcontainers.md` to the new guides
- Vale vocabulary entries for `pgx`, `Micronaut`, `psycopg`, `pytest`

All guide code was compiled and tests verified passing in containers
with Docker socket mounted.

## Related issues or tickets

No related issues found.

## Reviews

- [ ] Technical review
- [ ] Editorial review
- [ ] Product review
2026-03-23 13:58:19 +00:00

131 lines
3.7 KiB
Markdown

---
title: Create the Python project
linkTitle: Create the project
description: Set up a Python project with a PostgreSQL-backed customer service.
weight: 10
---
## Initialize the project
Start by creating a Python project with a virtual environment:
```console
$ mkdir tc-python-demo
$ cd tc-python-demo
$ python3 -m venv venv
$ source venv/bin/activate
```
This guide uses [psycopg3](https://www.psycopg.org/psycopg3/) to interact
with the Postgres database, [pytest](https://pytest.org/) for testing, and
[testcontainers-python](https://testcontainers-python.readthedocs.io/) for
running a PostgreSQL database in a container.
Install the dependencies:
```console
$ pip install psycopg pytest testcontainers[postgres]
$ pip freeze > requirements.txt
```
The `pip freeze` command generates a `requirements.txt` file so that others
can install the same package versions using `pip install -r requirements.txt`.
## Create the database helper
Create a `db/connection.py` file with a function to get a database connection:
```python
import os
import psycopg
def get_connection():
host = os.getenv("DB_HOST", "localhost")
port = os.getenv("DB_PORT", "5432")
username = os.getenv("DB_USERNAME", "postgres")
password = os.getenv("DB_PASSWORD", "postgres")
database = os.getenv("DB_NAME", "postgres")
return psycopg.connect(f"host={host} dbname={database} user={username} password={password} port={port}")
```
Instead of hard-coding the database connection parameters, the function uses
environment variables. This makes it possible to run the application in
different environments without changing code.
## Create the business logic
Create a `customers/customers.py` file and define the `Customer` class:
```python
class Customer:
def __init__(self, cust_id, name, email):
self.id = cust_id
self.name = name
self.email = email
def __str__(self):
return f"Customer({self.id}, {self.name}, {self.email})"
```
Add a `create_table()` function to create the `customers` table:
```python
from db.connection import get_connection
def create_table():
with get_connection() as conn:
with conn.cursor() as cur:
cur.execute("""
CREATE TABLE customers (
id serial PRIMARY KEY,
name varchar not null,
email varchar not null unique)
""")
conn.commit()
```
The function obtains a database connection using `get_connection()` and creates
the `customers` table. The `with` statement automatically closes the connection
when done.
Add the remaining CRUD functions:
```python
def create_customer(name, email):
with get_connection() as conn:
with conn.cursor() as cur:
cur.execute(
"INSERT INTO customers (name, email) VALUES (%s, %s)", (name, email))
conn.commit()
def get_all_customers() -> list[Customer]:
with get_connection() as conn:
with conn.cursor() as cur:
cur.execute("SELECT * FROM customers")
return [Customer(cid, name, email) for cid, name, email in cur]
def get_customer_by_email(email) -> Customer:
with get_connection() as conn:
with conn.cursor() as cur:
cur.execute("SELECT id, name, email FROM customers WHERE email = %s", (email,))
(cid, name, email) = cur.fetchone()
return Customer(cid, name, email)
def delete_all_customers():
with get_connection() as conn:
with conn.cursor() as cur:
cur.execute("DELETE FROM customers")
conn.commit()
```
> [!NOTE]
> To keep it straightforward for this guide, each function creates a new
> connection. In a real-world application, use a connection pool to reuse
> connections.