Skip to content

Docker Compose + Plesk

This is one of several ways to install RepoFerry (others — building from source, building your own Docker images, or Docker Compose without Plesk — will be documented here too as they’re written). This guide covers Docker Compose behind Plesk: RepoFerry ships as three Docker images (backend, frontend, website) plus MongoDB, and the production server never compiles anything — images are built and published from a development machine, and the server only pulls and runs them.

This guide assumes Plesk is already managing the server and acts as the reverse proxy and TLS terminator — the same way it would for any other site on the box.

The Docker stack doesn’t manage domains or TLS at all: each service exposes plain HTTP on a local port (127.0.0.1:<port>), and Plesk reverse-proxies to it with a Let’s Encrypt certificate. Default ports:

Domain Service Local port
https://repoferry.com website 127.0.0.1:8082
https://app.repoferry.com frontend 127.0.0.1:8081
https://api.repoferry.com backend 127.0.0.1:8080

Ports are configurable (BACKEND_PORT, FRONTEND_PORT, WEBSITE_PORT in .env) in case any of them clash with something else already running on the server. MongoDB is never exposed on any host port — only backend can reach it, over Docker’s internal network.

  • On the development machine (where images are built and published): Docker, and a Docker Hub session (docker login).
  • On the server: Docker Engine and the docker compose (v2) plugin. Plesk doesn’t need to know about Docker at all — regular SSH access is enough. The chosen ports free on 127.0.0.1.

2. Publish the images (from the development machine)

Section titled “2. Publish the images (from the development machine)”
Terminal window
docker login # once, if not already logged in
scripts/docker/build-and-push.sh # publishes :latest for all 3 images

To publish a specific version instead of just latest: scripts/docker/build-and-push.sh 1.2.0 (publishes 1.2.0 and also updates latest to point at the same image).

Terminal window
cd docker/prod
./00_init.sh # creates data/mongodb and .env from the template
nano .env # fill in MONGO_ROOT_USERNAME/PASSWORD, JWT_SECRET, SECRETS_ENCRYPTION_KEY
./01_launch.sh # pulls the images and starts the full stack
./02_ps.sh # check the 4 containers are "healthy"

.env.example documents every variable, including optional ones: SMTP, public URL, self-registration, and an unattended admin bootstrap (ADMIN_EMAIL/ADMIN_USERNAME/ADMIN_PASSWORD — if all three are set, the administrator account is created automatically on first boot, no wizard needed).

To update after publishing a new image, just run docker/prod/01_launch.sh again.

For each of the three domains:

  1. Add the domain/subdomain if it doesn’t exist yet, pointing its DNS at the server.

  2. SSL/TLS Certificates: issue a Let’s Encrypt certificate (Plesk renews it automatically).

  3. Apache & nginx Settings → add, under “Additional nginx directives”, a reverse-proxy rule to the matching local port:

    location / {
    proxy_pass http://127.0.0.1:<port>;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    }

    If your Plesk installation has the Docker extension, its own proxy-rules UI works too — the target (local port) is the same.

  4. Enable “Redirect from http to https” so all traffic comes in over TLS.

Visit your frontend domain. Since this is the first boot (no users in MongoDB yet), you’ll see the install wizard to create the administrator account — unless you filled in ADMIN_EMAIL/ADMIN_USERNAME/ADMIN_PASSWORD in .env, in which case the admin already exists and you’ll land directly on the login screen.

MongoDB data lives as a bind mount (docker/prod/data/mongodb) — plain files on the host, easy to fold into whatever backup routine the server already has. For a one-off logical dump:

Terminal window
cd docker/prod
docker compose -f compose.yaml exec mongodb \
mongodump --username "$MONGO_ROOT_USERNAME" --password "$MONGO_ROOT_PASSWORD" --authenticationDatabase admin --archive \
> repoferry-$(date +%F).archive
  • MongoDB is never reachable outside Docker’s internal network.
  • .env holds real secrets: keep it chmod 600 (the init script already does this) and never commit it.
  • The backend runs with SPRING_PROFILES_ACTIVE=prod, which disables the Swagger UI/OpenAPI docs.
  • All three application containers have their own HEALTHCHECK; 02_ps.sh shows their status.