# How to Deploy MCP-PostgreSQL-Ops Using Docker for Isolated Database Operations

> Easily deploy MCP-PostgreSQL-Ops with Docker for isolated and reproducible database operations. Clone the repo, configure env vars, and run docker-compose up for a seamless setup.

- Repository: [JungJungIn/mcp-postgresql-ops](https://github.com/call518/mcp-postgresql-ops)
- Tags: how-to-guide
- Published: 2026-02-26

---

**Deploy MCP-PostgreSQL-Ops using Docker by cloning the repository, configuring environment variables from `.env.example`, and executing `docker-compose up -d` to orchestrate the MCP Server, MCPO Proxy, and optional PostgreSQL containers in an isolated, reproducible stack.**

The **MCP-PostgreSQL-Ops** project by `call518` provides a containerized Model Context Protocol (MCP) server that exposes PostgreSQL monitoring and operational tools via HTTP or stdio interfaces. Deploying via Docker ensures consistent dependency management across Python 3.12, required system libraries, and database drivers, while the included [`docker-compose.yml`](https://github.com/call518/mcp-postgresql-ops/blob/main/docker-compose.yml) automates network configuration and service discovery. This guide walks through the complete Docker deployment process using the official repository structure and production-ready configuration patterns.

## Architecture Overview and Component Stack

The Docker deployment consists of four primary services defined in **[`docker-compose.yml`](https://github.com/call518/mcp-postgresql-ops/blob/main/docker-compose.yml)**, each serving a distinct role in the observability pipeline.

**MCP Server** — The core Python service built from **`Dockerfile.MCP-Server`**. This image installs Python 3.12 alongside the `mcpo`, `fastmcp`, `aiohttp`, and `asyncpg` packages. At runtime, the container executes **[`scripts/mcp-server-docker-cmd.sh`](https://github.com/call518/mcp-postgresql-ops/blob/main/scripts/mcp-server-docker-cmd.sh)**, which loads environment variables from the mounted `.env` file and launches the server via `python -m mcp_postgresql_ops`.

**MCPO Proxy** — An optional reverse-proxy container (`call518/mcpo-proxy-postgresql-ops:1.0.3`) that translates MCP Server HTTP traffic to a clean endpoint (`/postgresql-ops`). The proxy depends on the MCP Server container health status and exposes port **8000** internally, mapped to the host via `DOCKER_EXTERNAL_PORT_MCPO_PROXY`.

**PostgreSQL** — A target database container using the **Percona PostgreSQL** image (default version 17). This service exposes port **5432** internally, mapped to host port `POSTGRES_PORT` (default **15432**). The **`postgres-init-extensions`** service pre-loads `pg_stat_statements` and `pg_stat_monitor` extensions, then creates synthetic test data for immediate validation.

**OpenWebUI** — An optional frontend (`ghcr.io/open-webui/open-webui:0.7.2`) that consumes MCP tools as LLM-augmented chat functions, connecting through the MCPO Proxy.

All services communicate over a shared Docker network, using `host.docker.internal` for Docker Desktop environments or direct service names (`postgres`, `mcp-server`) for Linux deployments.

## Step-by-Step Docker Deployment

### 1. Clone and Prepare Environment

Begin by cloning the repository and initializing the configuration file:

```bash
git clone https://github.com/call518/mcp-postgresql-ops.git
cd mcp-postgresql-ops
cp .env.example .env

```

Edit `.env` to specify database credentials and external ports. The repository provides **[`docker-compose.custom-db.yml`](https://github.com/call518/mcp-postgresql-ops/blob/main/docker-compose.custom-db.yml)** for production scenarios where you omit the bundled PostgreSQL container and point to an existing database instance.

### 2. Build or Pull the MCP Server Image

The default [`docker-compose.yml`](https://github.com/call518/mcp-postgresql-ops/blob/main/docker-compose.yml) references the pre-built image `call518/mcp-server-postgresql-ops:1.0.1`. To build locally from **`Dockerfile.MCP-Server`**:

```bash
docker build -t local/mcp-server -f Dockerfile.MCP-Server .

```

Update the compose file to use `image: local/mcp-server` if building manually, or rely on the registry version for immediate deployment.

### 3. Launch the Stack

Execute the orchestration command to start all services in detached mode:

```bash
docker-compose up -d

```

For production databases, use the alternative compose configuration:

```bash
docker-compose -f docker-compose.custom-db.yml up -d

```

This command brings up the MCP Server, MCPO Proxy, and optionally PostgreSQL with extensions initialized. The **[`scripts/mcp-server-docker-cmd.sh`](https://github.com/call518/mcp-postgresql-ops/blob/main/scripts/mcp-server-docker-cmd.sh)** entry-point automatically sources the mounted `.env` file and configures the FastMCP server parameters.

### 4. Verify Container Health

Wait 10-15 seconds for initialization, then validate service status:

```bash
docker-compose ps
docker-compose logs -f mcp-server

```

Look for log entries indicating "Starting OpenStack MCP server" and successful PostgreSQL connection handshakes. The MCP Server exposes its raw endpoint on the port defined by `DOCKER_EXTERNAL_PORT_MCP_SERVER` (default **18003**), while the MCPO Proxy serves the documented API on `DOCKER_EXTERNAL_PORT_MCPO_PROXY` (default **8003**).

## Configuration and Environment Variables

The **` .env.example`** file centralizes all deployment parameters. Key variables include:

- **`POSTGRES_HOST`** — Use `host.docker.internal` for host-accessible databases or `postgres` for the compose-managed container.
- **`FASTMCP_TYPE`** — Set to `streamable-http` for Docker deployments (stdio mode is reserved for local `uvx` execution).
- **`FASTMCP_PORT`** — Internal container port (default **8000**), distinct from the host-mapped `DOCKER_EXTERNAL_PORT_MCP_SERVER`.
- **`REMOTE_AUTH_ENABLE`** — Set to `true` and configure `REMOTE_SECRET_KEY` for production authentication.

Example minimal configuration for a self-contained demo:

```dotenv
POSTGRES_HOST=host.docker.internal
POSTGRES_PORT=15432
POSTGRES_USER=postgres
POSTGRES_PASSWORD=changeme!@34
POSTGRES_DB=ecommerce

FASTMCP_TYPE=streamable-http
FASTMCP_HOST=0.0.0.0
FASTMCP_PORT=8000
REMOTE_AUTH_ENABLE=false

```

## Building Custom Images and Registry Deployment

To customize the MCP Server with additional Python dependencies or modified source code in [`src/mcp_postgresql_ops/mcp_main.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/mcp_main.py), rebuild the image:

```bash
docker build -t myorg/mcp-server:latest -f Dockerfile.MCP-Server .

```

Tag and push to a private registry:

```bash
docker tag myorg/mcp-server:latest registry.example.com/myorg/mcp-server:latest
docker push registry.example.com/myorg/mcp-server:latest

```

Update **[`docker-compose.yml`](https://github.com/call518/mcp-postgresql-ops/blob/main/docker-compose.yml)** to reference your custom image:

```yaml
services:
  mcp-server:
    image: registry.example.com/myorg/mcp-server:latest
    env_file: .env
    ports:
      - "${DOCKER_EXTERNAL_PORT_MCP_SERVER}:8000"

```

## Accessing the MCP API Endpoints

Once deployed, interact with the tools via HTTP requests. The MCPO Proxy routes calls to `http://localhost:${DOCKER_EXTERNAL_PORT_MCPO_PROXY}/postgresql-ops/`.

Test connectivity and list active database sessions:

```bash
curl -s http://localhost:8003/postgresql-ops/get_active_connections | jq .

```

View the auto-generated OpenAPI documentation at:

```

http://localhost:${DOCKER_EXTERNAL_PORT_MCPO_PROXY}/postgresql-ops/docs

```

For direct MCP Server access (bypassing the proxy), use the port mapped to `DOCKER_EXTERNAL_PORT_MCP_SERVER` (default **18003**).

## Summary

- **Deploy MCP-PostgreSQL-Ops using Docker** by cloning `call518/mcp-postgresql-ops`, copying `.env.example` to `.env`, and running `docker-compose up -d`.
- The **`Dockerfile.MCP-Server`** builds a Python 3.12 environment with `fastmcp`, `asyncpg`, and `aiohttp`, while **[`scripts/mcp-server-docker-cmd.sh`](https://github.com/call518/mcp-postgresql-ops/blob/main/scripts/mcp-server-docker-cmd.sh)** handles runtime initialization.
- Use **[`docker-compose.custom-db.yml`](https://github.com/call518/mcp-postgresql-ops/blob/main/docker-compose.custom-db.yml)** to connect to existing production PostgreSQL instances instead of the bundled Percona container.
- The **MCPO Proxy** (`call518/mcpo-proxy-postgresql-ops:1.0.3`) provides a clean HTTP interface on port **8000** (externally mapped via `DOCKER_EXTERNAL_PORT_MCPO_PROXY`).
- All configuration is externalized to `.env`, enabling version-controlled, reproducible deployments across development and production environments.

## Frequently Asked Questions

### How do I connect MCP-PostgreSQL-Ops to an existing production database instead of the test container?

Use the **[`docker-compose.custom-db.yml`](https://github.com/call518/mcp-postgresql-ops/blob/main/docker-compose.custom-db.yml)** file provided in the repository root. This configuration omits the `postgres` and `postgres-init-extensions` services. Set `POSTGRES_HOST` in your `.env` file to `host.docker.internal` (for Docker Desktop) or your database server's IP address, ensuring the `POSTGRES_PORT`, `POSTGRES_USER`, and `POSTGRES_PASSWORD` variables match your production credentials.

### What is the difference between the raw MCP Server port and the MCPO Proxy port?

The **MCP Server** (defined in `Dockerfile.MCP-Server` and started via [`scripts/mcp-server-docker-cmd.sh`](https://github.com/call518/mcp-postgresql-ops/blob/main/scripts/mcp-server-docker-cmd.sh)) listens on port **8000** internally for FastMCP streamable HTTP traffic, exposed to the host via `DOCKER_EXTERNAL_PORT_MCP_SERVER` (default **18003**). The **MCPO Proxy** sits in front of the server to provide URL routing (`/postgresql-ops`), enhanced logging, and health checks, exposing port **8000** internally mapped to `DOCKER_EXTERNAL_PORT_MCPO_PROXY` (default **8003**). Production deployments should route traffic through the proxy.

### How do I enable authentication for the HTTP API?

Set `REMOTE_AUTH_ENABLE=true` in your `.env` file and define a strong `REMOTE_SECRET_KEY`. The **[`src/mcp_postgresql_ops/mcp_main.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/mcp_main.py)** implementation checks these variables to enforce bearer token validation on HTTP endpoints. When enabled, all requests to the MCPO Proxy or direct MCP Server must include an `Authorization: Bearer <token>` header matching the configured secret.

### Can I modify the source code without rebuilding the Docker image?

Yes. The default **[`docker-compose.yml`](https://github.com/call518/mcp-postgresql-ops/blob/main/docker-compose.yml)** mounts the local `./src` directory as a volume inside the container at `/app/src`. Changes to [`src/mcp_postgresql_ops/functions.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/functions.py) or [`mcp_main.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/mcp_main.py) reflect immediately upon container restart without requiring a new image build. For permanent deployment, rebuild the image using `Dockerfile.MCP-Server` and push to your registry.