PHP-FPM does not start after container creation - php

I made a Dockerfile, but when I run it and enter the container, the php8.0-fpm service is not running.
How do I make it run at build time? Note that I run the command service php8.0-fpm start in the Dockerfile and even then it is not running.
What should I do for the php8.0-fpm service to start along with the container?
Below is the Dockerfile I made:
FROM ubuntu:jammy
ENV DEBIAN_FRONTEND=noninteractive
# Instalação Apache e PHP
RUN apt-get update && \
apt-get install software-properties-common -y && \
add-apt-repository ppa:ondrej/php -y && \
apt-get update && \
apt-get install -y \
apache2 \
libapache2-mod-php8.0 \
libapache2-mod-php \
php8.0-fpm \
libapache2-mod-fcgid \
# Alteração sequência index
COPY /src/dir.conf /etc/apache2/mods-enabled
# Commitando a nova configuração
RUN service apache2 restart
RUN service php8.0-fpm restart
# Inserindo página info.php
COPY /src/info.php /var/www/html
# Alterando módulos de multiprocessamento
RUN service apache2 stop && \
a2dismod php8.0 && \
a2dismod php8.1 && \
a2dismod mpm_prefork && \
a2enmod mpm_event && \
a2enconf php8.0-fpm && \
a2enmod proxy && \
a2enmod proxy_fcgi && \
service apache2 restart && \
service php8.0-fpm start
# Entrypoint para o conteiner iniciar o Apache
ENTRYPOINT ["apache2ctl", "-D", "FOREGROUND"]```

You need to run php fpm on startup. if you installed bash in your vm os, you can do it this way.
STOPSIGNAL SIGTERM
CMD ["/bin/bash", "-c", "php-fpm8 && include your apache here"]
Full guide: How to setup PHP 8, NGINX and PHP-FPM with docker

A Docker container only runs a single process. It doesn't "run services" per se. The image build doesn't preserve any running processes either. When you start the container, the image's ENTRYPOINT or CMD is the only thing that will be running in the container.
Avoiding the technical reasons, I'd broadly suggest that commands like service or systemctl just don't work in Docker. RUN service php8.0-fpm restart, for example, does nothing: PHP-FPM wasn't running before this command, and after the RUN command it won't be running either.
You'd typically restructure this into multiple separate containers, using a tool like Docker Compose to run them all together. Docker has a couple of official sample applications that demonstrate this. A Compose-based setup for this might look like
# docker-compose.yaml
version: '3.8'
services:
php:
build: . # using default Dockerfile
apache:
build:
context: .
dockerfile: Dockerfile.apache
ports:
- '8000:80'
Your Dockerfile would begin FROM php:8.0-fpm and contain only the PHP-related setup; Dockerfile.apache would begin FROM httpd:2.4 and only copy in the static assets and Apache configuration. Your proxy setup would need to reference the other container by name ProxyPass "/" "fcgi://php:9000"; see Networking in Compose in the Docker documentation for additional details.
Note that, even in this case, something like docker-compose exec apache service apache2 status still wouldn't show "a service is running", but if you docker-compose exec apache ps -e you'd see the HTTP daemon as process 1 within the container. This is normal.

I managed to leave it in just one container, PHP has an extension called Supervisor and with it installed we were able to start two or more services inside the container.
The Dockerfile looked like this:
FROM httpd:2.4-alpine
RUN apk update && \
apk add \
php \
php-fpm \
php-zip \
composer \
supervisor
COPY . /usr/local/apache2/htdocs
COPY httpd.conf /usr/local/apache2/conf/httpd.conf
COPY supervisor /etc/supervisor
WORKDIR /usr/local/apache2/htdocs
CMD ["supervisord","-n", "-c", "/etc/supervisor/supervisord.conf"]
And I created two configuration files for Supervisor.
apache.conf
[program:apache]
command=httpd -DFOREGROUND
autostart=true
autorestart=true
priority=10
startretries=1
startsecs=1
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
fpm.conf
[program:php-fpm]
command = php-fpm8 --nodaemonize
autostart=true
autorestart=true
priority=5
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
With that the two services started and it is working perfectly!

Related

How to run cron and web application in same container?

I am new to docker. Hardly I have containerized my php application to run it in the web interface. But I have some cron to run with it. I learnt how to create separate cron image and run it from How to run a cron job inside a docker container?. But my use case is different. I need to use the php files from my php application container which seems not possible from my way. I tried creating the docker-compose.yml as follow to see if it would work
docker-compose.yml:
version: "3"
services:
app:
build:
context: ./docker/php
container_name: 'app'
restart: 'always'
ports:
- "80:80"
- "443:443"
links:
- db
volumes:
- ${DOCUMENT_ROOT-./src}:/var/www/html
- ${PHP_INI-./docker/php/php.ini}:/usr/local/etc/php/php.ini
- ${VHOSTS_DIR-./docker/apache2/vhosts}:/etc/apache2/sites-enabled
- ${LOG_DIR-./docker/logs/apache2}:/var/log/apache2
extra_hosts:
- "test.local:127.0.0.1"
hostname: cloudservice.local
domainname: local
#entrypoint: sh /var/www/html/cron.sh
As I have commented entry point here and if I do docker-compose up, everything works perfectly fine, My Dockerfile is as under
Dockerfile:
FROM php:7.2.27-apache
RUN apt-get update
RUN apt-get install -y cron
RUN apt-get -y update --fix-missing
RUN apt-get upgrade -y
# Install useful tools
RUN apt-get -y install apt-utils nano wget dialog
# Install important libraries
RUN apt-get -y install --fix-missing apt-utils build-essential git curl libcurl4 libcurl4-openssl-dev zip
# Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Install xdebug
#RUN pecl install xdebug-2.5.0
#RUN docker-php-ext-enable xdebug
# Other PHP7 Extensions
RUN apt-get -y install libsqlite3-dev libsqlite3-0 default-mysql-client
RUN docker-php-ext-install pdo_mysql
RUN docker-php-ext-install pdo_sqlite
RUN docker-php-ext-install mysqli
RUN docker-php-ext-install curl
RUN docker-php-ext-install tokenizer
RUN docker-php-ext-install json
RUN apt-get -y install zlib1g-dev
RUN docker-php-ext-install zip
RUN apt-get -y install libicu-dev
RUN docker-php-ext-install -j$(nproc) intl
RUN docker-php-ext-install mbstring
RUN apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev
RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/
RUN docker-php-ext-install -j$(nproc) gd
RUN pecl install redis-5.1.1 \
&& docker-php-ext-enable redis
# Enable apache modules
RUN a2enmod rewrite headers
My cron.sh file is as under
#!/usr/bin/env bash
# Ensure the log file exists
touch /var/www/html/logs/crontab.log
# Ensure permission on the command
chmod a+x /var/www/html/cron-local/hn-shc-rapid-daily.sh
# Added a cronjob in a new crontab
echo "* * * * * bash /var/www/html/cron-local/hn-shc-rapid-daily.sh >> /var/www/html/logs/crontab.log 2>&1" > /etc/crontab
# Registering the new crontab
crontab /etc/crontab
# Starting the cron
/usr/sbin/service cron start
# Displaying logs
# Useful when executing docker-compose logs mycron
tail -f /var/www/html/logs/crontab.log
But with the entry point commented, i cannot run cron. If i don't comment entrypoint, then cron runs, my web application doesn't. Is there any possibility to fix this?
Thanks
At the end of the docker file i added the following code after removing
RUN a2enmod rewrite headers
# Copy hello-cron file to the cron.d directory
COPY hello-cron /etc/cron.d/hello-cron #just any name
# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron
# Apply cron job
RUN crontab /etc/cron.d/hello-cron
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
# Enable apache modules
RUN a2enmod rewrite headers
CMD cron && /usr/sbin/apache2ctl -D FOREGROUND
and cron.sh was changed to
* * * * * echo "hello world" >> /var/www/html/logs/crontab.log 2>&1
This worked for me. I need not have to add entry neither on docker-compose nor on docker file, but I guess entry also would work.
I don't know if this is the right way to do. If anyone would give me more advance idea, I would be happy to give it a try.
Thanks
I think it's better if you specify the entry point in the docker-compose file without "sh" in front of it. Remember that declaring a new entrypoint in the docker-compose file overwrites the entrypoint in the dockerfile. Link
I would advise you to create your own Entrypoint Script which will execute your crons in the container CMD ["/entrypoint.sh"]
Example:
Create an file and named "entrypoint.sh" or whatever and save it in the same folder where your Dockerfile is located. In this file push your Content from your cron.sh.
RUN apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev
RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/
RUN docker-php-ext-install -j$(nproc) gd
RUN pecl install redis-5.1.1 \
&& docker-php-ext-enable redis
# Enable apache modules
RUN a2enmod rewrite headers
COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
CMD ["/entrypoint.sh"]
But you could also just add your cron directly in the docker file.
...
# Enable apache modules
RUN a2enmod rewrite headers
COPY your-cron.cron /
RUN crontab /your-cron.cron
...

GCP Cloud run container service : [pool www] failed to write the ACL of the socket '/run/php-fpm/www.sock'

I am running a containerized web based application on AWS ECS fargate for a few months now. But due to few issues with AWS my team planned to take it multicloud with GCP. So when deploy my container image on GCP Cloud Run it gives me this errors
ERROR: [pool www] failed to write the ACL of the socket '/run/php-fpm/www.sock': Operation not permitted (1)"
ERROR: FPM initialization failed
Then i tried to change permission make of /run/php-fpm using
chmod 777 -R /run/php-fpm
It again shows me same error
After than i run the container locally and exec into the container to check the www.sock file, its permission was
srw-rw----+ root root www.sock
and the permission of /run/php-fpm was
drwxrwxrwx. root root php-fpm
After that i tried to change permissions with
chmod 777 -R /run/php-fpm/*
in the docker file but it gives me an error that file doesn't exists
I also tried using setfacl but when i exec into container and check it locally the permission off www.sock is not changed and give same error when deployed on cloud run
I don't want to move to azure so i need the solution for cloud run only. I am using port 80 to expose to docker file
Here is my dockerfile
FROM amazonlinux:2
# Environment variables
ENV PORT 80
# Install dependencies
RUN amazon-linux-extras install php7.2
RUN yum clean metadata && yum update -y && \
yum install -y \
curl \
httpd httpd-tools\
git \
openssh-server \
openssh-clients \
php-cli php-pdo php-fpm php-json \
php-bcmath \
php-cli \
php-common \
php-dba \
php-devel \
php-embedded \
php-enchant\
php-gd\
php-intl \
php-lda\
php-mbstrin\
php-mysqlnd \
php-odbc \
php-pd\
php-pear.noarch \
php-pgsql\
php-process \
php-pspel \
php-recode \
php-snmp \
php-soap \
php-xml \
php-xmlrpc \
php-mbstring \
unzip \
&& ln -s /usr/sbin/httpd /usr/sbin/apache2 \
&& curl -sS https://getcomposer.org/installer | php \
&& mv composer.phar /usr/local/bin/composer \
&& ln -s /usr/local/bin/composer /usr/bin/composer
COPY github_key .
COPY httpd.conf /etc/httpd/conf/httpd.conf
# Install app
RUN rm -rf /var/www/html/* && mkdir -p /var/www/html
# git clone command
#few sed commands
WORKDIR /var/www/html/
RUN composer require mpdf/mpdf && \
chmod 777 -R vendor/mpdf/mpdf/tmp
EXPOSE $PORT
ENTRYPOINT ["sh", "-c", "/usr/sbin/php-fpm && /usr/sbin/apache2 -DFOREGROUND"]
Well after alot of searching and hit n trail i got the solution.
Most of solutions online recommend set values in /etc/php-fpm.d/www.conf to
;listen.owner = nginx
;listen.group = nginx
listen.acl_users = apache, nginx
listen.acl_groups = apache, nginx
But this does NOT WORK
For perfect deployment on Cloud Run we have to comment listen.acl_users and listen.acl_groups
;listen.acl_users = apache, nginx
;listen.acl_groups = apahce, nginx
For that i am using sed command in Dockerfile
RUN sed -i 's/listen.acl_users/;listen.acl_users/g' /etc/php-fpm.d/www.conf
RUN sed -i 's/listen.acl_groups/;listen.acl_groups/g' /etc/php-fpm.d/www.conf
After that my app will perfectly deployed on Cloud Run but started giving error on AWS ECS Fargate. So, i end up making 2 different Dockerfiles for each service.

unable to run Apache/php from docker container

My requirement is using openface i need to train the dataset(images) and test each input image from webinterface (PHP) and all this activity should run from docker container.
I am able to achieve the above requirment on ubuntu machine. we are trying to install the complete setup(apache/php & openface) in docker. currently we are unable to invoke the html files from apache server using docker
The following the docker file used to import the project into docker and install apache/PHP. Please let me know if any changes need to be done in the dockerfile.
FROM ubuntu:16.04
RUN apt-get update && \
apt-get -y install sudo
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
ADD opencv-3.0.0 /
ADD openface_setup.sh /
RUN /openface_setup.sh
ADD openface_work /
RUN apt-get update && apt-get -y upgrade && DEBIAN_FRONTEND=noninteractive apt-get -y install \
apache2 php7.0 libapache2-mod-php7.0 curl lynx-cur
RUN a2enmod php7.0
RUN a2enmod rewrite
RUN sed -i "s/short_open_tag = Off/short_open_tag = On/" /etc/php/7.0/apache2/php.ini
RUN sed -i "s/error_reporting = .*$/error_reporting = E_ERROR | E_WARNING | E_PARSE/" /etc/php/7.0/apache2/php.ini
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2
ENV APACHE_PID_FILE /var/run/apache2.pid
EXPOSE 8080
VOLUME /var/www/html # **my PHP/html files are located here. In the docker container the html/php files are not reflecting**
ADD apache-config.conf /etc/apache2/sites-enabled/000-default.conf
CMD /usr/sbin/apache2ctl -D FOREGROUND
Once the container is started i want the test.html(located in /var/www/html) to be running.
FYI :
command to created docker image
sudo docker build -t myname/apache-test .
command to start the docker container
docker run -p 8080:80 -d <imageid>
I'd suggest to use the official PHP image with a pre-installed Apache installation.
Your project might look like this:
.
├── Dockerfile
└── src
└── index.php
while your Dockerfile consists of this:
FROM php:7.1-apache
# now RUN here your commands to install openface etc.
and your index.php could look like this:
<?php phpinfo();
Then build the image:
docker build -t myapache .
docker run --rm -p 8080:80 -v $(pwd)/src:/var/www/html myapache
http://localhost:8080 shows the php-info page.
You can extend the image to your needs and it's much simpler than your approach. Hope this might help.
If you do not need to install anything else, you can directly use the php:7.1-apache image when creating a new container.
try typing docker ps to get all the processes running in containers.
Then just type docker run -it container-id
It will start the apache server and show the address where it hosted it unless you want to add a different one in /etc/docker/daemon.json (https://docs.docker.com/engine/userguide/networking/default_network/custom-docker0/)

How can I run my docker container with installed Nginx?

I have docker image with Dockerfile, that successfully build with docker build . command. The Dockerfile content is:
FROM ubuntu
RUN apt-get update && apt-get install -y nginx php5 php5-fpm
ADD . /code
How can I run my docker container to see that Nginx is work?
UPDATE: When I try to use next Dockerfile:
FROM ubuntu
RUN apt-get update && apt-get install -y nginx php5 php5-fpm
RUN sudo echo "daemon off;" >> /etc/nginx/nginx.conf
CMD service php5-fpm start && nginx
It build successfully with docker build -t my/nginx ., but when I enter docker run --rm -ti my/nginx command, my terminal not response:
When you build the image you probably want to specify the image name with -t option.
docker build -t my/nginx .
To run a container use the run command
docker run --rm -ti my/nginx
You probably should add the following command to your Dockerfile
CMD ["nginx"]
Or with php5-fpm
CMD service php5-fpm start && nginx
UPDATE.
You should run nginx as daemon off. Add the following to your Dockerfile after installing nginx.
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
Update2.
-ti option in run allows you to check the log messages if any.
Usually you should run a container in background using -d instead of -ti.
You can attach to a running container using the attach command.
You may also check docker reference to see how to stop and remove a container and other commands.

Linking to a Docker memcached container

I have been experimenting with Docker for a few days now and have grown to like it. However, there are a few things that still elude me. Here is what I have thus far
Create a low footprint Ubuntu 14.04 image
//I got this from a post on this forum
#!/bin/bash
docker rm ubuntu-essential-multilayer 2>/dev/null
set -ve
docker build -t textlab/ubuntu-essential-multilayer - <<'EOF'
FROM ubuntu:14.04
# Make an exception for apt: it gets deselected, even though it probably shouldn't.
RUN dpkg --clear-selections && echo apt install |dpkg --set-selections && \
SUDO_FORCE_REMOVE=yes DEBIAN_FRONTEND=noninteractive apt-get --purge -y dselect-upgrade && \
dpkg-query -Wf '${db:Status-Abbrev}\t${binary:Package}\n' |grep '^.i' |awk -F'\t' '{print $2 " install"}' |dpkg --set-selections && \
rm -r /var/cache/apt /var/lib/apt/lists
EOF
TMP_FILE="`mktemp -t ubuntu-essential-XXXXXXX.tar.gz`"
docker run --rm -i textlab/ubuntu-essential-multilayer tar zpc --exclude=/etc/hostname \
--exclude=/etc/resolv.conf --exclude=/etc/hosts --one-file-system / >"$TMP_FILE"
docker rmi textlab/ubuntu-essential-multilayer
docker import - textlab/ubuntu-essential-nocmd <"$TMP_FILE"
docker build -t textlab/ubuntu-essential - <<'EOF'
FROM textlab/ubuntu-essential-nocmd
CMD ["/bin/bash"]
EOF
docker rmi textlab/ubuntu-essential-nocmd
rm -f "$TMP_FILE"
Create a Dockerfile for an Apache image
FROM textlab/ubuntu-essential
RUN apt-get update && apt-get -y install apache2 && apt-get clean
RUN a2enmod ssl
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
EXPOSE 80
EXPOSE 443
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
docker build -t droidos/apache .
Create a Dockerfile for PHP5
FROM droidos/apache
RUN apt-get update && apt-get -y --reinstall install php5 php5-redis php5-memcached php5-curl libssh2-php php5-mysqlnd php5-mcrypt && apt-get clean
RUN php5enmod mcrypt
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
EXPOSE 80
EXPOSE 443
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
docker build -t droidos/php5 .
Create a Dockerfile for memcached and build the image
FROM textlab/ubuntu-essential
# Install packages
RUN DEBIAN_FRONTEND=noninteractive apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install memcached
# memcached public variable
EXPOSE 11211
CMD ["/usr/bin/memcached", "-u", "memcache", "-v"]
docker build -t droidos/memcached .
Fireup a docker container with memcached
docker run -d -P --name memcached droidos/memcached
Fireup a docker container with apache and link it to the memcached container created earlier
docker run -d --name apache --link memcached:memcached -v /var/droidos/site:/var/www/html -v /var/droidos/logs:/var/log/apache2 -p 8080:80 droidos/php5
Browse to example.com:8080
Everything seems ok
Create a memcached test script in /var/droidos/site
<?php
error_reporting(E_ALL);
header('Content-type:text/plain');
$mc = new Memcached();
$mc->addServer("localhost", 11211);
$flag = $mc->add('name','droidos');
echo ($flag)?'y':'n';
echo $mc->getResultCode();
?>
This script returns n47 implying that the memcached server is disabled.
Either my linking is incorrect or memcached has not been started or the memcached container port is not visible in the apache container. SSHing into the memcached container
docker exec -it <container-id> /bin/bash
and running
service memcached status
indicates that the service is not in fact running. So I start it
service memcached start
verify it has started and run the script above again. No joy - I still get an n47 reply rather than the y0 I would like to see. Clearly, I am missing a step somewhere here. I'd be most obliged to anyone who might be able to tell me what that might be.
I think it fails because you're trying to access memcached from the apache container connecting to the localhost of the apache container, while the memcached container is made accessible to the apache one on a different IP address.
This is the line I think is wrong:
$mc->addServer("localhost", 11211);
When you link containers, Docker adds a host entry for the source container to the /etc/hosts file (see the docs about linking).
Therefore you should be able to connect from the apache container to the memcached one using this PHP command:
$mc->addServer("memcached", 11211);
If it doesn't work, check that you can connect to the memcached service from the memcached container itself.

Categories