Port offset
SPLENT automatically adjusts feature port numbers per product so you can run multiple products on the same host without collisions.
Table of contents
Why it exists
Every infrastructure feature declares host ports in its .env.example (e.g. REDIS_HOST_PORT=6380, PMA_HOST_PORT=8081). If two products use the same features, their ports would collide. The port offset solves this by shifting every feature port by a deterministic, product-specific amount.
How it works
When product:env --merge runs, it does the following.
- Scans the merged environment for variables that look like port declarations (ending in
_HOST_PORT,_PORT_ONE,_PORT_TWO). -
Computes a deterministic offset from the product name.
offset = crc32(product_name.encode("utf-8")) % 1000 - Adds the offset to each detected port value.
- Writes the adjusted values to the product’s merged
.env.
The offset is stable. The same product name always produces the same offset, so ports don’t change between runs.
Example
For a product named my_first_app (offset 591), the adjustments look like this.
| Feature | Variable | Base port | Adjusted port |
|---|---|---|---|
| Redis | REDIS_HOST_PORT |
6380 | 6971 |
| phpMyAdmin | PMA_HOST_PORT |
8081 | 8672 |
| Mailhog SMTP | MAILHOG_SMTP_HOST_PORT |
1025 | 1616 |
| Mailhog UI | MAILHOG_UI_HOST_PORT |
8025 | 8616 |
The merge output confirms adjustments.
ports adjusted 4 feature port(s) (+591)
merged 4 feature .env file(s) into product .env
What is and isn’t adjusted
Only feature port variables are adjusted. Product-level ports (like the web server port in
docker-compose.dev.yml) are never touched.
Three rules apply.
- Variables ending in
_HOST_PORT,_PORT_ONE, or_PORT_TWOare adjusted. - Feature ports that already exist in the product’s
.envare left unchanged (product values take precedence). - The offset only applies during
product:env --merge. Base values in each feature’s.env.exampleare never modified.
Implications for feature authors
When creating a new infrastructure feature with Docker services, follow these steps.
- Use an
_HOST_PORTsuffix for your port variable (e.g.NGINX_HTTP_HOST_PORT=80). - Pick a sensible base value that doesn’t overlap with common system ports.
-
Reference the variable in your
docker-compose.yml.ports: - "${NGINX_HTTP_HOST_PORT}:80" - The offset mechanism handles the rest, with no extra code needed.
The offset only means anything because each product runs its own instance of the feature’s stack: a port of one’s own presupposes a container of one’s own to publish it. That is the other half of the same rule, and it comes with three more conditions on the compose file.
Related
- Features that run a server. The rest of the rule this offset is part of
product:env --merge. The CLI command that triggers port adjustment- Feature anatomy. How features declare Docker infrastructure