Cannot run supervisor specifying custom user - php

I'm building a Laravel image which runs with the user backend that have the id 1000. This user should allow me to prevent the following error:
File could not be opened in append mode: failed to open stream: Permission denied
The problem's that when I run the supervisor I get this error:
IOError: [Errno 13] Permission denied: '/var/log/supervisord.log'
This is my Dockerfile:
FROM php:8.1.10-fpm-buster
WORKDIR /var/www
RUN docker-php-ext-install bcmath pdo_mysql
RUN apt-get update
RUN apt-get install -y git zip unzip netcat
# Supervisor
RUN apt-get install -y supervisor
# Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Configurations
COPY docker/php/config/supervisor.conf /etc/supervisord.conf
COPY docker/php/config/php.ini /usr/local/etc/php/conf.d/app.ini
# Log file
RUN mkdir /var/log/php
RUN touch /var/log/php/errors.log && chmod 777 /var/log/php/errors.log
# Deploy
COPY /docker/php/scripts/start.sh /start.sh
RUN chmod +x /start.sh
# Add user for laravel application
RUN groupadd -g 1000 backend
RUN useradd -u 1000 -ms /bin/bash -g backend backend
# Copy existing application directory contents
COPY . /var/www
# Copy existing application directory permissions
COPY --chown=backend:backend . /var/www
USER backend
EXPOSE 9000
ENTRYPOINT /start.sh
This is my docker-compose file:
version: '3.9'
services:
php:
container_name: ${APP_NAME}_app
#user: ${CURRENT_UID}
restart: always
build:
context: .
dockerfile: ./docker/php/Dockerfile
volumes:
- ./src:/var/www
env_file: .env
And this is the entrypoint script:
#!/bin/bash
# Run composer install
composer install
# Generate key and clear cache
php artisan key:generate
php artisan config:clear
php artisan config:cache
# Wait db connection
until nc -z ${DB_HOST} ${DB_PORT}; do sleep 1; echo "Wait database ..."; done
# Execute migrations
php artisan migrate --seed
/usr/bin/supervisord -c /etc/supervisord.conf
Last but not least, the supervisor.conf:
[supervisord]
nodaemon=true
loglevel = info
logfile=/var/log/supervisord.log
pidfile=/var/run/supervisord.pid
[group:laravel-worker]
priority=999
programs=laravel-app,laravel-schedule,laravel-notification,laravel-queue
[program:laravel-app]
priority=5
autostart=true
autorestart=true
stderr_logfile_maxbytes=0
stdout_logfile_maxbytes=0
command=/usr/local/sbin/php-fpm -R
stderr_logfile=/var/log/php/php-error.log
stdout_logfile=/var/log/php/php-access.log
[program:laravel-schedule]
numprocs=1
autostart=true
autorestart=true
redirect_stderr=true
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/artisan schedule:run
stdout_logfile=/var/log/php/schedule.log
[program:laravel-notification]
numprocs=1
autostart=true
autorestart=true
redirect_stderr=true
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/artisan notification:worker
stdout_logfile=/var/log/php/notification.log
[program:laravel-queue]
numprocs=5
autostart=true
autorestart=true
redirect_stderr=true
process_name=%(program_name)s_%(process_num)02d
stdout_logfile=/var/log/php/worker.log
command=php /var/www/artisan queue:work sqs --sleep=3 --tries=3
Is there any way to fix the permission issue?

This is my supervisord.conf as an example.
I am always adding user=root row. And never got a permission error.
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
user=root
numprocs=1
redirect_stderr=true

this issue because using USER backend in Docker file, you need to configure supervisor for using same user in Docker file user=backend

Related

Docker laravel container service exits with Supervisord

