Skip to content

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-flask from the Dockerfile in the repo root
  • Run it as a service called web on port 5000
  • Check /health to 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:

  1. One container in the containers section -- your application image
  2. One service in the deploy section -- with a port and health check
  3. 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 port in appmecca.yaml must match the port your app listens on inside the container
  • Every service with a port needs a health_check.path that 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