It's true there are a lot of Laravel/PHP docker tutorials, but after days of search I coudn't find a complete, clean and automatic way of dockerizing it with no other touch, just ready to use.
This means for me:
- create the required containers
- create .env file from .env.example
- create the database (which is the same from .env file)
- set folders permission
- install the php dependencies
- generate the app key
- migrate
- seed
I came into this step working with other developer on a certain project that they don't know and they don't wanna know PHP/Laravel, but they want it ready to use and since I`m not a docker guru, I need to implement this and having it ready to use right after they clone my repo and use docker-compose up.
I have successfully setup the my docker services using the following services:
- mariaDB
- nginx
- php/laravel app
but the missing piece is the automatisation and most probably some improvements.
So, assuming we`re working with latest Laravel 8 fresh install, I have the following files:
Dockerfile
FROM php:7.4-fpm
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 pdo_mysql mbstring exif pcntl bcmath gd
# Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Set working directory
WORKDIR /var/www/my-project
COPY ./docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
docker-compose.yml
version: '3'
services:
nginx:
image: nginx:stable-alpine
container_name: nginx
ports:
- "80:80"
volumes:
- '.:/var/www/my-project'
- './docker/nginx/default.conf:/etc/nginx/conf.d/default.conf'
depends_on:
- db
- app
db:
container_name: db
image: mariadb:10.3.23
ports:
- '3306:3306'
environment:
MYSQL_DATABASE: my_db
MYSQL_USER: someuser
MYSQL_PASSWORD: somepw
MYSQL_ROOT_PASSWORD: somepw
volumes:
- ./docker/dump:/docker-entrypoint-initdb.d
app:
build: .
container_name: app
volumes:
- '.:/var/www/my-project'
depends_on:
- db
ports:
- '9000:9000'
docker/dump/database.sql
CREATE DATABASE IF NOT EXISTS my_db;
GRANT ALL PRIVILEGES ON my_db.* TO 'someuser' identified by 'somepw';
docker/nginx/default.conf
server {
listen 80;
index index.php index.html;
server_name localhost;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/my-project/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
.env.example
...
APP_KEY=
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=my_db
DB_USERNAME=someuser
DB_PASSWORD=somepw
...
entrypoint.sh
#!/usr/bin/env sh
composer install
mv .env.example .env
php artisan key:generaate
php artisan migrate
php artisan db:seed
...
#is it ok to pun npm i && npm run dev here ?
As can be seen, for creating the database, I tried to create an entrypoint which should run before app and finally run another app entrypoint where I should handle the other commands.
Using these setup, the app (php) container acts like a proxy. Is it really necessary ?
In the end, I get an SQLSTATE[HY000] [2002] Connection refused error.
How can I achieve this overall automatisation in a easier, cleaner and better way ?