Trackly Blog 4: Dockerizing a Full-Stack Go + React Application with PostgreSQL

When I started building Trackly, I wanted more than just another side project. I wanted it to be production-ready, portable, and a strong showcase of my ability to work with Docker, Compose, and containerised workflows.

In this blog, I’ll share how I used Docker and Docker Hub to run Trackly — a Go backend, React frontend, and PostgreSQL database — consistently across local development and production.

This is not a “Hello World” Docker example. It’s a real, full-stack application containerised end-to-end.

Trackly :- https://github.com/sidharth-chauhan/Trackly

#. Why Docker for Trackly?

Trackly has three core components:

  • PostgreSQL → database for persistent storage

  • Go backend → REST API + background monitoring jobs

  • React frontend → Vite-based UI for project dashboards

Running these manually means installing dependencies, wiring environment variables, and debugging mismatches. With Docker, I get:

  • Consistency → identical environment across dev, CI/CD, and prod

  • Portability → push images to Docker Hub, run anywhere

  • Isolation → each service runs in its own container, no conflicts

  • Simplicity → one command to launch the entire stack

docker compose up --build

#. Backend Dockerfile (Go)

# Stage 1: Build
FROM golang:1.24.1-alpine AS builder
RUN apk add --no-cache git

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN go build -o main ./cmd/main.go

# Stage 2: Runtime
FROM alpine:latest
RUN apk --no-cache add ca-certificates

WORKDIR /root/
COPY --from=builder /app/main .

CMD ["./main"]
  • Multi-stage builds keep the final image small.

  • I compile in a golang:alpine environment, but only ship the binary in a clean alpine:latest.

  • This reduces the attack surface and ensures faster deployments.


#. Frontend Dockerfile (React + Vite)

FROM node:20-alpine

WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm install

COPY . .
EXPOSE 5173

CMD ["npm", "run", "dev"]
  • A lightweight Node base image ensures faster builds.

  • Keeps the dev experience simple with npm run dev.

  • For production, I can easily switch to npm run build + serve with Nginx for optimal performance.


#. PostgreSQL Service

services:
  db:
    image: postgres:15
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: yourpassword
      POSTGRES_DB: openanalytics
    ports:
      - "5432:5432"
    volumes:
      - postgres-data:/var/lib/postgresql/data
  • I rely on the official postgres:15 image instead of reinventing the wheel.

  • Credentials and DB name are set via environment variables.

  • Data persists across container restarts using Docker volumes.

  • Exposes port 5432.


#. docker-compose.yaml

version: "3.9"

services:
  db:
    image: postgres:15
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: yourpassword
      POSTGRES_DB: openanalytics
    ports:
      - "5432:5432"
    volumes:
      - postgres-data:/var/lib/postgresql/data

  backend:
    image: sidharthchauhan/backend-trackly:latest
    environment:
      DB_HOST: db
      DB_PORT: 5432
      DB_USER: postgres
      DB_PASSWORD: yourpassword
      DB_NAME: openanalytics
      JWT_SECRET: supersecretkey
    depends_on:
      - db
    ports:
      - "8080:8080"
    restart: unless-stopped

  frontend:
    image: sidharthchauhan/frontend-trackly:latest
    environment:
      VITE_BACKEND_URL: http://backend:8080
    ports:
      - "5173:5173"
    depends_on:
      - db
      - backend
    restart: unless-stopped

volumes:
  postgres-data:
  • Service dependencies → backend won’t start until Postgres is up.

  • Environment variables → configuration is clean and externalized.

  • Volumes → persistent storage for DB data.

  • Restart policies → containers auto-recover if they crash.

  • Networking → services talk to each other by name (backend resolves db internally).


#. Docker Hub

docker pull sidharthchauhan/backend-trackly

Frontend:- sidharthchauhan/frontend-trackly

docker pull sidharthchauhan/frontend-trackly

#. Running Trackly Locally

Quick start:-

docker compose up --build

And then access the services:


Final Thoughts

With this setup, Trackly became a fully containerised application. I can run the same codebase in development, testing, and production — without worrying about environment drift.

Docker and Docker Compose transformed Trackly from just “a project” into a cloud-ready, portable application. Publishing my images to Docker Hub turned it into something that anyone can spin up with a single command.

This is exactly why I believe containerization is a foundational skill for modern developers — and Trackly has been my way of mastering it in practice.

0
Subscribe to my newsletter

Read articles from Sidharth chauhan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sidharth chauhan
Sidharth chauhan

🌟 Hello! I'm Sidharth Chauhan, a passionate DevOps Engineer dedicated to automating and optimizing processes to enhance software development and deployment. With expertise in Docker, Kubernetes, CI/CD, AWS, and more, I thrive in environments that leverage cutting-edge technologies and tools.I love sharing my knowledge and experiences through blogging, and I'm always eager to connect with like-minded professionals. Whether you're looking to collaborate on a project, need help with DevOps, or just want to chat about the latest tech trends, feel free to reach out!🔗 Connect with Me: