Skip to content

Commit dbd50a8

Browse files
author
Matthew Fisher
committed
feat(logspout): import progrium/logspout
2 parents 35ff77d + 0d86a0c commit dbd50a8

13 files changed

Lines changed: 906 additions & 0 deletions

File tree

logspout/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
build

logspout/Dockerfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM flynn/busybox
2+
MAINTAINER Jeff Lindsay <progrium@gmail.com>
3+
4+
ADD ./stage/logspout /bin/logspout
5+
6+
ENV DOCKER_HOST unix:///tmp/docker.sock
7+
ENV ROUTESPATH /mnt/routes
8+
VOLUME /mnt/routes
9+
10+
EXPOSE 8000
11+
12+
ENTRYPOINT ["/bin/logspout"]
13+
CMD []

logspout/LICENSE

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Copyright (C) 2014 Jeff Lindsay
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4+
5+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6+
7+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

logspout/Makefile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
build/container: stage/logspout Dockerfile
2+
docker build --no-cache -t logspout .
3+
touch build/container
4+
5+
build/logspout: *.go
6+
GOOS=linux GOARCH=amd64 go build -o build/logspout
7+
8+
stage/logspout: build/logspout
9+
mkdir -p stage
10+
cp build/logspout stage/logspout
11+
12+
release:
13+
docker tag logspout progrium/logspout
14+
docker push progrium/logspout
15+
16+
.PHONY: clean
17+
clean:
18+
rm -rf build

