docker-composeでのコンテナに複数IFを持たせ全IFに固定IPを付与する方法

SRv6の勉強をしようと思った時にコンテナ版FRRを使えば簡単に環境準備ができるかなと思い、下記構成での構築を検討した。その際、思いの外docker-composeを利用した状態でのコンテナへの複数IF及び固定IP付与に手こずったので、忘れないようにメモ

![スクリーンショット 2024-05-05 20.44.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83723/41427eb4-c700-4c4b-8a45-958d3a04d9a9.png)

# 環境
- MacbookPro(2020)
- Podman-desktop(1.9.1)

# docerk-compose
ポイントとしては、複数のyamlファイルを作成して実行することで複数IFへの固定IP付与が可能となる。
下記yamlファイルはvolumesとか色々今回の内容としては不要な部分も記載しているが、上図の環境を構築する際にはそのまま使用できるyamlファイルなのでそのまま記載

一つ目のyamlファイル
```
version: '3'
services:
  frr1:
    image: frrouting/frr
    container_name: frr1
    hostname: frr1
    privileged: true
    volumes:
     - ./frr1:/etc/frr
    networks:
      net1_2:
        ipv4_address: 192.168.12.1
  
  frr2:
    image: frrouting/frr
    container_name: frr2
    hostname: frr2
    privileged: true
    volumes:
      - ./frr2:/etc/frr
    networks:
      net1_2:
        ipv4_address: 192.168.12.2

  frr3:
    image: frrouting/frr
    container_name: frr3
    hostname: frr3
    privileged: true
    volumes:
      - ./frr3:/etc/frr
    networks:
      net1_3:
        ipv4_address: 192.168.13.3

  frr4:
    image: frrouting/frr
    container_name: frr4
    hostname: frr4
    privileged: true
    volumes:
      - ./frr4:/etc/frr
    networks:
      net1_4:
        ipv4_address: 192.168.14.4

networks:
  net1_2:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.12.0/24

  net1_3:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.13.0/24

  net1_4:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.14.0/24

  net2_3:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.23.0/24

  net2_4:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.24.0/24

  net3_4:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.34.0/24

volumes:
  frr1:
  frr2:
  frr3:
  frr4:                                                              

```

二つ目のyamlファイル
```
version: '3'
services:
  frr1:
    networks:
      net1_3:
        ipv4_address: 192.168.13.1

  frr2:
    networks:
      net2_3:
        ipv4_address: 192.168.23.2

  frr3:
    networks:
      net2_3:
        ipv4_address: 192.168.23.3

  frr4:
    networks:
      net2_4:
        ipv4_address: 192.168.24.4
```

三つ目のyamlファイル
```
version: '3'
services:
  frr1:
    networks:
      net1_4:
        ipv4_address: 192.168.14.1

  frr2:
    networks:
      net2_4:
        ipv4_address: 192.168.24.2

  frr3:
    networks:
      net3_4:
        ipv4_address: 192.168.34.3

  frr4:
    networks:
      net3_4:
        ipv4_address: 192.168.34.4
```

# 実行
-f で複数ファイルを指定してコマンドを実行する形となる

```
gemunopedy@gemunopedynoMacBook-Pro frr % podman compose -f frr-compose.yaml -f frr2-compose.yaml -f frr3-compose.yaml up --detach
>>>> Executing external compose provider "/usr/local/bin/docker-compose". Please refer to the documentation for details. <<<<

[+] Running 10/10
 ✔ Network frr_net3_4  Created                                                                                                                           0.0s 
 ✔ Network frr_net1_2  Created                                                                                                                           0.0s 
 ✔ Network frr_net1_3  Created                                                                                                                           0.0s 
 ✔ Network frr_net1_4  Created                                                                                                                           0.0s 
 ✔ Network frr_net2_3  Created                                                                                                                           0.0s 
 ✔ Network frr_net2_4  Created                                                                                                                           0.0s 
 ✔ Container frr1      Started                                                                                                                           0.2s 
 ✔ Container frr4      Started                                                                                                                           0.2s 
 ✔ Container frr3      Started                                                                                                                           0.2s 
 ✔ Container frr2      Started                                                                                                                           0.2s 
gemunopedy@gemunopedynoMacBook-Pro frr % 
```
コンテナも正しく起動している
![スクリーンショット 2024-05-05 21.08.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83723/3e05f61f-9117-da2c-7aeb-192918c27837.png)

