Skip to content

Commit 85d3673

Browse files
authored
Dev container configuration + README updates
2 parents edeb464 + f161b21 commit 85d3673

8 files changed

Lines changed: 408 additions & 60 deletions

File tree

.devcontainer/Dockerfile

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
FROM python:3.9-slim-bookworm
2+
3+
# Avoid prompts from apt
4+
ENV DEBIAN_FRONTEND=noninteractive
5+
6+
# Install system dependencies
7+
RUN apt-get update && apt-get install -y --no-install-recommends \
8+
git \
9+
curl \
10+
wget \
11+
make \
12+
gcc \
13+
g++ \
14+
libpq-dev \
15+
libgeos-dev \
16+
libproj-dev \
17+
postgresql-client \
18+
&& rm -rf /var/lib/apt/lists/*
19+
20+
# Set working directory
21+
WORKDIR /workspace
22+
23+
# Upgrade pip
24+
RUN pip install --upgrade pip setuptools wheel

.devcontainer/README.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Dev Container for c2corg v6_api
2+
3+
This directory contains a [Dev Container](https://containers.dev/) configuration
4+
that provides a fully configured development environment with all services
5+
(PostgreSQL/PostGIS, Elasticsearch, Redis) running as companion containers.
6+
7+
## Prerequisites
8+
9+
- [Docker Desktop](https://www.docker.com/products/docker-desktop/) (or a compatible Docker engine)
10+
- [VS Code](https://code.visualstudio.com/) with the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
11+
12+
## Getting started
13+
14+
1. Open this repository in VS Code
15+
2. When prompted, click **"Reopen in Container"** — or use the command palette:
16+
`Dev Containers: Reopen in Container`
17+
3. Wait for the container to build and the `postCreateCommand` setup script to
18+
finish (first run takes a few minutes)
19+
4. You're ready to go!
20+
21+
## What's included
22+
23+
| Service | Hostname | Port |
24+
|----------------|-----------------|------|
25+
| PostgreSQL | `postgresql` | 5432 |
26+
| Elasticsearch | `elasticsearch` | 9200 |
27+
| Redis | `redis` | 6379 |
28+
| API (when run) | `localhost` | 6543 |
29+
30+
All ports are forwarded to your host machine for convenience.
31+
32+
## Common commands
33+
34+
```bash
35+
# Run the test suite
36+
pytest
37+
38+
# Run a specific test file
39+
pytest c2corg_api/tests/models/test_book.py
40+
41+
# Run the linter
42+
flake8 c2corg_api es_migration
43+
44+
# Start the API server (with auto-reload)
45+
pserve development.ini --reload
46+
47+
# Or use make targets
48+
make test
49+
make serve
50+
make lint
51+
```
52+
53+
## Rebuilding
54+
55+
If dependencies change, rebuild the container:
56+
57+
- Command palette → `Dev Containers: Rebuild Container`
58+
59+
## Troubleshooting
60+
61+
- **Database errors**: The setup script creates both databases automatically. If you need to re-run:
62+
63+
```bash
64+
PGPASSWORD=test PGUSER=postgres PGHOST=postgresql \
65+
bash .devcontainer/setup.sh
66+
```
67+
68+
- **Elasticsearch not ready**: The setup script waits for ES, but if tests
69+
fail with connection errors, check: `curl http://elasticsearch:9200`
70+
71+
- **Config out of date**: Re-generate config files:
72+
73+
```bash
74+
bash .devcontainer/setup.sh
75+
```

.devcontainer/devcontainer.json

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"name": "c2corg v6_api",
3+
"dockerComposeFile": "docker-compose.yml",
4+
"service": "app",
5+
"workspaceFolder": "/workspace",
6+
7+
// VS Code settings
8+
"customizations": {
9+
"vscode": {
10+
"settings": {
11+
"python.defaultInterpreterPath": "/usr/local/bin/python",
12+
"python.testing.pytestEnabled": true,
13+
"python.testing.pytestArgs": ["c2corg_api/tests"],
14+
"python.linting.flake8Enabled": true,
15+
"editor.formatOnSave": true
16+
},
17+
"extensions": [
18+
"ms-python.python",
19+
"ms-python.vscode-pylance",
20+
"ms-python.flake8"
21+
]
22+
}
23+
},
24+
25+
// Forward ports for local access
26+
"forwardPorts": [6543, 9200, 6379, 5432],
27+
"portsAttributes": {
28+
"6543": { "label": "API Server" },
29+
"9200": { "label": "Elasticsearch" },
30+
"6379": { "label": "Redis" },
31+
"5432": { "label": "PostgreSQL" }
32+
},
33+
34+
// Run after the container is created (one-time setup)
35+
"postCreateCommand": "bash .devcontainer/setup.sh",
36+
37+
// Run every time the container starts
38+
"postStartCommand": "echo 'Dev container ready. Run: make test'"
39+
}

.devcontainer/docker-compose.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
services:
2+
app:
3+
build:
4+
context: .
5+
dockerfile: Dockerfile
6+
volumes:
7+
- ..:/workspace:cached
8+
command: sleep infinity
9+
depends_on:
10+
postgresql:
11+
condition: service_healthy
12+
elasticsearch:
13+
condition: service_started
14+
redis:
15+
condition: service_healthy
16+
environment:
17+
# Point services to their container hostnames
18+
PGHOST: postgresql
19+
PGUSER: postgres
20+
PGPASSWORD: test
21+
22+
postgresql:
23+
image: postgis/postgis:16-3.4
24+
environment:
25+
POSTGRES_USER: postgres
26+
POSTGRES_PASSWORD: test
27+
volumes:
28+
- postgres_data:/var/lib/postgresql/data
29+
- ..:/v6_api
30+
- ../docker/conf/postgresql.conf:/etc/postgresql.conf
31+
command: ["postgres", "-c", "config_file=/etc/postgresql.conf"]
32+
healthcheck:
33+
test: ["CMD", "pg_isready", "-U", "postgres"]
34+
interval: 10s
35+
timeout: 5s
36+
retries: 5
37+
38+
elasticsearch:
39+
image: "docker.io/c2corg/c2corg_es:anon-2018-11-02"
40+
command: -Des.index.number_of_replicas=0 -Des.path.data=/c2corg_anon -Des.script.inline=true
41+
ulimits:
42+
nofile:
43+
soft: 65536
44+
hard: 65536
45+
46+
redis:
47+
image: redis:7.2
48+
healthcheck:
49+
test: ["CMD", "redis-cli", "ping"]
50+
interval: 10s
51+
timeout: 5s
52+
retries: 5
53+
54+
volumes:
55+
postgres_data:

.devcontainer/setup.sh

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/bin/bash
2+
set -e
3+
4+
echo "==> Installing Python dependencies..."
5+
pip install -e ".[dev]"
6+
7+
echo "==> Copying env.local.sample to env.local (if not present)..."
8+
if [ ! -f config/env.local ]; then
9+
cp config/env.local.sample config/env.local
10+
fi
11+
12+
# Override hosts to point to docker-compose service names
13+
# (inside the devcontainer network, services are reachable by name)
14+
cat > config/env.devcontainer <<'EOF'
15+
#!/bin/sh
16+
version=0.0.0dev0
17+
db_host=postgresql
18+
tests_db_host=postgresql
19+
elasticsearch_host=elasticsearch
20+
redis_url=redis://redis:6379/
21+
EOF
22+
23+
echo "==> Generating config files from templates..."
24+
./scripts/env_replace config/env.default config/env.dev config/env.devcontainer < alembic.ini.in > alembic.ini
25+
./scripts/env_replace config/env.default config/env.dev config/env.devcontainer < common.ini.in > common.ini
26+
./scripts/env_replace config/env.default config/env.dev config/env.devcontainer < development.ini.in > development.ini
27+
./scripts/env_replace config/env.default config/env.dev config/env.devcontainer < test.ini.in > test.ini
28+
29+
echo "==> Waiting for PostgreSQL to be ready..."
30+
until pg_isready -h postgresql -U postgres; do
31+
echo " PostgreSQL not ready yet, retrying in 2s..."
32+
sleep 2
33+
done
34+
35+
echo "==> Initializing dev database..."
36+
export PGPASSWORD=test
37+
export PGUSER=postgres
38+
export PGHOST=postgresql
39+
export POSTGRES_USER=postgres
40+
41+
# Create dev database (adapted from scripts/database/create_schema.sh)
42+
DBNAME="c2corg"
43+
if psql -tAc "SELECT 1 FROM pg_database WHERE datname='${DBNAME}'" | grep -q 1; then
44+
echo " Dev database already exists: ${DBNAME}"
45+
else
46+
echo " Creating dev database: ${DBNAME}"
47+
psql -v ON_ERROR_STOP=1 --username "$PGUSER" <<SQL
48+
CREATE DATABASE ${DBNAME} OWNER "postgres";
49+
\c ${DBNAME}
50+
CREATE EXTENSION IF NOT EXISTS postgis;
51+
CREATE SCHEMA IF NOT EXISTS guidebook AUTHORIZATION "postgres";
52+
CREATE SCHEMA IF NOT EXISTS users AUTHORIZATION "postgres";
53+
CREATE SCHEMA IF NOT EXISTS sympa AUTHORIZATION "postgres";
54+
CREATE SCHEMA IF NOT EXISTS alembic AUTHORIZATION "postgres";
55+
SQL
56+
fi
57+
initialize_c2corg_api_db development.ini || true
58+
59+
# Create test database (adapted from scripts/database/create_test_schema.sh)
60+
echo "==> Initializing test database..."
61+
DBNAME="c2corg_tests"
62+
if psql -tAc "SELECT 1 FROM pg_database WHERE datname='${DBNAME}'" | grep -q 1; then
63+
echo " Test database already exists: ${DBNAME}"
64+
else
65+
echo " Creating test database: ${DBNAME}"
66+
psql -v ON_ERROR_STOP=1 --username "$PGUSER" <<SQL
67+
CREATE DATABASE ${DBNAME} OWNER "postgres";
68+
\c ${DBNAME}
69+
CREATE EXTENSION IF NOT EXISTS postgis;
70+
CREATE SCHEMA IF NOT EXISTS guidebook AUTHORIZATION "postgres";
71+
CREATE SCHEMA IF NOT EXISTS users AUTHORIZATION "postgres";
72+
CREATE SCHEMA IF NOT EXISTS sympa AUTHORIZATION "postgres";
73+
CREATE SCHEMA IF NOT EXISTS alembic AUTHORIZATION "postgres";
74+
SQL
75+
fi
76+
77+
echo "==> Waiting for Elasticsearch to be ready..."
78+
until curl -s http://elasticsearch:9200 > /dev/null 2>&1; do
79+
echo " Elasticsearch not ready yet, retrying in 5s..."
80+
sleep 5
81+
done
82+
83+
echo "==> Initializing Elasticsearch indexes..."
84+
fill_es_index development.ini || true
85+
86+
echo ""
87+
echo "============================================="
88+
echo " Dev container setup complete!"
89+
echo ""
90+
echo " Run the API: pserve development.ini --reload"
91+
echo " Run tests: pytest"
92+
echo " Run linter: flake8 c2corg_api es_migration"
93+
echo " Or use make: make test / make serve / make lint"
94+
echo "============================================="

0 commit comments

Comments
 (0)