TL;DR: Build a small derived Docker image that layers the pgvector extension onto the official postgres:17 image, deploy it with the Plesk Docker extension, persist data to the host, then CREATE EXTENSION vector; in your database. You’ll be up and running in minutes—with clean upgrades, backups, and security baked in.
What You’ll Build
- A PostgreSQL 17 container on a Plesk server (Ubuntu 22.04 assumed)
- The pgvector extension installed and available to all databases
- Persistent storage on the host at
/var/lib/postgres/pg17-data - A repeatable, pinned build (no “latest” surprises)
Estimated time: 20–30 minutes
Prerequisites
- Plesk Obsidian with the Docker extension installed
- SSH access with sudo privileges
- Docker engine available on the host
- Basic familiarity with Plesk’s Docker UI (Add Container, environment variables, volumes, ports)
Why a derived image? We pin the Postgres major version and the pgvector version for reproducibility and security. You can rebuild the image at any time and know exactly what you’re getting.
Step 1 — Create the Derived Image (PostgreSQL 17 + pgvector)
Create a new directory on the server (e.g., /root/pgvector-build/) and add this Dockerfile:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# syntax=docker/dockerfile:1 ARG PG_MAJOR=17 FROM postgres:${PG_MAJOR} # Pin the pgvector release (adjust as needed) ARG PGVECTOR_VERSION=0.7.4 RUN set -eux; \ apt-get update; \ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ ca-certificates curl make gcc g++ postgresql-server-dev-$PG_MAJOR \ ; \ curl -fsSL -o /tmp/pgvector.tar.gz \ https://github.com/pgvector/pgvector/archive/refs/tags/v${PGVECTOR_VERSION}.tar.gz; \ tar -xzf /tmp/pgvector.tar.gz -C /tmp; \ cd /tmp/pgvector-${PGVECTOR_VERSION}; \ make; \ make install; \ cd /; rm -rf /tmp/pgvector*; \ apt-get purge -y --auto-remove curl make gcc g++ postgresql-server-dev-$PG_MAJOR; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* |
Build it:
|
1 2 3 4 5 6 |
cd /root/pgvector-build docker build -t postgres:17-pgvector-0.7.4 \ --build-arg PG_MAJOR=17 \ --build-arg PGVECTOR_VERSION=0.7.4 \ . |
Alternative: Use the prebuilt
ankane/pgvector:pg17image. It’s great for quick starts. A custom derived image is handy if you want precise control or to layer in org-specific defaults.
Step 2 — Prepare Persistent Storage on the Host
Create a directory for your Postgres data and fix ownership/permissions for the container’s postgres user (uid/gid 999):
|
1 2 3 4 |
sudo mkdir -p /var/lib/postgres/pg17-data sudo chown -R 999:999 /var/lib/postgres/pg17-data sudo chmod 700 /var/lib/postgres/pg17-data |
Why here?
/var/lib/postgreskeeps things tidy and separate from other service data. You can back this directory up with your normal server backups/snapshots.
Step 3 — Deploy the Container via Plesk
- In Plesk, go to Server Management → Docker → Add Container.
- Image: choose your local image
postgres:17-pgvector-0.7.4(click Refresh if you don’t see it yet). - Environment variables:
POSTGRES_PASSWORD=yourStrongPassword- (optional)
POSTGRES_USER=appuser - (optional)
POSTGRES_DB=appdb - (optional)
TZ=America/New_York
- Volumes:
- Host:
/var/lib/postgres/pg17-data→ Container:/var/lib/postgresql/data
- Host:
- Ports: map container
5432/tcpto a host port. Use5432if free, or5433if 5432 is busy. - Restart policy: enable Start after system reboot (or
Restart: always). - Click OK to create the container.
Security tip: If apps live on the same host, restrict external access with your firewall (see Step 6). Plesk’s port mapping typically binds to all interfaces.
Step 4 — Verify PostgreSQL and Enable pgvector
Install a client on the host if needed:
|
1 2 3 |
sudo apt-get update sudo apt-get install -y postgresql-client |
Connect and enable pgvector:
|
1 2 3 4 5 6 |
psql -h 127.0.0.1 -p 5432 -U postgres -d postgres -W -- inside psql CREATE EXTENSION IF NOT EXISTS vector; \dx vector |
Check availability details:
|
1 2 3 4 |
SELECT name, default_version, installed_version FROM pg_available_extensions WHERE name = 'vector'; |
If
pg_available_extensionsdoesn’t listvector, the image wasn’t built correctly. See Troubleshooting.
Step 5 — Quick Functional Test (Vectors IRL)
Run a tiny demo to confirm the type and index work:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3)); INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[1,1,1]'), ('[0,0,1]'); -- KNN search (L2 distance) SELECT id, embedding, embedding <-> '[1,2,2]' AS dist FROM items ORDER BY embedding <-> '[1,2,2]' LIMIT 3; -- Add an index for speed CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100); |
Step 6 — Secure the Port
If external clients don’t need direct access, lock it down with UFW:
|
1 2 3 4 5 6 7 |
# Allow a single IP to connect (example) sudo ufw allow from 203.0.113.50 to any port 5432 proto tcp # If 5432 was open to the world, close it sudo ufw deny 5432/tcp sudo ufw reload |
For multi-tenant hosts, also consider VPC firewalls / security groups upstream of the server.
Step 7 — Backups & Restores
Host-based tools (recommended):
|
1 2 3 4 5 6 |
# Backup a single database pg_dump -h 127.0.0.1 -p 5432 -U postgres -d appdb -F c -f /root/appdb_$(date +%F).dump # Restore pg_restore -h 127.0.0.1 -p 5432 -U postgres -d appdb --clean --if-exists /root/appdb_YYYY-MM-DD.dump |
From inside the container:
|
1 2 3 |
docker exec -i <container_name> pg_dump -U postgres -d appdb -F c > /root/appdb.dump cat /root/appdb.dump | docker exec -i <container_name> pg_restore -U postgres -d appdb --clean --if-exists |
For full-instance backups, add regular volume snapshots (e.g., EBS, LVM, ZFS) to your playbook for fast rollback.
Step 8 — Operations Cheatsheet
- Logs: Plesk → Docker → your container → Logs (or
docker logs <name>) - Change config: edit files under
/var/lib/postgres/pg17-data/(postgresql.conf,pg_hba.conf), then restart the container from Plesk - Minor upgrades: rebuild/pull a newer
postgres:17-pgvector-*, stop container, start a new one with the same data volume - Major upgrades (17→18): use
pg_dump/pg_restoreorpg_upgradeprocedure—not just an image swap
Troubleshooting
Address already in use (5432): pick another host port (e.g., 5433) or free 5432.
Data directory ownership/permissions error:
|
1 2 3 |
sudo chown -R 999:999 /var/lib/postgres/pg17-data sudo chmod 700 /var/lib/postgres/pg17-data |
vector not available in pg_available_extensions: The image likely didn’t compile/install pgvector. Verify the files exist in the container:
|
1 2 3 |
/usr/share/postgresql/17/extension/vector.control /usr/lib/postgresql/17/lib/vector.so |
Rebuild the image and ensure the build step isn’t failing.
CREATE EXTENSION vector; fails with permission/role errors: Connect as a superuser (default is postgres) or grant the necessary privileges.
Connection refused/timeouts: Check Plesk port mapping, host firewall, and container logs.
Variations & Tips
- Prebuilt image:
ankane/pgvector:pg17is a solid alternative if you don’t need a custom build. - Pin your versions: Keep
PG_MAJORandPGVECTOR_VERSIONpinned to avoid surprise upgrades. - Time zone: Set
TZto keep logs and timestamps consistent.
Alternative: Use a Prebuilt Image (ankane/pgvector:pg17)
- In Plesk, Add Container.
- Image:
ankane/pgvector:pg17. - Environment variables, volume, and ports: set exactly as in Step 3.
- Start the container, then connect to your database and run
CREATE EXTENSION vector;.
Fastest path if you don’t need a custom build. For pinned versions and internal security reviews, prefer the derived image above.
Wrap-Up
You now have a clean, reproducible PostgreSQL 17 + pgvector stack running under Plesk’s Docker extension—with persistent storage, straightforward upgrades, and a secure posture. From here, wire your applications to the database and start building semantic search, RAG, recommendations, and more.
Need Help?
Reliable Penguin provides systems administration and managed hosting services. We can:
- Build and harden PostgreSQL 17 + pgvector containers under Plesk
- Configure secure networking (firewalling, port binding, TLS where applicable)
- Set up monitoring, alerting, and centralized logs
- Design and test backup/restore + disaster-recovery plans
- Plan and execute version upgrades and migrations
- Tune performance (parameters, I/O, indexing strategy guidance) and right-size resources
- Implement high availability/failover architectures
- Document the stack and provide runbooks; offer on-call/24×7 support options
Note: We don’t build application features. For app-level vector usage, we’re happy to coordinate with your dev team to ensure the platform is ready and well-supported.
Want this in production fast and stable? Get in touch and we’ll handle the infrastructure so your team can focus on the application.




