I'm new in Docker and I'm facing a problem with my custom Dockerfile which needs some help from you guys. It's working fine until I add some code to run the cronjob in the docker container.
This is my Dockerfile file:
FROM php:7.2-fpm-alpine
COPY cronjobs /etc/crontabs/root
// old commands
ENTRYPOINT ["crond", "-f", "-d", "8"]
This is cronjobs file:
* * * * * cd /var/www/html && php artisan schedule:run >> /dev/null 2>&1
This is docker-compose.yml file:
version: '3'
networks:
laravel:
services:
nginx:
image: nginx:stable-alpine
container_name: nginx_ctrade
ports:
- "8081:80"
volumes:
- ./app:/var/www/html
- ./config/nginx/default.conf:/etc/nginx/conf.d/default.conf
- ./config/certs:/etc/nginx/certs
- ./log/nginx:/var/log/nginx
depends_on:
- php
- mysql
networks:
- laravel
working_dir: /var/www/html
php:
build:
context: ./build
dockerfile: php.dockerfile
container_name: php_ctrade
volumes:
- ./app:/var/www/html
- ./config/php/php.ini:/usr/local/etc/php/php.ini
networks:
- laravel
mysql:
image: mysql:latest
container_name: mysql_ctrade
tty: true
volumes:
- ./data:/var/lib/mysql
- ./config/mysql/my.cnf:/etc/mysql/my.cnf
environment:
- MYSQL_ROOT_PASSWORD=secret
- MYSQL_USER=admin
- MYSQL_DATABASE=laravel
- MYSQL_PASSWORD=secret
networks:
- laravel
I re-build the docker images and run it. The cronjob is working ok but when I access the localhost at localhost:8081. It isn't working anymore. The page show 502 Bad Gateway, so I checked the Nginx error log. This is the Nginx error shown me:
2020/04/10 13:33:36 [error] 8#8: *28 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.224.1, server: localhost, request: "GET /trades HTTP/1.1", upstream: "fastcgi://192.168.224.3:9000", host: "localhost:8081", referrer: "http://localhost:8081/home"
All the containers are still running after updated.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a2403ece8509 nginx:stable-alpine "nginx -g 'daemon of…" 18 seconds ago Up 17 seconds 0.0.0.0:8081->80/tcp nginx_ctrade
69032097b7e4 ctrade_php "docker-php-entrypoi…" 19 seconds ago Up 18 seconds 9000/tcp php_ctrade
592b483305d5 mysql:latest "docker-entrypoint.s…" 3 hours ago Up 18 seconds 3306/tcp, 33060/tcp mysql_ctrade
Is there someone get this issue before? Any help would be appreciated! Thanks so much!
According to the documentation, running two (or more) services inside of a Docker container breaks it's philosophy of single responsability.
It is generally recommended that you separate areas of concern by using one service per container. That service may fork into multiple processes (for example, Apache web server starts multiple worker processes). It’s ok to have multiple processes, but to get the most benefit out of Docker, avoid one container being responsible for multiple aspects of your overall application. [...]
If you choose to follow this recommendation, you will end up with two options:
Option 1. Create a separated container that will handle the scheduling tasks.
Example:
# File: Dockerfile
FROM php:7.4.8-fpm-alpine
COPY ./cron.d/tasks /cron-tasks
RUN touch /var/log/cron.log
RUN chown www-data:www-data /var/log/cron.log
RUN /usr/bin/crontab -u www-data /cron-tasks
CMD ["crond", "-f", "-l", "8"]
# File: cron.d/tasks
* * * * * echo "Cron is working :D" >> /var/log/cron.log 2>&1
# File: docker-compose.yml
services:
[...]
scheduling:
build:
context: ./build
dockerfile: cron.dockerfile
[...]
Option 2. Use own host's crontab to execute the scheduled tasks on containers (as defended in this post).
Example:
# File on host: /etc/cron.d/my-laravel-apps
* * * * * root docker exec -t laravel-container-A php artisan schedule:run >> /dev/null 2>&1
* * * * * root docker exec -t laravel-container-B php artisan schedule:run >> /dev/null 2>&1
* * * * * root docker exec -t laravel-container-C php artisan schedule:run >> /dev/null 2>&1
PS: In your case, replace <laravel-container-*> by php_ctrade.
Option 3: Use supervisord
On the other hand, if you really want just one container at all, you may still use supervisord as your main process and configure it to initialize (and supervise) both php-fpm and crontab applications.
Note that this is a moderately heavy-weight approach and requires you to package supervisord and its configuration in your image (or base your image on one that includes supervisord), along with the different applications it manages.
You will find an example of how to do it here.
References:
Recommended reading: