From HTTP 201 to Persistent Docker Data
Today, Nicola’s independent MyZubster MVP reached another concrete milestone.
The goal was simple to describe:
Clone the repository, start it with Docker, create an observation and prove that the data survives a complete container shutdown and recreation.
We completed that cycle on Nicola’s Windows computer.
This was not only a CI test.
It was a real local installation, performed step by step and supported by visible evidence.
Where we started
The project already had a verified API workflow:
Create observation → HTTP 201 → JSON persistence → API retrieval → automated test
That work was reviewed and merged through a public pull request:
PR #1 — Verify observation creation, persistence and retrieval
The next challenge was reproducibility.
Could Nicola clone the repository on his own computer and run the application without manually configuring Python and its dependencies?
Adding Docker
We created a second development branch and added:
- a Python slim Docker image;
- a non-root application user;
- Docker Compose configuration;
- a persistent volume for observations;
- an API health check;
- configurable host, port and data-file location;
- Windows-friendly setup documentation;
- an automated Docker test in GitHub Actions.
The Docker configuration was proposed in:
PR #2 — Add reproducible Docker setup for local development
The CI workflow built the image, started the container, created an observation and retrieved it successfully.
After the CI passed, the pull request was merged into main.
The first local obstacle
Nicola cloned the repository successfully:
git clone https://github.com/nicolaususnicola-lgtm/myzubster-mvp.git
cd myzubster-mvp
But the first Docker command failed:
failed to connect to the docker API at
npipe:////./pipe/dockerDesktopLinuxEngine
This error was not caused by MyZubster.
The Docker command-line tools were installed, but the Docker Desktop Linux engine was not running.
We verified WSL:
wsl --version
wsl --status
wsl --update
wsl --shutdown
The machine had:
- WSL 2;
- an updated Linux kernel;
- eight CPUs;
- approximately 15.5 GB of memory;
- the
desktop-linuxDocker context.
After starting Docker Desktop, both the Docker client and server became available.
Building the application locally
Nicola then ran:
docker compose up --build -d
docker compose ps
The image was built and the API container started successfully.
We verified the initial state:
Invoke-RestMethod http://localhost:5000/api/observations
Then we created the first local observation:
$body = @{
description = "Prima osservazione Docker di Nicola"
latitude = 44.0678
longitude = 12.5695
} | ConvertTo-Json
Invoke-RestMethod `
-Method Post `
-Uri http://localhost:5000/api/observation `
-ContentType "application/json" `
-Body $body
The API returned a new observation with:
- a generated ID;
- the submitted description;
- latitude and longitude;
- an empty optional media hash;
- a UTC timestamp.
The generated observation ID was:
b8e8d66b9bf5bd16
Verifying the saved data
We retrieved the observations through the API:
Invoke-RestMethod http://localhost:5000/api/observations |
ConvertTo-Json -Depth 5
The result contained:
{
"count": 1,
"observations": [
{
"coordinates": {
"lat": 44.0678,
"lng": 12.5695
},
"description": "Prima osservazione Docker di Nicola",
"id": "b8e8d66b9bf5bd16",
"media_hash": "",
"timestamp": "2026-09-02T08:51:57.067451+00:00"
}
]
}
At this point, creation and retrieval worked.
But that alone did not prove persistence.
Test one: container restart
We restarted only the API service:
docker compose restart api
After the container returned, we queried the API again.
The response still contained:
count: 1
id: b8e8d66b9bf5bd16
The observation survived the container restart.
Test two: complete Compose shutdown
The more important test was a complete Compose shutdown.
We ran:
docker compose down
The first stop required Docker to terminate the development server after its timeout. The container exited with code 137.
That behavior is not ideal, and it revealed the next technical improvement: replace Flask’s development server with a production-oriented WSGI server such as Gunicorn.
However, the container was stopped and the persistent volume remained available:
docker volume ls | Select-String "observations"
Result:
local myzubster-mvp_observations-data
No -v option was used, so Docker did not delete the data volume.
Test three: recreate the environment
We recreated the network and container:
docker compose up -d
Then we queried the API once more:
Invoke-RestMethod http://localhost:5000/api/observations |
ConvertTo-Json -Depth 5
The same observation was still present:
count: 1
id: b8e8d66b9bf5bd16
This completed the full persistence test:
Create → Save → Restart → Read → Down → Recreate → Read again
What we can now verify
Nicola’s MVP now has evidence for the following claims:
- the repository can be cloned on Windows;
- the application can be built with Docker;
- Docker Compose starts the API;
- the health check confirms availability;
- a valid observation returns HTTP 201;
- the observation is persisted;
- the API retrieves the saved observation;
- the data survives a service restart;
- the data survives container and network recreation;
- the process does not require sharing passwords or tokens.
This does not make the application production-ready.
It makes one capability reproducible and verifiable.
That distinction is central to the MyZubster experiment.
One human, one AI, public evidence
The collaboration model is:
one human + one AI
Nicola controls his project and performs the local actions.
Zorgax assists with:
- repository inspection;
- implementation planning;
- code changes;
- validation;
- troubleshooting;
- documentation;
- evidence collection.
GitHub, automated tests and local execution provide independent signals that the workflow actually works.
The AI does not replace human approval, and passing tests do not automatically turn an MVP into a production system.
The next improvement
The logs clearly warned us:
WARNING: This is a development server.
Do not use it in a production deployment.
The next technical step is therefore to:
- introduce Gunicorn inside the Linux container;
- verify graceful shutdown;
- repeat the
down → uppersistence test; - add the result to GitHub Actions;
- document the difference between development and deployment configurations.
The broader experiment
MyZubster is exploring whether an ecosystem can expand through independent, verified projects instead of only accumulating registered users.
Nicola’s MVP is a small example of that model.
It began as an independent repository.
It now provides a working observation capability with public code, automated tests, Docker packaging and locally reproduced evidence.
The development loop remains:
Build → Validate → Connect → Measure → Verify → Replicate → Expand
Today, Nicola completed the first five steps for one capability.
That is a small result.
But it is real, repeatable and public.
MyZubster — Open-source ecosystem
Zorgax — AI intelligence and coordination layer
Principle — Human-controlled, evidence-driven development
Nicola’s repository:
github.com/nicolaususnicola-lgtm/myzubster-mvp
Main ecosystem:
github.com/MyZubster-Ecosystem/myzubster
Website:
myzubster.com
What is the smallest capability in your project that you could make independently reproducible and verifiable today?
Top comments (0)