Skip to content

Commit bb7f8ad

Browse files
author
Sergei Egorov
committed
initial
0 parents  commit bb7f8ad

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Simple utility for auto forwarding ports from Docker container in boot2docker VM to the host

main.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"strconv"
6+
"strings"
7+
8+
// Fork used because original version is not providing forwarded ports info
9+
"github.com/bsideup/go-virtualbox"
10+
"github.com/fsouza/go-dockerclient"
11+
)
12+
13+
const forward2dockerPrefix = "forward2docker-"
14+
15+
func main() {
16+
client, err := docker.NewClientFromEnv()
17+
18+
if err != nil {
19+
log.Fatal(err)
20+
}
21+
22+
reload(client)
23+
24+
listener := make(chan *docker.APIEvents)
25+
client.AddEventListener(listener)
26+
for {
27+
select {
28+
case event := <-listener:
29+
switch event.Status {
30+
case "start", "die":
31+
reload(client)
32+
}
33+
}
34+
}
35+
}
36+
37+
func reload(client *docker.Client) {
38+
machine, err := virtualbox.GetMachine("boot2docker-vm")
39+
40+
if err != nil {
41+
log.Fatal(err)
42+
}
43+
forwards := make(map[int64]bool)
44+
45+
for _, forwarding := range machine.Forwardings {
46+
if !strings.HasPrefix(forwarding.Name, forward2dockerPrefix) {
47+
continue
48+
}
49+
50+
forwards[int64(forwarding.GuestPort)] = true
51+
}
52+
53+
log.Printf("Previously mapped: %v\n", forwards)
54+
55+
opts := docker.ListContainersOptions{}
56+
containers, err := client.ListContainers(opts)
57+
58+
if err != nil {
59+
log.Println("Failed to list containers", err)
60+
return
61+
}
62+
63+
for _, container := range containers {
64+
for _, binding := range container.Ports {
65+
_, exists := forwards[binding.PublicPort]
66+
if !exists {
67+
log.Printf("Adding port mapping for %d\n", binding.PublicPort)
68+
if binding.PublicPort < 1024 {
69+
log.Printf("Exposed port %d is lower than 1024 and will not work if VirtualBox is started without root privileges\n", binding.PublicPort)
70+
}
71+
rule := virtualbox.PFRule{
72+
Proto: virtualbox.PFTCP,
73+
HostPort: uint16(binding.PublicPort),
74+
GuestPort: uint16(binding.PublicPort),
75+
}
76+
machine.AddNATPF(1, forward2dockerPrefix+strconv.FormatInt(binding.PublicPort, 10), rule)
77+
}
78+
79+
delete(forwards, binding.PublicPort)
80+
}
81+
}
82+
83+
if len(forwards) > 0 {
84+
log.Printf("To be deleted: %v\n", forwards)
85+
for port := range forwards {
86+
machine.DelNATPF(1, forward2dockerPrefix+strconv.FormatInt(port, 10))
87+
}
88+
}
89+
90+
}

0 commit comments

Comments
 (0)