Several apps on one server
Run several apps on one server, let them talk through shared networks, mount remote storage with Docker volume plugins, and keep one app from starving the others.
One server can run any number of apps and environments. A deploy of one app never touches another app's containers.
- Shared by all apps: the server's switch, registry, watchdog and port filter.
- Kept by each app environment: its own Compose project,
<app>-<env>, with its own networks, volumes, releases and lock.
Shared networks
Each app has its own networks, so by default apps cannot reach each other. When they must (say, a game server that writes to the backend's Postgres), create a network that belongs to the server, and let both apps join it:
dockflow server network create shared# compose.yml of the backend
services:
postgres:
image: postgres:17
networks:
default: {}
shared: { aliases: [backend-db] }
networks:
shared: { external: true }# compose.yml of the game server
services:
game:
image: itzg/minecraft-server
environment:
DB_HOST: backend-db
networks:
default: {}
shared: {}
networks:
shared: { external: true }The game server reaches backend-db:5432, an alias the backend chose. It does not need to know the backend's project name.
If an app joins a shared network the server does not have, its deploy fails before changing anything, and prints the command that creates the network.
| Command | What it does |
|---|---|
dockflow server network create [<env>] <name> | Creates a bridge network owned by the server. Creating one that exists changes nothing. |
dockflow server network list [<env>] | The shared networks, with the containers attached to each. |
dockflow server network remove [<env>] <name> | Removes a shared network. It refuses while containers use it: remove it from the apps' Compose files and deploy them first. |
<env> names the environment whose server it is, as for a deploy.
Volume plugins
A Docker volume plugin mounts storage that lives elsewhere as a volume: S3 or SFTP with rclone's plugin, NFS, and others. Install the plugin once per server:
dockflow server plugin install rclone/docker-volume-rclone:amd64 --alias rclone \
args="-v"Then give a volume of your Compose file its driver:
# compose.yml (fragment)
services:
backend:
volumes: [archives:/archives]
volumes:
archives:
driver: rclone
driver_opts:
remote: "s3:archives"
s3-access-key-id: ${S3_ACCESS_KEY}
s3-secret-access-key: ${S3_SECRET_KEY}| Command | What it does |
|---|---|
dockflow server plugin install [<env>] <plugin> [--alias <name>] [<key>=<value>…] | Pulls the plugin, grants the privileges it asks for and shows them, sets its settings, and enables it. --alias is the name Compose volumes give as their driver. |
dockflow server plugin list [<env>] | The plugins, enabled or not, with their types and the names of their settings. |
dockflow server plugin remove [<env>] <plugin> | Disables and removes a plugin. It refuses while volumes use it. |
If a volume needs a plugin the server does not have, the deploy fails before changing anything, and prints the command that installs it.
A plugin runs as root, with the privileges it asked for, which install prints. Install only plugins you trust.
The values of settings are masked in Dockflow's output, and plugin list shows only their names. But Docker keeps the values in the plugin's configuration, readable by anyone with Docker access on the server. For credentials, prefer driver_opts with secrets, as above.
These are Docker's plugins, not Dockflow plugins, which bundle uploads and hooks.
Resource limits
On a server that runs several app environments, a service without limits can take the memory of all of them. Set limits in Compose:
# compose.yml (fragment)
services:
backend:
deploy:
resources:
limits: { memory: 512m, cpus: "1.0" }As soon as another app environment runs on the server, the plan warns about each service without limits (plan.no_limits).
Isolation
Apps on one server are separated by project and network, not by a security boundary. Anyone who can deploy one app can reach the server's Docker, and so every other app. When that matters, give each client its own server. See security.