diff --git a/daemon/logger/syslog/syslog.go b/daemon/logger/syslog/syslog.go index 6a6377f833..706a0ef912 100644 --- a/daemon/logger/syslog/syslog.go +++ b/daemon/logger/syslog/syslog.go @@ -3,14 +3,17 @@ package syslog import ( - "fmt" "io" "log/syslog" + "net" + "net/url" "os" "path" + "strings" "github.com/Sirupsen/logrus" "github.com/docker/docker/daemon/logger" + "github.com/docker/docker/pkg/urlutil" ) const name = "syslog" @@ -27,7 +30,18 @@ func init() { func New(ctx logger.Context) (logger.Logger, error) { tag := ctx.ContainerID[:12] - log, err := syslog.New(syslog.LOG_DAEMON, fmt.Sprintf("%s/%s", path.Base(os.Args[0]), tag)) + + proto, address, err := parseAddress(ctx.Config["syslog-address"]) + if err != nil { + return nil, err + } + + log, err := syslog.Dial( + proto, + address, + syslog.LOG_DAEMON, + path.Base(os.Args[0])+"/"+tag, + ) if err != nil { return nil, err } @@ -55,3 +69,33 @@ func (s *Syslog) Name() string { func (s *Syslog) GetReader() (io.Reader, error) { return nil, logger.ReadLogsNotSupported } + +func parseAddress(address string) (string, string, error) { + if urlutil.IsTransportURL(address) { + url, err := url.Parse(address) + if err != nil { + return "", "", err + } + + // unix socket validation + if url.Scheme == "unix" { + if _, err := os.Stat(url.Path); err != nil { + return "", "", err + } + return url.Scheme, url.Path, nil + } + + // here we process tcp|udp + host := url.Host + if _, _, err := net.SplitHostPort(host); err != nil { + if !strings.Contains(err.Error(), "missing port in address") { + return "", "", err + } + host = host + ":514" + } + + return url.Scheme, host, nil + } + + return "", "", nil +} diff --git a/docs/man/docker-create.1.md b/docs/man/docker-create.1.md index 26b6711309..546eb3407e 100644 --- a/docs/man/docker-create.1.md +++ b/docs/man/docker-create.1.md @@ -33,6 +33,7 @@ docker-create - Create a new container [**--link**[=*[]*]] [**--lxc-conf**[=*[]*]] [**--log-driver**[=*[]*]] +[**--log-opt**[=*[]*]] [**-m**|**--memory**[=*MEMORY*]] [**--memory-swap**[=*MEMORY-SWAP*]] [**--mac-address**[=*MAC-ADDRESS*]] @@ -148,6 +149,9 @@ two memory nodes. Logging driver for container. Default is defined by daemon `--log-driver` flag. **Warning**: `docker logs` command works only for `json-file` logging driver. +**--log-opt**=[] + Logging driver specific options. + **-m**, **--memory**="" Memory limit (format: , where unit = b, k, m or g) diff --git a/docs/man/docker-run.1.md b/docs/man/docker-run.1.md index 1544c35458..ee70159ad3 100644 --- a/docs/man/docker-run.1.md +++ b/docs/man/docker-run.1.md @@ -34,6 +34,7 @@ docker-run - Run a command in a new container [**--link**[=*[]*]] [**--lxc-conf**[=*[]*]] [**--log-driver**[=*[]*]] +[**--log-opt**[=*[]*]] [**-m**|**--memory**[=*MEMORY*]] [**--memory-swap**[=*MEMORY-SWAP*]] [**--mac-address**[=*MAC-ADDRESS*]] @@ -255,6 +256,9 @@ which interface and port to use. Logging driver for container. Default is defined by daemon `--log-driver` flag. **Warning**: `docker logs` command works only for `json-file` logging driver. +**--log-opt**=[] + Logging driver specific options. + **-m**, **--memory**="" Memory limit (format: , where unit = b, k, m or g) diff --git a/docs/man/docker.1.md b/docs/man/docker.1.md index 884f181ca3..0b1de775f1 100644 --- a/docs/man/docker.1.md +++ b/docs/man/docker.1.md @@ -105,6 +105,9 @@ unix://[/path/to/socket] to use. Default driver for container logs. Default is `json-file`. **Warning**: `docker logs` command works only for `json-file` logging driver. +**--log-opt**=[] + Logging driver specific options. + **--mtu**=VALUE Set the containers network mtu. Default is `0`. diff --git a/docs/sources/reference/api/docker_remote_api_v1.19.md b/docs/sources/reference/api/docker_remote_api_v1.19.md index a6603094ce..458d17479c 100644 --- a/docs/sources/reference/api/docker_remote_api_v1.19.md +++ b/docs/sources/reference/api/docker_remote_api_v1.19.md @@ -270,8 +270,8 @@ Json Parameters: - **LogConfig** - Log configuration for the container, specified as a JSON object in the form `{ "Type": "", "Config": {"key1": "val1"}}`. Available types: `json-file`, `syslog`, `journald`, `none`. - `json-file` logging driver. - - **CgroupParent** - Path to `cgroups` under which the container's `cgroup` is created. If the path is not absolute, the path is considered to be relative to the `cgroups` path of the init process. Cgroups are created if they do not already exist. + `syslog` available options are: `address`. + - **CgroupParent** - Path to cgroups under which the cgroup for the container will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist. Query Parameters: diff --git a/docs/sources/reference/commandline/cli.md b/docs/sources/reference/commandline/cli.md index 662ddacd9c..986bcdedac 100644 --- a/docs/sources/reference/commandline/cli.md +++ b/docs/sources/reference/commandline/cli.md @@ -175,6 +175,7 @@ expect an integer, and they can only be specified once. -l, --log-level="info" Set the logging level --label=[] Set key=value labels to the daemon --log-driver="json-file" Default driver for container logs + --log-opt=[] Log driver specific options --mtu=0 Set the containers network MTU -p, --pidfile="/var/run/docker.pid" Path to use for daemon PID file --registry-mirror=[] Preferred Docker registry mirror @@ -998,6 +999,7 @@ Creates a new container. --label-file=[] Read in a line delimited file of labels --link=[] Add link to another container --log-driver="" Logging driver for container + --log-opt=[] Log driver specific options --lxc-conf=[] Add custom lxc options -m, --memory="" Memory limit --mac-address="" Container MAC address (e.g. 92:d0:c6:0a:29:33) @@ -1963,6 +1965,7 @@ To remove an image using its digest: --ipc="" IPC namespace to use --link=[] Add link to another container --log-driver="" Logging driver for container + --log-opt=[] Log driver specific options --lxc-conf=[] Add custom lxc options -m, --memory="" Memory limit -l, --label=[] Set metadata on the container (e.g., --label=com.example.key=value) diff --git a/docs/sources/reference/run.md b/docs/sources/reference/run.md index 7c5113f6de..f1c4a44d7c 100644 --- a/docs/sources/reference/run.md +++ b/docs/sources/reference/run.md @@ -873,18 +873,31 @@ this driver. Default logging driver for Docker. Writes JSON messages to file. `docker logs` command is available only for this logging driver +The following logging options are supported for this logging driver: [none] + #### Logging driver: syslog Syslog logging driver for Docker. Writes log messages to syslog. `docker logs` command is not available for this logging driver +The following logging options are supported for this logging driver: + + --log-opt address=[tcp|udp]://host:port + --log-opt address=unix://path + +`address` specifies the remote syslog server address where the driver connects to. +If not specified it defaults to the local unix socket of the running system. +If transport is either `tcp` or `udp` and `port` is not specified it defaults to `514` +The following example shows how to have the `syslog` driver connect to a `syslog` +remote server at `192.168.0.42` on port `123` + + $ docker run --log-driver=syslog --log-opt address=tcp://192.168.0.42:123 + #### Logging driver: journald Journald logging driver for Docker. Writes log messages to journald; the container id will be stored in the journal's `CONTAINER_ID` field. `docker logs` command is not available for this logging driver. For detailed information on working with this logging driver, see [the journald logging driver](reference/logging/journald) reference documentation. -#### Log Opts : - -Logging options for configuring a log driver. The following log options are supported: [none] +The following logging options are supported for this logging driver: [none] ## Overriding Dockerfile image defaults diff --git a/opts/opts.go b/opts/opts.go index c330c27a5d..8dcc8c5988 100644 --- a/opts/opts.go +++ b/opts/opts.go @@ -33,7 +33,7 @@ func MapVar(values map[string]string, names []string, usage string) { } func LogOptsVar(values map[string]string, names []string, usage string) { - flag.Var(newMapOpt(values, ValidateLogOpts), names, usage) + flag.Var(newMapOpt(values, nil), names, usage) } func HostListVar(values *[]string, names []string, usage string) { @@ -176,15 +176,6 @@ func newMapOpt(values map[string]string, validator ValidatorFctType) *MapOpts { type ValidatorFctType func(val string) (string, error) type ValidatorFctListType func(val string) ([]string, error) -func ValidateLogOpts(val string) (string, error) { - allowedKeys := map[string]string{} - vals := strings.Split(val, "=") - if allowedKeys[vals[0]] != "" { - return val, nil - } - return "", fmt.Errorf("%s is not a valid log opt", vals[0]) -} - func ValidateAttach(val string) (string, error) { s := strings.ToLower(val) for _, str := range []string{"stdin", "stdout", "stderr"} { diff --git a/pkg/urlutil/url.go b/pkg/urlutil/url.go deleted file mode 100644 index eeae56efe7..0000000000 --- a/pkg/urlutil/url.go +++ /dev/null @@ -1,19 +0,0 @@ -package urlutil - -import "strings" - -var validUrlPrefixes = []string{ - "http://", - "https://", -} - -// IsURL returns true if the provided str is a valid URL by doing -// a simple change for the transport of the url. -func IsURL(str string) bool { - for _, prefix := range validUrlPrefixes { - if strings.HasPrefix(str, prefix) { - return true - } - } - return false -} diff --git a/pkg/urlutil/git.go b/pkg/urlutil/urlutil.go similarity index 53% rename from pkg/urlutil/git.go rename to pkg/urlutil/urlutil.go index dc4d6662e3..7250643dda 100644 --- a/pkg/urlutil/git.go +++ b/pkg/urlutil/urlutil.go @@ -6,26 +6,25 @@ import ( ) var ( - validPrefixes = []string{ - "git://", - "github.com/", - "git@", + validPrefixes = map[string][]string{ + "url": {"http://", "https://"}, + "git": {"git://", "github.com/", "git@"}, + "transport": {"tcp://", "udp://", "unix://"}, } - urlPathWithFragmentSuffix = regexp.MustCompile(".git(?:#.+)?$") ) +// IsURL returns true if the provided str is an HTTP(S) URL. +func IsURL(str string) bool { + return checkURL(str, "url") +} + // IsGitURL returns true if the provided str is a git repository URL. func IsGitURL(str string) bool { if IsURL(str) && urlPathWithFragmentSuffix.MatchString(str) { return true } - for _, prefix := range validPrefixes { - if strings.HasPrefix(str, prefix) { - return true - } - } - return false + return checkURL(str, "git") } // IsGitTransport returns true if the provided str is a git transport by inspecting @@ -33,3 +32,17 @@ func IsGitURL(str string) bool { func IsGitTransport(str string) bool { return IsURL(str) || strings.HasPrefix(str, "git://") || strings.HasPrefix(str, "git@") } + +// IsTransportURL returns true if the provided str is a transport (tcp, udp, unix) URL. +func IsTransportURL(str string) bool { + return checkURL(str, "transport") +} + +func checkURL(str, kind string) bool { + for _, prefix := range validPrefixes[kind] { + if strings.HasPrefix(str, prefix) { + return true + } + } + return false +} diff --git a/pkg/urlutil/git_test.go b/pkg/urlutil/urlutil_test.go similarity index 100% rename from pkg/urlutil/git_test.go rename to pkg/urlutil/urlutil_test.go