logspout/README.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# logspout
2+
3+
A log router for Docker container output that runs entirely inside Docker. It attaches to all containers on a host, then routes their logs wherever you want.
4+
5+
It's a 100% stateless log appliance (unless you persist routes). It's not meant for managing log files or looking at history. It is just a means to get your logs out to live somewhere else, where they belong.
6+
7+
For now it only captures stdout and stderr, but soon Docker will let us hook into more ... perhaps getting everything from every container's /dev/log.
8+
9+
## Getting logspout
10+
11+
Logspout is a very small Docker container (14MB virtual, based on busybox), so you can just pull it from the index:
12+
13+
$ docker pull progrium/logspout
14+
15+
## Using logspout
16+
17+
#### Route all container output to remote syslog
18+
19+
The simplest way to use logspout is to just take all logs and ship to a remote syslog. Just pass a default syslog target URI as the command. Also, we always mount the Docker Unix socket with `-v` to `/tmp/docker.sock`:
20+
21+
$ docker run -v=/var/run/docker.sock:/tmp/docker.sock progrium/logspout syslog://logs.papertrailapp.com:55555
22+
23+
Logs will be tagged with the container name. The hostname will be the hostname of the logspout container, so you probably want to set the container hostname to the actual hostname by adding `-h $HOSTNAME`.
24+
25+
#### Inspect log streams using curl
26+
27+
Whether or not you run it with a default routing target, if you publish its port 8000, you can connect with curl to see your local aggregated logs in realtime.
28+
29+
$ docker run -d -p 8000:8000 \
30+
-v=/var/run/docker.sock:/tmp/docker.sock \
31+
progrium/logspout
32+
$ curl $(docker port `docker ps -lq` 8000)/logs
33+
34+
You should see a nicely colored stream of all your container logs. You can filter by container name, log type, and more. You can also get JSON objects, or you can upgrade to WebSocket and get JSON logs in your browser.
35+
36+
See [Streaming Endpoints](#streaming-endpoints) for all options.
37+
38+
#### Create custom routes via HTTP
39+
40+
Along with streaming endpoints, logspout also exposes a `/routes` resource to create and manage routes.
41+
42+
$ curl $(docker port `docker ps -lq` 8000)/logs -X POST \
43+
-d '{"source": {"filter": "db", "types": ["stderr"]}, target": {"type": "syslog", "addr": "logs.papertrailapp.com:55555"}}'
44+
45+
That example creates a new syslog route to [Papertrail](https://papertrailapp.com) of only `stderr` for containers with `db` in their name.
46+
47+
By default, routes are ephemeral. But if you mount a volume to `/mnt/routes`, they will be persisted to disk.
48+
49+
See [Routes Resource](#routes-resource) for all options.
50+
51+
## HTTP API
52+
53+
### Streaming Endpoints
54+
55+
You can use these chunked transfer streaming endpoints for quick debugging with `curl` or for setting up easy TCP subscriptions to log sources. They also support WebSocket upgrades.
56+
57+
GET /logs
58+
GET /logs/filter:<container-name-substring>
59+
GET /logs/id:<container-id>
60+
GET /logs/name:<container-name>
61+
62+
You can select specific log types from a source using a comma-delimited list in the query param `types`. Right now the only types are `stdout` and `stderr`, but when Docker properly takes over each container's syslog socket (or however they end up doing it), other types will be possible.
63+
64+
If you include a request `Accept: application/json` header, the output will be JSON objects including the name and ID of the container and the log type. Note that when upgrading to WebSocket, it will always use JSON.
65+
66+
Since `/logs` and `/logs/filter:<string>` endpoints can return logs from multiple source, they will by default return color-coded loglines prefixed with the name of the container. You can turn off the color escape codes with query param `colors=off` or the alternative is to stream the data in JSON format, which won't use colors or prefixes.
67+
68+
69+
### Routes Resource
70+
71+
Routes let you configure logspout to hand-off logs to another system. Right now the only supported target type is via UDP `syslog`, but hey that's pretty much everything.
72+
73+
#### Creating a route
74+
75+
POST /routes
76+
77+
Takes a JSON object like this:
78+
79+
{
80+
"source": {
81+
"filter": "_db"
82+
"types": ["stdout"]
83+
},
84+
"target": {
85+
"type": "syslog",
86+
"addr": "logaggregator.service.consul"
87+
"append_tag": ".db"
88+
}
89+
}
90+
91+
The `source` field should be an object with `filter`, `name`, or `id` fields. You can specify specific log types with the `types` field to collect only `stdout` or `stderr`. If you don't specify `types`, it will route all types.
92+
93+
To route all logs of all types on all containers, don't specify a `source`.
94+
95+
The `append_tag` field of `target` is optional and specific to `syslog`. It lets you append to the tag of syslog packets for this route. By default the tag is `<container-name>`, so an `append_tag` value of `.app` would make the tag `<container-name>.app`.
96+
97+
And yes, you can just specify an IP and port for `addr`, but you can also specify a name that resolves via DNS to one or more SRV records. That means this works great with [Consul](http://www.consul.io/) for service discovery.
98+
99+
#### Listing routes
100+
101+
GET /routes
102+
103+
Returns a JSON list of current routes:
104+
105+
[
106+
{
107+
"id": "3631c027fb1b",
108+
"source": {
109+
"name": "mycontainer"
110+
},
111+
"target": {
112+
"type": "syslog",
113+
"addr": "192.168.1.111:514"
114+
}
115+
}
116+
]
117+
118+
#### Viewing a route
119+
120+
GET /routes/<id>
121+
122+
Returns a JSON route object:
123+
124+
{
125+
"id": "3631c027fb1b",
126+
"source": {
127+
"id": "a9efd0aeb470"
128+
"types": ["stderr"]
129+
},
130+
"target": {
131+
"type": "syslog",
132+
"addr": "192.168.1.111:514"
133+
}
134+
}
135+
136+
#### Deleting a route
137+
138+
DELETE /routes/<id>
139+
140+
## Sponsor
141+
142+
This project was made possible by [DigitalOcean](http://digitalocean.com).
143+
144+
## License
145+
146+
BSD

logspout/SPONSORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DigitalOcean http://digitalocean.com

0 commit comments

Comments
 (0)