コンテナに直接ログインしてみての確認。ip aにて各IFに指定したアドレスが付与されている。
```
gemunopedy@gemunopedynoMacBook-Pro frr % podman exec -it frr1 /bin/sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
    inet 1.1.1.1/32 brd 1.1.1.1 scope global lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth1@if306: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ca:53:e7:43:66:95 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.12.1/24 brd 192.168.12.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::c853:e7ff:fe43:6695/64 scope link 
       valid_lft forever preferred_lft forever
3: eth0@if307: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 22:6b:dc:d1:d7:1d brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.14.1/24 brd 192.168.14.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::206b:dcff:fed1:d71d/64 scope link 
       valid_lft forever preferred_lft forever
4: eth2@if309: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 7e:c3:16:40:64:25 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.13.1/24 brd 192.168.13.255 scope global eth2
       valid_lft forever preferred_lft forever
    inet6 fe80::7cc3:16ff:fe40:6425/64 scope link 
       valid_lft forever preferred_lft forever
/ # 
```
frr上で対向routerに対してping確認を実施
```
/ # vtysh 

Hello, this is FRRouting (version 8.4_git).
Copyright 1996-2005 Kunihiro Ishiguro, et al.

frr1# show int bri
Interface       Status  VRF             Addresses
---------       ------  ---             ---------
eth0            up      default         192.168.14.1/24
eth1            up      default         192.168.12.1/24
eth2            up      default         192.168.13.1/24
lo              up      default         1.1.1.1/32

frr1# ping 192.168.12.2
PING 192.168.12.2 (192.168.12.2): 56 data bytes
64 bytes from 192.168.12.2: seq=0 ttl=64 time=1.719 ms
64 bytes from 192.168.12.2: seq=1 ttl=64 time=0.066 ms
64 bytes from 192.168.12.2: seq=2 ttl=64 time=0.105 ms
^C
--- 192.168.12.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.066/0.630/1.719 ms
frr1# ping 192.168.13.3
PING 192.168.13.3 (192.168.13.3): 56 data bytes
64 bytes from 192.168.13.3: seq=0 ttl=64 time=0.780 ms
64 bytes from 192.168.13.3: seq=1 ttl=64 time=0.078 ms
64 bytes from 192.168.13.3: seq=2 ttl=64 time=0.102 ms
^C
--- 192.168.13.3 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.078/0.320/0.780 ms
frr1# ping 192.168.14.4
PING 192.168.14.4 (192.168.14.4): 56 data bytes
64 bytes from 192.168.14.4: seq=0 ttl=64 time=0.109 ms
64 bytes from 192.168.14.4: seq=1 ttl=64 time=0.082 ms
64 bytes from 192.168.14.4: seq=2 ttl=64 time=0.092 ms
^C
--- 192.168.14.4 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.082/0.094/0.109 ms
frr1# 
```
良さそう。これでサクッとSRv6の勉強に着手できそう。（あくまで着手するだけ）

# ハマりポイント（ダメなやり方）
どう頑張っても1yamlファイルだとうまくいかなかった。記載方法は二つ試してみた一つは、networksに複数記載するやり方（不要部分省略）
```
version: '3'
services:
  frr1:
    image: frrouting/frr
    privileged: true
    networks:
      - net1_2: 192.168.12.1
      - net1_3: 192.168.13.1

networks:
  net1_2:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.12.0/24

  net1_3:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.13.0/24

```

もう一つはaux_addressにて指定する方法
```
version: '3'
services:
  frr1:
    image: frrouting/frr
    container_name: frr1
    hostname: frr1
    privileged: true
    volumes:
     - ./frr1:/etc/frr
    networks:
      - net1_2
      - net1_3

networks:
  net1_2:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.12.0/24
          aux_addresses:
            frr1: 192.168.12.1
```
           
ダメな時は、そもそもコンテナが作成されなかったり、作成されたと思っても固定IPが振られていなかったり、zebraが起動しなかったりとした