Laravel Docker "Unable to create a directory at /var/www/storage/app/documents" - laravel

I use Laravel 9 with Docker if I want to upload images like this:
$document["file_object"]->store('documents')
I get the following error: Unable to create a directory at /var/www/storage/app/documents
It looks like it ist some kind of Docker permission error.
I use the local Filesystems Disk because none of my files should be public.
If I change the 'root' => storage_path('app') to 'root' => storage_path('') inside the filesystems config I don't get any error but the files are saved in here: /storage/documents but they should be in /storage/app/documents.
I think I need to modify some docker user permission, but im unsure how as I'm not the one who made the config an my docker skills are limited.
Dockerfile:
FROM php:8.1-apache
WORKDIR /var/www
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg-dev \
libpng-dev \
libwebp-dev \
--no-install-recommends \
&& docker-php-ext-enable opcache \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install pdo_mysql -j$(nproc) gd \
&& apt-get autoclean -y \
&& rm -rf /var/lib/apt/lists/*
RUN pecl install redis && docker-php-ext-enable redis
# Update apache conf to point to application public directory
ENV APACHE_DOCUMENT_ROOT=/var/www/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
# Update uploads config
RUN echo "file_uploads = On\n" \
"memory_limit = 1024M\n" \
"upload_max_filesize = 512M\n" \
"post_max_size = 512M\n" \
"max_execution_time = 1200\n" \
> /usr/local/etc/php/conf.d/uploads.ini
# Enable headers module
RUN a2enmod rewrite headers
ADD . /var/www
RUN chown -R www-data:www-data /var/www
docker-compose.yml:
# https://waihein.medium.com/configuring-redis-on-docker-in-laravel-58a39556ff97
# https://medium.com/#chewysalmon/laravel-docker-development-setup-an-updated-guide-72842dfe8bdf
# https://shouts.dev/articles/dockerize-a-laravel-app-with-apache-mariadb
# FIRST Start:
# 1. Run ON WINDOWS: docker run --rm -v ${pwd}:/app composer install
# or on UNIX: docker run --rm -v “$(pwd)”:/app composer install
# 2. Run: npm run setup
# npm run setup is doing: "docker-compose up -d --build && docker-compose exec app php artisan key:generate && docker-compose exec app php artisan migrate:fresh --seed && npm install && npm run dev"
# NORMAL Start: npm start
# npm start is doing: "docker-compose up -d && npm install && npm run dev"
# To stop: docker-compose down
version: '3.8'
services:
# Application & web server
app:
build:
context: .
working_dir: /var/www
container_name: immo-app
volumes:
- ./:/var/www
depends_on:
- "database"
ports:
- 80:80
networks:
- immonet
# Database
database:
image: 'mariadb:latest'
container_name: immo-database
restart: unless-stopped
expose:
- 3306
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_USER: ${DB_USERNAME}
volumes:
- dbdata:/var/lib/mysql
networks:
- immonet
# Database management
pma:
image: phpmyadmin:5.1
container_name: immo-phpmyadmin
environment:
- PMA_ARBITRARY=1
- PMA_HOST=${DB_HOST}
- PMA_USER=${DB_USERNAME}
- PMA_PASSWORD=${DB_PASSWORD}
- PMA_PORT=${DB_PORT}
depends_on:
- database
ports:
- 8888:80
networks:
- immonet
# Redis
redis:
image: redis:alpine
container_name: immo-redis
volumes:
- ./data/redis:/data
expose:
- 6379
networks:
- immonet
volumes:
dbdata:
networks:
immonet:
driver: bridge

You should not be using www-data as the owner and group of your /var/www folder. It should be your nomal user (possibly WSL user?). If the docker container does not work without www-data, then you need to refactor it a bit, but the issue is arround the permissions.
Just try having your normal user as the owner and group of /var/www

Related

docker compose and swarm for laravel app in production

everyone, I am confused I am new to the DevOps world and I have no idea how to use docker-compose or swarm in production I mean what are the best practices in production for both I followed up with this article on the digital ocean How To Install and Set Up Laravel with Docker Compose on Ubuntu 20.04
all works like a charm in local, test, and dev environments, and I tried to take this to the next step for production env, and I noticed some things should be changed for production mode like so
Removing any volume bindings for application code, so that code stays inside the container and can’t be changed from outside.
Binding to different ports on the host. check the link for more info use compose in production
I don't know how to achieve #1 point
here's my DockerFile below to build my custom laravel image and docker-compose for my services
FROM php:7.4-fpm
# Arguments defined in docker-compose.yml
ARG user
ARG uid
# Install system dependencies
RUN apt-get update && apt-get install -y \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Download php extension installer
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
# Give php extension installer a permission
RUN chmod +x /usr/local/bin/install-php-extensions
# Install php extensions via php extension installer
RUN install-php-extensions zip
# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Create system user to run Composer and Artisan Commands
RUN useradd -G www-data,root -u $uid -d /home/$user $user
RUN mkdir -p /home/$user/.composer && \
chown -R $user:$user /home/$user
# Set working directory
WORKDIR /var/www/html
USER $user
version: "3.7"
services:
app:
build:
args:
user: sammy
uid: 1000
context: ./
dockerfile: Dockerfile
image: app
container_name: app
restart: always
working_dir: /var/www/html
volumes:
- ./:/var/www/html
networks:
- backend
db:
image: mysql:8.0
container_name: db
restart: always
environment:
MYSQL_DATABASE: ROUTE
MYSQL_ROOT_PASSWORD: 2020
MYSQL_PASSWORD: 2020
MYSQL_USER: sqluser
volumes:
- db:/var/lib/mysql
networks:
- backend
nginx:
image: nginx:1.21.6
container_name: nginx
restart: always
ports:
- 8000:80
networks:
- backend
volumes:
- ./:/var/www/html
- ./docker-compose/nginx:/etc/nginx/conf.d/
phpmyadmin:
image: phpmyadmin
container_name: pma
restart: always
ports:
- 8283:80
environment:
PMA_HOSTS: db
PMA_ARBITRARY: 1
PMA_USER: sqluser
PMA_PASSWORD: 2020
networks:
- backend
networks:
backend:
driver: bridge
volumes:
db:
Note:-
in Nginx service, I Created two shared volumes. The first one will synchronize contents from the current directory to /var/www inside the container. This way, when you make local changes to the application files, they will be quickly reflected in the application being served by Nginx inside the container (Which is not good for production). The second volume will make sure our Nginx configuration file, located at docker-compose/nginx/, is copied to the container’s Nginx configuration folder.
i tried to remove the first volume but keep the second one to use my custom configuration but it did not work at all why?

Docker build with laravel - SQLSTATE[HY000] [2002]

I'm getting error with my docker image after building the docker containers.
on docker-compose up -d command, the application is connected to a database.
but when I tried to run docker build -t to make an image
and run it, I got 500 internal error php_network_getaddresses: getaddrinfo failed:
FROM webdevops/php-nginx:7.4-alpine
WORKDIR /app
# Install Laravel framework system requirements (https://laravel.com/docs/8.x/deployment#optimizing-configuration-loading)
RUN apk add oniguruma-dev postgresql-dev libxml2-dev
RUN docker-php-ext-install \
bcmath \
ctype \
fileinfo \
json \
mbstring \
pdo_mysql \
pdo_pgsql \
tokenizer \
xml
# Copy Composer binary from the Composer official Docker image
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
ENV WEB_DOCUMENT_ROOT /app/public
ENV APP_ENV production
# Copy existing application directory contents to the working directory
COPY . .
RUN composer install
RUN composer install --no-interaction --optimize-autoloader --no-dev
# Optimizing Configuration loading
RUN php artisan config:clear
# Optimizing Route loading
RUN php artisan cache:clear
RUN php artisan view:cache
RUN chown -R application:application .
for additional details here is my docker-compose.yml
version: "3.8"
services:
#php service
php:
build:
context: .
dockerfile: Dockerfile
container_name: dtltrcy_phpv1
volumes:
- .:/var/www/html
- ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
networks:
- laravel
#nginx service web server
nginx:
image: nginx:stable-alpine
container_name: dtltrcy_nginxv1
ports:
- "8080:80"
volumes:
- .:/var/www/html
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
- mysql
networks:
- dataliteracyapp
#mysql service
mysql:
image: mysql:8.0.21
container_name: dtltrcy_mysqlv1
restart: unless-stopped
tty: true
ports:
- "3306:3306"
volumes:
- ./mysql:/var/lib/mysql
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
environment:
MYSQL_DATABASE: database
MYSQL_USER: ${DB_USERNAME}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_ROOT_HOST: '%'
SERVICE_TAGS: dev
SERVICE_NAME: mysql
networks:
- laravel
phpmyadmin:
image: phpmyadmin/phpmyadmin
restart: always
container_name: dtltrcy_phpmyadminv1
depends_on:
- mysql
ports:
- "8081:80"
environment:
PMA_HOST: mysql
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
networks:
- laravel
#docker networks
networks:
laravel:
.env
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=database
DB_USERNAME=root
DB_PASSWORD=secret
I tried to change .env file with these.
DB_HOST=127.0.0.1 ERROR -> SQLSTATE[HY000] [2002] Connection refused
DB_HOST=localhost ERROR -> SQLSTATE[HY000] [2002] No such file or directory
DB_HOST=172.19.0.3 ERROR -> SQLSTATE[HY000] [2002] Operation time out
Container IP using docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_id
I was facing a similar issue, this is my Dockerfile and it works fine.
FROM php:8-apache
WORKDIR /var/www/html
# install the necessary packages
RUN apt-get update -y && apt-get install -y \
curl \
nano \
npm \
g++ \
git \
zip \
vim \
sudo \
unzip \
nodejs \
libpq-dev \
libicu-dev \
libbz2-dev \
libzip-dev \
libpng-dev \
libjpeg-dev \
libmcrypt-dev \
libreadline-dev \
libfreetype6-dev \
&& docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \
&& docker-php-ext-install pdo pdo_pgsql pgsql \
&& docker-php-ext-install mysqli pdo_mysql \
&& docker-php-ext-enable mysqli
RUN docker-php-ext-install \
zip \
bz2 \
intl \
iconv \
bcmath \
opcache \
calendar
# copy the config file over
#COPY /server/apache/ports.conf /etc/apache2/ports.conf
COPY /server/apache/vhost.conf /etc/apache2/sites-available/laravel.conf
#COPY 000-default.conf /etc/apache2/sites-enabled/000-default.conf
#COPY 000-default.conf /etc/apache2/sites-available/000-default.conf
# install composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# use custom configuration and disable built-in one
#RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
RUN a2enmod rewrite
RUN a2ensite laravel.conf
RUN a2dissite 000-default.conf
# copy over the project files
COPY . /var/www/html
# change ownership of the files
RUN chown -R www-data:www-data /var/www
RUN cd /var/www/html && npm instal && composer install && php artisan optimize
CMD ["/var/www/html/scripts/start-apache.sh"]
/scripts/start-apache.sh
#!/usr/bin/env bash
sed -i "s/Listen 80/Listen ${PORT:-80}/g" /etc/apache2/ports.conf
sed -i "s/:80/:${PORT:-80}/g" /etc/apache2/sites-enabled/*
apache2-foreground "$#"
/server/apache/vhost.conf (not relevant for your issue though, it is for changing the document root)
<VirtualHost *:80>
DocumentRoot /var/www/html/public
<Directory "/var/www/html/public">
DirectoryIndex index.php
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
docker-compose.yml
version: "2"
services:
laravel-app:
build:
context: '.'
dockerfile: Dockerfile
environment:
- MYSQL_DATABASE=routes-db
- MYSQL_ALLOW_EMPTY_PASSWORD=1
- MYSQL_PASSWORD=""
container_name: laravel-app
volumes:
- ./:/var/www/html
ports:
- "8000:80"
networks:
- laravel-app-network
depends_on:
- db
db:
image: mysql:5.7
ports:
- "3306:3306"
environment:
- MYSQL_DATABASE=routes-db
- MYSQL_ALLOW_EMPTY_PASSWORD=1
- MYSQL_PASSWORD=""
volumes:
- "./db:/var/lib/mysql"
networks:
- laravel-app-network
networks:
laravel-app-network:
driver: bridge
volumes:
mysql_data:
driver: local
If I remember correctly, it was either something to do with either the packages/libraries or permissions. Check the line:
RUN chown -R www-data:www-data /var/www
It makes sure you got the right permissions.
Sorry that I couldn't give more details.

Docker container called in Laravel

How do I call a docker container within Laravel? I am using the following package to download PDFs https://packagist.org/packages/spatie/browsershot, I have an npm container which I am trying to use with this package.
My site container doesn't have node or npm installed which is why I need to use my npm container instead.
Here is my docker file
version: '3'
networks:
laravel:
services:
site:
build:
context: .
dockerfile: docker/nginx/Dockerfile
container_name: nginx
ports:
- 80:80
volumes:
- ./src:/var/www/html:delegated
depends_on:
- php
- mysql
networks:
- laravel
mysql:
image: mysql:5.7.29
container_name: mysql
restart: unless-stopped
tty: true
ports:
- 3306:3306
environment:
MYSQL_DATABASE: odc
MYSQL_USER: admin
MYSQL_PASSWORD: ".d3aP/7N,c)&^EdC"
MYSQL_ROOT_PASSWORD: "%3h_Ssxm7sSj#bw!"
SERVICE_TAGS: dev
SERVICE_NAME: mysql
networks:
- laravel
php:
build:
context: .
dockerfile: docker/php/Dockerfile
container_name: php
volumes:
- ./src:/var/www/html:delegated
networks:
- laravel
composer:
build:
context: .
dockerfile: docker/composer/Dockerfile
container_name: composer
volumes:
- ./src:/var/www/html
working_dir: /var/www/html
depends_on:
- php
user: laravel
entrypoint: ['composer', '--ignore-platform-reqs']
networks:
- laravel
npm:
image: node:13.7
container_name: npm
volumes:
- ./src:/var/www/html
working_dir: /var/www/html
entrypoint: ['npm']
networks:
- laravel
chrome:
image: zenika/alpine-chrome:latest
container_name: headless-chrome
networks:
- laravel
command: [chromium-browser, "--headless", "--disable-gpu", "--no-sandbox", "--remote-debugging-address=0.0.0.0", "--remote-debugging-port=9222"]
Here is the code I am trying to use with Browsershot to point to my npm container
Browsershot::html($html)
->setIncludePath('npm')
->setNodeModulePath("npm")
->setChromePath('chrome')
->noSandbox()
->showBackground()
->format('A4')
->savePdf($path . '/portrait.pdf');
As you can see I am using the ->setIncludePath('npm') to try and call my npm container but I am still receiving this error when I try and run this code
sh: npm: not found sh: node: not found
You dont need a seperate Node / NPM Container. The Browsershot is part of your applications core. To make it work you need nodejs and npm. That saying I would construct my own container image incuding PHP and Node. That makes the implementation of Browershot more simple.
If neede you can split them up later. But in that case I would create a new BrowserShot service (PHP + Node).
As you can see, there are multiple ways doing it.
What about using NGINX Unit for your applications container base? You could use the Unit PHP base image and add node on top of it.
I did that here:
https://github.com/nginx/unit-examples/blob/master/Dockerfile
FROM nginx/unit:1.22.0-php7.3
RUN mkdir /var/apphome/ && groupadd -r appuser && useradd --no-log-init -r -g appuser appuser && \
chown -R appuser:appuser /var/apphome/ && \
apt-get update && apt-get install --no-install-recommends --no-install-suggests -y gnupg && \
curl -sL https://nginx.org/keys/nginx_signing.key | apt-key add - && \
echo "deb https://packages.nginx.org/unit/debian/ buster unit" >> /etc/apt/sources.list.d/unit.list && \
echo "deb-src https://packages.nginx.org/unit/debian/ buster unit" >> /etc/apt/sources.list.d/unit.list && \
apt update && apt install -y unit-dev npm php7.3-mysql php7.3-gd && \
npm install -g --unsafe-perm unit-http -y
COPY src/ /var/apphome/app/
RUN chown -R appuser:appuser /var/apphome/
COPY .unit.conf.json /docker-entrypoint.d/.unit.conf.json
CMD ["unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock"]
Note! This is a demo purpose. You can adapt it for your production needs!

Why is my Docker volume only sharing the docker-compose file?

I am trying to containerize a Laravel application using Docker Compose, but I am failing to use a shared volume to bring in my actual project app files. My docker-compose file looks like this:
version: "3.7"
services:
app:
build:
args:
user: sam
uid: 1000
context: ./
dockerfile: Dockerfile
image: converter
container_name: converter-app
restart: unless-stopped
working_dir: /var/www/
volumes:
- ./:/var/www
networks:
- converter
db:
image: mysql:5.7
container_name: converter-db
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_USER: ${DB_USERNAME}
SERVICE_TAGS: dev
SERVICE_NAME: mysql
volumes:
- ./docker-compose/mysql:/docker-entrypoint-initdb.d
networks:
- converter
nginx:
image: nginx:alpine
container_name: converter-nginx
restart: unless-stopped
ports:
- 8000:80
volumes:
- ./:/var/www
- ./docker-compose/nginx:/etc/nginx/conf.d/
networks:
- converter
networks:
converter:
driver: bridge
volumes:
app-volume:
and the Dockerfile for the app service:
FROM php:7.4-fpm
# Arguments defined in docker-compose.yml
ARG user
ARG uid
# Install system dependencies
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Get latest Composer
#RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Create system user to run Composer and Artisan Commands
RUN useradd -G www-data,root -u $uid -d /home/$user $user
RUN mkdir -p /home/$user/.composer && \
chown -R $user:$user /home/$user
# Set working directory
WORKDIR /var/www
USER $user
I then run docker-compose build app and docker-compose up -d to create the containers, which brings them up. When I go to check the /var/www folder of the app container using docker-compose exec app ls -l, the only file that shows is the docker-compose file:
Shouldn't the shared volume specified for the app service share my working directory in the app /var/www folder?
You need to add these config options to the app service in compose file:
links:
- nginx
depends_on:
- nginx
These options forces docker-compose to create 1st the nginx service, and after the app, this is neccessary becuse currently nginx is created after app, and nging overwrite the /var/www directory

Laravel Not Found, Docker, Apache2

I am traying to connect to my container but I am getting the following error. Before my container works without problems. I made a new build but it doesn’t work.
My Docker file is the following:
FROM php:7.2-apache
LABEL maintainer="christianahvilla#gmail.com"
# Install PHP
RUN apt-get update && apt-get install -y \
curl \
zlib1g-dev \
libzip-dev \
nano
# Add and Enable PHP-PDO Extenstions
RUN docker-php-ext-install mysqli pdo pdo_mysql
RUN docker-php-ext-enable pdo_mysql
RUN docker-php-ext-install zip
# # Install PHP Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
#set our application folder as an environment variable
ENV APP_HOME /var/www/html
#change uid and gid of apache to docker user uid/gid
RUN usermod -u 1000 www-data && groupmod -g 1000 www-data
COPY --chown=www-data:www-data . $APP_HOME
#Expose Port 8000 since this is our dev environment
EXPOSE 8000
My Docker-Compose:
version: "3.7"
services:
#Laravel App
web:
build:
context: .
dockerfile: Dockerfile
ports:
- 8000:80
volumes:
- ./:/var/www
- ./public:/var/www/html
networks:
- mynet
depends_on:
- db
#MySQL Service
db:
image: mysql:5.7
container_name: db
ports:
- 3306:3306
environment:
MYSQL_DATABASE:
MYSQL_USER:
MYSQL_PASSWORD:
MYSQL_ROOT_PASSWORD:
volumes:
- mysqldata:/var/lib/mysql/
networks:
- mynet
#Docker Networks
networks:
mynet:
driver: bridge
#Volumes
volumes:
mysqldata:
driver: local
When I try to access to http:localhost:8000/ I can do it but if I try to access to another route I get the error.
You have to configure the apache2.conf in /etc/apache2/apache2.conf from Dockerfile, and also a2endmode rewrite, finally you need to restart apache2:
RUN sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf
RUN a2enmod rewrite
RUN service apache2 restart
Then run docker-compose build and docker-compose up -d

Resources