203

I have Nginx installed on a Docker container, and am trying to run it like this:

docker run -i -t -p 80:80 mydockerimage /usr/sbin/nginx

The problem is that the way Nginx works, is that the initial process immediately spawns a master Nginx process and some workers, and then quits. Since Docker is only watching the PID of the original command, the container then halts.

How do I prevent the container from halting? I need to be able to tell it to bind to the first child process, or stop Nginx's initial process from exiting.

johntellsall
  • 14,394
  • 4
  • 46
  • 40
Seldo
  • 5,600
  • 4
  • 20
  • 11

11 Answers11

286

To expand on Charles Duffy's answer, Nginx uses the daemon off directive to run in the foreground. If it's inconvenient to put this in the configuration file, we can specify it directly on the command line. This makes it easy to run in debug mode (foreground) and directly switch to running in production mode (background) by changing command line args.

To run in foreground:

nginx -g 'daemon off;'

To run in background:

nginx
johntellsall
  • 14,394
  • 4
  • 46
  • 40
212

nginx, like all well-behaved programs, can be configured not to self-daemonize.

Use the daemon off configuration directive described in http://wiki.nginx.org/CoreModule.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • 21
    Thanks! To clarify, that means editing /etc/nginx/nginx.conf and adding "daemon off;" at the top (i.e. not inside a server or other directive) – Seldo Sep 17 '13 at 23:12
  • 7
    I'm somewhat concerned that [`daemon off` isn't endorsed by nginx](http://nginx.org/en/docs/faq/daemon_master_process_off.html). – Leonid Shevtsov Nov 22 '13 at 22:06
  • 10
    @LeonidShevtsov ...you mean _wasn't_ endorsed for production use prior to 1.0.9. The standing caveat, about in-place upgrades, doesn't matter to folks doing things The Docker Way. – Charles Duffy Nov 22 '13 at 22:39
  • They seem to have a redirection in place server-side now (to http://nginx.org/en/docs/ngx_core_module.html). – Charles Duffy May 10 '17 at 15:46
  • @Seldo nginx: [emerg] "daemon" directive is not allowed here in /etc/nginx/conf.d/nginx.conf:1 – Firsh - justifiedgrid.com May 23 '22 at 14:54
  • @Firsh-justifiedgrid.com, as the docs say, it's only allowed in the `main` context. I'd need to see how/where your `conf.d/nginx.conf` is included into the larger configuration to know which context is active for the line in question; no "edit this specific file" rule can be always accurate for every possible system, without knowing how the rest of that system is configured. – Charles Duffy May 23 '22 at 14:55
  • @CharlesDuffy Thank you I found the larger configuration! – Firsh - justifiedgrid.com May 23 '22 at 16:53
85

To expand on John's answer you can also use the Dockerfile CMD command as following (in case you want it to self start without additional args)

CMD ["nginx", "-g", "daemon off;"]
Paritosh Piplewar
  • 7,982
  • 5
  • 26
  • 41
Tomer Ben David
  • 8,286
  • 1
  • 43
  • 24
37

Just FYI, as of today (22 October 2019) official Nginx docker images all have line:

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

e.g. https://github.com/nginxinc/docker-nginx/blob/23a990403d6dbe102bf2c72ab2f6a239e940e3c3/mainline/alpine/Dockerfile#L117

number5
  • 15,913
  • 3
  • 54
  • 51
16

Adding this command to Dockerfile can disable it:

RUN echo "daemon off;" >> /etc/nginx/nginx.conf
Afshin Mehrabani
  • 33,262
  • 29
  • 136
  • 201
10

To add Tomer and Charles answers,

Syntax to run nginx in forground in Docker container using Entrypoint:

ENTRYPOINT nginx -g 'daemon off;' 

Not directly related but to run multiple commands with Entrypoint:

ENTRYPOINT /bin/bash -x /myscripts/myscript.sh && nginx -g 'daemon off;' 
Nitb
  • 366
  • 5
  • 15
  • 1
    Nitb is adding to Tomer, Tomer is adding to John, and John is adding to Charles. It would be nice if this site had a public editing function. – forresthopkinsa Nov 22 '20 at 03:43
8

Here you have an example of a Dockerfile that runs nginx. As mentionned by Charles, it uses the daemon off configuration:

https://github.com/darron/docker-nginx-php5/blob/master/Dockerfile#L17

creack
  • 116,210
  • 12
  • 97
  • 73
3

For all who come here trying to run a nginx image in a docker container, that will run as a service

As there is no whole Dockerfile, here is my whole Dockerfile solving the issue.

Nice and working. Thanks to all answers here in order to solve the final nginx issue.

FROM ubuntu:18.04
MAINTAINER stackoverfloguy "stackoverfloguy@foo.com"
RUN apt-get update -y
RUN apt-get install net-tools nginx ufw sudo -y
RUN adduser --disabled-password --gecos '' docker
RUN adduser docker sudo
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER docker
RUN sudo ufw default allow incoming
RUN sudo rm /etc/nginx/nginx.conf
RUN sudo rm /etc/nginx/sites-available/default
RUN sudo rm /var/www/html/index.nginx-debian.html
VOLUME /var/log
VOLUME /usr/share/nginx/html
VOLUME /etc/nginx
VOLUME /var/run
COPY conf/nginx.conf /etc/nginx/nginx.conf
COPY content/* /var/www/html/
COPY Dockerfile /var/www/html
COPY start.sh /etc/nginx/start.sh
RUN sudo chmod +x /etc/nginx/start.sh
RUN sudo chmod -R 777 /var/www/html
EXPOSE 80
EXPOSE 443
ENTRYPOINT sudo nginx -c /etc/nginx/nginx.conf -g 'daemon off;'

And run it with:

docker run -p 80:80 -p 443:443 -dit
  • 2
    Not very useful without your "start.sh" script. And if you have 777 permissions on your HTML content, if your container is compromised, attackers can change the content. Why does any user need to write to anything in your container? And why do you add the docker user and then use sudo to do everything? Again if you are compromised : having sudo could be a problem, you don't need it. Keep your container slim. Or use the nginx image from docker hub written by people who understand security. – Max Allan Jun 10 '21 at 14:41
  • This line of code saved me : `ENTRYPOINT sudo nginx -c /etc/nginx/nginx.conf -g 'daemon off;'`. Thank you. – zahra_oveyedzade Feb 11 '22 at 07:29
2

It is also good idea to use supervisord or runit[1] for service management.

[1] https://github.com/phusion/baseimage-docker

Kunthar
  • 472
  • 1
  • 5
  • 15
  • I think docker explicitly recommends against such configurations. Docker and all the tooling around docker is expecting that exactly one service is running inside the container. If you need to run a full-fledged Linux distribution inside a container, lxd or systemd-nspawn is a better choice. – Eugene Morozov Sep 22 '22 at 13:33
  • You are actually right @EugeneMorozov But as you know, sometimes someone needs a solution called as not a best practice but simply get the job done at year 2014. You would still run only one service and still would need the supervise it, if it is healthy or not. Now in 2022 it is not advisable to use supervisord though. One can use docker-compose container health check or Alpine derivatives to achieve success. – Kunthar Sep 23 '22 at 19:07
0

In the official notes for the official NGINX image on DockerHub it states:

If you add a custom CMD in the Dockerfile, be sure to include -g daemon off; in the CMD in order for nginx to stay in the foreground, so that Docker can track the process properly (otherwise your container will stop immediately after starting)!

This makes me thing removing the CMD [] might prevent this issue from occurring in the first place?

0

In new versions of the public container, a script is now default, so no need to add command/entrypoint

See also: https://stackoverflow.com/a/64991442/1736679

Efren
  • 4,003
  • 4
  • 33
  • 75