File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1+ # Build artifacts
2+ .build /
3+ StatusPost
4+
5+ # IDE
6+ .idea /
7+ .vscode /
8+ * .swp
9+
10+ # Git
11+ .git /
12+ .gitignore
13+
14+ # Documentation
15+ README.md
16+
17+ # Deployment (not needed in image)
18+ deployment /
19+ Dockerfile
20+ .dockerignore
Original file line number Diff line number Diff line change 1+ name : Build and Push
2+
3+ on :
4+ push :
5+ branches :
6+ - main
7+ tags :
8+ - ' v*'
9+ pull_request :
10+ branches :
11+ - main
12+
13+ env :
14+ REGISTRY : ghcr.io
15+ IMAGE_NAME : ${{ github.repository }}
16+
17+ jobs :
18+ build :
19+ runs-on : ubuntu-latest
20+ permissions :
21+ contents : read
22+ packages : write
23+
24+ steps :
25+ - name : Checkout repository
26+ uses : actions/checkout@v4
27+
28+ - name : Set up Docker Buildx
29+ uses : docker/setup-buildx-action@v3
30+
31+ - name : Log in to Container Registry
32+ if : github.event_name != 'pull_request'
33+ uses : docker/login-action@v3
34+ with :
35+ registry : ${{ env.REGISTRY }}
36+ username : ${{ github.actor }}
37+ password : ${{ secrets.GITHUB_TOKEN }}
38+
39+ - name : Extract metadata (tags, labels)
40+ id : meta
41+ uses : docker/metadata-action@v5
42+ with :
43+ images : ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
44+ tags : |
45+ type=ref,event=branch
46+ type=ref,event=pr
47+ type=semver,pattern={{version}}
48+ type=semver,pattern={{major}}.{{minor}}
49+ type=sha,prefix=
50+
51+ - name : Build and push Docker image
52+ uses : docker/build-push-action@v5
53+ with :
54+ context : .
55+ push : ${{ github.event_name != 'pull_request' }}
56+ tags : ${{ steps.meta.outputs.tags }}
57+ labels : ${{ steps.meta.outputs.labels }}
58+ cache-from : type=gha
59+ cache-to : type=gha,mode=max
Original file line number Diff line number Diff line change 1+ # =============================================================================
2+ # StatusPost - Multi-stage Docker Build
3+ # =============================================================================
4+ # Uses ARO buildsystem to compile, then ARO runtime to execute
5+ # =============================================================================
6+
7+ # -----------------------------------------------------------------------------
8+ # Stage 1: Build
9+ # -----------------------------------------------------------------------------
10+ FROM ghcr.io/arolang/aro-buildsystem:latest AS builder
11+
12+ WORKDIR /app
13+
14+ # Copy application source files
15+ COPY *.aro ./
16+ COPY openapi.yaml ./
17+ COPY templates/ ./templates/
18+
19+ # Compile to native binary
20+ RUN aro build . --optimize
21+
22+ # -----------------------------------------------------------------------------
23+ # Stage 2: Runtime
24+ # -----------------------------------------------------------------------------
25+ FROM ghcr.io/arolang/aro-runtime:latest
26+
27+ WORKDIR /app
28+
29+ # Copy compiled binary from builder
30+ COPY --from=builder /app/StatusPost ./StatusPost
31+
32+ # Copy runtime assets (templates, openapi spec)
33+ COPY --from=builder /app/openapi.yaml ./
34+ COPY --from=builder /app/templates/ ./templates/
35+
36+ # Expose HTTP port
37+ EXPOSE 8080
38+
39+ # Health check
40+ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
41+ CMD curl -f http://localhost:8080/ || exit 1
42+
43+ # Run the application
44+ CMD ["./StatusPost" ]
Original file line number Diff line number Diff line change @@ -43,3 +43,64 @@ StatusPost/
43432 . The page connects to ` /ws ` via WebSocket
44443 . When a message is posted, it's stored and broadcast to all connected clients
45454 . All clients receive the new message in real-time
46+
47+ ## Docker
48+
49+ Build the container image:
50+
51+ ``` bash
52+ docker build -t statuspost:latest .
53+ ```
54+
55+ Run locally:
56+
57+ ``` bash
58+ docker run -p 8080:8080 statuspost:latest
59+ ```
60+
61+ ## Kubernetes Deployment
62+
63+ Deploy to Kubernetes using kustomize:
64+
65+ ``` bash
66+ # Preview the manifests
67+ kubectl kustomize deployment/k8s/
68+
69+ # Apply to cluster
70+ kubectl apply -k deployment/k8s/
71+ ```
72+
73+ Or apply manifests directly:
74+
75+ ``` bash
76+ kubectl apply -f deployment/k8s/deployment.yaml
77+ kubectl apply -f deployment/k8s/service.yaml
78+ kubectl apply -f deployment/k8s/ingress.yaml
79+ ```
80+
81+ ### Configuration
82+
83+ Edit ` deployment/k8s/kustomization.yaml ` to customize the image:
84+
85+ ``` yaml
86+ images :
87+ - name : statuspost
88+ newName : your-registry/statuspost
89+ newTag : v1.0.0
90+ ` ` `
91+
92+ Edit ` deployment/k8s/ingress.yaml` to set your hostname:
93+
94+ ` ` ` yaml
95+ spec:
96+ rules:
97+ - host: your-domain.com
98+ ` ` `
99+
100+ # # CI/CD
101+
102+ GitHub Actions automatically builds and pushes the Docker image to `ghcr.io` on :
103+
104+ - Push to `main` branch → tagged as `main`
105+ - Version tags (`v*`) → tagged as version (e.g., `v1.0.0` → `1.0.0`)
106+ - Pull requests → build only (no push)
Original file line number Diff line number Diff line change 1+ apiVersion : apps/v1
2+ kind : Deployment
3+ metadata :
4+ name : statuspost
5+ labels :
6+ app : statuspost
7+ app.kubernetes.io/name : statuspost
8+ app.kubernetes.io/component : server
9+ spec :
10+ replicas : 1
11+ selector :
12+ matchLabels :
13+ app : statuspost
14+ template :
15+ metadata :
16+ labels :
17+ app : statuspost
18+ app.kubernetes.io/name : statuspost
19+ app.kubernetes.io/component : server
20+ spec :
21+ containers :
22+ - name : statuspost
23+ image : statuspost:latest
24+ imagePullPolicy : IfNotPresent
25+ ports :
26+ - name : http
27+ containerPort : 8080
28+ protocol : TCP
29+ livenessProbe :
30+ httpGet :
31+ path : /
32+ port : http
33+ initialDelaySeconds : 5
34+ periodSeconds : 10
35+ timeoutSeconds : 3
36+ failureThreshold : 3
37+ readinessProbe :
38+ httpGet :
39+ path : /
40+ port : http
41+ initialDelaySeconds : 3
42+ periodSeconds : 5
43+ timeoutSeconds : 2
44+ failureThreshold : 3
45+ resources :
46+ requests :
47+ memory : " 64Mi"
48+ cpu : " 50m"
49+ limits :
50+ memory : " 256Mi"
51+ cpu : " 500m"
52+ securityContext :
53+ readOnlyRootFilesystem : true
54+ runAsNonRoot : true
55+ runAsUser : 1000
56+ allowPrivilegeEscalation : false
57+ capabilities :
58+ drop :
59+ - ALL
60+ securityContext :
61+ seccompProfile :
62+ type : RuntimeDefault
Original file line number Diff line number Diff line change 1+ apiVersion : networking.k8s.io/v1
2+ kind : Ingress
3+ metadata :
4+ name : statuspost
5+ labels :
6+ app : statuspost
7+ app.kubernetes.io/name : statuspost
8+ app.kubernetes.io/component : server
9+ annotations :
10+ # Enable WebSocket support
11+ nginx.ingress.kubernetes.io/proxy-read-timeout : " 3600"
12+ nginx.ingress.kubernetes.io/proxy-send-timeout : " 3600"
13+ nginx.ingress.kubernetes.io/upstream-hash-by : " $remote_addr"
14+ # Optional: Enable SSL redirect
15+ # nginx.ingress.kubernetes.io/ssl-redirect: "true"
16+ spec :
17+ ingressClassName : nginx
18+ rules :
19+ - host : statuspost.example.com
20+ http :
21+ paths :
22+ - path : /
23+ pathType : Prefix
24+ backend :
25+ service :
26+ name : statuspost
27+ port :
28+ name : http
29+ # Optional: TLS configuration
30+ # tls:
31+ # - hosts:
32+ # - statuspost.example.com
33+ # secretName: statuspost-tls
Original file line number Diff line number Diff line change 1+ apiVersion : kustomize.config.k8s.io/v1beta1
2+ kind : Kustomization
3+
4+ metadata :
5+ name : statuspost
6+
7+ resources :
8+ - deployment.yaml
9+ - service.yaml
10+ - ingress.yaml
11+
12+ commonLabels :
13+ app.kubernetes.io/part-of : statuspost
14+ app.kubernetes.io/managed-by : kustomize
15+
16+ images :
17+ - name : statuspost
18+ newName : ghcr.io/arolang/statuspost
19+ newTag : latest
Original file line number Diff line number Diff line change 1+ apiVersion : v1
2+ kind : Service
3+ metadata :
4+ name : statuspost
5+ labels :
6+ app : statuspost
7+ app.kubernetes.io/name : statuspost
8+ app.kubernetes.io/component : server
9+ spec :
10+ type : ClusterIP
11+ ports :
12+ - name : http
13+ port : 80
14+ targetPort : http
15+ protocol : TCP
16+ selector :
17+ app : statuspost
You can’t perform that action at this time.
0 commit comments