Skip to content

julianoaj/docker-php-laravel-nginx-mysql

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

"I decided to follow the path of rabbit hole, let's see how far this can take us" - AJ

Sharing, learning and knowing people all around the world. Let's code!


Docker: Nginx, PHP (Laravel) and MySql.

With Docker Compose I'm running three containers, each one with: Nginx, PHP (with composer, xdebug and configs) and MySql.

The purpose of this guide is to give some reference and help, don't feel tied to the same configs.

Overview

  1. Install prerequisites

  2. Before doing anything install all prerequisites.

  3. Clone the project [optional]

  4. A simple and a fast way to get this environment.

  5. Docker used commands.

  6. Commands that maybe you will need use to build this environment.

  7. Directories Tree

  8. Where your projects, backup and configs will be.

  9. Makefile [optional]

  10. Automating your environment with a makefile.

  11. Setting php.dockerfile

  12. Installing xdebug, compose, libs and setting configs.

  13. Setting Nginx With SSL Certificates. [optional]

  14. Setting PHP-FPM for Nginx, generating our SSL certificate and setting it on our server.

  15. docker-compose.yml

  16. Building our images in containers.

  17. Running and testing our project.


Install prerequisites

This environment was created on windows but all docker things will work on any SO. Just follow install instructions on documentation:

Check if all dependencies is installed by entering the following command's in your terminal:

docker-compose 
docker -v
[docker-compose] will print all docker-compose commands and [docker -v] will print docker version.

Optional tools:

  • Git
  • Make (Chocolatey)

    choco install make

  • Make (Ubuntu)

    sudo apt-get -y install make

Clone the project

A simple and a fast way to you get this environment is to clone my project into a directory, open your terminal, navigate into project cloned directory and write some commands:

docker-compose build
docker-compose up -d

Check localhost in your browser and voilá

Ports used on the project:

  • http -> 80
  • https -> 443
  • php -> 9000
  • mysql -> 3306


Docker commands

Docker have a nice documentation (in my opinion) with all their commands, if what you want is not here, check the link.

Nginx restart server:

  docker exec [CONTAINER] nginx -s reload

Installing a package with composer:

  docker run --rm -v $(pwd)/web/app:/app composer create-project laravel/laravel example-app

Updating PHP dependencies with composer :

  docker run --rm -v $(pwd)/web/app:/app composer update

Checking installed PHP extensions :

  docker-compose exec php php -m

Get in of PHP interactive terminal :

  docker-compose exec php php -a

MySQL shell access :

  docker exec -it mysql bash
  mysql -u"$MYSQL_ROOT_USER" -p"$MYSQL_ROOT_PASSWORD"

Directories Tree

Before we start to configure our environment we need a directories tree. Here you can choose where your projects, backup's, servers and configs will be.

My project tree:

\---environmentProject
    |   docker-compose.yml
    |   Makefile
    |   nginx.dockerfile
    |   php.dockerfile
    |   README.md
    |
    +---confs
    |   +---Mysql_db
    |   |       backup.ibd
    |   |
    |   +---servers
    |   |       server.conf
    |   |
    |   \---ssl
    |           localhost.crt
    |           localhost.key
    |
    \---projects
        \---www
                index.php

Makefile

Instead of typing complexes commands in your terminal, you can use a Makefile to simplifying.

Prerequisite to use a Makefile is to install [make] command.

With [make] installed, I don't recommend, but you can clone my repository and use my Makefile with some already defined shortcut commands. If you're going to use it, make sure that your containers are named with the same name as mine and remember, I'm using windows and some commands maybe will not work on another SO.

Command Description
reload-nginx Restart Nginx web server
it-php Interactive mode on php image
start-ubuntu Start a ubuntu:latest image and remove when works done
gen-ssl Gen Certificate authority (CA) for your browser and webserver
start-laravel Install laravel project via composer

Show help:

make help
Pre requisite of this section: make, clone my project and Windows 10 user.

Setting php.dockerfile

Its time to we build our PHP container with xdebug, composer and configs inside a Dockerfile. Create the file inside follow path: /environmentProject/php.dockerfile

Inside the file we'll set our PHP 8.2 FPM version. To use it we need a tag that we can find on dockerhub. With tag in hands, our first line should be:

FROM php:8.2-fpm
Versions tag list here.

Core Extensions:

Following the version we need to install our core extensions:

RUN apt-get update && apt-get install -y \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libpng-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) gd \
    && docker-php-ext-install mysqli pdo pdo_mysql && docker-php-ext-enable pdo_mysql
Some extensions come by default. It depends on the PHP version you are using. Run docker run --rm php:8.2-fpm php -m in the your terminar to see full extension list.

PECL extensions:

Its time to bring some extensions for performance and utility, to it we'll use PECL, a PHP extension repository.
Here we'll install xdebug, libmencached and zlib1g. Lets add some more lines in our dockerfile:

RUN pecl install xdebug-3.0.4 \
    && docker-php-ext-enable xdebug
RUN apt-get install -y libmemcached-dev zlib1g-dev \
    && pecl install memcached-3.1.5 \
    && docker-php-ext-enable memcached
PECL extensions should be installed in series to fail properly if something went wrong. Otherwise errors are just skipped by PECL.

Packages:

For packages we'll use composer with zip and unzip:

RUN apt-get install zip unzip \
    && curl -sS https://getcomposer.org/installer -o composer-setup.php \
    && php composer-setup.php --install-dir=/usr/local/bin --filename=composer \
    && unlink composer-setup.php

