Serve a static website using NGINX inside a container built with Podman/Buildah on RHEL.
Containerfile— the blueprint (IaC) for your imageindex.html— example static page (replace with yours)nginx.conf— points NGINX to/var/www/html.containerignore— keeps the image clean.github/workflows/build.yml— GitHub Actions to build (and optionally push) the imageMakefile— handymake build/make runshortcuts
podman build -t static-site:latest -f Containerfile .
podman run --rm -p 8080:80 static-site:latest
# open http://localhost:8080Tip: Podman is daemonless and works rootless on RHEL. Mapping
8080:80exposes the container's port 80 on your host's port 8080.
- Go to GitHub → New repository → name it
containerized-static-web-deployment. - Choose Public (or Private) → Create repository.
- Upload files (Add file → Upload files) and drop everything from this folder.
- Commit the changes (green Commit button).
From now on, every change you push is version-controlled.
This repo ships with a ready workflow: .github/workflows/build.yml.
- On GitHub, open the Actions tab — enable workflows if prompted.
- Push/commit to
main— it will build your container image. - If you also want to publish to GitHub Container Registry (GHCR):
- Create a Personal Access Token (classic) with
write:packagesscope. - In your repo, go to Settings → Secrets and variables → Actions → New repository secret:
GHCR_USERNAME— your GitHub usernameGHCR_TOKEN— the token you created
- Edit
image_namein the workflow if you want a different name.
- Create a Personal Access Token (classic) with
After a successful run, pull the image anywhere with:
podman pull ghcr.io/<your-username>/static-site:latest
podman run --rm -p 8080:80 ghcr.io/<your-username>/static-site:latest- Replace
index.htmlwith your site files. Keep the same folder structure; theContainerfilecopies everything into/var/www/html. - Want a different port on your machine? Change
-p 8080:80to-p 3000:80(host:container).
- Isolation & security: web server is jailed inside the container.
- Portability: same image runs everywhere.
- Reproducibility: the
Containerfileis your single source of truth.
- Port already in use: choose another host port, e.g.
-p 9000:80. - Permission issues on rootless Podman: stick to port mapping (host high port → container 80) as shown.
- SELinux denials: keep site files inside the image (as we do), not bind-mounted, to avoid extra labeling steps.
MIT