Cannot setup WebRTCTransport to mediasoup server inside of Docker instance, using ip 127.0.0.1(gstreamer pipeline cmd publisher in docker)

Hi, I’m using gstreamer to do a streaming test, receiver side is webpage/WebRTCTransport, the pipeline cmd is:

    const callRTPStreamPushCmd = `GST_DEBUG="*:4" gst-launch-1.0 \
	rtpbin name=rtpbin \
    videotestsrc \
    ! queue \
    ! videoconvert \
	! vp8enc \
	! rtpvp8pay pt=101 ssrc=22222222 picture-id-mode=2 \
	! rtpbin.send_rtp_sink_0 \
	rtpbin.send_rtp_src_0 ! udpsink host=${videoTransportIp} port=${videoTransportPort} \
	rtpbin.send_rtcp_src_0 ! udpsink host=${videoTransportIp} port=${videoTransportRtcpPort} sync=false async=false`

This works on Mac (while mediasoup log says keyframe interval is 4s), & mediasoup log here:

on client Tu5vvKX1Y9ERHTnZAAAD connectTransport
2021-10-17T11:54:14.492Z mediasoup:WebRtcTransport connect()
2021-10-17T11:54:14.492Z mediasoup:Channel request() [method:transport.connect, id:7]
2021-10-17T11:54:14.492Z mediasoup:Channel request succeeded [method:transport.connect, id:7]
2021-10-17T11:54:14.498Z mediasoup:Channel [pid:52177] RTC::IceServer::HandleTuple() | transition from state 'new' to 'connected'
2021-10-17T11:54:14.499Z mediasoup:Channel [pid:52177] RTC::WebRtcTransport::OnIceServerSelectedTuple() | ICE selected tuple
2021-10-17T11:54:14.499Z mediasoup:Channel [pid:52177] RTC::WebRtcTransport::OnIceServerConnected() | ICE connected
2021-10-17T11:54:14.499Z mediasoup:Channel [pid:52177] RTC::WebRtcTransport::MayRunDtlsTransport() | running DTLS transport in local role 'server'
2021-10-17T11:54:14.499Z mediasoup:Channel [pid:52177] RTC::WebRtcTransport::OnDtlsTransportConnecting() | DTLS connecting
2021-10-17T11:54:14.499Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::Run() | running [role:server]
2021-10-17T11:54:14.499Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | DTLS handshake start
2021-10-17T11:54:14.499Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'before SSL initialization']
2021-10-17T11:54:14.499Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | role: server, waiting:'before SSL initialization']
2021-10-17T11:54:14.500Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'before SSL initialization']
2021-10-17T11:54:14.500Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'SSLv3/TLS read client hello']
2021-10-17T11:54:14.500Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'SSLv3/TLS write server hello']
2021-10-17T11:54:14.500Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'SSLv3/TLS write certificate']
2021-10-17T11:54:14.500Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'SSLv3/TLS write key exchange']
2021-10-17T11:54:14.500Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'SSLv3/TLS write certificate request']
2021-10-17T11:54:14.500Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'SSLv3/TLS write server done']
2021-10-17T11:54:14.500Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | role: server, waiting:'SSLv3/TLS write server done']
2021-10-17T11:54:14.501Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'SSLv3/TLS write server done']
2021-10-17T11:54:14.501Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'SSLv3/TLS read client certificate']
2021-10-17T11:54:14.501Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'SSLv3/TLS read client key exchange']
2021-10-17T11:54:14.502Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'SSLv3/TLS read certificate verify']
2021-10-17T11:54:14.502Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'SSLv3/TLS read change cipher spec']
2021-10-17T11:54:14.502Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'SSLv3/TLS read finished']
2021-10-17T11:54:14.502Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'SSLv3/TLS write change cipher spec']
2021-10-17T11:54:14.502Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | [role:server, action:'SSLv3/TLS write finished']
2021-10-17T11:54:14.502Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::OnSslInfo() | DTLS handshake done
2021-10-17T11:54:14.502Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::CheckRemoteFingerprint() | valid remote fingerprint
2021-10-17T11:54:14.502Z mediasoup:Channel [pid:52177] RTC::DtlsTransport::GetNegotiatedSrtpCryptoSuite() | chosen SRTP crypto suite: SRTP_AEAD_AES_256_GCM
2021-10-17T11:54:14.502Z mediasoup:Channel [pid:52177] RTC::WebRtcTransport::OnDtlsTransportConnected() | DTLS connected
on client Tu5vvKX1Y9ERHTnZAAAD resume
2021-10-17T11:54:14.507Z mediasoup:Consumer resume()
2021-10-17T11:54:14.507Z mediasoup:Channel request() [method:consumer.resume, id:8]
2021-10-17T11:54:14.508Z mediasoup:Channel request succeeded [method:consumer.resume, id:8]
2021-10-17T11:54:14.508Z mediasoup:Channel [pid:52177] RTC::Transport::HandleRtcpPacket() | PLI received, requesting key frame for Consumer [sender ssrc:1, media ssrc:852093862]
2021-10-17T11:54:14.547Z mediasoup:Channel [pid:52177] RTC::IceServer::HandleTuple() | transition from state 'connected' to 'completed'
2021-10-17T11:54:14.547Z mediasoup:Channel [pid:52177] RTC::WebRtcTransport::OnIceServerCompleted() | ICE completed
2021-10-17T11:54:16.951Z mediasoup:Channel [pid:52177] RTC::Producer::ReceiveRtpPacket() | key frame received [ssrc:22222222, seq:6564]
2021-10-17T11:54:16.951Z mediasoup:Channel [pid:52177] RTC::SimpleConsumer::SendRtpPacket() | sync key frame received
2021-10-17T11:54:16.951Z mediasoup:Channel [pid:52177] RTC::SimpleConsumer::SendRtpPacket() | sending sync packet [ssrc:852093862, seq:1, ts:4198747132] from original [seq:6564]
2021-10-17T11:54:21.215Z mediasoup:Channel [pid:52177] RTC::Producer::ReceiveRtpPacket() | key frame received [ssrc:22222222, seq:6705]
2021-10-17T11:54:25.481Z mediasoup:Channel [pid:52177] RTC::Producer::ReceiveRtpPacket() | key frame received [ssrc:22222222, seq:6846]
2021-10-17T11:54:29.750Z mediasoup:Channel [pid:52177] RTC::Producer::ReceiveRtpPacket() | key frame received [ssrc:22222222, seq:6987]

