Laravel complete docker automatisation

Viewed 463

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 ?

0 Answers
Related