---
# System prepended metadata

title: Docker Network
tags: [docker, Linux]

---

# Docker Network

## Docker Network 狀態
* 預設會有3個
```bash=
$ sudo docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
16c450163344   bridge    bridge    local
77bcc73aa5d2   host      host      local
73e1b85fe920   none      null      local
```

## Docker Network 簡介

* 預設會走 bridge
* 先跑幾個容器


![image](https://hackmd.io/_uploads/Hki-IqxHT.png)(https://godleon.github.io/blog/images/docker/bridge_network.jpg)

![image](https://hackmd.io/_uploads/SJZc89xSa.png)

### 查看橋接網卡
```bash=
[user@docker1 ~]$ brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242aefd8a1f	no		veth0b996df
							veth2e755f7
							veth5ab4339
virbr0		8000.525400dc98bd	yes		virbr0-nic
```

:::info
`brctl` 可以做很多事情, 包括增加/刪除網卡
:::

### 查看容器網卡資訊
* 網卡資訊
```bash=
[user@docker1 ~]$ sudo docker network inspect bridge
[
    {
        "Name": "bridge",    # docker network name
        "Id": "16c450163344edc8283d7f3db5058534b7a16e505aa4176af8f9f5a14d300de8",
        "Created": "2023-11-26T17:29:47.031410413+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            # busybox 1
            "019c290829e6f19d925c9058b2bc01ad30931e33f405ca52dfd89eb17b2edb7c": {
                "Name": "cranky_ganguly",
                "EndpointID": "126cee41d9a06df1c571e465299e7d6108b098ade3693462b4b5fcbb8b0358b7",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            # busybox 2
            "8c4545f8196b6690b01051ffe8fb94549ced8334076ac5c9da93611ea95f350a": {
                "Name": "quirky_hugle",
                "EndpointID": "962231e5a4005a3183b36620311c9e178a75f33142f2d0e1eb8d0c1c30bf78e6",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            # busybox 3
            "f9ebcc09f497a80e2ad8c31f64cf6d9e11533ccf6fbb641c9462ac99c334c191": {
                "Name": "stoic_mccarthy",
                "EndpointID": "cbb78e9e7bbc0d24628c83fd024d4c253e18f9f655c729911e38318a63ddc604",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",    # 本地網卡名字
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]
```
* 容器互ping
```bash=
/ # ping -c 3 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.079 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.111 ms
64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.097 ms

--- 172.17.0.3 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.079/0.095/0.111 ms
/ # ping -c 3 172.17.0.4
PING 172.17.0.4 (172.17.0.4): 56 data bytes
64 bytes from 172.17.0.4: seq=0 ttl=64 time=0.125 ms
64 bytes from 172.17.0.4: seq=1 ttl=64 time=0.085 ms
64 bytes from 172.17.0.4: seq=2 ttl=64 time=0.100 ms

--- 172.17.0.4 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.085/0.103/0.125 ms

# 用 "name" ping 不通
/ # ping -c 3 b2
ping: bad address 'b2'
/ # ping -c 3 b3
ping: bad address 'b3'
```

### 自訂 bridge network
* 建立 bridge 網路
```bash=
$ sudo docker network create --driver bridge test-br
71a26db5d96d0f38226d68ac4e9271a56121a602b177e3118865e7fdb64dff5d

$ sudo docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
16c450163344   bridge    bridge    local
77bcc73aa5d2   host      host      local
73e1b85fe920   none      null      local
71a26db5d96d   test-br   bridge    local
```
* 查看新增的資訊
```bash=
$ sudo ip a s
47: br-71a26db5d96d: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:dd:f9:0b:a4 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global br-71a26db5d96d
       valid_lft forever preferred_lft forever

$ sudo docker network inspect test-br
[
    {
        "Name": "test-br",
        "Id": "71a26db5d96d0f38226d68ac4e9271a56121a602b177e3118865e7fdb64dff5d",
        "Created": "2023-11-26T18:50:32.894562997+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
```

* 再開兩個終端
```bash=
sudo docker run -d --name br1 --network test-br busybox sh
sudo docker run -d --name br2 --network test-br busybox sh
```
**可用IP, Name 互ping**
![image](https://hackmd.io/_uploads/ByzrHjeH6.png)

:::info
預設的 bridge 無法用 name 互通, 如果在一個有 web server 跟 DB 的環境, 用自訂的 bridge 就不必知道對方IP
:::

* 新增網卡到 busybox 裡
    1. 最初
    ```bash=
    / # ip a s
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
        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
    41: eth0@if42: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
        link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    ```
    * 新增網卡
    ```bash=
    $ sudo docker network connect test-br b1
    ```
    * 添加完成
    ```bash=
    / # ip a s
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
        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
    41: eth0@if42: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
        link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    54: eth1@if55: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
        link/ether 02:42:ac:12:00:04 brd ff:ff:ff:ff:ff:ff
        inet 172.18.0.4/16 brd 172.18.255.255 scope global eth1
           valid_lft forever preferred_lft forever
    ```
    
## 實作測試

參考: 
【Docker系列】Python Flask + Redis 练习程序

————————————————
版权声明：本文为CSDN博主「小叶柏杉」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
原文链接：https://blog.csdn.net/weixin_48447848/article/details/122612582

* Python Flash + Redis
    * flash 為 python 前端框架
    * Redis 為 快取型資料庫
### 測試目錄準備
```bash=
$ tree docker_network/
docker_network/
├── app.py
└── Dockerfile
```
* app.py # 6379為 redis 預設port
```python=
from flask import Flask
from redis import Redis
import os
import socket

app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)


@app.route('/')
def hello():
    redis.incr('hits')
    return f"Hello Container World! I have been seen {redis.get('hits').decode('utf-8')} times and my hostname is {socket.gethostname()}.\n"
```
* Dockerfile
```dockerfile=
FROM python:3.9.18-slim

RUN pip install flask redis && \
    groupadd -r flask && useradd -r -g flask flask && \
    mkdir /src && \
    chown -R flask:flask /src

USER flask

COPY app.py /src/app.py

WORKDIR /src

ENV FLASK_APP=app.py REDIS_HOST=redis

EXPOSE 5000

CMD ["flask", "run", "-h", "0.0.0.0"]
```

### image prepare
```bash=
$ sudo docker pull redis
$ sudo docker build -t flask-test:0.3 .

$ sudo docker images
REPOSITORY                    TAG              IMAGE ID       CREATED          SIZE
flask-test                    0.3              473c2177dd0f   11 seconds ago   140MB
redis                         latest           961dda256baa   2 weeks ago      138MB
```

### network
```bash=
$ sudo docker network create --driver bridge test-network
```

### container
* 執行完後瀏覽器打開看看 (虛擬機可用127.0.0.1:5000)
```bash=
$ sudo docker run -d --name redis-server --network test-network redis
# --env REDIS_HOST=redis-server (container_name)
$ sudo docker run -d --name flask-python --network test-network -p 5000:5000 --env REDIS_HOST=redis-server flask-test:0.5
```

### docker_compose
* docker-compose.yml
```bash=
version: '2.3'
services:
  flask-demo:
    image: flask-test:0.5
    container_name: flask-python
    environment:
      REDIS_HOST: redis-server
    depends_on:    # 表示要等 redis-server 啟動
      - redis-server
    ports:
      - "5000:5000"
    networks:
      - test-network
  redis-server:
    image: redis:latest
    container_name: redis-server
    networks:
      - test-network
networks:
  test-network:
```
* run (開瀏覽器看)
```bash=
sudo docker-compose up -d
[+] Running 2/2
 ✔ Container redis-server  Started                                    0.0s 
 ✔ Container flask-python  Started                                    0.0s 
```


## Reference page
[[Docker] Bridge Network 簡介](https://godleon.github.io/blog/Docker/docker-network-bridge/)
