diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 000000000..7a8620bea
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,13 @@
+FROM node:20-slim
+
+WORKDIR /usr/src/app
+
+# Install dependencies first to leverage Docker layer caching
+COPY package*.json ./
+RUN npm install --omit=dev
+
+COPY . .
+
+EXPOSE 3000
+
+CMD ["npm", "start"]
diff --git a/Note.js b/Note.js
new file mode 100644
index 000000000..07d38bc91
--- /dev/null
+++ b/Note.js
@@ -0,0 +1,11 @@
+const mongoose = require('mongoose');
+
+const noteSchema = new mongoose.Schema(
+ {
+ title: { type: String, required: true },
+ content: { type: String, default: '' },
+ },
+ { timestamps: true }
+);
+
+module.exports = mongoose.model('Note', noteSchema);
diff --git a/README.md b/README.md
index 86f9adc2b..21cca9126 100644
--- a/README.md
+++ b/README.md
@@ -1,121 +1,79 @@
-# Awesome Compose [](https://awesome.re)
-
-
-
-> A curated list of Docker Compose samples.
-
-These samples provide a starting point for how to integrate different services using a Compose file and to manage their deployment with Docker Compose.
-
-> **Note**
-> The following samples are intended for use in local development environments such as project setups, tinkering with software stacks, etc. These samples must not be deployed in production environments.
-
-
-## Contents
-
-- [Samples of Docker Compose applications with multiple integrated services](#samples-of-docker-compose-applications-with-multiple-integrated-services).
-- [Single service samples](#single-service-samples).
-- [Basic setups for different platforms (not production ready - useful for personal use)](#basic-setups-for-different-platforms-not-production-ready---useful-for-personal-use).
-
-## Samples of Docker Compose applications with multiple integrated services
-
-
Icon indicates Sample is compatible with [Docker+Wasm](https://docs.docker.com/desktop/wasm/).
-
-- [`ASP.NET / MS-SQL`](aspnet-mssql) - Sample ASP.NET core application
-with MS SQL server database.
-- [`Elasticsearch / Logstash / Kibana`](elasticsearch-logstash-kibana) - Sample Elasticsearch, Logstash, and Kibana stack.
-- [`Go / NGINX / MySQL`](nginx-golang-mysql) - Sample Go application
-with an Nginx proxy and a MySQL database.
-- [`Go / NGINX / PostgreSQL`](nginx-golang-postgres) - Sample Go
-application with an Nginx proxy and a PostgreSQL database.
-- [`Java Spark / MySQL`](sparkjava-mysql) - Sample Java application and
-a MySQL database.
-- [`NGINX / ASP.NET / MySQL`](nginx-aspnet-mysql) - Sample Nginx reverse proxy with an C# backend using ASP.NET.
-- [`NGINX / Flask / MongoDB`](nginx-flask-mongo) - Sample Python/Flask
-application with Nginx proxy and a Mongo database.
-- [`NGINX / Flask / MySQL`](nginx-flask-mysql) - Sample Python/Flask application with an Nginx proxy and a MySQL database.
-- [`NGINX / Node.js / Redis`](nginx-nodejs-redis) - Sample Node.js application with Nginx proxy and a Redis database.
-- [`NGINX / Go`](nginx-golang) - Sample Nginx proxy with a Go backend.
-- [`NGINX / WSGI / Flask`](nginx-wsgi-flask) - Sample Nginx reverse proxy with a Flask backend using WSGI.
-- [`PostgreSQL / pgAdmin`](postgresql-pgadmin) - Sample setup for postgreSQL database with pgAdmin web interface.
-- [`Python / Flask / Redis`](flask-redis) - Sample Python/Flask and a Redis database.
-- [`React / Spring / MySQL`](react-java-mysql) - Sample React
-application with a Spring backend and a MySQL database.
-- [`React / Express / MySQL`](react-express-mysql) - Sample React
-application with a Node.js backend and a MySQL database.
-- [`React / Express / MongoDB`](react-express-mongodb) - Sample React
-application with a Node.js backend and a Mongo database.
-- [`React / Rust / PostgreSQL`](react-rust-postgres) - Sample React
-application with a Rust backend and a Postgres database.
-- [`React / Nginx`](react-nginx) - Sample React application with Nginx.
-- [`Spring / PostgreSQL`](spring-postgres) - Sample Java application
-with Spring framework and a Postgres database.
-- [`WasmEdge / MySQL / Nginx`](wasmedge-mysql-nginx) - Sample Wasm-based web application with a static HTML frontend, using a MySQL (MariaDB) database. The frontend connects to a Wasm microservice written in Rust, that runs using the WasmEdge runtime.
-- [`WasmEdge / Kafka / MySQL`](wasmedge-kafka-mysql) - Sample Wasm-based microservice that subscribes to a Kafka (Redpanda) queue topic, and transforms and saves any incoming message into a MySQL (MariaDB) database.
-
-## Single service samples
-
-- [`Angular`](angular)
-- [`Spark`](sparkjava)
-- [`VueJS`](vuejs)
-- [`Flask`](flask)
-- [`PHP`](apache-php)
-- [`Traefik`](traefik-golang)
-- [`Django`](django)
-- [`Minecraft server`](https://github.com/docker/awesome-compose/tree/master/minecraft)
-- [`Plex`](https://github.com/docker/awesome-compose/tree/master/plex)
-- [`Portainer`](https://github.com/docker/awesome-compose/tree/master/portainer)
-- [`Wireguard`](https://github.com/docker/awesome-compose/tree/master/wireguard)
-- [`FastAPI`](fastapi)
-
-## Basic setups for different platforms (not production ready - useful for personal use)
-
-- [`Gitea / PostgreSQL`](gitea-postgres)
-- [`Nextcloud / PostgreSQL`](nextcloud-postgres)
-- [`Nextcloud / Redis / MariaDB`](nextcloud-redis-mariadb)
-- [`Pi-hole / cloudflared`](pihole-cloudflared-DoH) - Sample Pi-hole setup with use of DoH cloudflared service
-- [`Prometheus / Grafana`](prometheus-grafana)
-- [`Wordpress / MySQL`](wordpress-mysql)
-
-
-
-## Getting started
-
-These instructions will get you through the bootstrap phase of creating and
-deploying samples of containerized applications with Docker Compose.
-
-### Prerequisites
-
-- Make sure that you have Docker and Docker Compose installed
- - Windows or macOS:
- [Install Docker Desktop](https://www.docker.com/get-started)
- - Linux: [Install Docker](https://www.docker.com/get-started) and then
- [Docker Compose](https://github.com/docker/compose)
-- Download some or all of the samples from this repository.
-
-### Running a sample
-
-The root directory of each sample contains the `compose.yaml` which
-describes the configuration of service components. All samples can be run in
-a local environment by going into the root directory of each one and executing:
-
-```console
-docker compose up -d
+# Express application with MongoDB database
+
+## App diagram
+
+The compose file defines an application with two services: `backend` and `mongo`.
+
+When deploying the application, `docker compose` maps port 3000 of the `backend`
+service container to port 3000 of the host as specified in the `compose.yaml`
+file.
+
+Make sure port 3000 on the host is not already in use.
+
+## Deploy with docker compose
+
+```shell
+$ docker compose up -d
+```
+
+Expected result: listing containers must show two containers running and
+healthy. Healthcheck isn't enabled by default, but the logs should show the
+server listening and connected to MongoDB.
+
+```shell
+$ docker compose ps
+
+NAME IMAGE COMMAND SERVICE STATUS
+backend express-mongodb-backend "docker-entrypoint.s…" backend running
+mongo mongo:7 "docker-entrypoint.s…" mongo running
+```
+
+After the application starts, navigate to `http://localhost:3000` in your web
+browser or run:
+
+```shell
+$ curl http://localhost:3000
+{"message":"Express + MongoDB API is running"}
+```
+
+### Try the API
+
+Create a note:
+
+```shell
+$ curl -X POST http://localhost:3000/notes \
+ -H "Content-Type: application/json" \
+ -d '{"title": "First note", "content": "Hello from MongoDB"}'
+```
+
+List notes:
+
+```shell
+$ curl http://localhost:3000/notes
```
-Check the `README.md` of each sample to get more details on the structure and
-what is the expected output.
-To stop and remove all containers of the sample application run:
+Stop and remove the containers:
-```console
-docker compose down
+```shell
+$ docker compose down
```
-### Quickstart guides
+## Expected result
+
+Listing containers must show two containers running and healthy:
-In addition to all the ready to run Compose samples listed above the folder [official-documentation-samples](official-documentation-samples/README.md) contains quickstart guides. Each of these step by step guides explain which files need to be created to build and run a Docker Compose application.
+```shell
+$ docker compose ps
+NAME IMAGE COMMAND SERVICE STATUS
+backend express-mongodb-backend "docker-entrypoint.s…" backend running
+mongo mongo:7 "docker-entrypoint.s…" mongo running
+```
+
+After the application starts, you can use the API endpoints described above
+to create, list, update, and delete notes stored in MongoDB.
-
-## Contribute
+Stop and remove the containers with:
-We welcome examples that help people understand how to use Docker Compose for
-common applications. Check the [Contribution Guide](CONTRIBUTING.md) for more details.
+```shell
+$ docker compose down
+```
diff --git a/compose.yaml b/compose.yaml
new file mode 100644
index 000000000..f82844976
--- /dev/null
+++ b/compose.yaml
@@ -0,0 +1,25 @@
+services:
+ backend:
+ build:
+ context: backend
+ container_name: backend
+ restart: always
+ ports:
+ - 3000:3000
+ environment:
+ NODE_PORT: 3000
+ MONGO_URL: mongodb://mongo:27017/notesdb
+ depends_on:
+ - mongo
+
+ mongo:
+ image: mongo:7
+ container_name: mongo
+ restart: always
+ volumes:
+ - db-data:/data/db
+ ports:
+ - 27017:27017
+
+volumes:
+ db-data:
diff --git a/notes.js b/notes.js
new file mode 100644
index 000000000..fcebe1d43
--- /dev/null
+++ b/notes.js
@@ -0,0 +1,50 @@
+const express = require('express');
+const Note = require('../models/Note');
+
+const router = express.Router();
+
+// GET /notes - list all notes
+router.get('/', async (req, res) => {
+ const notes = await Note.find().sort({ createdAt: -1 });
+ res.json(notes);
+});
+
+// POST /notes - create a note
+router.post('/', async (req, res) => {
+ try {
+ const note = await Note.create({
+ title: req.body.title,
+ content: req.body.content,
+ });
+ res.status(201).json(note);
+ } catch (err) {
+ res.status(400).json({ error: err.message });
+ }
+});
+
+// GET /notes/:id - get a single note
+router.get('/:id', async (req, res) => {
+ const note = await Note.findById(req.params.id);
+ if (!note) return res.status(404).json({ error: 'Note not found' });
+ res.json(note);
+});
+
+// PUT /notes/:id - update a note
+router.put('/:id', async (req, res) => {
+ const note = await Note.findByIdAndUpdate(
+ req.params.id,
+ { title: req.body.title, content: req.body.content },
+ { new: true, runValidators: true }
+ );
+ if (!note) return res.status(404).json({ error: 'Note not found' });
+ res.json(note);
+});
+
+// DELETE /notes/:id - delete a note
+router.delete('/:id', async (req, res) => {
+ const note = await Note.findByIdAndDelete(req.params.id);
+ if (!note) return res.status(404).json({ error: 'Note not found' });
+ res.status(204).send();
+});
+
+module.exports = router;
diff --git a/package.json b/package.json
new file mode 100644
index 000000000..c0d8512ee
--- /dev/null
+++ b/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "express-mongodb-backend",
+ "version": "1.0.0",
+ "description": "Sample Express REST API backed by MongoDB",
+ "main": "server.js",
+ "scripts": {
+ "start": "node server.js"
+ },
+ "dependencies": {
+ "express": "^4.19.2",
+ "mongoose": "^8.4.1"
+ }
+}
diff --git a/server.js b/server.js
new file mode 100644
index 000000000..a164b59bb
--- /dev/null
+++ b/server.js
@@ -0,0 +1,28 @@
+const express = require('express');
+const mongoose = require('mongoose');
+const notesRouter = require('./routes/notes');
+
+const app = express();
+const PORT = process.env.NODE_PORT || 3000;
+const MONGO_URL = process.env.MONGO_URL || 'mongodb://mongo:27017/notesdb';
+
+app.use(express.json());
+
+app.get('/', (req, res) => {
+ res.json({ message: 'Express + MongoDB API is running' });
+});
+
+app.use('/notes', notesRouter);
+
+mongoose
+ .connect(MONGO_URL)
+ .then(() => {
+ console.log('Connected to MongoDB');
+ app.listen(PORT, () => {
+ console.log(`Server listening on port ${PORT}`);
+ });
+ })
+ .catch((err) => {
+ console.error('Failed to connect to MongoDB', err);
+ process.exit(1);
+ });