diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d2211d7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM alpine +ENV NODE_ENV=production +RUN apk add --update nodejs npm +WORKDIR /app +COPY package*.json ./ +RUN npm install --omit=dev +COPY . . +RUN npm run build +CMD ["npm", "start"] \ No newline at end of file diff --git a/README.md b/README.md index ccb7e27..2a61e2c 100644 --- a/README.md +++ b/README.md @@ -29,3 +29,17 @@ bun dev Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. The port might be different if you have another Next project running on 3000. +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Running in a Container +constat can itself run in a container. + +It needs `/var/run/docker.sock` to be mounted inside to be able to talk to the Docker daemon on the machine where its running. + +```shell +docker run -p9001:3000 -v /var/run/docker.sock:/var/run/docker.sock +``` + +Open [http://localhost:9001](http://localhost:3000) with your browser to see the result. diff --git a/app/page.tsx b/app/page.tsx index ca5ae80..2a98be9 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,6 +1,6 @@ 'use strict'; -import { Docker } from "node-docker-api"; +export const dynamic = 'force-dynamic'; import { Card, CardTitle } from "@/components/ui/card"; import { @@ -13,8 +13,8 @@ import { } from "@/components/ui/table"; import LogViewer from "@/components/logviewer"; +import { getContainers } from "@/lib/docker-utils"; import Image from "next/image"; -import { Container } from "node-docker-api/lib/container"; interface ContainerData { Id: string; @@ -23,30 +23,27 @@ interface ContainerData { ImageID: string; Command: string; Created: number, - Ports: [[Object]], + Ports: [[object]], Labels: { string: string; }, State: string; Status: string; HostConfig: { string: string; }, - NetworkSettings: { Networks: [Object] }, - Mounts: [[Object], [Object]] + NetworkSettings: { Networks: [object] }, + Mounts: [[object], [object]] } const Home = async () => { - const docker = new Docker({ socketPath: '/var/run/docker.sock' }); - - const list = await docker.container.list() as Container[]; - + const list = await getContainers(); // console.log(list); - list.forEach((container) => { - const data: ContainerData = container.data as ContainerData; - console.log(data.Names); + // list.forEach((container) => { + // const data: ContainerData = container.data as ContainerData; + // console.log(data.Names); - }) + // }) return (
diff --git a/components/logviewer.tsx b/components/logviewer.tsx index 275bc9b..deb6439 100644 --- a/components/logviewer.tsx +++ b/components/logviewer.tsx @@ -9,7 +9,7 @@ import { } from "@/components/ui/sheet"; import { ScrollArea } from "@/components/ui/scroll-area"; -import { getContainerLogs } from "@/lib/docker-logs"; +import { getContainerLogs } from "@/lib/docker-utils"; import { useEffect, useState } from "react"; interface LogViewerProps { @@ -36,7 +36,7 @@ const LogViewer = (props: LogViewerProps) => { const intervalId = setInterval(updateMessages, 2000); return () => clearInterval(intervalId); - }, []); + }, [containerId]); return ( @@ -48,6 +48,7 @@ const LogViewer = (props: LogViewerProps) => { Logs for {containerId} - refreshing every 2 seconds {messages.split("\n").map(message => { + // eslint-disable-next-line react/jsx-key return
{message}
})}
diff --git a/lib/docker-logs.ts b/lib/docker-utils.ts similarity index 79% rename from lib/docker-logs.ts rename to lib/docker-utils.ts index 6a7902d..f35a816 100644 --- a/lib/docker-logs.ts +++ b/lib/docker-utils.ts @@ -2,6 +2,7 @@ "use server"; import { Docker } from "node-docker-api"; +import { Container } from "node-docker-api/lib/container"; const docker = new Docker({ socketPath: '/var/run/docker.sock' }); @@ -18,6 +19,7 @@ export const getContainerLogs = async (containerId: string, numLines: number): P stdout: true, stderr: true, tail: numLines, + // eslint-disable-next-line @typescript-eslint/no-explicit-any }).then((stream: any) => { stream.on("data", (chunk: Buffer) => { const line = chunk.slice(8).toString("utf8"); @@ -30,6 +32,7 @@ export const getContainerLogs = async (containerId: string, numLines: number): P resolve(logBuffer); }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any stream.on("error", (err: any) => { logBuffer += err.slice(8).toString("utf8"); // logBuffer += "\n"; @@ -39,6 +42,9 @@ export const getContainerLogs = async (containerId: string, numLines: number): P }); } +export const getContainers = async(): Promise => { + return await docker.container.list() as Container[]; +} // getContainerLogs("80cc84c5bf3a").then(logs => { // console.log(logs) diff --git a/package-lock.json b/package-lock.json index f78d3ab..39bf044 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", - "eslint": "^8", + "eslint": "^8.57.1", "eslint-config-next": "15.0.3", "postcss": "^8", "tailwindcss": "^3.4.1", diff --git a/package.json b/package.json index 2422b2e..66582ee 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", - "eslint": "^8", + "eslint": "^8.57.1", "eslint-config-next": "15.0.3", "postcss": "^8", "tailwindcss": "^3.4.1",