I have a laravel 9 application that I want to deploy to AWS ECS. The application uses redis for queue and I have installed horizon. I also installed Supervisor in the docker container but once I deploy my application and start up supervisor in my startup.sh script, my app is never reachable and I notice that both queue worker and horizon start and then exit.
Here's the dockerfile I am working with
FROM php:8.1.4-fpm-alpine3.14
RUN apk update
RUN apk add --no-cache git libzip-dev zip unzip php8-exif supervisor
RUN mkdir -p /usr/src/php/ext/redis; \
curl -fsSL https://pecl.php.net/get/redis --ipv4 | tar xvz -C "/usr/src/php/ext/redis" --strip 1; \
docker-php-ext-install redis;
RUN docker-php-ext-configure pcntl --enable-pcntl \
&& docker-php-ext-install \
pcntl
RUN docker-php-ext-install pdo pdo_mysql zip exif \
&& curl -sS https://getcomposer.org/installer | php -- \
--install-dir=/usr/local/bin --filename=composer
WORKDIR /var/www/html
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY . .
RUN chown -R www-data:www-data /var/www/html
RUN composer install --ignore-platform-req=ext-pcntl
RUN chmod 544 startup.sh
ENTRYPOINT ["./startup.sh"]
this is my supervisord.conf file content
[supervisord]
nodaemon=true
loglevel=debug
logfile=/var/www/html/storage/logs/supervisord.log
user=root
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=root
numprocs=8
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/worker.log
stopwaitsecs=3600
[program:horizon]
process_name=%(program_name)s
command=php /var/www/html/artisan horizon
autostart=true
autorestart=true
user=root
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/horizon.log
stopwaitsecs=3600
and my startup.sh script content is
#!/bin/sh
/usr/bin/supervisord
php artisan migrate
php artisan db:seed
php artisan config:cache
php artisan route:cache
php artisan serve --host=0.0.0.0 --port 80
If I comment out /usr/bin/supervisord and deploy to aws ecs, I am able to reach my app again. So what exactly am I doing wrong with the supervisor that is causing it to break my app and how can I fix it?

How to set up Supervisor and Laravel Horizon on Docker

I have successfully deployed a laravel application with horizon installed to AWS ECS. However horizon has remained Inactive and I am stuck trying to get it to work as my emails are getting queued and never sent. This is my docker file
FROM php:8.1.4-fpm-alpine3.14
RUN apk update
RUN apk add --no-cache git libzip-dev zip unzip php8-exif supervisor
RUN mkdir -p /usr/src/php/ext/redis; \
curl -fsSL https://pecl.php.net/get/redis --ipv4 | tar xvz -C "/usr/src/php/ext/redis" --strip 1; \
docker-php-ext-install redis;
RUN docker-php-ext-install pdo pdo_mysql zip exif \
&& curl -sS https://getcomposer.org/installer | php -- \
--install-dir=/usr/local/bin --filename=composer
WORKDIR /var/www/html
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY horizon.conf /etc/supervisor/conf.d/horizon.conf
COPY . .
RUN chown -R www-data:www-data /var/www/html
RUN composer install --ignore-platform-req=ext-pcntl
RUN chmod 544 startup.sh
CMD ["/usr/bin/supervisord"]
ENTRYPOINT ["./startup.sh"]
I created a supervisord.conf file with this content in it
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
a horizon.conf file with its content below
[program:horizon]
process_name=%(program_name)s
command=php /var/www/html/artisan horizon
autostart=true
autorestart=true
user=root
redirect_stderr=true
stdout_logfile=/var/log/horizon.log
stopwaitsecs=3600
and this is what my startup script startup.sh looks like
#!/bin/sh
php artisan migrate
php artisan db:seed
php artisan config:cache
php artisan route:cache
php artisan horizon
php artisan queue:restart
php artisan serve --host=0.0.0.0 --port 80
I am not exactly very knowledgable with supervisor on containers so I need help figuring out why I am not able to get horizon to be active and fix it.

could not translate host name "database" to address: Name or service not known [duplicate]

