Simple Web App¶
This guide walks through deploying a single-container web application on AppMecca. We will cover three sample apps: a Python Flask app, a Node.js Express API, and a Go web server. All three follow the same pattern -- one container, one service, no database.
hello-flask (Python / Flask)¶
The simplest possible AppMecca deployment.
Application code¶
app.py:
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello from AppMecca!"
@app.route("/health")
def health():
return jsonify({"status": "healthy"})
Dockerfile:
FROM python:3.12-slim
WORKDIR /app
RUN pip install flask gunicorn
COPY app.py .
EXPOSE 5000
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]
appmecca.yaml¶
containers:
- name: hello-flask
dockerfile: Dockerfile
context: .
deploy:
- name: web
container: hello-flask
port: 5000
health_check:
path: /health
That is all you need. This tells AppMecca:
- Build a Docker image called
hello-flaskfrom the Dockerfile in the repo root - Run it as a service called
webon port 5000 - Check
/healthto confirm the app is alive
Deploy it¶
mecca register git@gitlab.com:appmecca-sample-apps/hello-flask.git -e dev
mecca build trigger -e dev -g git@gitlab.com:appmecca-sample-apps/hello-flask.git
mecca app deploy -e dev hello-flask
Your app is live at https://hello-flask-web.dev.appmecca.net — the service
name (web) is always part of the hostname.
node-express-api (Node.js / Express)¶
A REST API in Node.js following the same single-container pattern.
Application code¶
app.js:
const express = require("express");
const app = express();
const PORT = process.env.PORT || 3000;
app.get("/", (req, res) => {
res.json({ message: "Hello from Express on AppMecca!" });
});
app.get("/health", (req, res) => {
res.json({ status: "healthy" });
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Dockerfile:
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY app.js .
EXPOSE 3000
CMD ["node", "app.js"]
appmecca.yaml¶
containers:
- name: node-express-api
dockerfile: Dockerfile
context: .
deploy:
- name: api
container: node-express-api
port: 3000
health_check:
path: /health
Deploy it¶
mecca register git@gitlab.com:appmecca-sample-apps/node-express-api.git -e dev
mecca build trigger -e dev -g git@gitlab.com:appmecca-sample-apps/node-express-api.git
mecca app deploy -e dev node-express-api
Live at https://node-express-api-api.dev.appmecca.net (the service is named
api, hence the repeated segment).
go-web-server (Go / stdlib)¶
A compiled Go binary with a tiny Docker image.
Application code¶
main.go:
package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello from Go on AppMecca!")
})
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"status": "healthy"})
})
http.ListenAndServe(":8080", nil)
}
Dockerfile:
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY main.go .
RUN go build -o server main.go
FROM alpine:3.19
COPY --from=builder /app/server /server
EXPOSE 8080
CMD ["/server"]
appmecca.yaml¶
containers:
- name: go-web-server
dockerfile: Dockerfile
context: .
deploy:
- name: web
container: go-web-server
port: 8080
health_check:
path: /health
Multi-stage builds
The Go example uses a multi-stage Dockerfile. The first stage compiles the binary, and the second stage copies just the binary into a minimal Alpine image. This produces a much smaller image (around 15 MB vs 300+ MB).
Deploy it¶
mecca register git@gitlab.com:appmecca-sample-apps/go-web-server.git -e dev
mecca build trigger -e dev -g git@gitlab.com:appmecca-sample-apps/go-web-server.git
mecca app deploy -e dev go-web-server
Live at https://go-web-server-web.dev.appmecca.net.
The Pattern¶
All three examples follow the same structure:
- One container in the
containerssection -- your application image - One service in the
deploysection -- with a port and health check - No database or cache -- just a web process
This is the starting point for any AppMecca deployment. From here, you can add a database, more services, or background workers.
Key Takeaways¶
- The
portinappmecca.yamlmust match the port your app listens on inside the container - Every service with a port needs a
health_check.paththat returns HTTP 200 - Your app gets a URL automatically:
https://{app}-{service}.{env}.{domain}— the service name is always included, even when the app has only one service - You don't need to handle HTTPS -- the AppMecca HTTPS router terminates TLS for you and issues the certificate