Skip to content

Gro 109#24961

Merged
aevesdocker merged 4 commits intodocker:mainfrom
aevesdocker:gro-109
May 8, 2026
Merged

Gro 109#24961
aevesdocker merged 4 commits intodocker:mainfrom
aevesdocker:gro-109

Conversation

@aevesdocker
Copy link
Copy Markdown
Contributor

Description

Compose networking refresh

Related issues or tickets

Reviews

  • Technical review
  • Editorial review
  • Product review

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for docsdocker ready!

Name Link
🔨 Latest commit 69b4618
🔍 Latest deploy log https://app.netlify.com/projects/docsdocker/deploys/69fdeaae5e566800082be1d9
😎 Deploy Preview https://deploy-preview-24961--docsdocker.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@aevesdocker
Copy link
Copy Markdown
Contributor Author

/review

## Network drivers: bridge vs host

## Link containers
Compose supports multiple network drivers. The two most common are `bridge` and `host`.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if host is most common, and not sure if we should encourage users to use it; using host networking reduces the container's sandbox, and usually is reserved for expert use-cases where containers should not have a security boundary for networking.

Using host networking means that the container also won't have its own IP-address, and resolving containers won't be possible (as they share the host's IP-address.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was keen to demonstrate network_mode here and took bridge and host as my examples. You're right to pick up on the most common. I have removed. I've re-framed the rest of the content too to focus on network_mode instead of comparing the drivers.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeah, it's a tricky one; the "host" mode networking is really an expert use-case as it has many differences; unlike picking a different network-driver, host-mode means we completely disable the network namespace / network isolation of the container. It's useful for very specific situations, but for users not familiar with it (or aware of the wider consequences), it will be confusing.

Trying to think if we can find a different example, which could be a different network-driver, or if we want to keep it really basic none as networking (i.e., disable networking) to prevent going down the deep-end to explain the full network stack; https://docs.docker.com/engine/network/drivers/

We do have other driver (e.g. macvlan or ipvlan), but with those there's definitely a risk of going too much into depth on networking in general.

Perhaps @robmry has some ideas on some illustrative examples.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeh I think I'm leaning towards keeping it lighter with my new changes. We don't get a huge amount (if any) feedback on the lack of depth of the Compose network docs because we point to the Engine docs which are very comprehensive. I view this page as more of an entry point into networking

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, perhaps we should keep it simple for now, and indeed refer to the other docs for those that really need it. Of course we can revisit the if we come with a basic example to illustrate, but it may save us some headaches if users start to follow the example, then get back with questions.

Comment on lines -32 to +28
image: postgres:18
image: postgres:latest
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious why this was switched to :latest (it's less maintenance, but not usually best-practice to use :latest - even more so for database containers, as updates to (in this case PostgreSQL) usually involves a migration step.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this was a maintenance-related change. Also a consistency one - we do this quite a lot throughout the rest of docs. I personally think this is Ok for these non-normative examples

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's a tricky balance; we should have a closer look at some of these; for the really "one-off" examples (just a docker run alpine / ubuntu / busybox), it's usually fine.

For other, more complete examples that users could use as a "template" / starting point for what they're doing, we should be more careful, and better to follow best practices.

I know we once had WordPress examples using mysql:latest and we had a ton of users that saw their stack break when MySQL moved :latest from v5 to something newer and their databases broke.

From a maintenance perspective for this specific case; postgres does a major version once per Year, and those are supported for 5 Years, so even if it's the previous major version, we would still have a good time window to update.

But we should look at either having some variables; we already have some for various versions (engine, alpine, etc); and we could probably automate some of these updates (or have Gordon do it for us);

docs/hugo.yaml

Lines 159 to 184 in 1414b91

docker_ce_version: "29.4.2"
# Previous version of the Docker Engine
# (Used to show e.g., "latest" and "latest"-1 in engine install examples
docker_ce_version_prev: "29.4.1"
# Latest Docker Compose version
compose_version: "v5.1.2"
# Latest BuildKit version
buildkit_version: "0.28.0"
# Latest actions version
bake_action_version: "v7"
build_push_action_version: "v7"
login_action_version: "v4"
metadata_action_version: "v6"
setup_buildx_action_version: "v4"
setup_compose_action_version: "v2"
setup_docker_action_version: "v5"
setup_qemu_action_version: "v4"
github_builder_version: "v1"
# Generic actions
checkout_action_version: "v6"
cache_action_version: "v5"
# Example runtime/library/os versions
example_go_version: "1.25"
example_alpine_version: "3.23"
example_node_version: "24"

Copy link
Copy Markdown
Contributor

@docker-agent docker-agent Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assessment: 🟡 NEEDS ATTENTION

Comment thread content/manuals/compose/how-tos/networking.md Outdated
Comment thread content/manuals/compose/how-tos/networking.md Outdated
Comment thread content/manuals/compose/how-tos/networking.md Outdated
Comment thread content/manuals/compose/how-tos/networking.md Outdated
Comment thread content/manuals/compose/how-tos/networking.md Outdated
[network](/reference/cli/docker/network/create/) for your app. Each
container for a service joins the default network and is both reachable by
other containers on that network, and discoverable by the service's name.
Compose handles networking for you by default, but gives you fine-grained control when you need it. This page explains how the default network works and how containers discover each other by name. It also covers when and how to define custom networks, choose between network drivers, connect services across separate Compose projects, map custom hostnames, and debug connectivity issues.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a great intro tbh

- "8001:5432"
```

Since `networks` is empty or absent from the Compose file, Compose automatically connects all services to the default network.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we reword "is empty or absent from the Compose file"? I can see this introducing ambiguity. Maybe something like, 'Compose automatically connects all services to the default network, so you don't need to define networks explicitly in the Compose file.'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oo yes, subtle but makes a difference. done.

2. A container is created using `web`'s configuration. It joins `myapp_default` under the name `web`.
3. A container is created using `db`'s configuration. It joins `myapp_default` under the name `db`.

Each container can now look up the service name `web` or `db` and get back the appropriate container's IP address. The `web` service can connect to the database at `postgres://db:5432`. From the host machine, the same database is accessible at `postgres://localhost:8001` if your container is running locally.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is really clear and good

using the Postgres database.
> [!TIP]
>
> Always reference services by name, not IP address. When containers are recreated, for example after a configuration change, they receive a new IP address. The service name stays stable.
Copy link
Copy Markdown
Contributor

@akristen akristen May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I understand this and it's clear why I'd use the service name, but I'm not understanding the why, for some reason. Is this an aspect of how docker handles networks? if i'm using network: host, would the IP address stay stable or does this rule still apply? (asking in case i'm missing something, or maybe it needs to be clearer in the content before the tip)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeh this is a Docker thing, not a Compose-specific thing. You're right though that the tip just jumps straight in without setting that up and if you're new to this topic you'll want this info, so have added the line 'Docker assigns container IP addresses dynamically from the network's subnet each time a container starts; they are not persisted across restarts or recreations.'

`5432` (postgres default). Networked service-to-service
communication uses the `CONTAINER_PORT`. When `HOST_PORT` is defined,
the service is accessible outside the swarm as well.
Your app's network is given a name based on the "project name", which is based on the name of the directory it lives in. You can override the project name with either the [`--project-name` flag](/reference/cli/docker/compose/) or the [`COMPOSE_PROJECT_NAME` environment variable](environment-variables/envvars.md#compose_project_name).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Your app's network is given a name based on the "project name", which is based on the name of the directory it lives in."

Can we reword? Using 'based' twice is confusing. Do I read th is as the network is based on the project name, and the project name is based on the directory it lives in?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oui yes, good point. I went with 'Your app's network is given a name based on the "project name", which is taken from the name of the directory it lives in.'

Within the `web` container, your connection string to `db` would look like
`postgres://db:5432`, and from the host machine, the connection string would
look like `postgres://{DOCKER_IP}:8001` for example `postgres://localhost:8001` if your container is running locally.
The `HOST_PORT` and `CONTAINER_PORT` serve different purposes. In the example above, for `db`, the `HOST_PORT` is `8001` and the container port is `5432` (the Postgres default). Networked service-to-service communication uses the `CONTAINER_PORT`. The host port is only used when accessing the service from outside the network.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ohhhhhhh. Is there a benefit to using two different ports? When I've done this, I usually use the same port for each (which I based off the sample compose file in registry.) this is mostly because i'm curious and maybe could be useful for other users

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the same is fine as long as nothing else on your host is using it. The main reason to use different ports is to avoid conflicts, for example if you're running multiple projects locally. Again, this is a general Docker thing so not sure whether it needs to be expanded further

Comment thread content/manuals/compose/how-tos/networking.md Outdated
cache:
image: redis
networks:
- internal
Copy link
Copy Markdown
Contributor

@akristen akristen May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above paragraph defines networks: - internal without the true value, but in the example it's just internal. is true implied by virtue of defining networks as internal?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah so this is coz I've given it confusing names. So am renaming 'internal' to 'isolated' then the key value 'internal: true' will be clearer

public: # Regular network connected to host
```

Note that a service connected to both an internal and a non-internal network (like `worker` above) can still reach the internet via the non-internal network `public`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do users need to define or configure public anywhere, or is it an "out of the box" feature (so to speak) that comes with default network

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 So it tells Compose to create it as a standard bridge network. It's not the same as the default network Compose creates automatically, it's just an explicitly named custom network that just happens to have default settings. Have updated the comment to make this clearer!

api:
image: myapi:latest
networks:
- shared
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be shared-network instead of shared?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you use shared later on. What's the difference between the two, if any. lol maybe i'm missing something...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeh this is weird compose file parsing rules.

  • shared is the Compose network alias that is used to reference the network within that Compose file
  • shared-network is the actual Docker network name which gets created by docker network create and what Docker itself knows it as.

Having them be similar in the example isn't helpful though so have changed!

- "host.docker.internal:host-gateway"
```

On Linux, `host-gateway` resolves to the host's IP on the default bridge network. On Mac and Windows, Docker automatically provides this - `host-gateway` resolves to the same internal IP address as `host.docker.internal`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
On Linux, `host-gateway` resolves to the host's IP on the default bridge network. On Mac and Windows, Docker automatically provides this - `host-gateway` resolves to the same internal IP address as `host.docker.internal`.
On Linux, `host-gateway` resolves to the host's IP on the default bridge network. On Mac and Windows, Docker automatically resolves `host-gateway` to the same internal IP address as `host.docker.internal`.

maybe?


## Link containers

Links allow you to define extra aliases by which a service is reachable from another service. They are not required for basic service-to-service communication — by default, any service can reach any other service at that service's name. In the following example, `db` is reachable from `web` at both the hostnames `db` and `database`:
Copy link
Copy Markdown
Contributor

@akristen akristen May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Links allow you to define extra aliases by which a service is reachable from another service. They are not required for basic service-to-service communication — by default, any service can reach any other service at that service's name. In the following example, `db` is reachable from `web` at both the hostnames `db` and `database`:
Links allow you to define extra aliases by which a service is reachable from another service. They are not required for basic service-to-service communication. By default, any service can reach any other service at that service's name. In the following example, `web` can reach `db` at both the hostnames `db` and `database`:

by all means keep the emdash lol but i think it can be separated into two distinct sentences

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed!

Copy link
Copy Markdown
Contributor

@akristen akristen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made some small suggestions that are non-blocking and perhaps even obvious answers to our users. :) Overall I feel confident that I could do more advanced networking with what you have here. My only other thought:

Is it worth describing that you can test your network mode with the docker exec command? Maybe in a what's next section? I've found this helpful when I want to test that I've configured networks correctly.

@aevesdocker
Copy link
Copy Markdown
Contributor Author

Is it worth describing that you can test your network mode with the docker exec command? Maybe in a what's next section? I've found this helpful when I want to test that I've configured networks correctly.

Yes! (Although it'll be docker compose exec ;)). I do have docker network inspect, but it achieves a separate thing, so have added.

@aevesdocker aevesdocker marked this pull request as ready for review May 8, 2026 13:52
Copy link
Copy Markdown

@docker-agent docker-agent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assessment: 🟡 NEEDS ATTENTION

5 medium-severity documentation style issues found in the added lines. No critical or high-severity problems. The page is a significant expansion of the original focused how-to.

[network](/reference/cli/docker/network/create/) for your app. Each
container for a service joins the default network and is both reachable by
other containers on that network, and discoverable by the service's name.
Compose handles networking for you by default, but gives you fine-grained control when you need it. This page explains how the default network works and how containers discover each other by name. It also covers when and how to define custom networks, connect services across separate Compose projects, map custom hostnames, and debug connectivity issues.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] Hedge language: "fine-grained control"

"Fine-grained" is a hedge word that the Docker style guide explicitly flags as language to avoid (along with "simply", "easily", "seamlessly"). It implies a quality rather than describing what the product does.

Suggestion: Replace with a factual description, for example:

"Compose sets up networking automatically, but lets you configure custom networks, drivers, and DNS when you need it."

## Change the network mode

## Link containers
By default, each service joins the project's bridge network. It is the most secure networking mode. If you don't specify [`network_mode`](/reference/compose-file/services.md#network_mode), this is the type of network you are creating.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] Unqualified superlative: "the most secure networking mode"

"It is the most secure networking mode" is a marketing-style claim that is also factually questionable. The none mode disables all networking entirely, which is arguably more restrictive than bridge. The Docker style guide says to describe what something does rather than making superlative statements.

Suggestion: Remove the superlative and describe behaviour instead:

"By default, each service joins the project's bridge network, which isolates containers from external networks while allowing inter-service communication."

public: # Standard bridge network, created by Compose on docker compose up
```

Note that a service connected to both an internal and a non-internal network (like `worker` above) can still reach the internet via the non-internal network `public`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] Meta-commentary: "Note that"

The Docker style guide explicitly lists "Note that..." as forbidden meta-commentary that adds no value and should be replaced by stating the information directly (alongside "It's worth noting that...", "Keep in mind that...").

Suggestion: Remove the opener and state the information directly:

"A service connected to both an internal and a non-internal network, like worker above, can still reach the internet via public."

- "host.docker.internal:host-gateway"
```

On Linux, `host-gateway` resolves to the host's IP on the default bridge network. On Mac and Windows, Docker automatically provides this, `host-gateway` resolves to the same internal IP address as `host.docker.internal`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] "Mac" should be "macOS"; comma splice

Two issues on this line:

  1. Terminology: Docker documentation uses "macOS" (not "Mac") when referring to Apple's operating system, consistent with Apple's own branding and Docker's terminology conventions.

  2. Comma splice: "Docker automatically provides this, host-gateway resolves..." joins two independent clauses with only a comma. This should be two sentences.

Suggestion:

"On Linux, host-gateway resolves to the host's IP on the default bridge network. On macOS and Windows, Docker automatically provides this mapping and host-gateway resolves to the same internal IP address as host.docker.internal."

[network](/reference/cli/docker/network/create/) for your app. Each
container for a service joins the default network and is both reachable by
other containers on that network, and discoverable by the service's name.
Compose handles networking for you by default, but gives you fine-grained control when you need it. This page explains how the default network works and how containers discover each other by name. It also covers when and how to define custom networks, connect services across separate Compose projects, map custom hostnames, and debug connectivity issues.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] Scope inflation: focused how-to expanded into comprehensive reference

The Docker style guide ("Scope preservation") explicitly cautions against expanding a focused document unnecessarily: "If the document is brief and direct (90 lines), keep it that way. Don't transform a focused guide into an exhaustive tutorial." and "Bad additions change the document's character."

This PR adds roughly 200 lines of new sections to what was a focused how-to:

  • Change the network mode
  • Internal networks
  • Hybrid networking
  • Custom DNS with extra_hosts
  • Debugging (port mapping, network membership, connectivity)
  • Connecting multiple Compose projects

Many of these topics (hybrid networking, extra_hosts deep-dives, the full debugging workflow) are self-contained enough to live as separate pages or in reference documentation, which would preserve this page's focused character while still making the content available.

@aevesdocker aevesdocker merged commit 563667a into docker:main May 8, 2026
19 of 20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants