├── Dockerfile ├── LICENCE ├── README.md ├── commands ├── development │ ├── start-composer.sh │ └── start-npm.sh └── production │ ├── start-composer.sh │ └── start-npm.sh ├── development ├── mysql │ └── my.cnf ├── nginx │ └── conf.d │ │ └── app.conf └── php │ └── local.ini ├── docker-compose.production.yml ├── docker-compose.yml ├── production ├── mysql │ └── my.cnf ├── nginx │ └── conf.d │ │ └── app.conf └── php │ └── local.ini └── script.sh /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:8.0-fpm 2 | 3 | LABEL maintainer="Mohammad Rahmani " 4 | 5 | RUN apt-get update 6 | RUN apt install -y apt-utils 7 | 8 | # Install dependencies 9 | RUN apt-get install -qq -y \ 10 | curl \ 11 | git \ 12 | libzip-dev \ 13 | zlib1g-dev \ 14 | zip unzip 15 | 16 | RUN apt install -y libmcrypt-dev libicu-dev libxml2-dev 17 | RUN apt-get install -y libjpeg-dev libpng-dev libfreetype6-dev libjpeg62-turbo-dev 18 | RUN docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/ 19 | RUN docker-php-ext-install gd 20 | 21 | RUN apt install -y libmagickwand-dev --no-install-recommends && \ 22 | pecl install imagick && docker-php-ext-enable imagick 23 | 24 | # Clear cache 25 | RUN apt-get clean && rm -rf /var/lib/apt/lists/* 26 | 27 | # Install extensions 28 | RUN docker-php-ext-install \ 29 | bcmath \ 30 | pdo_mysql \ 31 | pcntl \ 32 | zip \ 33 | pdo \ 34 | ctype \ 35 | tokenizer \ 36 | fileinfo \ 37 | xml \ 38 | intl 39 | 40 | # Install composer 41 | RUN curl -sS https://getcomposer.org/installer | php -- \ 42 | --install-dir=/usr/local/bin --filename=composer && chmod +x /usr/local/bin/composer 43 | 44 | RUN rm /bin/sh && ln -s /bin/bash /bin/sh 45 | 46 | ENV NODE_VERSION=15.4.0 47 | 48 | RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash 49 | 50 | ENV NVM_DIR=/root/.nvm 51 | 52 | RUN . "$NVM_DIR/nvm.sh" && nvm install ${NODE_VERSION} 53 | RUN . "$NVM_DIR/nvm.sh" && nvm use v${NODE_VERSION} 54 | RUN . "$NVM_DIR/nvm.sh" && nvm alias default v${NODE_VERSION} 55 | ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin/:${PATH}" 56 | 57 | COPY . /var/www 58 | 59 | WORKDIR /var/www 60 | 61 | Run npm install 62 | 63 | RUN chown -R www-data:www-data /var/www 64 | RUN chmod -R 755 /var/www/storage 65 | 66 | CMD php-fpm 67 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Julien Guyomard 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker Images for Laravel Development 2 | 3 | This repository provides you a development environment without requiring you to install PHP, a web server, and any other server software on your local machine. For this, it requires Docker and Docker Compose. 4 | 5 | ## Installation 6 | 7 | 1. Install [docker](https://docs.docker.com/engine/installation/) and [docker-compose](https://docs.docker.com/compose/install/). 8 | 9 | 2. Copy `docker-compose.yml` file to your project root path, and edit it according to your needs. 10 | 11 | 3. From your project directory, start up your application by running: 12 | 13 | ```sh 14 | docker-compose up 15 | ``` 16 | 4. You can run `composer` or `npm` or `artisan` through docker. For instance: 17 | 18 | ```sh 19 | docker-compose exec app composer install 20 | docker-compose exec app php artisan migrate 21 | docker-compose exec npm $yourCommandHere 22 | ``` 23 | But I have already provided a `script.sh` command line tool that helps us run our commands easily: 24 | ```sh 25 | bash script.sh -a "migrate" # This command can run php artisan migrate 26 | bash script.sh -c "require 'package-name'" # Install composer package 27 | ``` 28 | ## Customize Docker Images 29 | 30 | These docker images are configured in `docker-compose.yml` file 31 | and also the production version is `docker-compose.production.yml`. 32 | 33 | If you're not using Vuejs with your Laravel application, you can simply comment the `npm` container. 34 | ``` 35 | npm: 36 | container_name: npm 37 | image: node:14.1.0-slim 38 | command: /bin/bash "/var/www/commands/development/start-npm.sh" 39 | volumes: 40 | - ./:/var/www 41 | networks: 42 | - application-network 43 | ``` 44 | ## MySQL Configuration 45 | This is a simple environment configuration I have provided in `docker-compose.yml` file: 46 | ``` 47 | environment: 48 | MYSQL_DATABASE: laravel 49 | MYSQL_ROOT_PASSWORD: password 50 | ``` 51 | But you can add more configurations to your MySQL by adding: 52 | ``` 53 | environment: 54 | MYSQL_DATABASE: 'laravel' 55 | MYSQL_USER: 'laravel-user' 56 | MYSQL_PASSWORD: 'laravel@123' 57 | MYSQL_ROOT_PASSWORD: 'root@123' 58 | ``` 59 | ## Deployment 60 | When you're ready to deploy your Laravel application to production, there are some important things you can do to make sure your application is running as efficiently as possible. 61 | Read [this doc](https://laravel.com/docs/7.x/deployment) to prepare your project. But I have provided the `nginx` configuration in two diffrent environments, `development` and `production`, and also I have enabled the caching server and gzip in `nginx`. 62 | ``` 63 | server { 64 | gzip on; 65 | gzip_vary on; 66 | gzip_proxied any; 67 | gzip_comp_level 6; 68 | gzip_buffers 16 8k; 69 | gzip_http_version 1.1; 70 | gzip_min_length 256; 71 | gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon; 72 | 73 | client_max_body_size 20M; 74 | listen 80; 75 | server_name server.dev; 76 | index index.php index.html; 77 | error_log /var/log/nginx/error.log; 78 | access_log /var/log/nginx/access.log; 79 | root /var/www/public; 80 | 81 | location ~ \.php$ { 82 | try_files $uri =404; 83 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 84 | 85 | # app is our php container 86 | fastcgi_pass app:9000; 87 | fastcgi_index index.php; 88 | include fastcgi_params; 89 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 90 | fastcgi_param PATH_INFO $fastcgi_path_info; 91 | } 92 | 93 | location / { 94 | try_files $uri $uri/ /index.php?$query_string; 95 | } 96 | 97 | # ---------------------------------------------------------------------- 98 | # Expire rules for static content 99 | # ---------------------------------------------------------------------- 100 | 101 | # cache.appcache, your document html and data 102 | location ~* \.(?:manifest|appcache|html?|xml|json)$ { 103 | expires -1; 104 | } 105 | 106 | # Feed 107 | location ~* \.(?:rss|atom)$ { 108 | expires 1h; 109 | add_header Cache-Control "public"; 110 | } 111 | 112 | # Media: images, icons, video, audio, HTC 113 | location ~* \.(?:jpg|jpeg|gif|png|cur|gz|svgz|mp4|ogg|ogv|webm|htc)$ { 114 | expires 1M; 115 | access_log off; 116 | add_header Cache-Control "public"; 117 | } 118 | 119 | # CSS and Javascript 120 | location ~* \.(?:css|js|ico|woff|eot|svg|ttf|otf)$ { 121 | expires 1y; 122 | access_log off; 123 | add_header Cache-Control "public"; 124 | } 125 | } 126 | ``` 127 | 128 | ## Contributing 129 | 130 | Contributions are very welcome! 131 | Leave an issue on Github, or create a Pull Request. 132 | 133 | ## Licence 134 | 135 | [MIT](LICENCE) licence. 136 | -------------------------------------------------------------------------------- /commands/development/start-composer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ---------------------------------------------------------------------- 4 | # Create the .env file if it does not exist. 5 | # ---------------------------------------------------------------------- 6 | 7 | if [[ ! -f "/app/.env" ]] && [[ -f "/app/.env.example" ]]; 8 | then 9 | cp /app/.env.example /app/.env 10 | fi 11 | 12 | # ---------------------------------------------------------------------- 13 | # Run Composer 14 | # ---------------------------------------------------------------------- 15 | 16 | if [[ ! -d "/app/vendor" ]]; 17 | then 18 | cd /app 19 | composer install 20 | composer dump-autoload -o 21 | fi 22 | -------------------------------------------------------------------------------- /commands/development/start-npm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ---------------------------------------------------------------------- 4 | # Move to project directory 5 | # ---------------------------------------------------------------------- 6 | cd /var/www 7 | 8 | # ---------------------------------------------------------------------- 9 | # Check is node_modules exist 10 | # ---------------------------------------------------------------------- 11 | if [[ ! -d "/var/www/node_modules" ]]; 12 | then 13 | echo "––––––––––––––––––––––––––––––––––––––––" 14 | echo "Installing package.json dependencies" 15 | echo "––––––––––––––––––––––––––––––––––––––––" 16 | npm install 17 | fi 18 | 19 | echo "––––––––––––––––––––––––––––––––––––––––" 20 | echo "Starting npm watch ..." 21 | echo "––––––––––––––––––––––––––––––––––––––––" 22 | npm run watch 23 | -------------------------------------------------------------------------------- /commands/production/start-composer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ---------------------------------------------------------------------- 4 | # Create the .env file if it does not exist. 5 | # ---------------------------------------------------------------------- 6 | 7 | if [[ ! -f "/app/.env" ]] && [[ -f "/app/.env.example" ]]; 8 | then 9 | cp /app/.env.example /app/.env 10 | fi 11 | 12 | # ---------------------------------------------------------------------- 13 | # Run Composer 14 | # ---------------------------------------------------------------------- 15 | 16 | if [[ ! -d "/app/vendor" ]]; 17 | then 18 | cd /app 19 | composer install 20 | composer dump-autoload -o 21 | fi 22 | -------------------------------------------------------------------------------- /commands/production/start-npm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ---------------------------------------------------------------------- 4 | # Move to project directory 5 | # ---------------------------------------------------------------------- 6 | cd /var/www 7 | 8 | # ---------------------------------------------------------------------- 9 | # Check is node_modules exist 10 | # ---------------------------------------------------------------------- 11 | if [[ ! -d "/var/www/node_modules" ]]; 12 | then 13 | echo "––––––––––––––––––––––––––––––––––––––––" 14 | echo "Installing package.json dependencies" 15 | echo "––––––––––––––––––––––––––––––––––––––––" 16 | npm install 17 | fi 18 | 19 | echo "––––––––––––––––––––––––––––––––––––––––" 20 | echo "Starting npm watch ..." 21 | echo "––––––––––––––––––––––––––––––––––––––––" 22 | npm run prod 23 | -------------------------------------------------------------------------------- /development/mysql/my.cnf: -------------------------------------------------------------------------------- 1 | [mysqld] 2 | general_log =1 3 | general_log_file =/var/lib/mysql/general.log 4 | secure-file-priv=NULL 5 | default_authentication_plugin=mysql_native_password 6 | -------------------------------------------------------------------------------- /development/nginx/conf.d/app.conf: -------------------------------------------------------------------------------- 1 | server { 2 | client_max_body_size 20M; 3 | listen 80; 4 | server_name server.dev; 5 | index index.php index.html; 6 | error_log /var/log/nginx/error.log; 7 | access_log /var/log/nginx/access.log; 8 | root /var/www/public; 9 | 10 | location ~ \.php$ { 11 | try_files $uri =404; 12 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 13 | 14 | # app is our php container 15 | fastcgi_pass app:9000; 16 | fastcgi_index index.php; 17 | include fastcgi_params; 18 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 19 | fastcgi_param PATH_INFO $fastcgi_path_info; 20 | } 21 | 22 | location / { 23 | try_files $uri $uri/ /index.php?$query_string; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /development/php/local.ini: -------------------------------------------------------------------------------- 1 | upload_max_filesize=40M 2 | post_max_size=40M 3 | -------------------------------------------------------------------------------- /docker-compose.production.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | app: 5 | container_name: app 6 | build: 7 | context: . 8 | dockerfile: Dockerfile 9 | volumes: 10 | - ./development/php/local.ini:/usr/local/etc/php/conf.d/local.ini 11 | networks: 12 | - application-network 13 | 14 | composer: 15 | container_name: composer 16 | image: composer 17 | command: /bin/bash "/app/commands/production/start-composer.sh" 18 | volumes: 19 | - ./:/app 20 | networks: 21 | - application-network 22 | 23 | npm: 24 | container_name: npm 25 | image: node:14.1.0-slim 26 | command: /bin/bash "/var/www/commands/production/start-npm.sh" 27 | volumes: 28 | - ./:/var/www 29 | networks: 30 | - application-network 31 | 32 | nginx: 33 | container_name: nginx 34 | image: nginx:alpine 35 | ports: 36 | - 80:80 37 | volumes: 38 | - ./:/var/www 39 | - ./production/nginx/conf.d/:/etc/nginx/conf.d/ 40 | networks: 41 | - application-network 42 | 43 | database: 44 | image: mysql:8.0 45 | container_name: database 46 | command: --default-authentication-plugin=mysql_native_password 47 | ports: 48 | - 3306:3306 49 | environment: 50 | MYSQL_DATABASE: laravel 51 | MYSQL_ROOT_PASSWORD: password 52 | volumes: 53 | - data:/var/lib/mysql 54 | - ./production/mysql/my.conf:/etc/mysql/my.conf 55 | networks: 56 | - application-network 57 | 58 | networks: 59 | application-network: 60 | driver: bridge 61 | 62 | volumes: 63 | data: 64 | driver: local 65 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | app: 5 | container_name: app 6 | build: 7 | context: . 8 | dockerfile: Dockerfile 9 | volumes: 10 | - ./:/var/www 11 | - ./development/php/local.ini:/usr/local/etc/php/conf.d/local.ini 12 | networks: 13 | - application-network 14 | 15 | composer: 16 | container_name: composer 17 | image: composer 18 | command: /bin/bash "/app/commands/development/start-composer.sh" 19 | volumes: 20 | - ./:/app 21 | networks: 22 | - application-network 23 | 24 | npm: 25 | container_name: npm 26 | image: node:14.1.0-slim 27 | command: /bin/bash "/var/www/commands/development/start-npm.sh" 28 | volumes: 29 | - ./:/var/www 30 | networks: 31 | - application-network 32 | 33 | nginx: 34 | container_name: nginx 35 | image: nginx:alpine 36 | ports: 37 | - 80:80 38 | volumes: 39 | - ./:/var/www 40 | - ./development/nginx/conf.d/:/etc/nginx/conf.d/ 41 | networks: 42 | - application-network 43 | 44 | database: 45 | image: mysql:8.0 46 | container_name: database 47 | command: --default-authentication-plugin=mysql_native_password 48 | ports: 49 | - 3306:3306 50 | environment: 51 | MYSQL_DATABASE: laravel 52 | MYSQL_ROOT_PASSWORD: password 53 | volumes: 54 | - data:/var/lib/mysql 55 | - ./development/mysql/my.conf:/etc/mysql/my.conf 56 | networks: 57 | - application-network 58 | 59 | networks: 60 | application-network: 61 | driver: bridge 62 | 63 | volumes: 64 | data: 65 | driver: local 66 | -------------------------------------------------------------------------------- /production/mysql/my.cnf: -------------------------------------------------------------------------------- 1 | [mysqld] 2 | general_log =1 3 | general_log_file =/var/lib/mysql/general.log 4 | secure-file-priv=NULL 5 | default_authentication_plugin=mysql_native_password 6 | -------------------------------------------------------------------------------- /production/nginx/conf.d/app.conf: -------------------------------------------------------------------------------- 1 | server { 2 | gzip on; 3 | gzip_vary on; 4 | gzip_proxied any; 5 | gzip_comp_level 6; 6 | gzip_buffers 16 8k; 7 | gzip_http_version 1.1; 8 | gzip_min_length 256; 9 | gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon; 10 | 11 | client_max_body_size 20M; 12 | listen 80; 13 | server_name server.dev; 14 | index index.php index.html; 15 | error_log /var/log/nginx/error.log; 16 | access_log /var/log/nginx/access.log; 17 | root /var/www/public; 18 | 19 | location ~ \.php$ { 20 | try_files $uri =404; 21 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 22 | 23 | # app is our php container 24 | fastcgi_pass app:9000; 25 | fastcgi_index index.php; 26 | include fastcgi_params; 27 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 28 | fastcgi_param PATH_INFO $fastcgi_path_info; 29 | } 30 | 31 | location / { 32 | try_files $uri $uri/ /index.php?$query_string; 33 | } 34 | 35 | # ---------------------------------------------------------------------- 36 | # Expire rules for static content 37 | # ---------------------------------------------------------------------- 38 | 39 | # cache.appcache, your document html and data 40 | location ~* \.(?:manifest|appcache|html?|xml|json)$ { 41 | expires -1; 42 | } 43 | 44 | # Feed 45 | location ~* \.(?:rss|atom)$ { 46 | expires 1h; 47 | add_header Cache-Control "public"; 48 | } 49 | 50 | # Media: images, icons, video, audio, HTC 51 | location ~* \.(?:jpg|jpeg|gif|png|cur|gz|svgz|mp4|ogg|ogv|webm|htc)$ { 52 | expires 1M; 53 | access_log off; 54 | add_header Cache-Control "public"; 55 | } 56 | 57 | # CSS and Javascript 58 | location ~* \.(?:css|js|ico|woff|eot|svg|ttf|otf)$ { 59 | expires 1y; 60 | access_log off; 61 | add_header Cache-Control "public"; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /production/php/local.ini: -------------------------------------------------------------------------------- 1 | upload_max_filesize=40M 2 | post_max_size=40M 3 | -------------------------------------------------------------------------------- /script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ---------------------------------------------------------------------- 4 | # Help function on commands. 5 | # ---------------------------------------------------------------------- 6 | helpFunction() 7 | { 8 | echo "" 9 | echo "Usage: $0" 10 | echo "" 11 | echo "Options: " 12 | echo " -c composer command" 13 | echo " -n npm command" 14 | echo " -a artisan command" 15 | echo "" 16 | echo "For example:" 17 | echo "If you want to run this command 'php artisan migrate' simply write this:" 18 | echo -e "\t -a migrate" 19 | exit 1 20 | } 21 | 22 | # ---------------------------------------------------------------------- 23 | # Run PHP artisan commands. 24 | # ---------------------------------------------------------------------- 25 | artisanCommands() 26 | { 27 | echo "Runnin php artisna $parameterA" 28 | docker exec app php artisan $parameterA 29 | exit 1 30 | } 31 | 32 | # ---------------------------------------------------------------------- 33 | # Run npm commands. 34 | # ---------------------------------------------------------------------- 35 | npmCommands() 36 | { 37 | echo "Runnin npm $parameterN" 38 | docker exec npm npm $parameterN 39 | exit 1 40 | } 41 | 42 | # ---------------------------------------------------------------------- 43 | # Run composer commands. 44 | # ---------------------------------------------------------------------- 45 | composerCommands() 46 | { 47 | echo "Runnin composer $parameterC" 48 | docker exec app composer $parameterC 49 | exit 1 50 | } 51 | 52 | while getopts "a:n:c:" opt 53 | do 54 | case "$opt" in 55 | a ) parameterA="$OPTARG" ;; 56 | n ) parameterN="$OPTARG" ;; 57 | c ) parameterC="$OPTARG" ;; 58 | ? ) helpFunction ;; # Print helpFunction in case parameter is non-existent 59 | esac 60 | done 61 | 62 | # ---------------------------------------------------------------------- 63 | # Check parameter a for artisan commands. 64 | # ---------------------------------------------------------------------- 65 | if [ "$parameterA" ] 66 | then 67 | artisanCommands 68 | fi 69 | 70 | # ---------------------------------------------------------------------- 71 | # Check parameter c for composer commands. 72 | # ---------------------------------------------------------------------- 73 | if [ "$parameterC" ] 74 | then 75 | composerCommands 76 | fi 77 | 78 | # ---------------------------------------------------------------------- 79 | # Check parameter n for npm commands. 80 | # ---------------------------------------------------------------------- 81 | if [ "$parameterN" ] 82 | then 83 | npmCommands 84 | fi 85 | 86 | # ---------------------------------------------------------------------- 87 | # Print helpFunction in case parameters are empty 88 | # ---------------------------------------------------------------------- 89 | if [ -z "$parameterA" ] || [ -z "$parameterN" ] || [ -z "$parameterC" ] 90 | then 91 | helpFunction 92 | fi 93 | --------------------------------------------------------------------------------