Keep Nginx running in a Docker container

Run the Nginx master in the foreground, test the mounted configuration in the same image, and investigate exits before adding a restart policy.

Best practices
Illustration of server operations and log analysis

A container runs while its main process runs. The official Nginx image already starts Nginx in foreground mode, so a normal detached Docker launch does not need a keep-alive shell loop.

docker run -d --name web -p 8080:80 nginx:stable

Docker's -d detaches your terminal; it does not require Nginx to daemonize inside the container. Use an approved pinned image version or digest for reproducible deployments.

Mount configuration and site files

Create both host paths before starting the container:

docker run -d --name web-custom -p 8081:80 \
  --mount "type=bind,src=$PWD/nginx.conf,dst=/etc/nginx/nginx.conf,readonly" \
  --mount "type=bind,src=$PWD/html,dst=/usr/share/nginx/html,readonly" \
  nginx:stable

The replacement nginx.conf must be a complete valid main configuration. Publishing port 443 does not configure TLS; add it only with the intended certificate and HTTPS configuration.

Use an exec-form command in a custom image

FROM nginx:stable
COPY nginx.conf /etc/nginx/nginx.conf
COPY html/ /usr/share/nginx/html/
EXPOSE 80

This inherits the official image's startup behavior. If you install Nginx into a different base image yourself, the usual command is:

CMD ["nginx", "-g", "daemon off;"]

Do not define daemon off; in both the command and configuration. If a wrapper starts Nginx, use exec so signal delivery and process lifetime follow the intended main process.

Diagnose an exiting container

docker ps -a --filter name=web
docker logs --tail 100 web
docker inspect --format '{{json .State}}' web

Exit code 0 may indicate that the configured main command completed; it does not prove daemon mode was the cause. A nonzero exit needs the actual error, and OOMKilled is a separate useful clue.

docker exec cannot run in a stopped container. Test a stopped container's configuration by starting a separate one-shot container with the same image and mounts:

docker run --rm \
  --mount "type=bind,src=$PWD/nginx.conf,dst=/etc/nginx/nginx.conf,readonly" \
  --mount "type=bind,src=$PWD/html,dst=/usr/share/nginx/html,readonly" \
  nginx:stable nginx -t

Include other certificate, module, or template mounts used by the real deployment. Host Nginx may be a different version and is not an equivalent test.

Add runtime restrictions deliberately

For the standard image layout, an example is:

docker run -d --name web-restricted --restart unless-stopped \
  -p 8082:80 --read-only \
  --tmpfs /var/cache/nginx --tmpfs /var/run nginx:stable

Custom templates, cache paths, PID paths, or entrypoint scripts may need additional writable locations. Test them with the chosen image. A restart policy restarts a failed process; it does not make a broken configuration healthy.

FAQ

Does worker_processes auto always honor a container CPU quota?

Do not assume that. Visible CPUs, CPU affinity, cgroup quotas, Nginx version, and image startup scripts can differ. Check actual worker count and resource limits, then tune if required.

Must a configuration reload restart the container?

No: for a running container, run docker exec web nginx -t before docker exec web nginx -s reload, and check logs afterward. Image or mount changes can still require recreation.

How do I verify logging?

Request a known page and a missing path, then inspect stdout/stderr. Guance container collection needs runtime access and suitable collection rules; timings and upstream addresses must first be present in Nginx's log format.

References: official Nginx container source, Docker container lifecycle.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting