@@ -347,17 +347,36 @@ func (d *LocalRunner) Stop() error {
347
347
// reservePort finds the first available port from the startPort and reserves it
348
348
// Note that we have to keep track of the port in 'reservedPorts' because
349
349
// the port allocation happens before the services uses it and binds to it.
350
- func (d * LocalRunner ) reservePort (startPort int ) int {
350
+ func (d * LocalRunner ) reservePort (startPort int , protocol string ) int {
351
351
for i := startPort ; i < startPort + 1000 ; i ++ {
352
352
if _ , ok := d .reservedPorts [i ]; ok {
353
353
continue
354
354
}
355
- // make a net.Listen on the port to see if it is aavailable
356
- listener , err := net . Listen ( "tcp" , fmt . Sprintf ( ":%d" , i ))
357
- if err != nil {
358
- continue
355
+
356
+ bindAddr := "0.0.0.0"
357
+ if d . bindHostPortsLocally {
358
+ bindAddr = "127.0.0.1"
359
359
}
360
- listener .Close ()
360
+
361
+ if protocol == ProtocolUDP {
362
+ listener , err := net .ListenUDP ("udp" , & net.UDPAddr {
363
+ Port : i ,
364
+ IP : net .ParseIP (bindAddr ),
365
+ })
366
+ if err != nil {
367
+ continue
368
+ }
369
+ listener .Close ()
370
+ } else if protocol == ProtocolTCP {
371
+ listener , err := net .Listen (protocol , fmt .Sprintf ("%s:%d" , bindAddr , i ))
372
+ if err != nil {
373
+ continue
374
+ }
375
+ listener .Close ()
376
+ } else {
377
+ panic (fmt .Sprintf ("invalid protocol: %s" , protocol ))
378
+ }
379
+
361
380
d .reservedPorts [i ] = true
362
381
return i
363
382
}
@@ -642,7 +661,7 @@ func (d *LocalRunner) generateDockerCompose() ([]byte, error) {
642
661
// between services running inside docker and the ones running on the host machine.
643
662
for _ , svc := range d .manifest .services {
644
663
for _ , port := range svc .ports {
645
- port .HostPort = d .reservePort (port .Port )
664
+ port .HostPort = d .reservePort (port .Port , port . Protocol )
646
665
}
647
666
}
648
667
0 commit comments