27

I have this Docker image -

FROM centos:7
MAINTAINER Me <me.me>
RUN yum update -y
RUN yum install -y git https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

RUN yum install -y ansible
RUN git clone https://github.com/.../dockerAnsible.git
RUN ansible-playbook dockerFileBootstrap.yml
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;

VOLUME [ "/sys/fs/cgroup" ]
EXPOSE 80 443 3306

CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

Basically, I want it so that php-fpm starts when the docker container starts. I have php-fpm working if I manually go into the container and turn it on with /usr/sbin/php-fpm.

I tried it inside of my ansible file with this command (it didn't work). I tried using the service module as well with no luck.-

 - name: Start php fpm
   command: /usr/sbin/php-fpm

How can I have php-fpm running along with apache?

J. Doe
  • 1,479
  • 5
  • 25
  • 49

7 Answers7

27

You should use supervisor in order to launch several services

In your dockerfile, install supervisor, then you launch

COPY ./docker/supervisord.conf /etc/supervisord.conf
....
CMD ["/usr/bin/supervisord", "-n"]

And your docker/supervisord.conf contains all the services you want to start, so you can have something like that

[program:php-fpm]
  command=/opt/remi/php70/root/usr/sbin/php-fpm -c /etc/php-fpm.conf
  ;command=/usr/sbin/php70-fpm -c /etc/php-fpm.d
  stdout_logfile=/dev/stdout
  stdout_logfile_maxbytes=0
  stderr_logfile=/dev/stderr
  stderr_logfile_maxbytes=0

[program:nginx]
  command=/usr/sbin/nginx
  stdout_logfile=/dev/stdout
  stdout_logfile_maxbytes=0
  stderr_logfile=/dev/stderr
  stderr_logfile_maxbytes=0

Of course you should adapt with your path and php-fpm versions and your services (nginx in my example, apache for you etc...), but basically supervisor is the best way to manage the start of several services from one start point.

Here you can find the official doc of docker about supervisor

https://docs.docker.com/engine/admin/using_supervisord/

olibiaz
  • 2,551
  • 4
  • 29
  • 31
  • 2
    While this method seems like it would work, it seems like overkill for just the one extra service that I need to start. Is it possible to do something like chain my CMD's together, or start it when the Docker container is being initialized? – J. Doe May 19 '16 at 06:20
  • 1
    Another option is to run php-fpm in another container and put the two containers on the same network. Then point the php-fpm httpd config at the other container. – Matt May 19 '16 at 11:07
  • 4
    I don't really find this method overkill, supervisor is a common way to handle multi processors management and the recommended way by docker, its only your docker file that will change a bit and one more config file. Your container will be more flexible if you want to add some services later. But if you find a easier "legit" method, please let us know, i'm interested – olibiaz May 19 '16 at 14:33
  • Suggesting adding another layer of complexity is not a good answer. Downvoting. – zeros-and-ones Oct 17 '17 at 23:55
  • 1
    We should consider that nowadays containers are indeed designed for a single service. From that perspective, this answer is legit. – fschuindt Mar 10 '19 at 01:36
  • I like `supervisord` approach. It is THE way to handle situations like this. – Vahid Amiri May 04 '21 at 15:12
  • This is an insane amount of configuration just to start a single service that starts automatically on non-Docker machines. – Andrew Koster Dec 07 '21 at 20:17
27

I came here looking for how to run php-fpm in the foreground so it could be PID 1 in a docker container. The solution is

php-fpm -F -R

Explanation

We can check the available options with php-fpm --help

-F, --nodaemonize 
      force to stay in foreground, and ignore daemonize option from config file

If you are running php-fpm in a docker container, there is a good chance you are running the process as root. php-fpm won't start as root without an extra flag:

  -R, --allow-to-run-as-root
        Allow pool to run as root (disabled by default)
ckeeney
  • 1,270
  • 13
  • 18
  • 3
    Hi, is it safe to run php-fpm as root ? I'm worry – Dylan B Jan 22 '19 at 07:05
  • 2
    This answer only applies to running php-fpm inside a containerized environment. If you are not using docker or some other container, running php-fpm as root greatly increases your exposure to hackers. – ckeeney Jan 23 '19 at 08:51
  • 2
    This command doesn't work in a Dockerfile, which is the use case for this answer. – Andrew Koster Dec 07 '21 at 20:20
  • I used this at the end of a bash startup script so I could do a lot of custom configuration. The -R is a bit scary though. If you're working off the official base image it should be ran as www-data. – Throttlehead Sep 28 '22 at 01:19
18

I needed similar thing recently. For alpine linux images it sufficed to run both php-fpm and a web server as the container command. Defined in Dockerfile somewhat like this:

CMD /usr/bin/php-fpm -D; nginx

ie. to daemonize php-fpm and then run nginx in foreground.

On ubuntu/debian images there is also necessary to allow starting recently installed packages by running a Dockerfile RUN command like this:

RUN echo "exit 0" > /usr/sbin/policy-rc.d

and then restart the php-fpm within a CMD command

CMD /etc/init.d/php7.0-fpm restart && nginx -g "daemon off;"

More on policy-rc.d to be found in this askubuntu question

helvete
  • 2,455
  • 13
  • 33
  • 37
3

You may find this config useful if you'd like to run php-fpm and Apache (usually using MPM Event) in the same container:

[supervisord]

[program:php-fpm]
command=php-fpm -F -R
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:apachectl]
command=apachectl -D "FOREGROUND" -k start
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
Vahid Amiri
  • 10,769
  • 13
  • 68
  • 113
2

This works for me on Docker running Ubuntu 20.04 with nginx and php-fpm.

CMD /etc/init.d/php7.4-fpm start -F && nginx -g "daemon off;"

No supervisors or cron jobs are required.

Andrey K
  • 31
  • 2
  • I would also suggest make an `ARG phpver=7.4` and then make it more general like this `RUN cp /etc/init.d/php${phpver}-fpm /etc/init.d/php-fpm`. Then you add `CMD /etc/init.d/php-fpm start -F && nginx -g "daemon off;"`. In future you can change the php version from the ARG line. – Dimitar Atanasov Jul 29 '22 at 12:52
1

I use rc.local to start services inside a container, and then run a command inside that container to execute rc.local. So here's a sample run command:

sudo docker run --restart=always -itd --name mycontainer -p 80:80 -p 443:443 myimage/name /bin/bash -c "/etc/rc.local && while true; do echo hello world; sleep 100; done"

And this is one of the rc.local files from /etc

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
sleep 5
service mysql start
sleep 5
service php5-fpm start
sleep 5
service nginx start
exit 0

What this does is launch a container called "mycontainer" using the image "myimage/name" with ports 80 and 443 exposed. Once launched it calls mysql, php5-fpm, and nginx to start up, pausing between each for 5 seconds. In this manner you can call any service to start that you would want to run inside that container. Remember to add open ports for those services though.

This run command will also append "Hello World" into your log file every 100 seconds as a "pulse" that will let you know when it was running and when it was stopped.

1

I believe @ckeeney's answer above could be accepted as the correct answer but I was unable to get it working with my particular case.

use dumb-init

I have been able to proxy PID1 through dumb-init, and daemonize PHP-FPM with the following command : dumb-init /usr/sbin/php-fpm7.2 -F -R https://engineeringblog.yelp.com/2016/01/dumb-init-an-init-for-docker.html

bxbxckx
  • 111
  • 8