PHP7-FPM Docker CMD results in 502 Nginx Error
I've a docker compose that use two containers: nginx and php7-fpm. I'm building php via Dockerfile and I need cron installed on it:
FROM 'php:7-fpm'
# PDO
RUN docker-php-ext-install pdo_mysql
# Cron
RUN apt-get update -q -q && apt-get install -y cron
ADD crontab /etc/cron.d/crontab
RUN chmod 0644 /etc/cron.d/crontab
RUN touch /var/log/cron.log
CMD cron && tail -f /var/log/cron.log // this line is breaking things
This way, nginx report a 502 Bad Gateway error. If i remove the last line, CMD, everything works fine. How can I fix this?
Solution 1:
In docker container, you can only have one entrypoint or a command executed when you start the container. When you have at the end of your Dockerfile:
CMD cron && tail -f /var/log/cron.log
It means the only command that will run is cron. So your initial entrypoint for php-fpm service becomes irrelevant. In order to launch several processes in a docker container, you have to use a wrapper script or supervisor. For wrapper script, write it and copy through the build process. The script should have the start commands for all your services.
The CMD will have something like:
CMD ./wrapper_script.sh
For supervisor, there are good tutorials available online that explains how to use supervisor with docker.
Your Dockerfile will look like this:
FROM 'php:7-fpm'
# PDO
RUN docker-php-ext-install pdo_mysql
# Cron
RUN apt-get update -q -q && apt-get install -y cron supervisor
ADD crontab /etc/cron.d/crontab
RUN chmod 0644 /etc/cron.d/crontab
RUN touch /var/log/cron.log
ADD supervisord.conf /etc/supervisor.conf
ENTRYPOINT ["/usr/bin/supervisord -c /etc/supervisor.conf"]
Then create supervisord.conf file:
[supervisord]
nodaemon=true
[program:php-fpm]
command=php-fpm-commands
[program:cron]
command=cron-commands
Replace php-fpm-commands and cron-commands with the commands and options you need to be there for each service.
Solution 2:
I also came across the same question when using docker with php-fpm
and nginx
. The way I solved the problem was similar to the answer given previously.
TL;DR
FROM 'php:7-fpm'
# PDO
RUN docker-php-ext-install pdo_mysql
# Cron
RUN apt-get update -q -q && apt-get install -y cron
ADD crontab /etc/cron.d/crontab
RUN chmod 0644 /etc/cron.d/crontab
RUN touch /var/log/cron.log
CMD cron && docker-php-entrypoint php-fpm
Adding last line to start the process that php-fpm
intended to run
As stated above,
In docker container, you can only have one entrypoint or a command executed when you start the container.
Problem
But when you add our own entrypoint to the docker container by doing CMD ["custom_script.sh"]
or ENTRYPOINT ["custom_script.sh"]
, the default entrypoint script gets replaced by your custom one (in our case custom_script.sh
).
The way I came across solution to the problem was by writing script in such a way that doesn't replace original instead extend.
Solution
- To learn which script the docker container runs by default was found using
docker-compose ps
after running the container without the entrypoint script. The result in my machine looks like below;
Name Command State Ports
----------------------------------------------------------------------------------------------------------------
appointmentlaravel_appointment_app_1 docker-php-entrypoint php-fpm Up 0.0.0.0:9007->6001/tcp, 9000/tcp
As you can see, by default, the script container runs is docker-php-entrypoint php-fpm
so.
- We can create custom script in such a way that at the end runs the same script that it ran originally as shown below;
# arbitary code to run when docker-container starts
docker-php-entrypoint php-fpm
In your case, the dockerfile
may look like;
FROM 'php:7-fpm'
# PDO
RUN docker-php-ext-install pdo_mysql
# Cron
RUN apt-get update -q -q && apt-get install -y cron
ADD crontab /etc/cron.d/crontab
RUN chmod 0644 /etc/cron.d/crontab
RUN touch /var/log/cron.log
CMD cron && docker-php-entrypoint php-fpm
Look how I replaced the last line of your dockerfile to run docker-php-entrypoint php-fpm
.