I am having this weird problem with PHP-FPM. First of all, I am not an expert on PHP. I'm builing an app, and PHP will only communicate with MySQL to push and pull data.
The problem:
I have a Dockerfile where I'm making some changed in PHP-FPM config, and one of the lines is to reload PHP-FPM. Actually when you install PHP-FPM, it is not running, so I do:
RUN service php7.3-fpm start
When the app starts and I check PHP-FPM, it is not running. I had this issue before (with php7-0-fpm), I had resolved it by doing:
service php7.0-fpm stop && service php7.0-fpm start
But now, when I do it, it is still stopped.
So, I started reading and someone advised to put it in the CMD command, along with the main command. I did, and it worked:
CMD service php7.3-fpm start && nginx -g "daemon off;"
Now, the problem is that it is not taking the new configuration. When I access the machine, and I manually do service php7.3-fpm reload it starts working.
I tried putting it in the Dockrfile as well, but no luck. Any idea? I would like to resolve the first issue as well (I don't want to restart PHP-FPM from the CMD. It would be preferable to do it with a RUN layer in docker).
EDIT
Another weird thing is that when I do service php7.3-fpm start manually, it doesn't work, but it works when I do /etc/init.d/php7.3-fpm start. Seems to work, when I do it in the CMD line:
CMD /etc/init.d/php7.3-fpm start && nginx -g "daemon off;"
Dockerfile
FROM debian:buster
LABEL maintainer="me"
RUN apt-get update && apt-get install -y \
nginx \
default-mysql-client \
php7.3-fpm \
php7.3-mysql
RUN sed -i.bak "s/;clear_env = no/clear_env = no/g" /etc/php/7.3/fpm/pool.d/www.conf && \
sed -i.bak "s/;php_flag\[\display_errors\]\ = off/php_flag\[\display_errors\]\ = on/g" /etc/php/7.3/fpm/pool.d/www.conf
COPY ./html/ /var/www/html/
RUN rm /var/www/html/index.nginx-debian.html
WORKDIR /var/www/html/
EXPOSE 80
CMD service php7.3-fpm start && nginx -g "daemon off;"
Execute a command or restart php-fpm using RUN directive will not effect because each layer runs in a separate shell.
The best way is to copy the config file from host, rebuild the image and then run the container.
for Example
FROM debian:buster
COPY config/php7.ini /usr/local/etc/php/conf.d/
COPY config/fpm/php-fpm.conf /usr/local/etc/
COPY config/fpm/pool.d /usr/local/etc/pool.d
Also better to run the separate container for each process, rule of thumb single process per container.
You CMD seem fine it starts PHP and Nginx both.
To verify process inside your container add
RUN apt-get update && apt-get install procps -y
then run
docker exec -it your_container_id bash -c "ps -aux"
Related
I have 3 different Ubuntu droplets with Docker on Digital Ocean. They are all running Caddy as proxy with 2 of them using PHP-FPM and 1 using PHP-FPM Alpine.
After the server has been running a while, sometimes a few days, sometimes 3-4 weeks, the request stops responding.
All has the same type of problem.
I can SSH into the droplet. The caddy seems to be running all fine. I can access everything through caddy that is not the PHP.
The interessting part from the Caddy Docker log is this:
{
"level": "error",
"logger": "http.log.error",
"msg": "dialing backend: dial tcp 172.30.0.3:9000: i/o timeout",
"duration": 3.014910236,
"status": 502,
"err_id": "j14574vxr",
"err_trace": "reverseproxy.statusError (reverseproxy.go:1196)"
}
If I do a docker logs -f PHP_CONTAINER all I can see is a valid request from the time before PHP stopped responding.
If i restart only the PHP container it starts working again. The strange part is that if I ONLY do a restart of CADDY container it will also start working.
I didn't seem to have this problem with NGINX earlier. So I my initial thought was that CADDY was the problem. But I do get connection to other services on the same Docker server. For instance PHP-FPM service doesn't respond, but my phpMyAdmin service is still working.
The caddy file is like this:
mydomain.com {
root * /var/www/public
php_fastcgi /* php:9000
file_server
}
The PHP-FPM Dockerfile is like this:
FROM php:8.1.6-fpm
ARG user
ARG uid
RUN apt-get update && apt-get install -y \
curl \
zip \
unzip
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
r
RUN useradd -G www-data,root -u $uid -d /home/$user $user
RUN mkdir -p /home/$user/.composer && \
chown -R $user:$user /home/$user
WORKDIR /var/www
USER $user
I have tried multiple versions of PHP-FPM, it still happening.
For my WordPress site, using the FPM-Alpine version, I basically use the same Dockerfile as this (some smaller modifications only)
https://github.com/docker-library/wordpress/blob/master/latest/php8.1/fpm-alpine/Dockerfile
Does anyone has tips to what I can try to figure out why this error keeps happening.
We have a php application which was running fine using
Docker Image :
php:7.2-apache-stretch
We now have to make use of the below image for better performance and make the application work as it was before .
php:7.2.17-fpm-stretch
As this image does not have apache in it . I updated the Dockerfile starting from the installation of apache2 and related packages based on various forums .
There is many other steps . I have just added the instructions which I have updated in the Dockerfile.
FROM php:7.2.17-fpm-stretch
RUN apt-get update && apt-get install -y apache2 wget
RUN cd /tmp && wget http://mirrors.kernel.org/ubuntu/pool/multiverse/liba/libapache-mod-fastcgi/libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb && dpkg -i libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb;apt-get install -f
RUN a2enmod actions proxy_fcgi fastcgi
COPY 000-default.conf /etc/apache2/sites-available/000-default.conf
COPY info.php /var/www/html/info.php
COPY run.sh /app/run.sh
# EXPOSE 9000
RUN chmod 755 /app/run.sh
CMD "/app/run.sh"
The info.php contains <?php phpinfo( ); ?> . In the run.sh script , we start the php-fpm service and apache2 as below
php-fpm -D
/usr/sbin/apachectl -D FOREGROUND
previously I was trying to access the app from the port which was mapped to 9000 ( fpm ) . When I accessed the correct port where apache was running , I was able to view info.php .
The Content in the vhost.conf file.
<FilesMatch \.php$>
SetHandler "proxy:fcgi://localhost:9000"
</FilesMatch>
I got it working making a few modifications.
I used this slightly modified dockerfile:
FROM php:7.2.17-fpm-stretch
RUN apt-get update; apt-get install -y apache2 wget
RUN cd /tmp && wget http://mirrors.kernel.org/ubuntu/pool/multiverse/liba/libapache-mod-fastcgi/libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb && dpkg -i libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb;apt-get install -f
RUN a2enmod actions proxy_fcgi fastcgi
COPY run.sh /app/run.sh
RUN chmod 755 /app/run.sh
CMD "/app/run.sh"
I also added the following snippet (the same modification you did) to /etc/apache2/sites-available/000-default.conf:
<FilesMatch \.php$>
SetHandler "proxy:fcgi://localhost:9000"
</FilesMatch>
Here is the output I get:
[09-Apr-2019 21:23:06] NOTICE: fpm is running, pid 9
[09-Apr-2019 21:23:06] NOTICE: ready to handle connections
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
Also, did you try building the dockerfile without the cache? Sometimes, caching can cause issues with package installation (see here for more details). To do a clean build of an image, just use:
docker build --no-cache
I got your new configuration working using this dockerfile:
FROM php:7.2.17-fpm-stretch
RUN apt-get update && apt-get install -y apache2 wget
RUN cd /tmp && wget http://mirrors.kernel.org/ubuntu/pool/multiverse/liba/libapache-mod-fastcgi/libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb && dpkg -i libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb;apt-get install -f
RUN a2enmod actions proxy_fcgi fastcgi
COPY 000-default.conf /etc/apache2/sites-available/000-default.conf
COPY info.php /var/www/html/info.php
COPY run.sh /app/run.sh
RUN chmod 755 /app/run.sh
EXPOSE 80
CMD "/app/run.sh"
The command I ran was:
docker run -P -d --rm <php-image>
The exposed ports are:
0.0.0.0:32773->80/tcp, 0.0.0.0:32772->9000/tcp
I was able to access info.php using http://localhost:32773/info.php
I was able to access the php page . Everything was working fine . But I was looking in the wrong direction . When I run the container .
docker run -P -d --rm php:test-fpm
The output was
82071c9ff023 php:test-fpm "docker-php-entrypoi…" 2 seconds ago Up 1 second 0.0.0.0:32778->80/tcp, 0.0.0.0:32777->9000/tcp practical_mclean
I was accessing localhost:32777/info.php . But I should I accessed the 32778 where apache is exposed and localhost: 32778/info.php worked !!! .
Is there a way to avoid the port mapping of 9000. ???
This question already has answers here:
Why can't I use Docker CMD multiple times to run multiple services?
(5 answers)
Closed 4 years ago.
I have a dockerfile that sets up NGINX, PHP, adds a Wordpress Repository. I want at boot time, to start PHP and NGINX. However, I am failing to do so. I tried adding the two commands in the CMD array, and I also tried to put them in a shell file and starting the shell file. Nothing worked. Below is my Dockerfile
FROM ubuntu:16.04
WORKDIR /opt/
#Install nginx
RUN apt-get update
RUN apt-get install -y nginx=1.10.* php7.0 php7.0-fpm php7.0-mysql
#Add the customized NGINX configuration
RUN rm -f /etc/nginx/nginx.conf
RUN rm -f /etc/nginx/sites-enabled/*
COPY nginx/nginx.conf /etc/nginx/
COPY nginx/site.conf /etc/nginx/sites-enabled
#Copy the certificates
RUN mkdir -p /etc/pki/nginx
COPY nginx/certs/* /etc/pki/nginx/
RUN rm -f /etc/pki/nginx/placeholder
#Copy the build to its destination on the server
RUN mkdir -p /mnt/wordpress-blog/
COPY . /mnt/wordpress-blog/
#COPY wp-config.php
COPY nginx/wp-config.php /mnt/wordpress-blog/
#The command to run the container
CMD ["/bin/bash", "-c", "service php7.0-fpm start", "service nginx start"]
I tried to put the commands in the CMD in a shell file, and run the shell file in the CMD command. It still didn't work. what am i missing?
start.sh
#!/bin/bash
/usr/sbin/service php7.0-fpm start
/usr/sbin/service nginx start
tail -f /dev/null
Dockerfile
COPY ["start.sh", "/root/start.sh"]
WORKDIR /root
CMD ["./start.sh"]
With this, you can put more complex logic in start.sh.
You can replace the CMD line for some like ...
CMD ["/bin/bash", "-c", "/usr/sbin/service php7.0-fpm start && nginx -g 'daemon off;'"]
TL;DR: You don't have an entry point.
Main idea in the Docker is to have one responsibility per container. So, in order to keep running a Docker container you have to start a program in foreground upon container boot.
However, in your Dockerfile, there is no entrypoint to start a program in foreground. So, just after your container boot, your container exits.
So, in order to prevent your container from exiting, just start a program in foreground.
Nginx for instance.
Example scenario:
entrypoint.sh content:
#!/bin/bash
service php7.0-fpm start
nginx -g 'daemon off;
somewhere in Dockerfile:
COPY [ "./entrypoint.sh", "/root/entrypoint.sh" ]
at the end of the Dockerfile:
ENTRYPOINT /root/entrypoint.sh
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?
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/
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)
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
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
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.
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.
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
I'm beginner with Docker, and I'm trying to build my own image: Ubuntu + Nginx + PHP.
So, I have a directory called test. Inside directory two other directories, app and sites-enabled. Also, there's a Dockerfile, with content:
FROM ubuntu:trusty
RUN apt-get update && \
apt-get install -y nginx php5-fpm php5-mysql php-apc php5-imagick php5-imap php5-mcrypt php5-gd libssh2-php && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
ADD sites-enabled/ /etc/nginx/sites-enabled/
ADD app/ /app/
EXPOSE 80
CMD ["php5-fpm", "-c", "/etc/php5/fpm"]
CMD ["/usr/sbin/nginx"]
I build this image successfully. Then I create container with docker run -d image_name. I get the ID, and then I run docker inspect -f "{{.NetworkSettings.IPAddress}}" ID in order to get the IP address of the container.
I need this IP address, because I also run HAProxy in another container, so I can configure it to point to the right localtion.
So, both HAProxy and container with PHP app are running OK. HAProxy is pointing at the right application. PHP application files are uploaded at the right location inside the container.
But, Nginx doesn't execute PHP. Instead, when I try to access the application, I just get a downloaded file with my index.php PHP code.
What could be the problem? Please help.
My first guess was that I'm doing something wrong in Dockerfile when I run php5-fpm. I've tried few different ways, but non of them seem to work.
One CMD only.
If you need "services", look into supervisord or runit.