diff --git a/.gitea/workflows/docker.yml b/.gitea/workflows/docker.yml
new file mode 100644
index 0000000..cdd601d
--- /dev/null
+++ b/.gitea/workflows/docker.yml
@@ -0,0 +1,28 @@
+name: Build docker image
+
+on:
+  push:
+    branches: ["main"]
+
+env:
+  REGISTRY: git.matterlinux.xyz
+  IMAGE: ${{gitea.repository}}
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout repository
+        uses: "https://github.com/actions/checkout@v4"
+
+      - name: Login to container repo
+        uses: "https://github.com/docker/login-action@v1"
+        with:
+          registry: ${{env.REGISTRY}}
+          username: ${{gitea.actor}}
+          password: ${{secrets.PACKAGES_TOKEN}}
+
+      - name: Build image
+        run: |
+          docker build --tag ${{env.REGISTRY}}/${{env.IMAGE}}:latest .
+          docker push ${{env.REGISTRY}}/${{env.IMAGE}}:latest
diff --git a/Dockerfile b/Dockerfile
index 1db3817..baf826f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,16 +2,23 @@ FROM golang:1.23.5
 
 WORKDIR /app
 
-COPY *.go  ./
-COPY *.mod ./
-COPY *.sum ./
+RUN useradd runner -r -u 1001 -d /app
+RUN chown -R runner:runner /app
+USER runner
 
+COPY *.mod    ./
+COPY *.sum    ./
+
+RUN go mod download
+
+COPY *.go      ./
+COPY Makefile  ./
 COPY lib       ./lib
 COPY log       ./log
 COPY public    ./public
 COPY routes    ./routes
 COPY templates ./templates
 
-RUN go build .
+RUN make
 
 ENTRYPOINT ["/app/tracker"]
diff --git a/README.md b/README.md
index 0b612d2..1ae0e8c 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,7 @@
 # tracker | MatterLinux package tracker
+
+![](https://git.matterlinux.xyz/matter/tracker/actions/workflows/docker.yml/badge.svg)
+
 Soruce code of MatterLinux's package tracker, located at
 [tracker.matterlinux.xyz](https://tracker.matterlinux.xyz)
 
@@ -39,23 +42,19 @@ official MatterLinux 24 repos:
 ```
 
 ### Deployment
-Web server can be built and deployed with docker compose using the following
-configuration file:
+Web server can be deployed with docker compose using the following configuration file:
 ```yaml
-version: "3"
-
 services:
   tracker:
-    image: mattertracker
-    restart: unless-stopped
-    build:
-      context: ./
+    container_name: mattertracker
+    image: git.matterlinux.xyz/matter/tracker
     ports:
-      - "127.0.0.1:9877:9877"
+    - "127.0.0.1:9877:9877"
     volumes:
-      - "./config.json:/app/config.json:ro"
+    - "./config.json:/app/config.json:ro"
+    restart: unless-stopped
 ```
-After saving the configuration file, you can build and run the docker container:
+After saving the configuration file, you can run the docker container:
 ```bash
 docker-compose up -d
 ```
diff --git a/go.mod b/go.mod
index 3995958..5bfda66 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.22.5
 
 require (
 	github.com/bigkevmcd/go-configparser v0.0.0-20240808124832-fc81059ea0bd
-	github.com/gofiber/fiber/v2 v2.52.5
+	github.com/gofiber/fiber/v2 v2.52.6
 	github.com/gofiber/template/html/v2 v2.1.2
 )
 
@@ -21,5 +21,5 @@ require (
 	github.com/valyala/bytebufferpool v1.0.0 // indirect
 	github.com/valyala/fasthttp v1.57.0 // indirect
 	github.com/valyala/tcplisten v1.0.0 // indirect
-	golang.org/x/sys v0.27.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
 )
diff --git a/go.sum b/go.sum
index bd3cf2e..37da460 100644
--- a/go.sum
+++ b/go.sum
@@ -6,6 +6,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo=
 github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
+github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI=
+github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
 github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc=
 github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8=
 github.com/gofiber/template/html/v2 v2.1.2 h1:wkK/mYJ3nIhongTkG3t0QgV4ADdgOYJYVSAF2AHnh8Y=
@@ -46,6 +48,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
 golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=