Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd9ddcf427 | ||
|
|
bbc7794006 | ||
|
|
7dc37f130c | ||
|
|
0711bc1c76 | ||
|
|
0aa24386b2 | ||
|
|
ca35b93671 | ||
|
|
a6220e4d38 | ||
|
|
4ed64a7cce | ||
|
|
0f27e11084 | ||
|
|
85eafc9c40 | ||
|
|
332cc384ea | ||
|
|
72fd31f85b | ||
|
|
a0ce370e9e | ||
|
|
e823904865 | ||
|
|
22bbfe1592 | ||
|
|
770e1818f0 | ||
|
|
d6fab75f8f | ||
|
|
17c18c156e | ||
|
|
5eca19840e | ||
|
|
b1d7b8ba55 | ||
|
|
e2ee430bbd | ||
|
|
0755a71dc2 | ||
|
|
60758db9c8 | ||
|
|
7b96196904 | ||
|
|
efcfa0e375 | ||
|
|
66f9204ae6 | ||
|
|
73c023ce22 | ||
|
|
261517ac3f | ||
|
|
2e0a546aa2 | ||
|
|
72ed7b50ba | ||
|
|
486bcec363 | ||
|
|
3db0ad42fe | ||
|
|
c1a75e21ba | ||
|
|
96c5e24501 | ||
|
|
c1a16fd76e | ||
|
|
42fab58c9f | ||
|
|
400cef767f | ||
|
|
84ae558467 | ||
|
|
0ebc9c562a | ||
|
|
f67664470f | ||
|
|
1f811da273 | ||
|
|
fdfc9fceba |
6
.github/workflows/deploy.yml
vendored
6
.github/workflows/deploy.yml
vendored
@@ -39,9 +39,9 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Build images
|
||||
run: docker-compose -f e2e/docker-compose.yml build
|
||||
run: COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f e2e/docker-compose.yml build
|
||||
- name: Run tests
|
||||
run: docker-compose -f e2e/docker-compose.yml up --build --force-recreate --exit-code-from cypress
|
||||
run: COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f e2e/docker-compose.yml up --build --force-recreate --exit-code-from cypress
|
||||
buildx:
|
||||
needs: [go-test, npm-test, int-test]
|
||||
name: Release
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3.1.0
|
||||
uses: docker/build-push-action@v3.1.1
|
||||
with:
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64/v8
|
||||
|
||||
4
.github/workflows/dev.yml
vendored
4
.github/workflows/dev.yml
vendored
@@ -27,10 +27,10 @@ jobs:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3.1.0
|
||||
uses: docker/build-push-action@v3.1.1
|
||||
with:
|
||||
push: true
|
||||
platforms: linux/amd64
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64/v8
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
build-args: TAG=${{ steps.meta.outputs.version }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
8
.github/workflows/test.yml
vendored
8
.github/workflows/test.yml
vendored
@@ -43,8 +43,12 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2.0.0
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2.0.0
|
||||
- name: Build images
|
||||
run: docker-compose -f e2e/docker-compose.yml build
|
||||
run: COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f e2e/docker-compose.yml build
|
||||
- name: Set commit message for push
|
||||
if: github.event_name == 'push'
|
||||
run: |
|
||||
@@ -58,4 +62,4 @@ jobs:
|
||||
git log -1 --pretty=%B ${{github.event.pull_request.head.sha}} >> $GITHUB_ENV
|
||||
echo 'EOF' >> $GITHUB_ENV
|
||||
- name: Run tests
|
||||
run: docker-compose -f e2e/docker-compose.yml up --build --force-recreate --exit-code-from cypress
|
||||
run: COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f e2e/docker-compose.yml up --build --force-recreate --exit-code-from cypress
|
||||
|
||||
13
Dockerfile
13
Dockerfile
@@ -1,7 +1,7 @@
|
||||
# Build assets
|
||||
FROM node:18-alpine as node
|
||||
FROM --platform=$BUILDPLATFORM node:18-alpine as node
|
||||
|
||||
RUN apk add --no-cache git openssh make g++ util-linux python3 && npm install -g pnpm
|
||||
RUN npm install -g pnpm
|
||||
|
||||
|
||||
WORKDIR /build
|
||||
@@ -19,9 +19,9 @@ COPY assets ./assets
|
||||
# Install dependencies
|
||||
RUN pnpm install -r --offline --prod --ignore-scripts && pnpm build
|
||||
|
||||
FROM golang:1.18.4-alpine AS builder
|
||||
FROM --platform=$BUILDPLATFORM golang:1.19.0-alpine AS builder
|
||||
|
||||
RUN apk add --no-cache git ca-certificates && mkdir /dozzle
|
||||
RUN apk add --no-cache ca-certificates && mkdir /dozzle
|
||||
|
||||
WORKDIR /dozzle
|
||||
|
||||
@@ -41,9 +41,10 @@ COPY main.go ./
|
||||
|
||||
# Args
|
||||
ARG TAG=dev
|
||||
ARG TARGETOS TARGETARCH
|
||||
|
||||
# Build binary
|
||||
RUN CGO_ENABLED=0 go build -ldflags "-s -w -X main.version=$TAG" -o dozzle
|
||||
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -ldflags "-s -w -X main.version=$TAG" -o dozzle
|
||||
|
||||
|
||||
FROM scratch
|
||||
@@ -53,8 +54,6 @@ ENV PATH /bin
|
||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||
COPY --from=builder /dozzle/dozzle /dozzle
|
||||
|
||||
HEALTHCHECK --start-period=4s --interval=2s CMD [ "/dozzle", "healthcheck" ]
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
ENTRYPOINT ["/dozzle"]
|
||||
|
||||
24
README.md
24
README.md
@@ -58,6 +58,30 @@ Dozzle will be available at [http://localhost:8888/](http://localhost:8888/). Yo
|
||||
ports:
|
||||
- 9999:8080
|
||||
|
||||
|
||||
### Enabling health check
|
||||
|
||||
Dozzle doesn't enable healthcheck by default as it adds extra CPU usage. `healthcheck` can be enabled manually.
|
||||
|
||||
version: "3"
|
||||
services:
|
||||
dozzle:
|
||||
container_name: dozzle
|
||||
image: amir20/dozzle:latest
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
ports:
|
||||
- 8080:8080
|
||||
environment:
|
||||
DOZZLE_LEVEL: trace
|
||||
healthcheck:
|
||||
test: [ "CMD", "/dozzle", "healthcheck" ]
|
||||
interval: 3s
|
||||
timeout: 30s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
|
||||
|
||||
#### Security
|
||||
|
||||
You can control the device Dozzle binds to by passing `--addr` parameter. For example,
|
||||
|
||||
@@ -138,14 +138,20 @@ func (d *dockerClient) ContainerStats(ctx context.Context, id string, stats chan
|
||||
log.Errorf("decoder for stats api returned an unknown error %v", err)
|
||||
}
|
||||
|
||||
ncpus := uint8(v.CPUStats.OnlineCPUs)
|
||||
if ncpus == 0 {
|
||||
ncpus = uint8(len(v.CPUStats.CPUUsage.PercpuUsage))
|
||||
}
|
||||
|
||||
var (
|
||||
cpuDelta = float64(v.CPUStats.CPUUsage.TotalUsage) - float64(v.PreCPUStats.CPUUsage.TotalUsage)
|
||||
systemDelta = float64(v.CPUStats.SystemUsage) - float64(v.PreCPUStats.SystemUsage)
|
||||
cpuPercent = int64((cpuDelta / systemDelta) * float64(len(v.CPUStats.CPUUsage.PercpuUsage)) * 100)
|
||||
cpuPercent = int64((cpuDelta / systemDelta) * float64(ncpus) * 100)
|
||||
memUsage = int64(v.MemoryStats.Usage - v.MemoryStats.Stats["cache"])
|
||||
memPercent = int64(float64(memUsage) / float64(v.MemoryStats.Limit) * 100)
|
||||
)
|
||||
|
||||
|
||||
if cpuPercent > 0 || memUsage > 0 {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
@@ -167,6 +173,12 @@ func (d *dockerClient) ContainerStats(ctx context.Context, id string, stats chan
|
||||
func (d *dockerClient) ContainerLogs(ctx context.Context, id string, tailSize int, since string) (io.ReadCloser, error) {
|
||||
log.WithField("id", id).WithField("since", since).Debug("streaming logs for container")
|
||||
|
||||
if since != "" {
|
||||
if sinceTime, err := time.Parse(time.RFC3339Nano, since); err == nil {
|
||||
since = sinceTime.Add(time.Microsecond).Format(time.RFC3339Nano)
|
||||
}
|
||||
}
|
||||
|
||||
options := types.ContainerLogsOptions{
|
||||
ShowStdout: true,
|
||||
ShowStderr: true,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM cypress/included:10.3.0
|
||||
FROM cypress/included:10.4.0
|
||||
|
||||
RUN apt install curl && curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
|
||||
|
||||
|
||||
36
package.json
36
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dozzle",
|
||||
"version": "3.12.9",
|
||||
"version": "3.13.1",
|
||||
"description": "Realtime log viewer for docker containers. ",
|
||||
"homepage": "https://github.com/amir20/dozzle#readme",
|
||||
"bugs": {
|
||||
@@ -22,43 +22,43 @@
|
||||
"postinstall": "husky install"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify-json/carbon": "^1.1.6",
|
||||
"@iconify-json/carbon": "^1.1.7",
|
||||
"@iconify-json/cil": "^1.1.2",
|
||||
"@iconify-json/mdi": "^1.1.29",
|
||||
"@iconify-json/mdi-light": "^1.1.2",
|
||||
"@iconify-json/octicon": "^1.1.13",
|
||||
"@iconify-json/octicon": "^1.1.15",
|
||||
"@oruga-ui/oruga-next": "^0.5.4",
|
||||
"@oruga-ui/theme-bulma": "^0.2.6",
|
||||
"@vitejs/plugin-vue": "3.0.1",
|
||||
"@vue/compiler-sfc": "^3.2.37",
|
||||
"@vueuse/core": "^8.9.4",
|
||||
"@vueuse/router": "^8.9.4",
|
||||
"@vueuse/core": "^9.1.0",
|
||||
"@vueuse/router": "^9.1.0",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"bulma": "^0.9.4",
|
||||
"date-fns": "^2.28.0",
|
||||
"date-fns": "^2.29.1",
|
||||
"fuzzysort": "^2.0.1",
|
||||
"hotkeys-js": "^3.9.4",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"pinia": "^2.0.16",
|
||||
"sass": "^1.53.0",
|
||||
"pinia": "^2.0.17",
|
||||
"sass": "^1.54.2",
|
||||
"semver": "^7.3.7",
|
||||
"splitpanes": "^3.1.1",
|
||||
"typescript": "^4.7.4",
|
||||
"unplugin-auto-import": "^0.9.3",
|
||||
"unplugin-icons": "^0.14.7",
|
||||
"unplugin-vue-components": "^0.21.1",
|
||||
"vite": "3.0.2",
|
||||
"unplugin-auto-import": "^0.10.3",
|
||||
"unplugin-icons": "^0.14.8",
|
||||
"unplugin-vue-components": "^0.22.0",
|
||||
"vite": "3.0.4",
|
||||
"vue": "^3.2.37",
|
||||
"vue-router": "^4.1.2"
|
||||
"vue-router": "^4.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@pinia/testing": "^0.0.12",
|
||||
"@pinia/testing": "^0.0.13",
|
||||
"@types/jest": "^28.1.6",
|
||||
"@types/lodash.debounce": "^4.0.7",
|
||||
"@types/node": "^18.0.6",
|
||||
"@types/node": "^18.6.3",
|
||||
"@types/semver": "^7.3.10",
|
||||
"@vue/test-utils": "^2.0.2",
|
||||
"c8": "^7.11.3",
|
||||
"c8": "^7.12.0",
|
||||
"eventsourcemock": "^2.0.0",
|
||||
"husky": "^8.0.1",
|
||||
"jest-serializer-vue": "^2.0.2",
|
||||
@@ -66,9 +66,9 @@
|
||||
"lint-staged": "^13.0.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^2.7.1",
|
||||
"release-it": "^15.1.2",
|
||||
"release-it": "^15.2.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"vitest": "^0.18.1"
|
||||
"vitest": "^0.20.3"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,vue,css}": [
|
||||
|
||||
661
pnpm-lock.yaml
generated
661
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
17
web/logs.go
17
web/logs.go
@@ -105,12 +105,27 @@ func (h *handler) streamLogs(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
ticker := time.NewTicker(5 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-r.Context().Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
fmt.Fprintf(w, ":ping \n\n")
|
||||
f.Flush()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
buffered := bufio.NewReader(reader)
|
||||
var readerError error
|
||||
var message string
|
||||
for {
|
||||
message, readerError = buffered.ReadString('\n')
|
||||
fmt.Fprintf(w, "data: %s\n", message)
|
||||
fmt.Fprintf(w, "data: %s\n", strings.TrimRight(message, "\n"))
|
||||
if index := strings.IndexAny(message, " "); index != -1 {
|
||||
id := message[:index]
|
||||
if _, err := time.Parse(time.RFC3339Nano, id); err == nil {
|
||||
|
||||
Reference in New Issue
Block a user