However, when i run mediasoup server inside docker, something wrong happened:
The log line

RTC::IceServer::HandleTuple() | transition from state 'new' to 'connected'

would never hit, and chrome browser page consumer logs:

mediasoup-client:Transport consume() | Consumer for RTP probation created +6ms
mediasoup-client:Transport connection state changed to disconnected +15s

To me, it looks like webrtc client cannot setup ICE-lite connection with the server in docker, which makes me puzzled

Please help! Anyone could give some hints?

My mediasoup config is:

const CONFIG = {
    listenIp: '0.0.0.0',
    listenPort: 80, //http for local test;
    listenPortTls: 443, //https for remote access;
...
      webRtcTransport: {
        listenIps: [
          {
            ip: '127.0.0.1',
            announcedIp: null, //TODO: how to set it inside docker?
          }
        ],
        maxIncomingBitrate: 15000000,
        initialAvailableOutgoingBitrate: 1000000,
      }
    }

The RTP port range is 10000~10010, so i put the line below into Dockerfile:

EXPOSE 443
EXPOSE 6666
EXPOSE 10000/udp
EXPOSE 10001/udp
EXPOSE 10002/udp
EXPOSE 10003/udp
EXPOSE 10004/udp
EXPOSE 10005/udp
EXPOSE 10006/udp
EXPOSE 10007/udp
EXPOSE 10008/udp
EXPOSE 10009/udp
EXPOSE 10010/udp

gstreamer is running inside of docker, producer side seems OK.

My docker instance start cmdline is:

docker run --rm -it \
  -p 80:80 -p 443:443 \
  -p 10000-10010:10000-10010/udp \
  --name gui-render-server-dev-instance \
  --mount type=bind,source="$(pwd)"/../../,target=/repo \
  gui-render-server-dev:latest bash

I didn’t config announcedIp here, for i’m using http://127.0.0.1:80 to access server in docker, even not using LAN ip.

I’ve tried --network host option for docker run, and it’s not working.

To sum generally: Cannot setup WebRTCTransport from 127.0.0.1 to server inside of docker, with latest mediasoup, it seems i’ve found similar issues when searching for ICE docker

