fixed issue for container not being excluded on restart

This commit is contained in:
yusing 2024-09-30 15:19:59 +08:00
parent 860e914b90
commit b38d7595a7
16 changed files with 67 additions and 52 deletions

View file

@ -27,7 +27,7 @@ logs:
docker compose logs -f
get:
cd cmd && go get -u && go mod tidy && cd ..
go get -u ./cmd && go mod tidy
debug:
make BUILD_FLAG="" build && sudo GOPROXY_DEBUG=1 bin/go-proxy

View file

@ -17,6 +17,8 @@ const (
ConfigFileName = "config.yml"
ConfigExampleFileName = "config.example.yml"
ConfigPath = ConfigBasePath + "/" + ConfigFileName
MiddlewareDefsBasePath = ConfigBasePath + "/middlewares"
)
const (

View file

@ -20,6 +20,7 @@ func FromDocker(c *types.Container, dockerHost string) (res Container) {
res.ProxyProperties = &ProxyProperties{
DockerHost: dockerHost,
ContainerName: res.getName(),
ContainerID: c.ID,
ImageName: res.getImageName(),
PublicPortMapping: res.getPublicPortMapping(),
PrivatePortMapping: res.getPrivatePortMapping(),

View file

@ -63,7 +63,9 @@ func Register(entry *P.ReverseProxyEntry) (*watcher, E.NestedError) {
watcherMapMu.Lock()
defer watcherMapMu.Unlock()
if w, ok := watcherMap[entry.ContainerName]; ok {
key := entry.ContainerID
if w, ok := watcherMap[key]; ok {
w.refCount.Add(1)
w.ReverseProxyEntry = entry
return w, nil
@ -85,7 +87,7 @@ func Register(entry *P.ReverseProxyEntry) (*watcher, E.NestedError) {
w.refCount.Add(1)
w.stopByMethod = w.getStopCallback()
watcherMap[w.ContainerName] = w
watcherMap[key] = w
go func() {
newWatcherCh <- w
@ -94,8 +96,8 @@ func Register(entry *P.ReverseProxyEntry) (*watcher, E.NestedError) {
return w, nil
}
func Unregister(containerName string) {
if w, ok := watcherMap[containerName]; ok {
func Unregister(entry *P.ReverseProxyEntry) {
if w, ok := watcherMap[entry.ContainerID]; ok {
w.refCount.Add(-1)
}
}
@ -118,7 +120,7 @@ func Start() {
w.refCount.Wait() // wait for 0 ref count
w.client.Close()
delete(watcherMap, w.ContainerName)
delete(watcherMap, w.ContainerID)
w.l.Debug("unregistered")
mainLoopWg.Done()
}()
@ -138,29 +140,29 @@ func (w *watcher) PatchRoundTripper(rtp http.RoundTripper) roundTripper {
}
func (w *watcher) containerStop() error {
return w.client.ContainerStop(w.ctx, w.ContainerName, container.StopOptions{
return w.client.ContainerStop(w.ctx, w.ContainerID, container.StopOptions{
Signal: string(w.StopSignal),
Timeout: &w.StopTimeout})
}
func (w *watcher) containerPause() error {
return w.client.ContainerPause(w.ctx, w.ContainerName)
return w.client.ContainerPause(w.ctx, w.ContainerID)
}
func (w *watcher) containerKill() error {
return w.client.ContainerKill(w.ctx, w.ContainerName, string(w.StopSignal))
return w.client.ContainerKill(w.ctx, w.ContainerID, string(w.StopSignal))
}
func (w *watcher) containerUnpause() error {
return w.client.ContainerUnpause(w.ctx, w.ContainerName)
return w.client.ContainerUnpause(w.ctx, w.ContainerID)
}
func (w *watcher) containerStart() error {
return w.client.ContainerStart(w.ctx, w.ContainerName, container.StartOptions{})
return w.client.ContainerStart(w.ctx, w.ContainerID, container.StartOptions{})
}
func (w *watcher) containerStatus() (string, E.NestedError) {
json, err := w.client.ContainerInspect(w.ctx, w.ContainerName)
json, err := w.client.ContainerInspect(w.ctx, w.ContainerID)
if err != nil {
return "", E.FailWith("inspect container", err)
}
@ -219,7 +221,7 @@ func (w *watcher) watchUntilCancel() {
dockerEventCh, dockerEventErrCh := dockerWatcher.EventsWithOptions(w.ctx, W.DockerListOptions{
Filters: W.NewDockerFilter(
W.DockerFilterContainer,
W.DockerrFilterContainerName(w.ContainerName),
W.DockerrFilterContainer(w.ContainerID),
W.DockerFilterStart,
W.DockerFilterStop,
W.DockerFilterDie,

View file

@ -6,6 +6,7 @@ type PortMapping = map[string]types.Port
type ProxyProperties struct {
DockerHost string `yaml:"-" json:"docker_host"`
ContainerName string `yaml:"-" json:"container_name"`
ContainerID string `yaml:"-" json:"container_id"`
ImageName string `yaml:"-" json:"image_name"`
PublicPortMapping PortMapping `yaml:"-" json:"public_port_mapping"` // non-zero publicPort:types.Port
PrivatePortMapping PortMapping `yaml:"-" json:"private_port_mapping"` // privatePort:types.Port

View file

@ -49,8 +49,6 @@ func (b Builder) Addf(format string, args ...any) Builder {
func (b Builder) Build() NestedError {
if len(b.errors) == 0 {
return nil
} else if len(b.errors) == 1 {
return b.errors[0].Subjectf("%s", b.message)
}
return Join(b.message, b.errors...)
}

View file

@ -34,7 +34,7 @@ var CloudflareRealIP = &realIP{
},
}
func NewCloudflareRealIP(_ OptionsRaw, _ *ReverseProxy) (*Middleware, E.NestedError) {
func NewCloudflareRealIP(_ OptionsRaw) (*Middleware, E.NestedError) {
cri := new(realIP)
cri.m = &Middleware{
impl: cri,

View file

@ -14,7 +14,6 @@ import (
"time"
"github.com/sirupsen/logrus"
"github.com/yusing/go-proxy/internal/common"
D "github.com/yusing/go-proxy/internal/docker"
E "github.com/yusing/go-proxy/internal/error"
gpHTTP "github.com/yusing/go-proxy/internal/net/http"
@ -31,6 +30,7 @@ type (
TrustForwardHeader bool
AuthResponseHeaders []string
AddAuthCookiesToResponse []string
transport http.RoundTripper
}
)
@ -56,16 +56,29 @@ var ForwardAuth = func() *forwardAuth {
}()
var faLogger = logrus.WithField("middleware", "ForwardAuth")
func NewForwardAuthfunc(optsRaw OptionsRaw, rp *ReverseProxy) (*Middleware, E.NestedError) {
tr, ok := rp.Transport.(*http.Transport)
if ok {
tr = tr.Clone()
} else {
tr = common.DefaultTransport.Clone()
}
func NewForwardAuthfunc(optsRaw OptionsRaw) (*Middleware, E.NestedError) {
faWithOpts := new(forwardAuth)
faWithOpts.forwardAuthOpts = new(forwardAuthOpts)
err := Deserialize(optsRaw, faWithOpts.forwardAuthOpts)
if err != nil {
return nil, err
}
_, err = E.Check(url.Parse(faWithOpts.Address))
if err != nil {
return nil, E.Invalid("address", faWithOpts.Address)
}
faWithOpts.m = &Middleware{
impl: faWithOpts,
before: faWithOpts.forward,
}
// TODO: use tr from reverse proxy
tr, ok := faWithOpts.forwardAuthOpts.transport.(*http.Transport)
if ok {
tr = tr.Clone()
}
faWithOpts.client = http.Client{
CheckRedirect: func(r *Request, via []*Request) error {
return http.ErrUseLastResponse
@ -73,19 +86,6 @@ func NewForwardAuthfunc(optsRaw OptionsRaw, rp *ReverseProxy) (*Middleware, E.Ne
Timeout: 30 * time.Second,
Transport: tr,
}
faWithOpts.m = &Middleware{
impl: faWithOpts,
before: faWithOpts.forward,
}
err := Deserialize(optsRaw, faWithOpts.forwardAuthOpts)
if err != nil {
return nil, E.FailWith("set options", err)
}
_, err = E.Check(url.Parse(faWithOpts.Address))
if err != nil {
return nil, E.Invalid("address", faWithOpts.Address)
}
return faWithOpts.m, nil
}

View file

@ -23,7 +23,7 @@ type (
BeforeFunc func(next http.Handler, w ResponseWriter, r *Request)
RewriteFunc func(req *Request)
ModifyResponseFunc func(resp *Response) error
CloneWithOptFunc func(opts OptionsRaw, rp *ReverseProxy) (*Middleware, E.NestedError)
CloneWithOptFunc func(opts OptionsRaw) (*Middleware, E.NestedError)
OptionsRaw = map[string]any
Options any
@ -55,7 +55,7 @@ func (m *Middleware) String() string {
func (m *Middleware) WithOptionsClone(optsRaw OptionsRaw, rp *ReverseProxy) (*Middleware, E.NestedError) {
if len(optsRaw) != 0 && m.withOptions != nil {
if mWithOpt, err := m.withOptions(optsRaw, rp); err != nil {
if mWithOpt, err := m.withOptions(optsRaw); err != nil {
return nil, err
} else {
return mWithOpt, nil

View file

@ -30,7 +30,7 @@ var ModifyRequest = func() *modifyRequest {
return mr
}()
func NewModifyRequest(optsRaw OptionsRaw, _ *ReverseProxy) (*Middleware, E.NestedError) {
func NewModifyRequest(optsRaw OptionsRaw) (*Middleware, E.NestedError) {
mr := new(modifyRequest)
mr.m = &Middleware{
impl: mr,
@ -39,7 +39,7 @@ func NewModifyRequest(optsRaw OptionsRaw, _ *ReverseProxy) (*Middleware, E.Neste
mr.modifyRequestOpts = new(modifyRequestOpts)
err := Deserialize(optsRaw, mr.modifyRequestOpts)
if err != nil {
return nil, E.FailWith("set options", err)
return nil, err
}
return mr.m, nil
}

View file

@ -32,7 +32,7 @@ var ModifyResponse = func() (mr *modifyResponse) {
return
}()
func NewModifyResponse(optsRaw OptionsRaw, _ *ReverseProxy) (*Middleware, E.NestedError) {
func NewModifyResponse(optsRaw OptionsRaw) (*Middleware, E.NestedError) {
mr := new(modifyResponse)
mr.m = &Middleware{
impl: mr,
@ -41,7 +41,7 @@ func NewModifyResponse(optsRaw OptionsRaw, _ *ReverseProxy) (*Middleware, E.Nest
mr.modifyResponseOpts = new(modifyResponseOpts)
err := Deserialize(optsRaw, mr.modifyResponseOpts)
if err != nil {
return nil, E.FailWith("set options", err)
return nil, err
}
return mr.m, nil
}

View file

@ -58,7 +58,7 @@ var realIPOptsDefault = func() *realIPOpts {
var realIPLogger = logrus.WithField("middleware", "RealIP")
func NewRealIP(opts OptionsRaw, _ *ReverseProxy) (*Middleware, E.NestedError) {
func NewRealIP(opts OptionsRaw) (*Middleware, E.NestedError) {
riWithOpts := new(realIP)
riWithOpts.m = &Middleware{
impl: riWithOpts,
@ -67,7 +67,7 @@ func NewRealIP(opts OptionsRaw, _ *ReverseProxy) (*Middleware, E.NestedError) {
riWithOpts.realIPOpts = realIPOptsDefault()
err := Deserialize(opts, riWithOpts.realIPOpts)
if err != nil {
return nil, E.FailWith("set options", err)
return nil, err
}
return riWithOpts.m, nil
}

View file

@ -28,6 +28,7 @@ type (
StopSignal T.Signal
DockerHost string
ContainerName string
ContainerID string
ContainerRunning bool
}
StreamEntry struct {
@ -115,6 +116,7 @@ func validateRPEntry(m *M.RawEntry, s T.Scheme, b E.Builder) *ReverseProxyEntry
StopSignal: stopSignal,
DockerHost: m.DockerHost,
ContainerName: m.ContainerName,
ContainerID: m.ContainerID,
ContainerRunning: m.Running,
}
}

View file

@ -78,12 +78,17 @@ func (p *DockerProvider) LoadRoutesImpl() (routes R.Routes, err E.NestedError) {
return routes, errors.Build()
}
func (p *DockerProvider) shouldIgnore(container D.Container) bool {
return container.IsExcluded ||
!container.IsExplicit && p.ExplicitOnly
}
func (p *DockerProvider) OnEvent(event W.Event, routes R.Routes) (res EventResult) {
b := E.NewBuilder("event %s error", event)
defer b.To(&res.err)
routes.RangeAll(func(k string, v R.Route) {
if v.Entry().ContainerName == event.ActorName {
if v.Entry().ContainerID == event.ActorID {
b.Add(v.Stop())
routes.Delete(k)
res.nRemoved++
@ -101,6 +106,11 @@ func (p *DockerProvider) OnEvent(event W.Event, routes R.Routes) (res EventResul
b.Add(E.FailWith("inspect container", err))
return
}
if p.shouldIgnore(cont) {
return
}
entries, err := p.entriesFromContainerLabels(cont)
b.Add(err)
@ -126,8 +136,7 @@ func (p *DockerProvider) OnEvent(event W.Event, routes R.Routes) (res EventResul
func (p *DockerProvider) entriesFromContainerLabels(container D.Container) (entries M.RawEntries, _ E.NestedError) {
entries = M.NewProxyEntries()
if container.IsExcluded ||
!container.IsExplicit && p.ExplicitOnly {
if p.shouldIgnore(container) {
return
}

View file

@ -89,7 +89,7 @@ func NewHTTPRoute(entry *P.ReverseProxyEntry) (*HTTPRoute, E.NestedError) {
return nil
}
unregIdleWatcher = func() {
idlewatcher.Unregister(entry.ContainerName)
idlewatcher.Unregister(entry)
rp.Transport = trans
}
}

View file

@ -37,8 +37,8 @@ var (
dockerWatcherRetryInterval = 3 * time.Second
)
func DockerrFilterContainerName(name string) filters.KeyValuePair {
return filters.Arg("container", name)
func DockerrFilterContainer(nameOrID string) filters.KeyValuePair {
return filters.Arg("container", nameOrID)
}
func NewDockerWatcher(host string) DockerWatcher {