# Bridge network driver and more

# Bridge network driver

> All about using user-defined bridge networks and the default bridge

# Bridge network driver

   Table of contents

---

A Docker bridge network has an IPv4 subnet and, optionally, an IPv6 subnet.
Each container connected to the bridge network has a network interface with
addresses in the network's subnets. By default, it:

- Allows unrestricted network access to containers in the network from
  the host, and from other containers connected to the same bridge network.
- Blocks access from containers in other networks and from outside the
  Docker host.
- Uses masquerading to give containers external network access. Devices on
  the host's external networks only see the IP address of the Docker host.
- Supports port publishing, where network traffic is forwarded between
  container ports and ports on host IP addresses. The published ports
  can be accessed from outside the Docker host, on its IP addresses.

In terms of Docker, a bridge network uses a software bridge which lets
containers connected to the same bridge network communicate, while providing
isolation from containers that aren't connected to that bridge network. By
default, the Docker bridge driver automatically installs rules in the host
machine so that containers connected to different bridge networks can only
communicate with each other using published ports.

Bridge networks apply to containers running on the same Docker daemon host.
For communication among containers running on different Docker daemon hosts, you
can either manage routing at the OS level, or you can use an
[overlay network](https://docs.docker.com/engine/network/drivers/overlay/).

When you start Docker, a [default bridge network](#use-the-default-bridge-network) (also
called `bridge`) is created automatically, and newly-started containers connect
to it unless otherwise specified. You can also create user-defined custom bridge
networks. **User-defined bridge networks are superior to the defaultbridgenetwork.**

## Differences between user-defined bridges and the default bridge

- **User-defined bridges provide automatic DNS resolution between containers**.
  Containers on the default bridge network can only access each other by IP
  addresses, unless you use the [--linkoption](https://docs.docker.com/engine/network/links/), which is
  considered legacy. On a user-defined bridge network, containers can resolve
  each other by name or alias.
  Imagine an application with a web front-end and a database back-end. If you call
  your containers `web` and `db`, the web container can connect to the db container
  at `db`, no matter which Docker host the application stack is running on.
  If you run the same application stack on the default bridge network, you need
  to manually create links between the containers (using the legacy `--link`
  flag). These links need to be created in both directions, so you can see this
  gets complex with more than two containers which need to communicate.
  Alternatively, you can manipulate the `/etc/hosts` files within the containers,
  but this creates problems that are difficult to debug.
- **User-defined bridges provide better isolation**.
  All containers without a `--network` specified, are attached to the default bridge network. This can be a risk, as unrelated stacks/services/containers are then able to communicate.
  Using a user-defined network provides a scoped network in which only containers attached to that network are able to communicate.
- **Containers can be attached and detached from user-defined networks on the fly**.
  During a container's lifetime, you can connect or disconnect it from
  user-defined networks on the fly. To remove a container from the default
  bridge network, you need to stop the container and recreate it with different
  network options.
- **Each user-defined network creates a configurable bridge**.
  If your containers use the default bridge network, you can configure it, but
  all the containers use the same settings, such as MTU and `iptables` rules.
  In addition, configuring the default bridge network happens outside of Docker
  itself, and requires a restart of Docker.
  User-defined bridge networks are created and configured using
  `docker network create`. If different groups of applications have different
  network requirements, you can configure each user-defined bridge separately,
  as you create it.
- **Linked containers on the default bridge network share environment variables**.
  Originally, the only way to share environment variables between two containers
  was to link them using the [--linkflag](https://docs.docker.com/engine/network/links/). This type of
  variable sharing isn't possible with user-defined networks. However, there
  are superior ways to share environment variables. A few ideas:
  - Multiple containers can mount a file or directory containing the shared
    information, using a Docker volume.
  - Multiple containers can be started together using `docker-compose` and the
    compose file can define the shared variables.
  - You can use swarm services instead of standalone containers, and take
    advantage of shared
    [secrets](https://docs.docker.com/engine/swarm/secrets/) and
    [configs](https://docs.docker.com/engine/swarm/configs/).

Containers connected to the same user-defined bridge network effectively expose all ports
to each other. For a port to be accessible to containers or non-Docker hosts on
different networks, that port must be *published* using the `-p` or `--publish`
flag.

## Options

The following table describes the driver-specific options that you can pass to
`--opt` when creating a custom network using the `bridge` driver.

| Option | Default | Description |
| --- | --- | --- |
| com.docker.network.bridge.name |  | Interface name to use when creating the Linux bridge. |
| com.docker.network.bridge.enable_ip_masquerade | true | Enable IP masquerading. |
| com.docker.network.host_ipv4com.docker.network.host_ipv6 |  | Address to use for source NAT. SeePacket filtering and firewalls. |
| com.docker.network.bridge.gateway_mode_ipv4com.docker.network.bridge.gateway_mode_ipv6 | nat | Control external connectivity. SeePacket filtering and firewalls. |
| com.docker.network.bridge.enable_icc | true | Enable or Disable inter-container connectivity. |
| com.docker.network.bridge.host_binding_ipv4 | all IPv4 and IPv6 addresses | Default IP when binding container ports. |
| com.docker.network.driver.mtu | 0(no limit) | Set the containers network Maximum Transmission Unit (MTU). |
| com.docker.network.container_iface_prefix | eth | Set a custom prefix for container interfaces. |
| com.docker.network.bridge.inhibit_ipv4 | false | Prevent Docker fromassigning an IP addressto the bridge. |

Some of these options are also available as flags to the `dockerd` CLI, and you
can use them to configure the default `docker0` bridge when starting the Docker
daemon. The following table shows which options have equivalent flags in the
`dockerd` CLI.

| Option | Flag |
| --- | --- |
| com.docker.network.bridge.name | - |
| com.docker.network.bridge.enable_ip_masquerade | --ip-masq |
| com.docker.network.bridge.enable_icc | --icc |
| com.docker.network.bridge.host_binding_ipv4 | --ip |
| com.docker.network.driver.mtu | --mtu |
| com.docker.network.container_iface_prefix | - |

The Docker daemon supports a `--bridge` flag, which you can use to define
your own `docker0` bridge. Use this option if you want to run multiple daemon
instances on the same host. For details, see
[Run multiple daemons](https://docs.docker.com/reference/cli/dockerd/#run-multiple-daemons).

### Default host binding address

When no host address is given in port publishing options like `-p 80`
or `-p 8080:80`, the default is to make the container's port 80 available on all
host addresses, IPv4 and IPv6.

The bridge network driver option `com.docker.network.bridge.host_binding_ipv4`
can be used to modify the default address for published ports.

Despite the option's name, it is possible to specify an IPv6 address.

When the default binding address is an address assigned to a specific interface,
the container's port will only be accessible via that address.

Setting the default binding address to `::` means published ports will only be
available on the host's IPv6 addresses. However, setting it to `0.0.0.0` means it
will be available on the host's IPv4 and IPv6 addresses.

To restrict a published port to IPv4 only, the address must be included in the
container's publishing options. For example, `-p 0.0.0.0:8080:80`.

## Manage a user-defined bridge

Use the `docker network create` command to create a user-defined bridge
network.

```console
$ docker network create my-net
```

You can specify the subnet, the IP address range, the gateway, and other
options. See the
[docker network create](https://docs.docker.com/reference/cli/docker/network/create/#specify-advanced-options)
reference or the output of `docker network create --help` for details.

Use the `docker network rm` command to remove a user-defined bridge
network. If containers are currently connected to the network,
[disconnect them](#disconnect-a-container-from-a-user-defined-bridge)
first.

```console
$ docker network rm my-net
```

> **What's really happening?**
>
>
>
> When you create or remove a user-defined bridge or connect or disconnect a
> container from a user-defined bridge, Docker uses tools specific to the
> operating system to manage the underlying network infrastructure (such as adding
> or removing bridge devices or configuring `iptables` rules on Linux). These
> details should be considered implementation details. Let Docker manage your
> user-defined networks for you.

## Connect a container to a user-defined bridge

When you create a new container, you can specify one or more `--network` flags.
This example connects an Nginx container to the `my-net` network. It also
publishes port 80 in the container to port 8080 on the Docker host, so external
clients can access that port. Any other container connected to the `my-net`
network has access to all ports on the `my-nginx` container, and vice versa.

```console
$ docker create --name my-nginx \
  --network my-net \
  --publish 8080:80 \
  nginx:latest
```

To connect a **running** container to an existing user-defined bridge, use the
`docker network connect` command. The following command connects an already-running
`my-nginx` container to an already-existing `my-net` network:

```console
$ docker network connect my-net my-nginx
```

## Disconnect a container from a user-defined bridge

To disconnect a running container from a user-defined bridge, use the
`docker network disconnect` command. The following command disconnects
the `my-nginx` container from the `my-net` network.

```console
$ docker network disconnect my-net my-nginx
```

## Use IPv6 in a user-defined bridge network

When you create your network, you can specify the `--ipv6` flag to enable IPv6.

```console
$ docker network create --ipv6 --subnet 2001:db8:1234::/64 my-net
```

If you do not provide a `--subnet` option, a Unique Local Address (ULA) prefix
will be chosen automatically.

## IPv6-only bridge networks

To skip IPv4 address configuration on the bridge and in its containers, create
the network with option `--ipv4=false`, and enable IPv6 using `--ipv6`.

```console
$ docker network create --ipv6 --ipv4=false v6net
```

IPv4 address configuration cannot be disabled in the default bridge network.

## Use the default bridge network

The default `bridge` network is considered a legacy detail of Docker and is not
recommended for production use. Configuring it is a manual operation, and it has
[technical shortcomings](#differences-between-user-defined-bridges-and-the-default-bridge).

### Connect a container to the default bridge network

If you do not specify a network using the `--network` flag, and you do specify a
network driver, your container is connected to the default `bridge` network by
default. Containers connected to the default `bridge` network can communicate,
but only by IP address, unless they're linked using the
[legacy--linkflag](https://docs.docker.com/engine/network/links/).

### Configure the default bridge network

To configure the default `bridge` network, you specify options in `daemon.json`.
Here is an example `daemon.json` with several options specified. Only specify
the settings you need to customize.

```json
{
  "bip": "192.168.1.1/24",
  "fixed-cidr": "192.168.1.0/25",
  "mtu": 1500,
  "default-gateway": "192.168.1.254",
  "dns": ["10.20.1.2", "10.20.1.3"]
}
```

In this example:

- The bridge's address is "192.168.1.1/24" (from `bip`).
- The bridge network's subnet is "192.168.1.0/24" (from `bip`).
- Container addresses will be allocated from "192.168.1.0/25" (from `fixed-cidr`).

### Use IPv6 with the default bridge network

IPv6 can be enabled for the default bridge using the following options in
`daemon.json`, or their command line equivalents.

These three options only affect the default bridge, they are not used by
user-defined networks. The addresses in below are examples from the
IPv6 documentation range.

- Option `ipv6` is required.
- Option `bip6` is optional, it specifies the address of the default bridge, which
  will be used as the default gateway by containers. It also specifies the subnet
  for the bridge network.
- Option `fixed-cidr-v6` is optional, it specifies the address range Docker may
  automatically allocate to containers.
  - The prefix should normally be `/64` or shorter.
  - For experimentation on a local network, it is better to use a Unique Local
    Address (ULA) prefix (matching `fd00::/8`) than a Link Local prefix (matching
    `fe80::/10`).
- Option `default-gateway-v6` is optional. If unspecified, the default is the first
  address in the `fixed-cidr-v6` subnet.

```json
{
  "ipv6": true,
  "bip6": "2001:db8::1111/64",
  "fixed-cidr-v6": "2001:db8::/64",
  "default-gateway-v6": "2001:db8:abcd::89"
}
```

If no `bip6` is specified, `fixed-cidr-v6` defines the subnet for the bridge
network. If no `bip6` or `fixed-cidr-v6` is specified, a ULA prefix will be
chosen.

Restart Docker for changes to take effect.

## Connection limit for bridge networks

Due to limitations set by the Linux kernel, bridge networks become unstable and
inter-container communications may break when 1000 containers or more connect
to a single network.

For more information about this limitation, see
[moby/moby#44973](https://github.com/moby/moby/issues/44973#issuecomment-1543747718).

## Skip Bridge IP address configuration

The bridge is normally assigned the network's `--gateway` address, which is
used as the default route from the bridge network to other networks.

The `com.docker.network.bridge.inhibit_ipv4` option lets you create a network
without the IPv4 gateway address being assigned to the bridge. This is useful
if you want to configure the gateway IP address for the bridge manually. For
instance if you add a physical interface to your bridge, and need it to have
the gateway address.

With this configuration, north-south traffic (to and from the bridge network)
won't work unless you've manually configured the gateway address on the bridge,
or a device attached to it.

This option can only be used with user-defined bridge networks.

## Usage examples

This section provides hands-on examples for working with bridge networks.

### Use the default bridge network

This example shows how the default `bridge` network works. You start two
`alpine` containers on the default bridge and test how they communicate.

> Note
>
> The default `bridge` network is not recommended for production. Use
> user-defined bridge networks instead.

1. List current networks:
  ```console
  $ docker network ls
  NETWORK ID          NAME                DRIVER              SCOPE
  17e324f45964        bridge              bridge              local
  6ed54d316334        host                host                local
  7092879f2cc8        none                null                local
  ```
  The default `bridge` network is listed, along with `host` and `none`.
2. Start two `alpine` containers running `ash`. The `-dit` flags mean detached,
  interactive, and with a TTY. Since you haven't specified a `--network` flag,
  the containers connect to the default `bridge` network.
  ```console
  $ docker run -dit --name alpine1 alpine ash
  $ docker run -dit --name alpine2 alpine ash
  ```
  Verify both containers are running:
  ```console
  $ docker container ls
  CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
  602dbf1edc81        alpine              "ash"               4 seconds ago       Up 3 seconds                            alpine2
  da33b7aa74b0        alpine              "ash"               17 seconds ago      Up 16 seconds                           alpine1
  ```
3. Inspect the `bridge` network to see connected containers:
  ```console
  $ docker network inspect bridge
  ```
  The output shows both containers connected, with their assigned IP addresses
  (`172.17.0.2` for `alpine1` and `172.17.0.3` for `alpine2`).
4. Connect to `alpine1`:
  ```console
  $ docker attach alpine1
  / #
  ```
  Show the network interfaces for `alpine1` from within the container:
  ```console
  # ip addr show
  1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
      link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
      inet 127.0.0.1/8 scope host lo
         valid_lft forever preferred_lft forever
      inet6 ::1/128 scope host
         valid_lft forever preferred_lft forever
  27: eth0@if28: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
      link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
      inet 172.17.0.2/16 scope global eth0
         valid_lft forever preferred_lft forever
  ```
  In this example, the `eth0` interface has the IP address `172.17.0.2`.
5. From within `alpine1`, verify you can connect to the internet:
  ```console
  # ping -c 2 google.com
  PING google.com (172.217.3.174): 56 data bytes
  64 bytes from 172.217.3.174: seq=0 ttl=41 time=9.841 ms
  64 bytes from 172.217.3.174: seq=1 ttl=41 time=9.897 ms
  --- google.com ping statistics ---
  2 packets transmitted, 2 packets received, 0% packet loss
  round-trip min/avg/max = 9.841/9.869/9.897 ms
  ```
6. Ping the second container by its IP address:
  ```console
  # ping -c 2 172.17.0.3
  PING 172.17.0.3 (172.17.0.3): 56 data bytes
  64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.086 ms
  64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.094 ms
  --- 172.17.0.3 ping statistics ---
  2 packets transmitted, 2 packets received, 0% packet loss
  round-trip min/avg/max = 0.086/0.090/0.094 ms
  ```
  This succeeds. Now try pinging by container name:
  ```console
  # ping -c 2 alpine2
  ping: bad address 'alpine2'
  ```
  On the default bridge network, containers can't resolve each other by name.
7. Detach from `alpine1` without stopping it using `CTRL+p CTRL+q`.
8. Clean up: stop the containers and remove them.
  ```console
  $ docker container stop alpine1 alpine2
  $ docker container rm alpine1 alpine2
  ```
  Stopped containers lose their IP addresses.

### Use user-defined bridge networks

This example shows how user-defined bridge networks provide better isolation
and automatic DNS resolution between containers.

1. Create the `alpine-net` network:
  ```console
  $ docker network create --driver bridge alpine-net
  ```
2. List Docker's networks:
  ```console
  $ docker network ls
  NETWORK ID          NAME                DRIVER              SCOPE
  e9261a8c9a19        alpine-net          bridge              local
  17e324f45964        bridge              bridge              local
  6ed54d316334        host                host                local
  7092879f2cc8        none                null                local
  ```
  Inspect the `alpine-net` network:
  ```console
  $ docker network inspect alpine-net
  ```
  This shows the network's gateway (for example, `172.18.0.1`) and that no
  containers are connected yet.
3. Create four containers. Three connect to `alpine-net`, and one connects to
  the default `bridge`. Then connect one container to both networks:
  ```console
  $ docker run -dit --name alpine1 --network alpine-net alpine ash
  $ docker run -dit --name alpine2 --network alpine-net alpine ash
  $ docker run -dit --name alpine3 alpine ash
  $ docker run -dit --name alpine4 --network alpine-net alpine ash
  $ docker network connect bridge alpine4
  ```
  Verify all containers are running:
  ```console
  $ docker container ls
  CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
  156849ccd902        alpine              "ash"               41 seconds ago       Up 41 seconds                           alpine4
  fa1340b8d83e        alpine              "ash"               51 seconds ago       Up 51 seconds                           alpine3
  a535d969081e        alpine              "ash"               About a minute ago   Up About a minute                       alpine2
  0a02c449a6e9        alpine              "ash"               About a minute ago   Up About a minute                       alpine1
  ```
4. Inspect both networks again to see which containers are connected:
  ```console
  $ docker network inspect bridge
  ```
  Containers `alpine3` and `alpine4` are connected to the `bridge` network.
  ```console
  $ docker network inspect alpine-net
  ```
  Containers `alpine1`, `alpine2`, and `alpine4` are connected to
  `alpine-net`.
5. On user-defined networks, containers can resolve each other by name. Connect
  to `alpine1` and test:
  > Note
  >
  > Automatic service discovery only resolves custom container names, not
  > default automatically generated names.
  ```console
  $ docker container attach alpine1
  # ping -c 2 alpine2
  PING alpine2 (172.18.0.3): 56 data bytes
  64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.085 ms
  64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.090 ms
  --- alpine2 ping statistics ---
  2 packets transmitted, 2 packets received, 0% packet loss
  round-trip min/avg/max = 0.085/0.087/0.090 ms
  # ping -c 2 alpine4
  PING alpine4 (172.18.0.4): 56 data bytes
  64 bytes from 172.18.0.4: seq=0 ttl=64 time=0.076 ms
  64 bytes from 172.18.0.4: seq=1 ttl=64 time=0.091 ms
  --- alpine4 ping statistics ---
  2 packets transmitted, 2 packets received, 0% packet loss
  round-trip min/avg/max = 0.076/0.083/0.091 ms
  ```
6. From `alpine1`, you can't connect to `alpine3` because it's on a different
  network:
  ```console
  # ping -c 2 alpine3
  ping: bad address 'alpine3'
  ```
  You also can't connect by IP address. If `alpine3`'s IP is `172.17.0.2`:
  ```console
  # ping -c 2 172.17.0.2
  PING 172.17.0.2 (172.17.0.2): 56 data bytes
  --- 172.17.0.2 ping statistics ---
  2 packets transmitted, 0 packets received, 100% packet loss
  ```
  Detach from `alpine1` using `CTRL+p CTRL+q`.
7. Since `alpine4` is connected to both networks, it can reach all containers.
  However, you need to use `alpine3`'s IP address:
  ```console
  $ docker container attach alpine4
  # ping -c 2 alpine1
  PING alpine1 (172.18.0.2): 56 data bytes
  64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.074 ms
  64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.082 ms
  --- alpine1 ping statistics ---
  2 packets transmitted, 2 packets received, 0% packet loss
  round-trip min/avg/max = 0.074/0.078/0.082 ms
  # ping -c 2 alpine2
  PING alpine2 (172.18.0.3): 56 data bytes
  64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.075 ms
  64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.080 ms
  --- alpine2 ping statistics ---
  2 packets transmitted, 2 packets received, 0% packet loss
  round-trip min/avg/max = 0.075/0.077/0.080 ms
  # ping -c 2 alpine3
  ping: bad address 'alpine3'
  # ping -c 2 172.17.0.2
  PING 172.17.0.2 (172.17.0.2): 56 data bytes
  64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.089 ms
  64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.075 ms
  --- 172.17.0.2 ping statistics ---
  2 packets transmitted, 2 packets received, 0% packet loss
  round-trip min/avg/max = 0.075/0.082/0.089 ms
  ```
8. Verify all containers can connect to the internet:
  ```console
  # ping -c 2 google.com
  PING google.com (172.217.3.174): 56 data bytes
  64 bytes from 172.217.3.174: seq=0 ttl=41 time=9.778 ms
  64 bytes from 172.217.3.174: seq=1 ttl=41 time=9.634 ms
  --- google.com ping statistics ---
  2 packets transmitted, 2 packets received, 0% packet loss
  round-trip min/avg/max = 9.634/9.706/9.778 ms
  ```
  Detach with `CTRL+p CTRL+q` and repeat for `alpine3` and `alpine1` if
  desired.
9. Clean up:
  ```console
  $ docker container stop alpine1 alpine2 alpine3 alpine4
  $ docker container rm alpine1 alpine2 alpine3 alpine4
  $ docker network rm alpine-net
  ```

## Next steps

- Learn about [networking from the container's point of view](https://docs.docker.com/engine/network/)
- Learn about [overlay networks](https://docs.docker.com/engine/network/drivers/overlay/)
- Learn about [Macvlan networks](https://docs.docker.com/engine/network/drivers/macvlan/)

---

# Host network driver

> All about exposing containers on the Docker host's network

# Host network driver

   Table of contents

---

If you use the `host` network mode for a container, that container's network
stack isn't isolated from the Docker host (the container shares the host's
networking namespace), and the container doesn't get its own IP-address allocated.
For instance, if you run a container which binds to port 80 and you use `host`
networking, the container's application is available on port 80 on the host's IP
address.

> Note
>
> Given that the container does not have its own IP-address when using
> `host` mode networking, [port-mapping](https://docs.docker.com/engine/network/drivers/overlay/#publish-ports) doesn't
> take effect, and the `-p`, `--publish`, `-P`, and `--publish-all` option are
> ignored, producing a warning instead:
>
>
>
> ```console
> WARNING: Published ports are discarded when using host network mode
> ```

Host mode networking can be useful for the following use cases:

- To optimize performance
- In situations where a container needs to handle a large range of ports

This is because it doesn't require network address translation (NAT), and no "userland-proxy" is created for each port.

## Platform support

The host networking driver is supported on:

- Docker Engine on Linux
- Docker Desktop version 4.34 and later (requires enabling the feature in
  Settings)

> Note
>
> For Docker Desktop users, see the [Docker Desktop section](#docker-desktop)
> below for setup instructions.

You can also use a `host` network for a swarm service, by passing `--network host`
to the `docker service create` command. In this case, control traffic (traffic
related to managing the swarm and the service) is still sent across an overlay
network, but the individual swarm service containers send data using the Docker
daemon's host network and ports. This creates some extra limitations. For instance,
if a service container binds to port 80, only one service container can run on a
given swarm node.

## Docker Desktop

Host networking is supported on Docker Desktop version 4.34 and later.
To enable this feature:

1. Sign in to your Docker account in Docker Desktop.
2. Navigate to **Settings**.
3. Under the **Resources** tab, select **Network**.
4. Check the **Enable host networking** option.
5. Select **Apply and restart**.

This feature works in both directions. This means you can
access a server that is running in a container from your host and you can access
servers running on your host from any container that is started with host
networking enabled. TCP as well as UDP are supported as communication protocols.

### Examples

The following command starts netcat in a container that listens on port `8000`:

```console
$ docker run --rm -it --net=host nicolaka/netshoot nc -lkv 0.0.0.0 8000
```

Port `8000` will then be available on the host and you can connect to it with the following
command from another terminal:

```console
$ nc localhost 8000
```

What you type in here will then appear on the terminal where the container is
running.

To access a service running on the host from the container, you can start a container with
host networking enabled with this command:

```console
$ docker run --rm -it --net=host nicolaka/netshoot
```

If you then want to access a service on your host from the container (in this
example a web server running on port `80`), you can do it like this:

```console
$ nc localhost 80
```

### Limitations

- Processes inside the container cannot bind to the IP addresses of the host
  because the container has no direct access to the interfaces of the host.
- The host network feature of Docker Desktop works on layer 4. This means that
  unlike with Docker on Linux, network protocols that operate below TCP or UDP are
  not supported.
- This feature doesn't work with Enhanced Container Isolation enabled, since
  isolating your containers from the host and allowing them access to the host
  network contradict each other.
- Only Linux containers are supported. Host networking does not work with
  Windows containers.

## Usage example

This example shows how to start an Nginx container that binds directly to port
80 on the Docker host. From a networking perspective, this provides the same
level of isolation as if Nginx were running directly on the host, but the
container remains isolated in all other aspects (storage, process namespace,
user namespace).

### Prerequisites

- Port 80 must be available on the Docker host. To make Nginx listen on a
  different port, see the [Nginx image documentation](https://hub.docker.com/_/nginx/).
- The host networking driver only works on Linux hosts, and as an opt-in
  feature in Docker Desktop version 4.34 and later.

### Steps

1. Create and start the container as a detached process. The `--rm` option
  removes the container when it exits. The `-d` flag starts it in the
  background:
  ```console
  $ docker run --rm -d --network host --name my_nginx nginx
  ```
2. Access Nginx by browsing to [http://localhost:80/](http://localhost:80/).
3. Examine your network stack:
  Check all network interfaces and verify that no new interface was created:
  ```console
  $ ip addr show
  ```
  Verify which process is bound to port 80 using `netstat`. You need `sudo`
  because the process is owned by the Docker daemon user:
  ```console
  $ sudo netstat -tulpn | grep :80
  ```
4. Stop the container. It's removed automatically because of the `--rm` option:
  ```console
  $ docker container stop my_nginx
  ```

## Next steps

- Learn about [networking from the container's point of view](https://docs.docker.com/engine/network/)
- Learn about [bridge networks](https://docs.docker.com/engine/network/drivers/bridge/)
- Learn about [overlay networks](https://docs.docker.com/engine/network/drivers/overlay/)
- Learn about [Macvlan networks](https://docs.docker.com/engine/network/drivers/macvlan/)
