sharenet/deploy/prod-pod.yml
continuist 635a57645e
All checks were successful
Podman Rootless Demo / test-backend (push) Successful in 9m15s
Podman Rootless Demo / test-frontend (push) Has been skipped
Podman Rootless Demo / build-backend (push) Has been skipped
Podman Rootless Demo / build-frontend (push) Has been skipped
Podman Rootless Demo / deploy-prod (push) Has been skipped
Run database migration directly in backend main()
2025-09-21 14:53:29 -04:00

209 lines
No EOL
5.8 KiB
YAML

apiVersion: v1
kind: Pod
metadata:
name: sharenet-production-pod
labels:
app: sharenet-production
annotations:
io.containers.no-new-privileges: "true"
spec:
hostname: sharenet-production-pod
hostNetwork: true
containers:
- name: postgres
image: docker.io/postgres:16
# Security: drop all capabilities, read-only root filesystem except data volume
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
env:
- name: POSTGRES_DB
value: ${POSTGRES_DATABASE_NAME}
- name: POSTGRES_USER
value: ${POSTGRES_USERNAME}
- name: POSTGRES_PASSWORD
value: ${POSTGRES_PASSWORD}
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
ports:
- containerPort: ${POSTGRES_PORT}
protocol: TCP
volumeMounts:
- { name: pgdata, mountPath: /var/lib/postgresql/data, readOnly: false }
- { name: postgres-run, mountPath: /var/run/postgresql, readOnly: false }
# Health checks
livenessProbe:
exec:
command: ["pg_isready", "-U", "${POSTGRES_USERNAME}"]
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 3
readinessProbe:
exec:
command: ["pg_isready", "-U", "${POSTGRES_USERNAME}"]
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
# Resource limits
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
- name: backend
image: ${REGISTRY_HOST}/${APP_NAME}/sharenet-backend-api-postgres:${IMAGE_TAG}
# Security: drop all capabilities, read-only root filesystem
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
env:
- name: HOST
value: "0.0.0.0"
- name: DATABASE_URL
value: "postgres://${POSTGRES_USERNAME}:${POSTGRES_PASSWORD}@127.0.0.1:${POSTGRES_PORT}/${POSTGRES_DATABASE_NAME}?sslmode=disable"
- name: PORT
value: "${PROD_BACKEND_PORT}"
ports:
- containerPort: ${PROD_BACKEND_PORT}
protocol: TCP
volumeMounts:
- { name: backend-tmp, mountPath: /tmp }
- { name: backend-tmp, mountPath: /run }
# Health checks
livenessProbe:
httpGet:
path: /health
port: "${PROD_BACKEND_PORT}"
scheme: HTTP
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: "${PROD_BACKEND_PORT}"
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
# Resource limits
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "250m"
- name: frontend
image: ${REGISTRY_HOST}/${APP_NAME}/sharenet-frontend:${IMAGE_TAG}
# Security: drop all capabilities, read-only root filesystem
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
env:
- name: NEXT_PUBLIC_API_HOST
value: ${PROD_BACKEND_HOST}
- name: NEXT_PUBLIC_API_PORT
value: "${PROD_BACKEND_PORT}"
- name: PORT
value: "${PROD_FRONTEND_PORT}"
- name: HOSTNAME
value: "127.0.0.1"
ports:
- containerPort: ${PROD_FRONTEND_PORT}
protocol: TCP
volumeMounts:
- { name: frontend-tmp, mountPath: /tmp }
- { name: frontend-tmp, mountPath: /run }
# Resource limits
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "250m"
- name: nginx
image: docker.io/nginx:alpine
command: ["/bin/sh"]
args:
- "-c"
- |
mkdir -p /tmp/client_temp /tmp/proxy_temp /tmp/fastcgi_temp /tmp/uwsgi_temp /tmp/scgi_temp;
chmod 777 /tmp/client_temp /tmp/proxy_temp /tmp/fastcgi_temp /tmp/uwsgi_temp /tmp/scgi_temp;
exec nginx -g 'daemon off;'
# Security: drop all capabilities, read-only root filesystem
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
ports:
- containerPort: 8080 # inside pod
volumeMounts:
- { name: nginx-run, mountPath: /var/run, readOnly: false }
- { name: nginx-cache, mountPath: /var/cache/nginx, readOnly: false }
- { name: nginx-conf, mountPath: /etc/nginx/nginx.conf, readOnly: true, subPath: nginx.conf }
- name: nginx-tmp
mountPath: /tmp
# Health check
livenessProbe:
httpGet: { path: /healthz, port: 8080, scheme: HTTP }
initialDelaySeconds: 10
periodSeconds: 30
# Resource limits
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
volumes:
- name: pgdata
persistentVolumeClaim: {} # Let Podman manage the volume
# hostPath:
# path: /opt/sharenet/volumes/pgdata
# type: DirectoryOrCreate
- name: postgres-run
emptyDir: {}
- name: backend-tmp
emptyDir: { medium: Memory }
- name: frontend-tmp
emptyDir: { medium: Memory }
- name: nginx-run
emptyDir: {}
- name: nginx-cache
hostPath: { path: /opt/sharenet/volumes/nginx-cache, type: DirectoryOrCreate }
- name: nginx-conf
hostPath: { path: /opt/sharenet/nginx, type: Directory }
- name: nginx-tmp
emptyDir:
medium: Memory # Uses tmpfs for better performance