2021-10-17T12:17:29.459Z mediasoup:Channel [pid:171] mediasoup-worker::run_worker() | starting mediasoup-worker process [version:3.8.4]
2021-10-17T12:17:29.460Z mediasoup:Channel [pid:171] mediasoup-worker::run_worker() | little-endian CPU detected
2021-10-17T12:17:29.460Z mediasoup:Channel [pid:171] mediasoup-worker::run_worker() | 64 bits architecture detected
2021-10-17T12:17:29.460Z mediasoup:Channel [pid:171] Settings::PrintConfiguration() | <configuration>
2021-10-17T12:17:29.461Z mediasoup:Channel [pid:171] Settings::PrintConfiguration() |   logLevel            : debug
2021-10-17T12:17:29.461Z mediasoup:Channel [pid:171] Settings::PrintConfiguration() |   logTags             : info,ice,dtls,rtp,srtp,rtcp
2021-10-17T12:17:29.462Z mediasoup:Channel [pid:171] Settings::PrintConfiguration() |   rtcMinPort          : 10000
2021-10-17T12:17:29.462Z mediasoup:Channel [pid:171] Settings::PrintConfiguration() |   rtcMaxPort          : 10100
2021-10-17T12:17:29.462Z mediasoup:Channel [pid:171] Settings::PrintConfiguration() | </configuration>
2021-10-17T12:17:29.463Z mediasoup:Channel [pid:171] DepLibUV::PrintVersion() | libuv version: "1.42.0"
2021-10-17T12:17:29.463Z mediasoup:Channel [pid:171] DepOpenSSL::operator()() | openssl version: "OpenSSL 1.1.1k+quic  25 Mar 2021"
2021-10-17T12:17:29.463Z mediasoup:Channel [pid:171] DepLibSRTP::ClassInit() | libsrtp version: "libsrtp 2.3.0"
2021-10-17T12:17:29.463Z mediasoup:Channel [pid:171] DepUsrSCTP::ClassInit() | usrsctp

Hi,

When I pull mediasoup server out of docker, but still run gstreamer publisher inside of docker, using "host.docker.internal" to access server, then everything works fine.

Ok, host mode networking doesn’t work on docker for Mac.
But the problem here is: why can’t i setup chrome web page consumer (WebrtcTransport) to mediasoup inside of docker? Or it’s due to chrome version upgrade?
I’ve tried Firefox, it reports a “Uncaught (in promise) InvalidStateError: not loaded” error in createRecvTransport(), and i notice that the SDP offer firefox receives has en extra payloadType 100, but i only config a 101 for VP8!

The producer side PlainTransport can connect to mediasoup inside docker, but the consumer side WebrtcTransport cannot.

Also verify on latest 3.9.2: not working.

The server reports error for producer after initial time of success:

  mediasoup:Channel [pid:16] RTC::Producer::ReceiveRtpPacket() | key frame received [ssrc:22222222, seq:9996] +5s
  mediasoup:Channel [pid:16] RTC::Producer::ReceiveRtpPacket() | key frame received [ssrc:22222222, seq:10125] +5s
  mediasoup:Channel [pid:16] RTC::Producer::ReceiveRtpPacket() | key frame received [ssrc:22222222, seq:10254] +5s
  mediasoup:Channel [pid:16] RTC::PlainTransport::OnRtpDataReceived() | ignoring RTP packet from unknown IP:port +3s
  mediasoup:Channel [pid:16] RTC::PlainTransport::OnRtpDataReceived() | ignoring RTP packet from unknown IP:port +42ms
  mediasoup:Channel [pid:16] RTC::PlainTransport::OnRtpDataReceived() | ignoring RTP packet from unknown IP:port +40ms
  mediasoup:Channel [pid:16] RTC::PlainTransport::OnRtpDataReceived() | ignoring RTP packet from unknown IP:port +39ms
  mediasoup:Channel [pid:16] RTC::PlainTransport::OnRtpDataReceived() | ignoring RTP packet from unknown IP:port +39ms
  mediasoup:Channel [pid:16] RTC::PlainTransport::OnRtpDataReceived() | ignoring RTP packet from unknown IP:port +40ms
  mediasoup:Channel [pid:16] RTC::PlainTransport::OnRtpDataReceived() | ignoring RTP packet from unknown IP:port +41ms
...

