Compare commits

...

10 Commits

Author SHA1 Message Date
Amir Raminfar fc9fdaf8b6 1.2.3 2018-11-24 17:34:20 -08:00
Amir Raminfar 5979a6d0e5 Adds responsiveness for menu on left 2018-11-24 17:32:22 -08:00
Amir Raminfar ca2c46ffce 1.2.2 2018-11-20 09:20:42 -08:00
Amir Raminfar 1cc7e92466 Update README.md 2018-11-20 09:20:31 -08:00
Amir Raminfar cfc3e81820 Fixes typo #6 2018-11-20 07:45:24 -08:00
Amir Raminfar 67ab2ab170 1.2.1 2018-11-20 07:13:15 -08:00
Amir Raminfar e1ce378421 Adds SSL support for wss:// (#7)
* 1.2.0

* Adds SSL support
2018-11-20 07:12:13 -08:00
Amir Raminfar f083ea028d Fixes error in readme 2018-11-19 17:25:59 -08:00
Amir Raminfar 063a82198c Updates demo 2018-11-19 17:22:17 -08:00
Amir Raminfar d03c3440de 1.2.0 2018-11-19 13:04:25 -08:00
8 changed files with 91 additions and 41 deletions
+5 -5
View File
@@ -4,13 +4,13 @@ Dozzle is a log viewer for Docker. It's free. It's small. And it's right in your
While dozzle should work for most, it is not meant to be a full logging solution. For enterprise use, I recommend you look at [Loggly](https://www.loggly.com), [Papertrail](https://papertrailapp.com) or [Kibana](https://www.elastic.co/products/kibana).
But if you don't want to pay for those service, then you are in luck! Dozzle will be able capture all logs from your containers and send them in real-time to your browser. Installation is also very easy.
But if you don't want to pay for those services, then you are in luck! Dozzle will be able to capture all logs from your containers and send them in real-time to your browser. Installation is also very easy.
![Image](demo.gif)
## Getting dozzle
Dozzle is a very small Docker container (8.6MB virtual). Pull the latest release from the index:
Dozzle is a very small Docker container (4 MB compressed). Pull the latest release from the index:
$ docker pull amir20/dozzle:latest
@@ -28,14 +28,14 @@ dozzle doesn't support authentication out of the box. You can control the device
$ docker run --volume=/var/run/docker.sock:/var/run/docker.sock -p 8888:1224 amir20/dozzle:latest --addr localhost:1224
will bind to `localhost` on port `1224`. You can then use use reverse proxy to control who can see dozzle.
will bind to `localhost` on port `1224`. You can then use a reverse proxy to control who can see dozzle.
#### Changing base URL
dozzle by default mounts to "/". If you want to control the base path you can use the `--base` option. For example, if you want to mount at "/foobar",
then you can override by using `--base /foobar`.
$ docker run --volume=/var/run/docker.sock:/var/run/docker.sock -p 8888:1224 amir20/dozzle:latest --base /foobar
$ docker run --volume=/var/run/docker.sock:/var/run/docker.sock -p 8888:8080 amir20/dozzle:latest --base /foobar
dozzle will be available at [http://localhost:8080/foobar/](http://localhost:8080/foobar/).
@@ -46,7 +46,7 @@ If you see
2018/10/31 08:53:17 Error response from daemon: client version 1.40 is too new. Maximum supported API version is 1.38
Then you need to modify `DOCKER_API_VERSION` to let dozzle know which version of the API is supported. By default, `DOCKER_API_VERSION=1.38` and you can change it to by passing `-e` flag. For example, this would change the `DOCKER_API_VERSION` to `1.20`
Then you need to modify `DOCKER_API_VERSION` to let dozzle know which version of the API is supported. By default, `DOCKER_API_VERSION=1.38` and you can change it by passing `-e` flag. For example, this would change the `DOCKER_API_VERSION` to `1.20`
$ docker run --volume=/var/run/docker.sock:/var/run/docker.sock -e DOCKER_API_VERSION=1.20 -p 8888:8080 amir20/dozzle:latest
+46 -7
View File
@@ -1,9 +1,17 @@
<template lang="html">
<div class="columns is-marginless">
<aside class="column menu is-2 section">
<h1 class="title has-text-warning">Dozzle</h1>
<p class="menu-label">Containers</p>
<ul class="menu-list">
<aside class="column menu is-2">
<a
role="button"
class="navbar-burger burger is-white is-hidden-tablet is-pulled-right"
@click="showNav = !showNav;"
:class="{ 'is-active': showNav }"
>
<span></span> <span></span> <span></span>
</a>
<h1 class="title has-text-warning is-marginless">Dozzle</h1>
<p class="menu-label is-hidden-mobile" :class="{ 'is-active': showNav }">Containers</p>
<ul class="menu-list is-hidden-mobile" :class="{ 'is-active': showNav }">
<li v-for="item in containers">
<router-link
:to="{ name: 'container', params: { id: item.Id } }"
@@ -25,7 +33,8 @@ export default {
name: "App",
data() {
return {
containers: []
containers: [],
showNav: false
};
},
async created() {
@@ -34,10 +43,36 @@ export default {
};
</script>
<style scoped>
<style scoped lang="scss">
.is-hidden-mobile.is-active {
display: block !important;
}
.navbar-burger {
height: 2.35rem;
}
aside {
position: fixed;
padding-right: 0;
z-index: 2;
padding: 1em;
@media screen and (max-width: 768px) {
& {
position: sticky;
top: 0;
background: #222;
}
.tooltip::after,
.tooltip::before {
display: none !important;
}
.menu-label {
margin-top: 1em;
}
}
}
.hide-overflow {
@@ -45,4 +80,8 @@ aside {
white-space: nowrap;
overflow: hidden;
}
.burger.is-white {
color: #fff;
}
</style>
+16 -15
View File
@@ -1,19 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Dozzle</title>
<link href="https://fonts.googleapis.com/css?family=Roboto|Roboto+Mono|Gafata" rel="stylesheet">
<link href="styles.scss" rel="stylesheet">
<script>
window["BASE_PATH"] = "{{ .Base }}";
</script>
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
</head>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Dozzle</title>
<link href="https://fonts.googleapis.com/css?family=Roboto|Roboto+Mono|Gafata" rel="stylesheet" />
<link href="styles.scss" rel="stylesheet" />
<script>
window["BASE_PATH"] = "{{ .Base }}";
window["SSL_ENABLED"] = "{{ .SSL }}".toLowerCase() === "true";
</script>
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
</head>
<body class="is-dark">
<div id="app"></div>
<script src="main.js"></script>
</body>
<body class="is-dark">
<div id="app"></div>
<script src="main.js"></script>
</body>
</html>
+2 -1
View File
@@ -60,7 +60,8 @@ export default {
ws = null;
this.messages = [];
}
ws = new WebSocket(`ws://${window.location.host}${BASE_PATH}/api/logs?id=${this.id}`);
const protocol = SSL_ENABLED ? "wss" : "ws";
ws = new WebSocket(`${protocol}://${window.location.host}${BASE_PATH}/api/logs?id=${this.id}`);
ws.onopen = e => console.log("Connection opened.");
ws.onclose = e => console.log("Connection closed.");
ws.onerror = e => console.error("Connection error: " + e.data);
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 MiB

After

Width:  |  Height:  |  Size: 24 MiB

+19 -11
View File
@@ -20,8 +20,9 @@ import (
var (
cli *client.Client
addr = flag.String("addr", ":8080", "http service address")
base = flag.String("base", "/", "base address of the application to mount")
addr = ""
ssl = false
base = "/"
upgrader = websocket.Upgrader{}
version = "dev"
commit = "none"
@@ -29,6 +30,10 @@ var (
)
func init() {
flag.StringVar(&addr, "addr", ":8080", "http service address")
flag.StringVar(&base, "base", "/", "base address of the application to mount")
flag.BoolVarP(&ssl, "ssl", "s", false, "Uses websockets over ssl if enabled")
var err error
cli, err = client.NewClientWithOpts(client.FromEnv)
if err != nil {
@@ -40,19 +45,19 @@ func init() {
func main() {
r := mux.NewRouter()
if *base != "/" {
r.HandleFunc(*base, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
http.Redirect(w, req, *base+"/", http.StatusMovedPermanently)
if base != "/" {
r.HandleFunc(base, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
http.Redirect(w, req, base+"/", http.StatusMovedPermanently)
}))
}
s := r.PathPrefix(*base).Subrouter()
s := r.PathPrefix(base).Subrouter()
box := packr.NewBox("./static")
s.HandleFunc("/api/containers.json", listContainers)
s.HandleFunc("/api/logs", logs)
s.HandleFunc("/version", versionHandler)
s.PathPrefix("/").Handler(http.StripPrefix(*base, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
s.PathPrefix("/").Handler(http.StripPrefix(base, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
fileServer := http.FileServer(box)
if box.Has(req.URL.Path) && req.URL.Path != "" && req.URL.Path != "/" {
fileServer.ServeHTTP(w, req)
@@ -61,7 +66,7 @@ func main() {
}
})))
log.Fatal(http.ListenAndServe(*addr, r))
log.Fatal(http.ListenAndServe(addr, r))
}
func versionHandler(w http.ResponseWriter, r *http.Request) {
@@ -87,10 +92,13 @@ func handleIndex(box packr.Box, w http.ResponseWriter) {
}
path := ""
if *base != "/" {
path = *base
if base != "/" {
path = base
}
data := struct{ Base string }{Base: path}
data := struct {
Base string
SSL bool
}{path, ssl}
err = tmpl.Execute(w, data)
if err != nil {
panic(err)
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "dozzle",
"version": "1.1.2",
"version": "1.2.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+2 -1
View File
@@ -1,11 +1,12 @@
{
"name": "dozzle",
"version": "1.1.2",
"version": "1.2.3",
"description": "",
"main": "index.js",
"scripts": {
"start": "concurrently 'go run main.go' 'npm run watch-assets'",
"watch-assets": "parcel watch --public-url '__BASE__' assets/index.html -d static",
"prebuild": "npm run clean",
"build": "parcel build --public-url '__BASE__' assets/index.html -d static",
"clean": "rm -rf static",
"release": "goreleaser --rm-dist"