Trying to deploy the laravel application on docker stack .What I am
confused or not able to figure out is where can I run this php artisan
migrate:fresh to generate the tables required in mysql.
The services and the task are running well
docker-compose.yml
version: '3.3'
networks:
smstake:
ipam:
config:
- subnet: 10.0.10.0/24
services:
db:
image: mysql:5.7
networks:
- smstake
ports:
- "3306:3306"
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: smstake
MYSQL_USER: root
MYSQL_PASSWORD: password
deploy:
mode: replicated
placement:
constraints:
- node.role == manager
app:
image: smstake:latest
ports:
- 8000:80
networks:
- smstake
command: docker-compose exec app php artisan migrate --seed
deploy:
mode: replicated
replicas: 1
placement:
constraints:
- node.role == manager
volumes:
db_data:
Here is the dockerfile with which the image is generated
FROM alpine
ENV \
APP_DIR="/app" \
APP_PORT="80"
# the "app" directory (relative to Dockerfile) containers your Laravel app...
COPY app/ $APP_DIR
# or we can make the volume in compose to say use this directory
RUN apk update && \
apk add curl \
php7 \
php7-opcache \
php7-openssl \
php7-pdo \
php7-json \
php7-phar \
php7-dom \
php7-curl \
php7-mbstring \
php7-tokenizer \
php7-xml \
php7-xmlwriter \
php7-session \
php7-ctype \
php7-mysqli \
php7-pdo \
php7-pdo_mysql\
&& rm -rf /var/cache/apk/*
RUN curl -sS https://getcomposer.org/installer | php -- \
--install-dir=/usr/bin --filename=composer
RUN cd $APP_DIR && composer install
WORKDIR $APP_DIR
RUN chmod -R 775 storage
RUN chmod -R 775 bootstrap
#CMD php artisan migrate:fresh
CMD php artisan serve --host=0.0.0.0 --port=$APP_PORT
Tried adding to the Dockerfile as is commented but didn't solve the problem
Tried adding on docker-compose as command: php artisan migrate:fresh too
Previously was doing this in jenkins to make it work Now dont want it via jenkins
docker-compose up -d --force-recreate --build
#Running commands on already running service
docker-compose exec -T app php artisan migrate:fresh --seed --force
This is how I solved it .Created a bash script called run.sh and added the php artisan migrations commands followed by the php serve command.
run.sh
#!/bin/sh
cd /app
php artisan migrate:fresh --seed
php artisan serve --host=0.0.0.0 --port=$APP_PORT
Added entrypoint to the Dockerfile removing the CMD in the end which will run the commands desired.
copy ./run.sh /tmp
ENTRYPOINT ["/tmp/run.sh"]
Remove the command from the docker-compose.yml
To my opinion, automate migrate is not a good way when creating container. You can do this after container is up with this one line code manually;
docker exec your_container_name php artisan migrate
Yes, special script.
I try to build deploy and testing throw docker-compose, so i run migrations in script before starting supervisor in docker-service "jobs":
#!/bin/sh
cd /var/www
php artisan migrate --seed
/usr/bin/supervisord -n -c /etc/supervisord.conf
And piece from my deploy-docker-compose.yml:
services:
nginx:
depends_on:
- phpfpm ## NOT START BEFORE PHPFPM
phpfpm:
depends_on:
- jobs ## NOT START BEFORE MIGRATION
jobs:
# ....
This schema is not started in production yet;
UPD1
i had to create simple laravel command wait_db_alive:
public function handle()
{
$i = 1;
$ret = 1;
while($i <= 10){
echo 'connecting to host:'.config('database.connections.'.config('database.default').'.host').' try '.$i.'..';
try {
DB::connection()->getPdo();
echo 'ok'.PHP_EOL;
$ret = 0;
break;
} catch (\Exception $e) {
echo 'error:' . $e->getMessage() .PHP_EOL;
sleep(1);
$i++;
}
}
return $ret;
}
and edit init.sh to
#!/bin/sh
php artisan wait_db_alive && php artisan migrate --seed && /usr/bin/supervisord -n -c /etc/supervisord.conf
so, log for jobs:
jobs_1 | connecting to host:db try 1..error:SQLSTATE[HY000] [2002] Connection refused
jobs_1 | connecting to host:db try 2..error:SQLSTATE[HY000] [2002] Connection refused
jobs_1 | connecting to host:db try 3..ok
jobs_1 | Nothing to migrate.
jobs_1 | Seeding: ServicesTableSeeder
...
jobs_1 | Database seeding completed successfully.
jobs_1 | 2020-11-22 05:33:43,653 CRIT Supervisor is running as root.
UPD2
In some cases we need to start container without .env-file, then better init.sh for this:
#!/bin/sh
php artisan wait_db_alive && php artisan migrate --seed
/usr/bin/supervisord -n -c /etc/supervisord.conf
One quick way is to create temporary route to run migration.
Route::get('/migrate', function () {
\Artisan::call('migrate');
return \Artisan::output();
});
To run all migrate you need to be inside your container, for that you need to run your containers with docker-compose up, here u need to be with terminal in the directory where your docker-compose.yml file is.
after that, and with the same place of docker-compose.yml file, run this command to be inside your container:
docker exec -it name_of_container bash
and when you will be inside your container, go to your shared app inside the container, I think here is the app so cd app.
after all of this run:
php artisan migrate

Where to put the php artisan migrate command

Trying to deploy the laravel application on docker stack .What I am
confused or not able to figure out is where can I run this php artisan
migrate:fresh to generate the tables required in mysql.
The services and the task are running well
docker-compose.yml
version: '3.3'
networks:
smstake:
ipam:
config:
- subnet: 10.0.10.0/24
services:
db:
image: mysql:5.7
networks:
- smstake
ports:
- "3306:3306"
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: smstake
MYSQL_USER: root
MYSQL_PASSWORD: password
deploy:
mode: replicated
placement:
constraints:
- node.role == manager
app:
image: smstake:latest
ports:
- 8000:80
networks:
- smstake
command: docker-compose exec app php artisan migrate --seed
deploy:
mode: replicated
replicas: 1
placement:
constraints:
- node.role == manager
volumes:
db_data:
Here is the dockerfile with which the image is generated
FROM alpine
ENV \
APP_DIR="/app" \
APP_PORT="80"
# the "app" directory (relative to Dockerfile) containers your Laravel app...
COPY app/ $APP_DIR
# or we can make the volume in compose to say use this directory
RUN apk update && \
apk add curl \
php7 \
php7-opcache \
php7-openssl \
php7-pdo \
php7-json \
php7-phar \
php7-dom \
php7-curl \
php7-mbstring \
php7-tokenizer \
php7-xml \
php7-xmlwriter \
php7-session \
php7-ctype \
php7-mysqli \
php7-pdo \
php7-pdo_mysql\
&& rm -rf /var/cache/apk/*
RUN curl -sS https://getcomposer.org/installer | php -- \
--install-dir=/usr/bin --filename=composer
RUN cd $APP_DIR && composer install
WORKDIR $APP_DIR
RUN chmod -R 775 storage
RUN chmod -R 775 bootstrap
#CMD php artisan migrate:fresh
CMD php artisan serve --host=0.0.0.0 --port=$APP_PORT
Tried adding to the Dockerfile as is commented but didn't solve the problem
Tried adding on docker-compose as command: php artisan migrate:fresh too
Previously was doing this in jenkins to make it work Now dont want it via jenkins
docker-compose up -d --force-recreate --build
#Running commands on already running service
docker-compose exec -T app php artisan migrate:fresh --seed --force
This is how I solved it .Created a bash script called run.sh and added the php artisan migrations commands followed by the php serve command.
run.sh
#!/bin/sh
cd /app
php artisan migrate:fresh --seed
php artisan serve --host=0.0.0.0 --port=$APP_PORT
Added entrypoint to the Dockerfile removing the CMD in the end which will run the commands desired.
copy ./run.sh /tmp
ENTRYPOINT ["/tmp/run.sh"]
Remove the command from the docker-compose.yml
To my opinion, automate migrate is not a good way when creating container. You can do this after container is up with this one line code manually;
docker exec your_container_name php artisan migrate
Yes, special script.
I try to build deploy and testing throw docker-compose, so i run migrations in script before starting supervisor in docker-service "jobs":
#!/bin/sh
cd /var/www
php artisan migrate --seed
/usr/bin/supervisord -n -c /etc/supervisord.conf
And piece from my deploy-docker-compose.yml:
services:
nginx:
depends_on:
- phpfpm ## NOT START BEFORE PHPFPM
phpfpm:
depends_on:
- jobs ## NOT START BEFORE MIGRATION
jobs:
# ....
This schema is not started in production yet;
UPD1
i had to create simple laravel command wait_db_alive:
public function handle()
{
$i = 1;
$ret = 1;
while($i <= 10){
echo 'connecting to host:'.config('database.connections.'.config('database.default').'.host').' try '.$i.'..';
try {
DB::connection()->getPdo();
echo 'ok'.PHP_EOL;
$ret = 0;
break;
} catch (\Exception $e) {
echo 'error:' . $e->getMessage() .PHP_EOL;
sleep(1);
$i++;
}
}
return $ret;
}
and edit init.sh to
#!/bin/sh
php artisan wait_db_alive && php artisan migrate --seed && /usr/bin/supervisord -n -c /etc/supervisord.conf
so, log for jobs:
jobs_1 | connecting to host:db try 1..error:SQLSTATE[HY000] [2002] Connection refused
jobs_1 | connecting to host:db try 2..error:SQLSTATE[HY000] [2002] Connection refused
jobs_1 | connecting to host:db try 3..ok
jobs_1 | Nothing to migrate.
jobs_1 | Seeding: ServicesTableSeeder
...
jobs_1 | Database seeding completed successfully.
jobs_1 | 2020-11-22 05:33:43,653 CRIT Supervisor is running as root.
UPD2
In some cases we need to start container without .env-file, then better init.sh for this:
#!/bin/sh
php artisan wait_db_alive && php artisan migrate --seed
/usr/bin/supervisord -n -c /etc/supervisord.conf
One quick way is to create temporary route to run migration.
Route::get('/migrate', function () {
\Artisan::call('migrate');
return \Artisan::output();
});
To run all migrate you need to be inside your container, for that you need to run your containers with docker-compose up, here u need to be with terminal in the directory where your docker-compose.yml file is.
after that, and with the same place of docker-compose.yml file, run this command to be inside your container:
docker exec -it name_of_container bash
and when you will be inside your container, go to your shared app inside the container, I think here is the app so cd app.
after all of this run:
php artisan migrate

Supervise queue in laravel 5.1

I an using laravel 5.1 and Redis database for the queue. I want to supervise the queue:listen command Application is hosted in AWS.
For the installation I have used following command
sudo su - //it would be root user
easy_install supervisor
echo_supervisord_conf
echo_supervisord_conf > /etc/supervisord.conf
cd /etc
sudo vim supervisord.conf
Add the following line at the bottom
[program:queue]
command=/usr/bin/php /var/www/html/artisan --env="production" --timeout 240 queue:listen
and then
supervisord -c /etc/supervisord.conf
supervisorctl status
It generates the following log
sudo su - //it would be root user
easy_install supervisor
echo_supervisord_conf
echo_supervisord_conf > /etc/supervisord.conf
sudo vim /etc/supervisord.conf
Add the following code at the end of the file supervisord.conf
[program:queue]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work sqs --sleep=3 --tries=3 --daemon
autostart=true
autorestart=true
user=forge
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/supervisord.log
Run following command to start
supervisord -c /etc/supervisord.conf //To start
supervisorctl status

Categories