# Running webrtc in a docker container: candidate IP issue

**URL:** https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450
**Category:** Application Development
**Created:** [November 2, 2023, 5:56pm UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450 "2023-11-02T17:56:37Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![rayrapetyan](https://discourse.gstreamer.org/user_avatar/discourse.gstreamer.org/rayrapetyan/32/43_2.png) [@rayrapetyan](https://discourse.gstreamer.org/u/rayrapetyan)
#### Post date: [November 2, 2023, 5:56pm UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/1 "2023-11-02T17:56:37Z")

</div>

When running webrtc streamer inside a docker container, it reports candidate IPs as local docker IPs to the signalling server, therefore client fails to connect. Is there any option to forcefully define e.g. “EXTERNAL\_IP” reported to signalling server?  
Note: using `--network=host` is not an option for my case as there are other conflicts in my stack.

---

<div class="post-metadata">

### Author: ![arun](https://discourse.gstreamer.org/user_avatar/discourse.gstreamer.org/arun/32/87_2.png) [@arun](https://discourse.gstreamer.org/u/arun)
#### Post date: [November 2, 2023, 8:31pm UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/2 "2023-11-02T20:31:12Z")

</div>

With recent GStreamer, you can get the `ice-agent` on `webrtcbin` and use the `add-local-ip-address` signal on it to provide your external IP address.

---

<div class="post-metadata">

### Author: ![ocrete](https://discourse.gstreamer.org/user_avatar/discourse.gstreamer.org/ocrete/32/33_2.png) [@ocrete](https://discourse.gstreamer.org/u/ocrete)
#### Post date: [November 2, 2023, 8:33pm UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/3 "2023-11-02T20:33:36Z")

</div>

And be sure to do it before setting the local description, as this is the point where the list of local candidates is “frozen” in libnice.

---

<div class="post-metadata">

### Author: ![rayrapetyan](https://discourse.gstreamer.org/user_avatar/discourse.gstreamer.org/rayrapetyan/32/43_2.png) [@rayrapetyan](https://discourse.gstreamer.org/u/rayrapetyan)
#### Post date: [November 2, 2023, 8:49pm UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/4 "2023-11-02T20:49:45Z")

</div>

So no way to do the same from gst-launch right? Would it be a useful to add this as a parameter of webrtcbin?

---

<div class="post-metadata">

### Author: ![ystreet00](https://discourse.gstreamer.org/letter_avatar_proxy/v4/letter/y/3d9bf3/32.png) [@ystreet00](https://discourse.gstreamer.org/u/ystreet00)
#### Post date: [November 2, 2023, 11:15pm UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/5 "2023-11-02T23:15:54Z")

</div>

Not possible from gst-launch, no.

I’m not really going to entertain the idea of adding ICE-specific properties that are not specified in JSEP on the `webrtcbin` object.

---

<div class="post-metadata">

### Author: ![rayrapetyan](https://discourse.gstreamer.org/user_avatar/discourse.gstreamer.org/rayrapetyan/32/43_2.png) [@rayrapetyan](https://discourse.gstreamer.org/u/rayrapetyan)
#### Post date: [November 5, 2023, 1:27am UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/6 "2023-11-05T01:27:05Z")

</div>

Could you help to extract webrtcbin from the pipeline which uses webrtcsink? Basically something like:

```auto
wrs = Gst.ElementFactory.make("webrtcsink", "wrs")
wrb = wrs.get_property("webrtcbin")

```

doesn’t work.  
Or it’s also not possible and I need to build the whole pipeline from scratch without webrtcsink if I need to set a custom external IP?

---

<div class="post-metadata">

### Author: ![ystreet00](https://discourse.gstreamer.org/letter_avatar_proxy/v4/letter/y/3d9bf3/32.png) [@ystreet00](https://discourse.gstreamer.org/u/ystreet00)
#### Post date: [November 5, 2023, 9:43am UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/7 "2023-11-05T09:43:52Z")

</div>

Connect to the [consumer-added](https://gstreamer.freedesktop.org/documentation/rswebrtc/webrtcsink.html?gi-language=c#GstBaseWebRTCSink::consumer-added) signal on `webrtcsink`. See also [net/webrtc/src/webrtcsink/imp.rs · main · GStreamer / gst-plugins-rs · GitLab](https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/blob/main/net/webrtc/src/webrtcsink/imp.rs?ref_type=heads#L3682)

You can also connect to the [consumer-added](https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/blob/main/net/webrtc/src/signaller/iface.rs?ref_type=heads#L280) signal on the `signaller` which will also give you the same information.

---

<div class="post-metadata">

### Author: ![rayrapetyan](https://discourse.gstreamer.org/user_avatar/discourse.gstreamer.org/rayrapetyan/32/43_2.png) [@rayrapetyan](https://discourse.gstreamer.org/u/rayrapetyan)
#### Post date: [November 5, 2023, 4:29pm UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/8 "2023-11-05T16:29:35Z")

</div>

Tried this:

```auto
def consumer_added_callback(wrs, session_id, udata):
    print('Consumer {} added'.format(udata))
    iceagent = udata.get_property("ice-agent")
    print(iceagent)
    iceagent.emit('add-local-ip-address', '192.168.1.66')

```

And it gives:

```auto
Consumer < __gi__.GstWebRTCBin object at 0x7f2ee74fcd00 (GstWebRTCBin at 0x7f2ed8068120)> added
< __gi__.GstWebRTCNice object at 0x7f2ee74c30c0 (GstWebRTCNice at 0x7f2ed8074110)>

(runme.py:3748198): GStreamer-WebRTC-CRITICAL **: 08:24:09.901: gst_webrtc_ice_add_stream: assertion 'GST_IS_WEBRTC_ICE (ice)' failed

(runme.py:3748198): GStreamer-WebRTC-CRITICAL **: 08:24:09.901: gst_webrtc_ice_find_transport: assertion 'GST_IS_WEBRTC_ICE (ice)' failed

(runme.py:3748198): GStreamer-WebRTC-CRITICAL **: 08:24:09.901: gst_webrtc_dtls_transport_set_transport: assertion 'GST_IS_WEBRTC_ICE_TRANSPORT (ice)' failed

(runme.py:3748198): GStreamer-CRITICAL **: 08:24:09.901: gst_object_unref: assertion 'object != NULL' failed
Segmentation fault

```

Critical errors are coming after this particular line of code:

```auto
iceagent = udata.get_property("ice-agent")

```

As far as I understood, ice-agent is not yet initialized when consumer\_added\_callback is triggered…

---

<div class="post-metadata">

### Author: ![rayrapetyan](https://discourse.gstreamer.org/user_avatar/discourse.gstreamer.org/rayrapetyan/32/43_2.png) [@rayrapetyan](https://discourse.gstreamer.org/u/rayrapetyan)
#### Post date: [November 7, 2023, 6:08pm UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/9 "2023-11-07T18:08:39Z")

</div>

Ok, the latter most probably is a Pythons’ binder issue: [Certain referenced objects are being destroyed within a callback (#605) · Issues · GNOME / pygobject · GitLab](https://gitlab.gnome.org/GNOME/pygobject/-/issues/605)

---

<div class="post-metadata">

### Author: ![rayrapetyan](https://discourse.gstreamer.org/user_avatar/discourse.gstreamer.org/rayrapetyan/32/43_2.png) [@rayrapetyan](https://discourse.gstreamer.org/u/rayrapetyan)
#### Post date: [November 8, 2023, 1:16am UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/10 "2023-11-08T01:16:44Z")

</div>

@arun, @ocrete, the `add-local-ip-address` method doesn’t work as libnice tries to create a socket using this IP and fails (which is expected as external IPs are not available inside a docker container). E.g. if user passes 192.168.1.113, then:

```auto
libnice-DEBUG: 01:07:31.411: Agent 0x7f7e50093170: s1/c1: creation of host candidate udp:[192.168.1.113]:50003: can't create socket
libnice-DEBUG: 01:07:31.411: Interface: lo
libnice-DEBUG: 01:07:31.411: IP Address: 127.0.0.1
libnice-DEBUG: 01:07:31.411: Interface: eth0
libnice-DEBUG: 01:07:31.411: IP Address: 172.17.0.6
libnice-DEBUG: 01:07:31.411: Agent 0x7f7e50093170: s1/c1: creation of host candidate udp:[192.168.1.113]:50004: can't create socket
libnice-DEBUG: 01:07:31.411: Interface: lo
libnice-DEBUG: 01:07:31.411: IP Address: 127.0.0.1
libnice-DEBUG: 01:07:31.411: Interface: eth0
libnice-DEBUG: 01:07:31.411: IP Address: 172.17.0.6
libnice-DEBUG: 01:07:31.411: Agent 0x7f7e50093170: s1/c1: creation of host candidate udp:[192.168.1.113]:50005: can't create socket
libnice-DEBUG: 01:07:31.411: Interface: lo
libnice-DEBUG: 01:07:31.411: IP Address: 127.0.0.1
libnice-DEBUG: 01:07:31.411: Interface: eth0
libnice-DEBUG: 01:07:31.411: IP Address: 172.17.0.6

```

From one side, it’s expected, from another - this could be a bug and libnice should be tweaked to always create socket on 0.0.0.0 in case `add-local-ip-address` was used?

---

<div class="post-metadata">

### Author: ![ocrete](https://discourse.gstreamer.org/user_avatar/discourse.gstreamer.org/ocrete/32/33_2.png) [@ocrete](https://discourse.gstreamer.org/u/ocrete)
#### Post date: [November 8, 2023, 3:41am UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/11 "2023-11-08T03:41:41Z")

</div>

It’s on purpose, those APIs are meant to allow the application developer to select the local interface on which to create the socket.

---

<div class="post-metadata">

### Author: ![ocrete](https://discourse.gstreamer.org/user_avatar/discourse.gstreamer.org/ocrete/32/33_2.png) [@ocrete](https://discourse.gstreamer.org/u/ocrete)
#### Post date: [November 8, 2023, 3:44am UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/12 "2023-11-08T03:44:09Z")

</div>

The general solution is to use a stun server, as this can quickly get complicated, for example if you have your Docker inside a cloud server which itself has another set of private IP addresses.

Also, if you use some kind of address translation, it may also change the ports…

---

<div class="post-metadata">

### Author: ![rayrapetyan](https://discourse.gstreamer.org/user_avatar/discourse.gstreamer.org/rayrapetyan/32/43_2.png) [@rayrapetyan](https://discourse.gstreamer.org/u/rayrapetyan)
#### Post date: [November 8, 2023, 3:25pm UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/13 "2023-11-08T15:25:03Z")

</div>

Seems I’m looking for a non-existing “add-external-ip-address” interface then. I believe that having such an option in layered environments, as you’ve described, would prove to be highly beneficial.

Stun servers present a challenge due to the need to manage distinct stun server configurations at various layers, depending on where the server and client are deployed. This entails maintaining separate configurations when operating the server and client on localhost, within a local network, or beyond the LAN. It would be far more convenient to streamline this process by simply passing an external IP address as a configuration parameter.

Additionally, I have observed that responses from a coturn/coturn server operating in a stun-only mode may not be correctly identified by libnice. It’s possible that certain properties in the coturn configuration need to be adjusted to address this issue…

---

<div class="post-metadata">

### Author: ![rayrapetyan](https://discourse.gstreamer.org/user_avatar/discourse.gstreamer.org/rayrapetyan/32/43_2.png) [@rayrapetyan](https://discourse.gstreamer.org/u/rayrapetyan)
#### Post date: [November 11, 2023, 2:29am UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/14 "2023-11-11T02:29:13Z")

</div>

See also: [Running libnice in a containerized environment (#182) · Issues · libnice / libnice · GitLab](https://gitlab.freedesktop.org/libnice/libnice/-/issues/182)

---

<div class="post-metadata">

### Author: ![ocrete](https://discourse.gstreamer.org/user_avatar/discourse.gstreamer.org/ocrete/32/33_2.png) [@ocrete](https://discourse.gstreamer.org/u/ocrete)
#### Post date: [December 20, 2023, 12:15am UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/15 "2023-12-20T00:15:01Z")

</div>

Passing the external IP address is not really useful, you’d also need to be able to do the port mapping correctly…

---

<div class="post-metadata">

### Author: ![rayrapetyan](https://discourse.gstreamer.org/user_avatar/discourse.gstreamer.org/rayrapetyan/32/43_2.png) [@rayrapetyan](https://discourse.gstreamer.org/u/rayrapetyan)
#### Post date: [December 20, 2023, 12:46am UTC](https://discourse.gstreamer.org/t/running-webrtc-in-a-docker-container-candidate-ip-issue/450/16 "2023-12-20T00:46:49Z")

</div>

You’re correct, seems the only valid way to run webrtc server inside a docker container is with a --network=host parameter.
