Support SSH connection to Docker
This commit is contained in:
parent
b3c9a50ead
commit
125470f110
4 changed files with 92 additions and 24 deletions
|
@ -135,7 +135,7 @@ You can specify which Docker API Endpoint to use with the directive [`endpoint`]
|
|||
|
||||
??? success "Solutions"
|
||||
|
||||
Expose the Docker socket over TCP, instead of the default Unix socket file.
|
||||
Expose the Docker socket over TCP or SSH, instead of the default Unix socket file.
|
||||
It allows different implementation levels of the [AAA (Authentication, Authorization, Accounting) concepts](https://en.wikipedia.org/wiki/AAA_(computer_security)), depending on your security assessment:
|
||||
|
||||
- Authentication with Client Certificates as described in ["Protect the Docker daemon socket."](https://docs.docker.com/engine/security/https/)
|
||||
|
@ -145,6 +145,7 @@ You can specify which Docker API Endpoint to use with the directive [`endpoint`]
|
|||
- Accounting at container level, by exposing the socket on a another container than Traefik's.
|
||||
With Swarm mode, it allows scheduling of Traefik on worker nodes, with only the "socket exposer" container on the manager nodes.
|
||||
- Accounting at kernel level, by enforcing kernel calls with mechanisms like [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux), to only allows an identified set of actions for Traefik's process (or the "socket exposer" process).
|
||||
- SSH public key authentication (SSH is supported with Docker > 18.09)
|
||||
|
||||
??? info "More Resources and Examples"
|
||||
- ["Paranoid about mounting /var/run/docker.sock?"](https://medium.com/@containeroo/traefik-2-0-paranoid-about-mounting-var-run-docker-sock-22da9cb3e78c)
|
||||
|
@ -273,6 +274,30 @@ See the sections [Docker API Access](#docker-api-access) and [Docker Swarm API A
|
|||
# ...
|
||||
```
|
||||
|
||||
??? example "Using SSH"
|
||||
|
||||
Using Docker 18.09+ you can connect Traefik to daemon using SSH
|
||||
We specify the SSH host and user in Traefik's configuration file.
|
||||
Note that is server requires public keys for authentication you must have those accessible for user who runs Traefik.
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[providers.docker]
|
||||
endpoint = "ssh://traefik@192.168.2.5:2022"
|
||||
# ...
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
docker:
|
||||
endpoint: "ssh://traefik@192.168.2.5:2022"
|
||||
# ...
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--providers.docker.endpoint=ssh://traefik@192.168.2.5:2022
|
||||
# ...
|
||||
```
|
||||
|
||||
### `useBindPortIP`
|
||||
|
||||
_Optional, Default=false_
|
||||
|
|
5
go.mod
5
go.mod
|
@ -23,7 +23,7 @@ require (
|
|||
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/docker/cli v0.0.0-20190711175710-5b38d82aa076 // indirect
|
||||
github.com/docker/cli v0.0.0-20190711175710-5b38d82aa076
|
||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||
github.com/docker/docker v0.0.0-00010101000000-000000000000
|
||||
github.com/docker/docker-credential-helpers v0.6.3 // indirect
|
||||
|
@ -43,6 +43,7 @@ require (
|
|||
github.com/go-acme/lego/v3 v3.2.0
|
||||
github.com/go-check/check v0.0.0-00010101000000-000000000000
|
||||
github.com/go-kit/kit v0.9.0
|
||||
github.com/gogo/protobuf v1.3.0 // indirect
|
||||
github.com/golang/protobuf v1.3.2
|
||||
github.com/google/go-github/v28 v28.1.1
|
||||
github.com/googleapis/gnostic v0.1.0 // indirect
|
||||
|
@ -75,6 +76,7 @@ require (
|
|||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4
|
||||
github.com/rancher/go-rancher-metadata v0.0.0-00010101000000-000000000000
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/spf13/pflag v1.0.3 // indirect
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154
|
||||
github.com/tinylib/msgp v1.0.2 // indirect
|
||||
|
@ -92,6 +94,7 @@ require (
|
|||
golang.org/x/net v0.0.0-20191204025024-5ee1b9f4859a
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e // indirect
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0
|
||||
google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69 // indirect
|
||||
google.golang.org/grpc v1.22.1
|
||||
gopkg.in/DataDog/dd-trace-go.v1 v1.19.0
|
||||
gopkg.in/fsnotify.v1 v1.4.7
|
||||
|
|
8
go.sum
8
go.sum
|
@ -235,6 +235,8 @@ github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI=
|
|||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE=
|
||||
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
|
@ -379,6 +381,7 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7
|
|||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181 h1:TrxPzApUukas24OMMVDUMlCs1XCExJtnGaDEiIAR4oQ=
|
||||
github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
|
||||
|
@ -571,6 +574,8 @@ github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
|
|||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
|
@ -749,6 +754,7 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb
|
|||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
|
@ -782,6 +788,8 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn
|
|||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 h1:nfPFGzJkUDX6uBmpN/pSw7MbOAWegH5QDQuoXFHedLg=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69 h1:4rNOqY4ULrKzS6twXa619uQgI7h9PaVd4ZhjFQ7C5zs=
|
||||
google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/containous/traefik/v2/pkg/safe"
|
||||
"github.com/containous/traefik/v2/pkg/types"
|
||||
"github.com/containous/traefik/v2/pkg/version"
|
||||
"github.com/docker/cli/cli/connhelper"
|
||||
dockertypes "github.com/docker/docker/api/types"
|
||||
dockercontainertypes "github.com/docker/docker/api/types/container"
|
||||
eventtypes "github.com/docker/docker/api/types/events"
|
||||
|
@ -108,46 +109,77 @@ type networkData struct {
|
|||
}
|
||||
|
||||
func (p *Provider) createClient() (client.APIClient, error) {
|
||||
var httpClient *http.Client
|
||||
|
||||
if p.TLS != nil {
|
||||
ctx := log.With(context.Background(), log.Str(log.ProviderName, "docker"))
|
||||
conf, err := p.TLS.CreateTLSConfig(ctx)
|
||||
opts, err := p.getClientOpts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: conf,
|
||||
|
||||
httpHeaders := map[string]string{
|
||||
"User-Agent": "Traefik " + version.Version,
|
||||
}
|
||||
opts = append(opts, client.WithHTTPHeaders(httpHeaders))
|
||||
|
||||
apiVersion := DockerAPIVersion
|
||||
if p.SwarmMode {
|
||||
apiVersion = SwarmAPIVersion
|
||||
}
|
||||
opts = append(opts, client.WithVersion(apiVersion))
|
||||
|
||||
return client.NewClientWithOpts(opts...)
|
||||
}
|
||||
|
||||
func (p *Provider) getClientOpts() ([]client.Opt, error) {
|
||||
helper, err := connhelper.GetConnectionHelper(p.Endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// SSH
|
||||
if helper != nil {
|
||||
// https://github.com/docker/cli/blob/ebca1413117a3fcb81c89d6be226dcec74e5289f/cli/context/docker/load.go#L112-L123
|
||||
|
||||
httpClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: helper.Dialer,
|
||||
},
|
||||
}
|
||||
|
||||
return []client.Opt{
|
||||
client.WithHTTPClient(httpClient),
|
||||
client.WithHost(helper.Host), // To avoid 400 Bad Request: malformed Host header daemon error
|
||||
client.WithDialContext(helper.Dialer),
|
||||
}, nil
|
||||
}
|
||||
|
||||
opts := []client.Opt{
|
||||
client.WithHost(p.Endpoint),
|
||||
}
|
||||
|
||||
if p.TLS != nil {
|
||||
ctx := log.With(context.Background(), log.Str(log.ProviderName, "docker"))
|
||||
|
||||
conf, err := p.TLS.CreateTLSConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hostURL, err := client.ParseHostURL(p.Endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: conf,
|
||||
}
|
||||
|
||||
if err := sockets.ConfigureTransport(tr, hostURL.Scheme, hostURL.Host); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
httpClient = &http.Client{
|
||||
Transport: tr,
|
||||
}
|
||||
opts = append(opts, client.WithHTTPClient(&http.Client{Transport: tr}))
|
||||
}
|
||||
|
||||
httpHeaders := map[string]string{
|
||||
"User-Agent": "Traefik " + version.Version,
|
||||
}
|
||||
|
||||
apiVersion := DockerAPIVersion
|
||||
if p.SwarmMode {
|
||||
apiVersion = SwarmAPIVersion
|
||||
}
|
||||
|
||||
return client.NewClientWithOpts(
|
||||
client.WithHost(p.Endpoint),
|
||||
client.WithVersion(apiVersion),
|
||||
client.WithHTTPClient(httpClient),
|
||||
client.WithHTTPHeaders(httpHeaders),
|
||||
)
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
// Provide allows the docker provider to provide configurations to traefik using the given configuration channel.
|
||||
|
|
Loading…
Add table
Reference in a new issue