i added new log in server side:

    socket.on('createTransport', async (data, callback) => {
      console.log(`on client ${socket.id} createTransport`);
      try {
        const { transport, params } = await createWebRtcTransport({
            listenIps : [ { ip: "127.0.0.1", announcedIp: null } ],
            enableUdp : true,
            enableTcp : false,
            preferUdp : true
        });
        console.log("server/createTransport: webrtc params="+JSON.stringify(params));

& log output:

server/createTransport: webrtc params={"id":"d841e211-9f27-4ce2-bc13-97c5fa0973c8","iceParameters":{"iceLite":true,"password":"c0bl8v56gmknohqthxoa5gq71jdgh2ru","usernameFragment":"3fyo36g9vhzmjc5g"},"iceCandidates":[{"foundation":"udpcandidate","ip":"127.0.0.1","port":10004,"priority":1076558079,"protocol":"udp","type":"host"},{"foundation":"tcpcandidate","ip":"127.0.0.1","port":10001,"priority":1076302079,"protocol":"tcp","tcpType":"passive","type":"host"}],"dtlsParameters":{"fingerprints":[{"algorithm":"sha-1","value":"3F:F5:FE:35:0F:7C:B0:1B:8D:F7:0A:4D:44:FD:F9:84:85:C6:26:B9"},{"algorithm":"sha-224","value":"06:7B:AF:2D:EC:50:48:85:68:6B:64:FF:29:4C:09:77:84:E5:38:B3:76:EB:D4:68:78:F4:57:42"},{"algorithm":"sha-256","value":"51:A5:2F:AB:C9:2B:48:08:A0:E1:02:C1:1E:2F:18:03:63:F6:66:56:86:0E:CC:4B:5A:2F:81:F8:95:CB:BB:2E"},{"algorithm":"sha-384","value":"17:99:4C:2A:E4:D8:F6:F9:1F:AE:16:EB:73:87:1D:86:C9:F1:5C:F5:BE:80:12:DC:AA:ED:AC:F4:F8:95:BB:68:E7:0F:66:29:52:13:BB:3A:0D:59:72:30:40:3B:2A:BB"},{"algorithm":"sha-512","value":"7D:78:DD:6E:49:21:8A:92:A2:0D:0E:DD:21:2A:F2:90:0B:F2:31:8E:56:88:00:C9:CD:AA:48:30:15:A5:72:A1:29:93:EE:EF:31:06:E9:13:7A:98:78:85:08:07:A4:4E:AF:FE:D3:36:DE:4A:62:5F:9B:C1:28:F3:36:4D:B6:20"}],"role":"auto"}}

The problem here is: i’ve set enableTcp to false, why the params still has TCP port?

try set webpage client forceTcp to true:

  const data = await socket.request('createTransport', {
    forceTcp: true,
  });

but still not working.

Same in the other thread, just read the docs on IPs, there have been numerous posts about this on the forum.

Hi, i found i’ve already solved this problem, but i previously thought it was a regression bug…

The main config nodejs:

const ip = require('ip')
const local_ip_address = ip.address()
console.log(`CONFIG: local ip address is: ${local_ip_address}`);
console.log("CONFIG: process.env.ENV_HOST_IP="+process.env.ENV_HOST_IP);
...
      webRtcTransport: {
        listenIps: [
          {
            ip: local_ip_address,
            announcedIp: process.env.ENV_HOST_IP
          }
        ],

Then, start docker instance with env vars and -p options:

docker run --rm -it --env ENV_HOST_IP=192.168.0.10 -p 80:80 -p 443:443 -p 10000-10010:10000-10010/udp ui-preview-webrtcserver:latest bash

But i’m still a little puzzled, if it’s due to docker on Mac has virtual machine inside, and there is 2 “127.0.0.1” concepts, but why I can access TCP 80/443 port?

Also, PlainTransport is ok, i noticed i use “0.0.0.0” for it. Only WebrtcTransport needs to correctly config the listenIps map pair. What’s the difference between PlainTransport and WebrtcTransport?

A direct transport represents a direct connection between the mediasoup Node.js process and a Router instance in a mediasoup-worker subprocess.

A WebRTC transport represents a network path negotiated by both, a WebRTC endpoint and mediasoup, via ICE and DTLS procedures. A WebRTC transport may be used to receive media, to send media or to both receive and send. There is no limitation in mediasoup. However, due to their design, mediasoup-client and libmediasoupclient require separate WebRTC transports for sending and receiving.

All is documented but perhaps if something doesn’t make sense with documentation you could ask for a revision but it’s pretty straight forward.

I suspect Docker integration on macOS might include automatic re-binding of TCP ports from localhost of the VM. This is speculation, I didn’t check if it is actually the case.

I guess not, because PlainTransport for producer uses UDP port, and it has no problem~
Only WebrtcTransport has problem, and i suspect it’s related to ICE-Lite/SDP? Because PlainTransport doesn’t use this.

Hm, true. Did you use the same config and port range for both transports?

Browsers dont connect to 127.0.0.1 UDP when it comes to establish ICE/DTLS/RTP. Avoid that or announce the mac private IP in announcedIp.

1 Like

Yes, i obey the sample code config:

    mediasoup: {
      worker: {
        rtcMinPort: 10000,
        rtcMaxPort: 10010,
...

so it’s for both producer & consumer, whether PlainTransport or WebrtcTransport.