Skip to content

Local Docker Desktop K8s Setup Guide

Note: Kubernetes manifests (argocd/, kustomize overlays) are managed in a separate infrastructure repository. The steps below describe the ArgoCD setup pattern; adapt manifest paths to your infrastructure repo.

This guide walks you through setting up ArgoCD on Docker Desktop Kubernetes for local testing before cloud deployment.

Required Software

Install all tools before proceeding.

Docker Desktop (Kubernetes)

Download from docs.docker.com/desktop. After install:

  1. Settings → Kubernetes → Enable Kubernetes → Apply & Restart
  2. Allocate at least 4 GB RAM and 2 CPUs (Settings → Resources)

kubectl

# Linux
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

# macOS
brew install kubectl

# Verify
kubectl version --client

ArgoCD CLI

# Linux / WSL
VERSION=$(curl -s https://api.github.com/repos/argoproj/argo-cd/releases/latest | grep '"tag_name"' | cut -d'"' -f4)
curl -sSL -o /tmp/argocd "https://github.com/argoproj/argo-cd/releases/download/${VERSION}/argocd-linux-amd64"
sudo install -m 555 /tmp/argocd /usr/local/bin/argocd
rm /tmp/argocd

# macOS
brew install argocd

# Verify
argocd version --client

Kustomize

# Linux / WSL
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
sudo mv kustomize /usr/local/bin/

# macOS
brew install kustomize

# Verify
kustomize version

GitHub CLI (gh)

# Linux / WSL (Debian/Ubuntu)
(type -p wget >/dev/null || (sudo apt update && sudo apt install wget -y)) \
  && sudo mkdir -p -m 755 /etc/apt/keyrings \
  && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
  && sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
  && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
  && sudo apt update && sudo apt install gh -y

# macOS
brew install gh

# Authenticate
gh auth login

# Verify
gh --version

Helm

# Linux / WSL
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# macOS
brew install helm

# Verify
helm version
# Linux / WSL
curl -sS https://webinstall.dev/k9s | bash

# macOS
brew install derailed/k9s/k9s

# Launch
k9s

Prerequisites

  • ✅ Docker Desktop installed with Kubernetes enabled
  • ✅ kubectl, argocd, kustomize, gh, helm CLIs installed
  • ✅ Git installed and authenticated to GitHub

Step 1: Verify Kubernetes is Running

# Check Docker Desktop K8s is running
kubectl cluster-info

# Expected output:
# Kubernetes control plane is running at https://kubernetes.docker.internal:6443
# CoreDNS is running at https://kubernetes.docker.internal:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

If not running:

  1. Open Docker Desktop
  2. Settings → Kubernetes → Enable Kubernetes
  3. Apply & Restart
  4. Wait for "Kubernetes is running" status

Step 2: Install ArgoCD

# Create argocd namespace
kubectl create namespace argocd

# Install ArgoCD
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Wait for all pods to be ready (takes 2-3 minutes)
kubectl wait --for=condition=Ready pods --all -n argocd --timeout=300s

Verify installation:

kubectl get pods -n argocd

# Expected: All pods should be Running
# NAME                                  READY   STATUS
# argocd-server-xxxxx                   1/1     Running
# argocd-repo-server-xxxxx              1/1     Running
# argocd-application-controller-xxxxx   1/1     Running
# argocd-dex-server-xxxxx               1/1     Running
# argocd-redis-xxxxx                    1/1     Running

Step 3: Access ArgoCD UI

Deployed cluster (K3s VPS): ArgoCD is already accessible at https://argocd.thedataenginex.org via Traefik ingress with a Let's Encrypt cert. No port-forward needed — skip to Step 4.

The steps below only apply when running ArgoCD on a local Docker Desktop cluster (no ingress).

Option A: Port Forward (local Docker Desktop only)

ArgoCD serves HTTPS on container port 8080 regardless of which service port you forward. Always use https://.

kubectl port-forward svc/argocd-server -n argocd 8080:443
# Open: https://localhost:8080
# Accept the self-signed certificate warning in your browser

If you want plain HTTP locally, patch the server to disable TLS first:

kubectl patch deploy argocd-server -n argocd \
  --type=json \
  -p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--insecure"}]'
kubectl rollout status deployment/argocd-server -n argocd

kubectl port-forward svc/argocd-server -n argocd 8080:80
# Open: http://localhost:8080

Option B: Expose via NodePort (local Docker Desktop only)

kubectl patch svc argocd-server -n argocd -p '{"spec":{"type":"NodePort"}}'
kubectl get svc argocd-server -n argocd
# Access at: https://localhost:<NodePort>

Step 4: Get ArgoCD Admin Password

# Get initial admin password
ARGOCD_PASSWORD=$(kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d)

echo "ArgoCD Admin Password: $ARGOCD_PASSWORD"

Login:

# Download ArgoCD CLI for Linux
version="v2.11.2"
curl -sSL -o /tmp/argocd "https://github.com/argoproj/argo-cd/releases/download/${version}/argocd-linux-amd64"
sudo install -m 555 /tmp/argocd /usr/local/bin/argocd
rm /tmp/argocd

Login via CLI:

argocd login localhost:8080 --username admin --password $ARGOCD_PASSWORD --insecure

Step 6: Deploy DEX Application

# Apply the ArgoCD application manifest
kubectl apply -f argocd/application.yaml  # path in your infrastructure repo

# Verify applications created
kubectl get applications -n argocd

# Expected output:
# NAME        SYNC STATUS   HEALTH STATUS
# dex-dev     OutOfSync     Missing
# dex         OutOfSync     Missing

Step 7: Sync Applications

Option A: Via ArgoCD UI

  1. Go to https://localhost:8080
  2. Click on dex-dev application
  3. Click "SYNC" button
  4. Review changes → Click "SYNCHRONIZE"

Option B: Via ArgoCD CLI

# Sync dev environment
argocd app sync dex-dev

# Watch sync progress
argocd app wait dex-dev --health

# Check application status
argocd app get dex-dev

Step 8: Verify Deployment

# Check dev namespace pods
kubectl get pods -n dex-dev

# Expected:
# NAME                   READY   STATUS    RESTARTS   AGE
# dex-xxxxxxxxxx-xxxxx   1/1     Running   0          30s

# Check service
kubectl get svc -n dex-dev

# Check deployment
kubectl describe deployment dex -n dex-dev

Step 9: Access DEX Application

# Port forward DEX service
kubectl port-forward -n dex-dev svc/dex 17000:17000

# Access application at: http://localhost:17000

Test endpoints:

Step 10: Test GitOps Workflow

Simulate Image Update (Manual)

# Update dev kustomization.yaml
newTag="sha-test1234"
sed -i "s|newTag:.*|newTag: ${newTag}|g" argocd/overlays/dev/kustomization.yaml

# Commit and push (dev branch tracks dev environment)
git add argocd/overlays/dev/kustomization.yaml
git commit -m "test: update dev image to $newTag"
git push origin dev

Watch ArgoCD detect change:

# ArgoCD polls git every 3 minutes by default
# Force refresh immediately:
argocd app refresh dex-dev

# Watch sync
argocd app wait dex-dev --sync

Troubleshooting

ArgoCD pods not starting

# Check pod events
kubectl describe pod <pod-name> -n argocd

# Check pod logs
kubectl logs <pod-name> -n argocd

# Common fix: Increase Docker Desktop resources
# Settings → Resources → Memory: 4GB+, CPU: 2+

Application stuck in "OutOfSync"

# Check sync status
argocd app get dex-dev

# Force sync with prune
argocd app sync dex-dev --prune

# Check for errors
kubectl get events -n dex-dev --sort-by='.lastTimestamp'

Image pull errors

# If using ghcr.io, images must be public or you need imagePullSecrets
# For local testing, build with the same sha- convention:
SHORT_SHA=$(git rev-parse --short=8 HEAD)
docker build -t ghcr.io/thedataenginex/dataenginex:sha-${SHORT_SHA} .

# Update the dev overlay to use your local tag, then push to infradex dev branch
cd argocd/overlays/dev
kustomize edit set image ghcr.io/thedataenginex/dataenginex=ghcr.io/thedataenginex/dataenginex:sha-${SHORT_SHA}

Can't access localhost:8080

# Check port forward is running
ps -ef | grep kubectl

# Restart port forward
kubectl port-forward svc/argocd-server -n argocd 8080:443

Application health degraded

# Check deployment status
kubectl rollout status deployment/dex -n dex-dev

# Check pod logs
kubectl logs -f deployment/dex -n dex-dev

# Check resource constraints
kubectl top pods -n dex-dev

Clean Up

Remove specific application

# Delete application (keeps namespace)
argocd app delete dex-dev

# Or via kubectl
kubectl delete application dex-dev -n argocd

# Delete namespace
kubectl delete namespace dex-dev

Uninstall ArgoCD

# Delete all ArgoCD resources
kubectl delete -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Delete namespace
kubectl delete namespace argocd

DEX Testing Workflow with ArgoCD

This section covers how to test changes through the full GitOps promotion pipeline for both dex-studio and careerdex.

Environment Overview

feature branch → preview env → stage → prod (main)
Service Preview namespace Stage namespace Prod namespace Port
dex-studio dex-studio-preview-<branch-slug> dex-studio-stage dex-studio 7860
careerdex careerdex-preview-<branch-slug> careerdex-stage careerdex 8788

Step 1: Test on a Preview Environment

Push your feature branch — CI automatically creates a directory under argocd/previews/<service>/<branch-slug>/ in the infradex repo. ArgoCD's Git generator picks it up and deploys an ephemeral namespace.

# Verify preview apps appeared
argocd app list | grep preview

# dex-studio preview
argocd app wait dex-studio-preview-<branch-slug> --health
kubectl port-forward -n dex-studio-preview-<branch-slug> svc/dex-studio 7860:7860
# Access at: http://localhost:7860

# careerdex preview
argocd app wait careerdex-preview-<branch-slug> --health
kubectl port-forward -n careerdex-preview-<branch-slug> svc/careerdex 8788:8788
# Access at: http://localhost:8788

ArgoCD auto-prunes preview namespaces when the branch is deleted.

Step 2: Check Stage After Merging to dev

After your PR merges to dev, CI builds new images and updates the stage overlay tags. ArgoCD syncs automatically within ~3 minutes.

dex-studio stage

argocd app get dex-studio-stage
argocd app refresh dex-studio-stage           # force immediate refresh

kubectl rollout status deployment/dex-studio -n dex-studio-stage
kubectl get pods -n dex-studio-stage

kubectl port-forward -n dex-studio-stage svc/dex-studio 7860:7860

Test endpoints:

  • http://localhost:7860 — UI
  • http://localhost:17000/health — DEX API health
  • http://localhost:17000/ready — readiness probe
  • http://localhost:17000/docs — FastAPI Swagger UI

careerdex stage

argocd app get careerdex-stage
argocd app refresh careerdex-stage            # force immediate refresh

kubectl rollout status deployment/careerdex -n careerdex-stage
kubectl get pods -n careerdex-stage

kubectl port-forward -n careerdex-stage svc/careerdex 8788:8788
# Access at: http://localhost:8788

Step 3: Check Application Diff Before Promoting

# dex-studio
argocd app diff dex-studio-stage
argocd app history dex-studio-stage

# careerdex
argocd app diff careerdex-stage
argocd app history careerdex-stage

Step 4: Promote to Prod

Once stage is verified for both services, promote via scripts/promote.sh in the infradex repo:

# Option A: promote the entire dev branch to main (deploys all services)
./scripts/promote.sh

# Option B: pin a specific image tag for a service directly
./scripts/promote.sh --image-tag sha-abc12345

# Option C: auto-merge after CI passes
./scripts/promote.sh --auto-merge

Monitor prod rollout after PR merges:

# dex-studio prod
kubectl rollout status deployment/dex-studio -n dex-studio
kubectl get pods -n dex-studio

# careerdex prod
kubectl rollout status deployment/careerdex -n careerdex
kubectl get pods -n careerdex

Rollback

# dex-studio — ArgoCD rollback to previous revision
argocd app rollback dex-studio-stage <revision>
argocd app history dex-studio-stage

# careerdex — ArgoCD rollback to previous revision
argocd app rollback careerdex-stage <revision>
argocd app history careerdex-stage

# Or revert the image tag commit in infradex and push (affects all services)
git revert HEAD
git push origin main

Useful Commands Reference

# List all apps
argocd app list

# Force sync
argocd app sync dex-studio-stage
argocd app sync careerdex-stage

# Sync with resource pruning
argocd app sync dex-studio-stage --prune
argocd app sync careerdex-stage --prune

# Stream pod logs
kubectl logs -f deployment/dex-studio -n dex-studio-stage
kubectl logs -f deployment/careerdex -n careerdex-stage

# Check events (useful for ImagePullBackOff etc.)
kubectl get events -n dex-studio-stage --sort-by='.lastTimestamp'
kubectl get events -n careerdex-stage --sort-by='.lastTimestamp'

# Resource usage
kubectl top pods -n dex-studio-stage
kubectl top pods -n careerdex-stage

Next Steps

After local validation:

  1. ✅ ArgoCD working locally
  2. ⏭️ Set up ArgoCD in your target Kubernetes cluster (cloud-managed or self-hosted)
  3. ⏭️ Set up promotion workflow with PR-based promotion
  4. ⏭️ Configure webhooks for instant sync (instead of 3-min polling)

Tips

  • Fast Refresh: argocd app refresh <app> forces immediate git poll
  • Auto-Sync: Already enabled for both dev and prod
  • Prune: Auto-prune enabled (ArgoCD deletes resources removed from git)
  • Self-Heal: Enabled (ArgoCD reverts manual kubectl changes)
  • Diff: argocd app diff dex-dev shows pending changes
  • History: argocd app history dex-dev shows deployment history
  • Rollback: argocd app rollback dex-dev <revision> for instant rollback

Resources