Do network attach on docker event rather than intercepting start and restart commands.
This means it also works when the docker daemon restarts a container.
This commit is contained in:
1 parent
5c3efbdca0
commit
81e8ba223f
6 files changed
+76
-55
No files matched your search
+20
-2
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
// An observer for container events
|
||||
type ContainerObserver interface {
|
||||
ContainerStarted(ident string)
|
||||
ContainerDied(ident string)
|
||||
}
|
||||
|
||||
@@ -22,12 +23,26 @@ func NewClient(apiPath string) (*Client, error) {
|
||||
}
|
||||
client := &Client{dc}
|
||||
|
||||
env, err := client.Version()
|
||||
return client, client.checkWorking(apiPath)
|
||||
}
|
||||
|
||||
func NewVersionedClient(apiPath string, apiVersionString string) (*Client, error) {
|
||||
dc, err := docker.NewVersionedClient(apiPath, apiVersionString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client := &Client{dc}
|
||||
|
||||
return client, client.checkWorking(apiPath)
|
||||
}
|
||||
|
||||
func (c *Client) checkWorking(apiPath string) error {
|
||||
env, err := c.Version()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
Log.Infof("[docker] Using Docker API on %s: %v", apiPath, env)
|
||||
return client, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddObserver adds an observer for docker events
|
||||
@@ -41,6 +56,9 @@ func (c *Client) AddObserver(ob ContainerObserver) error {
|
||||
go func() {
|
||||
for event := range events {
|
||||
switch event.Status {
|
||||
case "start":
|
||||
id := event.ID
|
||||
ob.ContainerStarted(id)
|
||||
case "die":
|
||||
id := event.ID
|
||||
ob.ContainerDied(id)
|
||||
|
||||
@@ -226,6 +226,8 @@ func (alloc *Allocator) ContainerDied(ident string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (alloc *Allocator) ContainerStarted(ident string) {}
|
||||
|
||||
// Delete (Sync) - release all IP addresses for container with given name
|
||||
func (alloc *Allocator) Delete(ident string) error {
|
||||
errChan := make(chan error)
|
||||
|
||||
@@ -130,6 +130,8 @@ func (n *Nameserver) ReverseLookup(ip address.Address) (string, error) {
|
||||
return match.Hostname, nil
|
||||
}
|
||||
|
||||
func (n *Nameserver) ContainerStarted(ident string) {}
|
||||
|
||||
func (n *Nameserver) ContainerDied(ident string) {
|
||||
n.Lock()
|
||||
entries := n.entries.tombstone(n.ourName, func(e *Entry) bool {
|
||||
|
||||
+45
-6
@@ -11,8 +11,9 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/fsouza/go-dockerclient"
|
||||
docker "github.com/fsouza/go-dockerclient"
|
||||
. "github.com/weaveworks/weave/common"
|
||||
weavedocker "github.com/weaveworks/weave/common/docker"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -25,7 +26,6 @@ const (
|
||||
|
||||
var (
|
||||
containerCreateRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/create$")
|
||||
containerStartRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/[^/]*/(re)?start$")
|
||||
execCreateRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/[^/]*/exec$")
|
||||
|
||||
ErrWeaveCIDRNone = errors.New("the container was created with the '-e WEAVE_CIDR=none' option")
|
||||
@@ -64,11 +64,11 @@ func NewProxy(c Config) (*Proxy, error) {
|
||||
// to insulate ourselves from breaking changes to the API, as
|
||||
// happened in 1.20 (Docker 1.8.0) when the presentation of
|
||||
// volumes changed in `inspect`.
|
||||
client, err := docker.NewVersionedClient(dockerSockUnix, "1.15")
|
||||
client, err := weavedocker.NewVersionedClient(dockerSockUnix, "1.15")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.client = client
|
||||
p.client = client.Client
|
||||
|
||||
if !p.WithoutDNS {
|
||||
dockerBridgeIP, stderr, err := callWeave("docker-bridge-ip")
|
||||
@@ -88,6 +88,8 @@ func NewProxy(c Config) (*Proxy, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client.AddObserver(p)
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
@@ -121,8 +123,6 @@ func (proxy *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
switch {
|
||||
case containerCreateRegexp.MatchString(path):
|
||||
i = &createContainerInterceptor{proxy}
|
||||
case containerStartRegexp.MatchString(path):
|
||||
i = &startContainerInterceptor{proxy}
|
||||
case execCreateRegexp.MatchString(path):
|
||||
i = &createExecInterceptor{proxy}
|
||||
default:
|
||||
@@ -224,6 +224,45 @@ func (proxy *Proxy) listen(protoAndAddr string) (net.Listener, string, error) {
|
||||
return listener, fmt.Sprintf("%s://%s", proto, addr), nil
|
||||
}
|
||||
|
||||
// weavedocker.ContainerObserver interface
|
||||
func (proxy *Proxy) ContainerStarted(ident string) {
|
||||
container, err := proxy.client.InspectContainer(ident)
|
||||
if err != nil {
|
||||
Log.Warningf("Error inspecting container %s: %v", ident, err)
|
||||
return
|
||||
}
|
||||
// If this was a container we modified the entrypoint for, attach it to the network
|
||||
if len(container.Config.Entrypoint) > 0 && container.Config.Entrypoint[0] == weaveWaitEntrypoint[0] {
|
||||
proxy.attach(container)
|
||||
}
|
||||
}
|
||||
|
||||
func (proxy *Proxy) ContainerDied(ident string) {
|
||||
}
|
||||
|
||||
func (proxy *Proxy) attach(container *docker.Container) error {
|
||||
cidrs, err := proxy.weaveCIDRsFromConfig(container.Config, container.HostConfig)
|
||||
if err != nil {
|
||||
Log.Infof("Leaving container %s alone because %s", container.ID, err)
|
||||
return nil
|
||||
}
|
||||
Log.Infof("Attaching container %s with WEAVE_CIDR \"%s\" to weave network", container.ID, strings.Join(cidrs, " "))
|
||||
args := []string{"attach"}
|
||||
args = append(args, cidrs...)
|
||||
if !proxy.NoRewriteHosts {
|
||||
args = append(args, "--rewrite-hosts")
|
||||
}
|
||||
args = append(args, "--or-die", container.ID)
|
||||
if _, stderr, err := callWeave(args...); err != nil {
|
||||
Log.Warningf("Attaching container %s to weave network failed: %s", container.ID, string(stderr))
|
||||
return errors.New(string(stderr))
|
||||
} else if len(stderr) > 0 {
|
||||
Log.Warningf("Attaching container %s to weave network: %s", container.ID, string(stderr))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (proxy *Proxy) weaveCIDRsFromConfig(config *docker.Config, hostConfig *docker.HostConfig) ([]string, error) {
|
||||
netMode := ""
|
||||
if hostConfig != nil {
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
. "github.com/weaveworks/weave/common"
|
||||
)
|
||||
|
||||
type startContainerInterceptor struct{ proxy *Proxy }
|
||||
|
||||
func (i *startContainerInterceptor) InterceptRequest(r *http.Request) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *startContainerInterceptor) InterceptResponse(r *http.Response) error {
|
||||
if r.StatusCode < 200 || r.StatusCode >= 300 { // Docker didn't do the start
|
||||
return nil
|
||||
}
|
||||
|
||||
container, err := inspectContainerInPath(i.proxy.client, r.Request.URL.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cidrs, err := i.proxy.weaveCIDRsFromConfig(container.Config, container.HostConfig)
|
||||
if err != nil {
|
||||
Log.Infof("Leaving container %s alone because %s", container.ID, err)
|
||||
return nil
|
||||
}
|
||||
Log.Infof("Attaching container %s with WEAVE_CIDR \"%s\" to weave network", container.ID, strings.Join(cidrs, " "))
|
||||
args := []string{"attach"}
|
||||
args = append(args, cidrs...)
|
||||
if !i.proxy.NoRewriteHosts {
|
||||
args = append(args, "--rewrite-hosts")
|
||||
}
|
||||
args = append(args, "--or-die", container.ID)
|
||||
if _, stderr, err := callWeave(args...); err != nil {
|
||||
Log.Warningf("Attaching container %s to weave network failed: %s", container.ID, string(stderr))
|
||||
return errors.New(string(stderr))
|
||||
} else if len(stderr) > 0 {
|
||||
Log.Warningf("Attaching container %s to weave network: %s", container.ID, string(stderr))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -64,6 +64,10 @@ or
|
||||
[remote API](https://docs.docker.com/reference/api/docker_remote_api/)
|
||||
are attached to the weave network before they begin execution.
|
||||
|
||||
Containers started in this way that subsequently restart, either by an
|
||||
explicit `docker restart` command or by Docker restart policy, are
|
||||
re-attached to the weave network by the weave Docker API proxy.
|
||||
|
||||
### <a name="addressing"></a>Address allocation
|
||||
|
||||
Containers are automatically allocated an IP address that is unique
|
||||
@@ -248,6 +252,9 @@ invocation:
|
||||
host1$ weave detach net:default net:10.2.2.0/24 net:10.2.3.0/24 $C
|
||||
10.2.1.3 10.2.2.3 10.2.3.1
|
||||
|
||||
Note that addresses added by dynamic attachment are not re-attached
|
||||
if the container restarts.
|
||||
|
||||
### <a name="security"></a>Security
|
||||
|
||||
In order to connect containers across untrusted networks, weave peers
|
||||
|
||||
Reference in new issue
Block a user