# NGINX in Containers and Kubernetes — Nginx

Source: https://www.skillbyai.com/en/nginx/p-containers

> Run NGINX in Docker and understand ingress options in Kubernetes.

## Configuration as part of the image

In containers, NGINX typically runs in the foreground with `daemon off;` (the official image does this) and logs to stdout and stderr, which the official image achieves by linking log files to `/dev/stdout` and `/dev/stderr`. Build images with your configuration copied in, or mount it as a ConfigMap in Kubernetes. The official image supports **templates**: files in `/etc/nginx/templates/*.template` are processed with `envsubst` at start-up, so you can inject environment variables such as backend addresses. For static sites, a common pattern is a **multi-stage build**: build the frontend in a Node image, copy the output into a small `nginx` image. In **Kubernetes**, NGINX often appears as an **ingress controller**. The community **ingress-nginx** controller, long the most popular, was announced for retirement by the Kubernetes project, with maintenance ending in 2026; new clusters should evaluate **Gateway API** implementations (including F5's NGINX Gateway Fabric) or other maintained controllers such as F5's NGINX Ingress Controller, Traefik or cloud-provider gateways.

## NGINX in a container

Configuration is baked into the image or mounted; logs go to stdout for the platform to collect.

![A container box holding a config file icon and a server icon, with arrows going out to a log stream and in from a browser.](assets/figures/nginx/section-8-map.svg) — Figure 8.1 — Containerised NGINX with templated configuration.

## Multi-stage build for a single-page app

Build with Node, serve with NGINX, inject the API address at start-up.

```dockerfile
# Dockerfile
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:stable-alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx/default.conf.template /etc/nginx/templates/default.conf.template
# at start-up the image runs envsubst: ${API_UPSTREAM} -> real value
EXPOSE 80

# nginx/default.conf.template
# server {
#     listen 80;
#     root /usr/share/nginx/html;
#     location /api/ { proxy_pass ${API_UPSTREAM}; }
#     location / { try_files $uri $uri/ /index.html; }
# }
```

## envsubst touches every $

Template substitution replaces `${VAR}` placeholders; the official image restricts substitution to defined environment variables so NGINX variables like `$uri` survive, but test your rendered configuration with `nginx -T` inside the container.

**Quiz:** Why should new Kubernetes clusters avoid adopting the community ingress-nginx controller?

- [ ] It cannot route HTTP
- [ ] It only supports UDP
- [x] The Kubernetes project announced its retirement, so it no longer receives maintenance
- [ ] It requires NGINX Plus

*Answer:* The Kubernetes project announced its retirement, so it no longer receives maintenance. With the project retired, maintained controllers or Gateway API implementations are safer choices.