Configs (utils):

Setting our timezone and activating opcache for performance of PHP:

RUN echo 'date.timezone="America/Sao_Paulo"' >> /usr/local/etc/php/conf.d/date.ini \
    && echo 'opcache.enable=1' >> /usr/local/etc/php/conf.d/opcache.conf \
    && echo 'opcache.validate_timestamps=1' >> /usr/local/etc/php/conf.d/opcache.conf \
    && echo 'opcache.fast_shutdown=1' >> /usr/local/etc/php/conf.d/opcache
You can check the list of timezone supported by PHP here.

Setting Nginx FastCGI with SSL Certificates for PHP and Laravel

If you want to use PHP and Laravel with Nginx you need to configure FastCGI and a few other things. Let's break it into steps:

  1. Gen SSL (optional)

    You can use my Makefile to gen a SSL with just make gen-ssl in terminal (in case of you are a windows user), or follow the steps of this GUIDE.

  2. Server server.conf

    Create /environmentProject/confs/servers/server.conf file.

Edit server.conf, set a config that listen container port 80 and 443 (ssl port), set ssl_certificate and ssl_certificate_key with your SSL certificates location and pass all FastCGI configs for PHP-FPM. Example:

  server {
    ############# Ports #################
    listen 80;
    # listen 443 ssl;
    #####################################
    root /var/www/projects/;
    ########## SSL CERTIFICATE ##########
    # ssl_certificate /var/www/ssl/localhost.crt;
    # ssl_certificate_key /var/www/ssl/localhost.key; 
##################################### autoindex on;
########## FAST CGI CONFIG ########## location ~ \.php$ { fastcgi_index index.php; fastcgi_pass php:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }

This should be enough to run your native PHP app. With Laravel your server.conf should be like:

server {
    listen 80;
    server_name example.com;
    root /var/www/projects/example-app/public; 
add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / { try_files $uri $uri/ /index.php?$query_string; }
location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ { fastcgi_index index.php; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }
location ~ /\.(?!well-known).* { deny all; } }
Check Laravel documentation for more details.

docker-compose.yml

It's time to bring all together using docker-compose.

I'll not get in details in this guide about versions, services, volumes, etc... but you can learn more in Docker Documentation.

Create /environmentProject/docker-compose.yml file, edit it and lets start!

Version:

The first line of our docker-compose.yml should be the version of docker-compose. Here we'll use the latest:

version: "3.9"

Services:

Following version line let's build our containers. We'll set 3 (or 4) containers: Nginx, PHP, MySql and Node(NPM) (optional). Let's break it into steps:

  1. Nginx

    With this volumes setup, all principal configs can be made within your environment without the need of get in the container.

        services: 
          web-server:
            image: nginx:1.21.1
            container_name: webdev-nginx
            ports:
              - "80:80"
              - "443:443"
            networks:
              - web-dev
            volumes:
              - ./confs/servers/:/etc/nginx/conf.d/
              - ./projects:/var/www/projects
              - ./confs/ssl/:/var/www/ssl
        
  2. PHP

    volumes of PHP image need to be in the same directory of your web-server projects.

        php:
          build:
            dockerfile: ./php.dockerfile
            context: .
          image: php:8.2-fpm
          container_name: webdev-php
          volumes: 
            - "./projects:/var/www/projects"
          ports: 
            - "9000:9000"
          networks: 
            - web-dev
        
  3. MySql

    Here I'm creating a database on start for tests in the end. You can change MYSQL_USER and MYSQL_PASSWORD if you want.

        db:
          image: mysql:8.0.26
          container_name: webdev-mysql
          volumes: 
            - ./confs/mysql_db:/var/lib/mysql
          command: --default-authentication-plugin=mysql_native_password
          environment:
            MYSQL_ROOT_PASSWORD: root
            MYSQL_DATABASE: test_db
            MYSQL_USER: devuser
            MYSQL_PASSWORD: devpass
          ports:
            - "3306:3306"
          networks: 
            - web-dev
        
  4. Node

    If you want a live container for just NPM you can follow this step.

    My recommendation is to use a Makefile for packages instead of making a live container for it. Using a Makefile you can create a command (like make npm) that will instance a container, let you use the interactive mode and when you done all your interaction with NPM on your project, you can leave and the container created will not exist anymore, this can provide you performance (taking into account that a container with Node has 900MB~1GB), but this will take a little bit more time than create a live container.

        node:
        image: node:lts
        container_name: webdev-node-npm
        volumes: 
          - "./projects:/var/www"
        ports: 
          - "9002:9002"
        networks: 
          - web-dev
        tty: true
      
  5. Network

    web-dev bring all containers together in a network.

          networks: 
            web-dev:
              driver: bridge
        

Running and testing our project.

With all set up let's bring our environment to life.

In /environmentProject/ directory, build all images with:

docker-compose build

When its over, let's run all containers with:

docker-composer up -d

Get in your localhost and voilá!

With all running, you can test your MySql connection navigating to localhost/index.php. If all is okay you will receive a successfully message.

For laravel test, you will need to edit /example-app/.env and set your connection with mysql. Example:

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=test_db
DB_USERNAME=devuser
DB_PASSWORD=devpass

Save and exec follow commands:

docker exec (container_id) composer dump-autoload
docker exec (container_id) php artisan migrate

If you don't receive any error message your connection is fine and you are ready to codding.

Contact-me

If you want help or send a feedback, get in my website and send me a e-mail:

About

A Docker environment with PHP, Nginx and MySql using a laravel project as example.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published