Network isolation
Every environment gets its own private network, so a service name means one container and nothing crosses an environment boundary.
An environment gets a private Docker network named
deplo-env-<environment id>. Apps and managed databases there reach each
other by name. Apps outside projects use the team's deplo-team-<team id>
network instead. Pull request previews use an isolated
deplo-preview-<key> network.
Folders do not create a network boundary. To separate workloads, put them in different environments. Deplo derives the network from the app's location; you never create or select it.
What sees what
| From | To | Reachable |
|---|---|---|
| A service in a stack | Another service in the same stack | Yes |
| An app | Another app in the same environment, same server | Yes |
| An app | A database in the same environment, same server | Yes |
| An app | Anything in the same environment on another server | No |
| An app in Production | An app in Staging, same project | No |
| An app | An app in another project | No |
| An app | Anything of another team | No |
| A pull request preview | Anything at all | No |
| An app | A published port on the same server | Yes - see below |
A preview cannot reach your database
A pull request preview uses its own network and cannot reach the managed database of the environment it came from.
Give it a database inside the Compose file, or connect it to a database with a published port. There is no way to add a preview to an environment network.
Published ports bypass the boundary. Any container on the same server can reach a published port, regardless of team or environment. A firewall does not change this because the traffic stays inside the host.
Use a published port only when that reachability is intended. For app-to-app traffic, use the service name in the same environment.
The proxy answers from every network. Traefik joins each environment network, so a container can request any hostname served by that server, including domains belonging to other teams.
Anything with a domain is reachable through the proxy. Keep private services without a domain.
A network does not span servers. Apps in the same environment but on different servers cannot reach each other by name. Put them on one server, or publish a port and use the server address.
Folders affect permissions, not isolation. Moving an app between folders does not change its network. Moving it from an environment into a folder moves it to the team's network and away from that environment's databases; Deplo redeploys it on the new network before the move completes.
A domain is separate from network isolation: the proxy serves it from every network, so it remains reachable from other environments and from the internet.
Services that stay off the network
Deplo adds the environment network to every service, alongside any networks in the Compose file. A service keeps only the environment networks it is allowed to join.
Four kinds of service stay off it:
- One with
network_mode:. It joins no network of its own by definition, so there is nothing to add it to - and a domain pointed at it will not answer. - One whose name, or
hostname:, is one the platform answers to (postgres,traefik,deplo, and the three others). It stays on the stack's own private network, and Deplo keeps every other service on that network too, so the app still reaches it by name. - One whose networks you all marked
internal: true. That is a deliberate seal and Deplo leaves it alone. A domain still wins: route to the service and it joins, because otherwise the proxy cannot reach it. - One whose name is already answered by a neighbouring stack on that network. Two containers claiming one name would round-robin, so the newcomer is left off with a warning rather than quietly taking half the traffic.
services:
web:
image: my/app
networks: [backend] # on backend AND the environment's network
worker:
image: my/app # names nothing: on the environment's network
vault:
image: vault
networks: [sealed] # sealed off on purpose: stays private
networks:
backend: {}
sealed:
internal: trueDatabase placement
A managed database has a placement like an app. Choose it under Storage -> New database.
- In an environment - the apps in that environment reach it at
db-<name>. This is what you want almost always. - No environment - it sits on the team's network, reachable from apps that are not in a project.
The Networking card shows its placement and offers Move to environment. Deplo restarts the database on the new network before the action completes.
A database you stopped stays stopped: it follows the move the next time you start it.
A published port is outside the boundary. Exposing a database on a host port takes it out of all of this. Docker binds the port on the machine, so it answers every container on that server, whatever network they are on - and the server's own firewall does not stop them, because Docker publishes below it. The password is the only thing in the way. Leave the port off unless something outside the server really needs it.
Name collisions
Inside one environment the names have to be unique: two apps that both have a
service called web both answer to web on that network, and Docker splits the
lookups between them. Half your requests reach the wrong container.
Saving a compose file that takes a name already answered there is refused, and the message names one that is free:
`web` is already answered by Shop on that network, and Docker would split the
connections between the two. Rename it on this app (the service, or its
`hostname:`) - `web-2` is free - or pick another environment.An overlap that already exists - two stacks that landed there before the check, or arrived by different routes - is reported by the deploy instead:
`web` is also answered by a stack in Shop / Production, on the same network as
this one. Docker splits the lookups between them, so half will reach the wrong
container.Rename the service, or give it a hostname: of its own. Every service of your
stack takes a name on that network, not only the ones you route: a worker with no
domain is still part of the app and still has to reach your database.
Declaring your own networks does not take a service off it - frontend and
backend is organisation, not a request to be cut off, and your networks are kept
alongside the environment's. Three things do stay off:
| Stays off | Why |
|---|---|
A network you marked internal: true | That IS the request to be cut off, and adding the environment's network would hand back the egress you removed |
network_mode: on a service | It replaces the network stack entirely, so there is nothing to join - and a domain pointing at such a service is reported in the deploy log |
| A service named after Deplo's own infrastructure | Left off rather than refused, so an ordinary stack still deploys. It keeps a private network with the rest of your stack, so the two still talk |
Deplo also refuses a move that would create the overlap - putting an app into an environment where a database already answers to one of its names, or the reverse.
A stack Deplo wrote is renamed rather than refused: a template you deploy, or
an app a migration brings over from another panel. Deploying the same template
twice into one environment gives the second one myapp-db instead of db, and
everything that named it moves with it - the route, the variables, the config
files. The app's Activity says what was renamed; a migration puts it in the report
too. A compose file you wrote yourself is yours, so it is refused with the free
name instead of edited behind your back.
cannot resolve host
The one thing that breaks: an app pointing at another app by name, when the two are in different environments.
could not translate host name "gamewatcher-db" to address:
Name or service not knownDeplo says so before the container tries. The deploy log carries a line naming what you pointed at and where it lives:
DATABASE_URL points at `gamewatcher-db`, which lives in GW / Production and
is not reachable from here.The other shape says the placement is right and the machine is not:
DB_HOST points at `orders-db`, which is in Shop / Production with this app but
runs on ANOTHER SERVER.Three ways out, best first:
Put them in the same environment, on the same server
Move the app (or the database) so both sit in one environment and on one server. That is what the boundary is for - and the server part is not the boundary's doing, it is what a Docker network is.
Use a managed database
Create it in the environment that needs it. Deplo writes the connection string and keeps it reachable.
Publish a port
Only if the two genuinely must stay apart: expose the service on a host port and point at the server address instead of the container name. Treat that port as public - it answers every container on the server, not only the one you opened it for.
Migrate existing instances
The first time a Deplo with this feature starts, it moves every existing app and database onto its environment's network, one server at a time.
- A stack that cannot be reached stays where it is and keeps running. It is a delay, not an outage.
- The Overview shows how many the sweep could not reach, and Activity says which ones and why. A stack it deliberately skipped - one you had stopped, one mid-deploy - is not in that count.
- Deploying one moves it. Try again on the notice re-runs the whole sweep, and Dismiss - the cross on it - puts the notice away for good. Neither one touches a stack that is already where it belongs.
Databases that had no placement are given the environment that actually uses them, when exactly one place does. One used from two environments - or from an environment and from apps outside every project - stays at the team level for you to decide, because moving it would take it away from half its callers.
Stopped apps and stopped databases are left alone and follow when you start them. So does anything that was mid-deploy, on its next deploy.
What does not change
Domains, HTTPS, certificates, redirects and basic auth. Published ports, for apps and for databases. Logs, console, terminal, backups, cron, metrics and migrations - all of those reach a container through the server agent, never through the Docker network.
Did this page help you?