├── .env.example ├── .gitignore ├── LICENSE ├── README.md ├── docker-compose.yml └── docker ├── laravel-horizon ├── Dockerfile ├── supervisord.conf └── supervisord.d │ ├── .gitignore │ └── laravel-horizon.conf.example ├── nginx ├── .gitignore ├── Dockerfile ├── logrotate │ └── nginx ├── nginx.conf ├── sites │ └── laravel.conf ├── ssl │ └── generate-keys.sh └── startup.sh └── php-fpm ├── Dockerfile ├── docker-entrypoint.sh └── laravel.ini /.env.example: -------------------------------------------------------------------------------- 1 | #### DOCKER 2 | FORWARD_DB_PORT= 3 | DATA_PATH_HOST=~/.sail/data 4 | DOCKER_HOST_IP=172.17.0.1 5 | 6 | # Point to the path of your applications code on your host 7 | APP_CODE_PATH_HOST=./ 8 | 9 | # Point to where the `APP_CODE_PATH_HOST` should be in the container 10 | APP_CODE_PATH_CONTAINER=/var/www/laravel/current 11 | 12 | # You may add flags to the path `:cached`, `:delegated`. When using Docker Sync add `:nocopy` 13 | APP_CODE_CONTAINER_FLAG=:cached 14 | 15 | ##### NGINX ################################################# 16 | 17 | NGINX_HOST_HTTP_PORT=80 18 | NGINX_HOST_HTTPS_PORT=443 19 | NGINX_HOST_LOG_PATH=./docker/logs/nginx/ 20 | NGINX_SITES_PATH=./docker/nginx/sites/ 21 | NGINX_PHP_UPSTREAM_CONTAINER=php-fpm 22 | NGINX_PHP_UPSTREAM_PORT=9000 23 | NGINX_SSL_PATH=./docker/nginx/ssl/ 24 | 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.crt 2 | *.csr 3 | *.key 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Acadea 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Setting up Nginx and PHP-fpm in Laravel Sail 2 | Source code for my [blog article](https://medium.com/p/f7b3c85187ed). 3 | 4 | 5 | ## Quick start 6 | 7 | 1. Copy and paste the files in this repo to your project.  8 | 2. Edit `nginx/sites/laravel.conf` 9 | 3. Copy the values in `.env.example` to the actual .env file.  10 | 4. Edit your machine's host file if needed to add a custom domain. 11 | 5. Run `docker-compose up -d` and enjoy! 12 | 13 | ## Youtube tutorial 14 | [![Watch the video](https://img.youtube.com/vi/jMhlooG2cYg/default.jpg)](https://youtu.be/jMhlooG2cYg) 15 | 16 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | # For more information: https://laravel.com/docs/sail 2 | version: '3' 3 | services: 4 | # laravel.test: 5 | # build: 6 | # context: ./vendor/laravel/sail/runtimes/8.1 7 | # dockerfile: Dockerfile 8 | # args: 9 | # WWWGROUP: '${WWWGROUP}' 10 | # image: sail-8.1/app 11 | # extra_hosts: 12 | # - 'host.docker.internal:${DOCKER_HOST_IP}' 13 | # ports: 14 | # - '${APP_PORT:-80}:80' 15 | # environment: 16 | # WWWUSER: '${WWWUSER}' 17 | # LARAVEL_SAIL: 1 18 | # XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}' 19 | # XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}' 20 | # volumes: 21 | # - '.:/var/www/html' 22 | # networks: 23 | # - sail 24 | # depends_on: 25 | # - mysql 26 | # - redis 27 | ## - meilisearch 28 | ## - selenium 29 | mysql: 30 | image: 'mysql/mysql-server:8.0' 31 | ports: 32 | - '${FORWARD_DB_PORT:-3306}:3306' 33 | environment: 34 | MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}' 35 | MYSQL_ROOT_HOST: "%" 36 | MYSQL_DATABASE: '${DB_DATABASE}' 37 | MYSQL_USER: '${DB_USERNAME}' 38 | MYSQL_PASSWORD: '${DB_PASSWORD}' 39 | MYSQL_ALLOW_EMPTY_PASSWORD: 1 40 | volumes: 41 | - '${DATA_PATH_HOST}/mysql:/var/lib/mysql' 42 | - './vendor/laravel/sail/database/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh' 43 | networks: 44 | - sail 45 | healthcheck: 46 | test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"] 47 | retries: 3 48 | timeout: 5s 49 | redis: 50 | image: 'redis:alpine' 51 | ports: 52 | - '${FORWARD_REDIS_PORT:-6379}:6379' 53 | volumes: 54 | - '${DATA_PATH_HOST}/redis:/data' 55 | networks: 56 | - sail 57 | healthcheck: 58 | test: ["CMD", "redis-cli", "ping"] 59 | retries: 3 60 | timeout: 5s 61 | nginx: 62 | build: 63 | context: "./docker/nginx" 64 | depends_on: 65 | - php-fpm 66 | volumes: 67 | - ${NGINX_SSL_PATH}:/etc/nginx/ssl 68 | - ${APP_CODE_PATH_HOST}:${APP_CODE_PATH_CONTAINER}${APP_CODE_CONTAINER_FLAG} 69 | - ${NGINX_HOST_LOG_PATH}:/var/log/nginx 70 | - ${NGINX_SITES_PATH}:/etc/nginx/sites-available 71 | ports: 72 | # port mappings, host to docker 73 | - "${NGINX_HOST_HTTPS_PORT}:443" 74 | - "${NGINX_HOST_HTTP_PORT}:80" 75 | networks: 76 | - sail 77 | 78 | 79 | php-fpm: 80 | build: 81 | context: "./docker/php-fpm" 82 | volumes: 83 | - ${APP_CODE_PATH_HOST}:${APP_CODE_PATH_CONTAINER}${APP_CODE_CONTAINER_FLAG} 84 | networks: 85 | - sail 86 | expose: 87 | - "9000" 88 | 89 | laravel-horizon: 90 | build: 91 | context: ./docker/laravel-horizon 92 | volumes: 93 | - ${APP_CODE_PATH_HOST}:${APP_CODE_PATH_CONTAINER} 94 | - ./docker/laravel-horizon/supervisord.d:/etc/supervisord.d 95 | depends_on: 96 | - php-fpm 97 | extra_hosts: 98 | - "dockerhost:${DOCKER_HOST_IP}" 99 | networks: 100 | - sail 101 | 102 | 103 | # meilisearch: 104 | # image: 'getmeili/meilisearch:latest' 105 | # ports: 106 | # - '${FORWARD_MEILISEARCH_PORT:-7700}:7700' 107 | # volumes: 108 | # - 'sail-meilisearch:/data.ms' 109 | # networks: 110 | # - sail 111 | # healthcheck: 112 | # test: ["CMD", "wget", "--no-verbose", "--spider", "http://localhost:7700/health"] 113 | # retries: 3 114 | # timeout: 5s 115 | # mailhog: 116 | # image: 'mailhog/mailhog:latest' 117 | # ports: 118 | # - '${FORWARD_MAILHOG_PORT:-1025}:1025' 119 | # - '${FORWARD_MAILHOG_DASHBOARD_PORT:-8025}:8025' 120 | # networks: 121 | # - sail 122 | # selenium: 123 | # image: 'selenium/standalone-chrome' 124 | # volumes: 125 | # - '/dev/shm:/dev/shm' 126 | # networks: 127 | # - sail 128 | networks: 129 | sail: 130 | driver: bridge 131 | volumes: 132 | sail-mysql: 133 | driver: local 134 | sail-redis: 135 | driver: local 136 | sail-meilisearch: 137 | driver: local 138 | -------------------------------------------------------------------------------- /docker/laravel-horizon/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | #-------------------------------------------------------------------------- 3 | # Image Setup 4 | #-------------------------------------------------------------------------- 5 | # 6 | 7 | # no memcached 8 | 9 | FROM php:8.1-alpine 10 | 11 | RUN apk --update add wget \ 12 | curl \ 13 | git \ 14 | build-base \ 15 | libmemcached-dev \ 16 | libmcrypt-dev \ 17 | libxml2-dev \ 18 | zlib-dev \ 19 | autoconf \ 20 | cyrus-sasl-dev \ 21 | libgsasl-dev \ 22 | supervisor \ 23 | oniguruma-dev \ 24 | procps \ 25 | libzip-dev \ 26 | postgresql-dev \ 27 | gmp-dev 28 | 29 | # Install soap extention 30 | 31 | # Install for image manipulation 32 | 33 | # Install the PHP pcntl extention 34 | 35 | # Install the PHP zip extention 36 | 37 | # Install the PHP pdo_mysql extention 38 | 39 | # Install the PHP pdo_pgsql extention 40 | 41 | # Install the PHP bcmath extension 42 | 43 | # Install the PHP intl extention 44 | 45 | # Install the PHP gmp extention 46 | #Install Sockets package: 47 | RUN docker-php-ext-install gmp soap exif pcntl zip pdo_mysql pdo_pgsql bcmath intl sockets 48 | 49 | 50 | ##################################### 51 | # PHPRedis: 52 | ##################################### 53 | RUN pecl install redis && docker-php-ext-enable redis 54 | 55 | ##################################### 56 | # Imagick: 57 | ##################################### 58 | RUN apk add imagemagick-dev 59 | RUN pecl install imagick && \ 60 | docker-php-ext-enable imagick 61 | 62 | ##################################### 63 | # GD: 64 | ##################################### 65 | 66 | # Install the PHP gd library 67 | RUN apk add libpng-dev jpeg-dev libjpeg-turbo-dev freetype-dev 68 | RUN docker-php-ext-install gd && \ 69 | docker-php-ext-configure gd --with-freetype --with-jpeg && \ 70 | docker-php-ext-install gd 71 | 72 | 73 | # Add a non-root user to help install ffmpeg: 74 | ARG PUID=1000 75 | ENV PUID ${PUID} 76 | ARG PGID=1000 77 | ENV PGID ${PGID} 78 | 79 | RUN addgroup -g ${PGID} sail && \ 80 | adduser -D -G sail -u ${PUID} sail 81 | 82 | #Install BZ2: 83 | ARG INSTALL_BZ2=false 84 | RUN if [ ${INSTALL_BZ2} = true ]; then \ 85 | apk --update add bzip2-dev; \ 86 | docker-php-ext-install bz2 \ 87 | ;fi 88 | 89 | ########################################################################### 90 | # PHP GnuPG: 91 | ########################################################################### 92 | 93 | ARG INSTALL_GNUPG=true 94 | 95 | RUN set -eux; if [ ${INSTALL_GNUPG} = true ]; then \ 96 | apk add --no-cache --no-progress --virtual BUILD_DEPS_PHP_GNUPG gpgme-dev; \ 97 | apk add --no-cache --no-progress gpgme; \ 98 | if [ $(php -r "echo PHP_MAJOR_VERSION;") = "8" ]; then \ 99 | pecl install gnupg-1.5.0RC2; \ 100 | else \ 101 | pecl install gnupg; \ 102 | fi; \ 103 | docker-php-ext-enable gnupg; \ 104 | fi 105 | 106 | 107 | #-------------------------------------------------------------------------- 108 | # Optional Supervisord Configuration 109 | #-------------------------------------------------------------------------- 110 | # 111 | # Modify the ./supervisor.conf file to match your App's requirements. 112 | # Make sure you rebuild your container with every change. 113 | # 114 | 115 | COPY supervisord.conf /etc/supervisord.conf 116 | 117 | ENTRYPOINT ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisord.conf"] 118 | 119 | # 120 | #-------------------------------------------------------------------------- 121 | # Optional Software's Installation 122 | #-------------------------------------------------------------------------- 123 | # 124 | # If you need to modify this image, feel free to do it right here. 125 | # 126 | # -- Your awesome modifications go here -- # 127 | 128 | 129 | #-------------------------------------------------------------------------- 130 | # Check PHP version 131 | #-------------------------------------------------------------------------- 132 | # 133 | 134 | RUN php -v 135 | 136 | # 137 | #-------------------------------------------------------------------------- 138 | # Final Touch 139 | #-------------------------------------------------------------------------- 140 | # 141 | 142 | WORKDIR /etc/supervisor/conf.d/ 143 | -------------------------------------------------------------------------------- /docker/laravel-horizon/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | [supervisorctl] 4 | [inet_http_server] 5 | port = 127.0.0.1:9001 6 | [rpcinterface:supervisor] 7 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface 8 | 9 | [include] 10 | files = supervisord.d/*.conf -------------------------------------------------------------------------------- /docker/laravel-horizon/supervisord.d/.gitignore: -------------------------------------------------------------------------------- 1 | *.conf 2 | -------------------------------------------------------------------------------- /docker/laravel-horizon/supervisord.d/laravel-horizon.conf.example: -------------------------------------------------------------------------------- 1 | [program:laravel-horizon] 2 | process_name=%(program_name)s_%(process_num)02d 3 | user=sail 4 | command=php /var/www/laravel/current/artisan horizon 5 | autostart=true 6 | autorestart=true 7 | redirect_stderr=true 8 | -------------------------------------------------------------------------------- /docker/nginx/.gitignore: -------------------------------------------------------------------------------- 1 | *.crt 2 | *.csr 3 | *.key 4 | *.pem -------------------------------------------------------------------------------- /docker/nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:alpine 2 | 3 | COPY nginx.conf /etc/nginx/ 4 | 5 | RUN apk update \ 6 | && apk upgrade \ 7 | && apk --update add logrotate \ 8 | && apk add --no-cache openssl \ 9 | && apk add --no-cache bash 10 | 11 | RUN apk add --no-cache curl 12 | 13 | RUN set -x ; \ 14 | addgroup -g 82 -S www-data ; \ 15 | adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1 16 | 17 | ARG PHP_UPSTREAM_CONTAINER=php-fpm 18 | ARG PHP_UPSTREAM_PORT=9000 19 | 20 | # Create 'messages' file used from 'logrotate' 21 | RUN touch /var/log/messages 22 | 23 | # Copy 'logrotate' config file 24 | COPY logrotate/nginx /etc/logrotate.d/ 25 | 26 | # Set upstream conf and remove the default conf 27 | RUN echo "upstream php-upstream { server ${PHP_UPSTREAM_CONTAINER}:${PHP_UPSTREAM_PORT}; }" > /etc/nginx/conf.d/upstream.conf \ 28 | && rm /etc/nginx/conf.d/default.conf 29 | 30 | ADD ./startup.sh /opt/startup.sh 31 | RUN sed -i 's/\r//g' /opt/startup.sh 32 | CMD ["/bin/bash", "/opt/startup.sh"] 33 | 34 | EXPOSE 80 81 443 35 | -------------------------------------------------------------------------------- /docker/nginx/logrotate/nginx: -------------------------------------------------------------------------------- 1 | /var/log/nginx/*.log { 2 | daily 3 | missingok 4 | rotate 32 5 | compress 6 | delaycompress 7 | nodateext 8 | notifempty 9 | create 644 www-data root 10 | sharedscripts 11 | postrotate 12 | [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid` 13 | endscript 14 | } 15 | -------------------------------------------------------------------------------- /docker/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | user www-data; 2 | worker_processes 4; 3 | pid /run/nginx.pid; 4 | daemon off; 5 | 6 | events { 7 | worker_connections 2048; 8 | multi_accept on; 9 | use epoll; 10 | } 11 | 12 | http { 13 | server_tokens off; 14 | sendfile on; 15 | tcp_nopush on; 16 | tcp_nodelay on; 17 | keepalive_timeout 15; 18 | types_hash_max_size 2048; 19 | client_max_body_size 20M; 20 | include /etc/nginx/mime.types; 21 | default_type application/octet-stream; 22 | access_log /dev/stdout; 23 | error_log /dev/stderr; 24 | gzip on; 25 | gzip_disable "msie6"; 26 | 27 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 28 | ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; 29 | 30 | include /etc/nginx/conf.d/*.conf; 31 | include /etc/nginx/sites-available/*.conf; 32 | open_file_cache off; # Disabled for issue 619 33 | charset UTF-8; 34 | } 35 | -------------------------------------------------------------------------------- /docker/nginx/sites/laravel.conf: -------------------------------------------------------------------------------- 1 | 2 | server { 3 | 4 | listen 80; 5 | listen [::]:80; 6 | 7 | add_header X-Frame-Options "SAMEORIGIN"; 8 | add_header X-Content-Type-Options "nosniff"; 9 | charset utf-8; 10 | 11 | # For https 12 | listen 443 ssl; 13 | listen [::]:443 ssl ipv6only=on; 14 | ssl_certificate /etc/nginx/ssl/default.crt; 15 | ssl_certificate_key /etc/nginx/ssl/default.key; 16 | 17 | server_name laravel.dev.local; 18 | root /var/www/laravel/current/public; 19 | index index.php index.html index.htm; 20 | 21 | location / { 22 | try_files $uri $uri/ /index.php$is_args$args; 23 | } 24 | 25 | location ~ \.php$ { 26 | try_files $uri /index.php =404; 27 | fastcgi_pass php-upstream; 28 | fastcgi_index index.php; 29 | fastcgi_buffers 16 16k; 30 | fastcgi_buffer_size 32k; 31 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 32 | #fixes timeouts 33 | fastcgi_read_timeout 600; 34 | include fastcgi_params; 35 | } 36 | 37 | location ~ /\.ht { 38 | deny all; 39 | } 40 | 41 | location /.well-known/acme-challenge/ { 42 | root /var/www/letsencrypt/; 43 | log_not_found off; 44 | } 45 | location = /favicon.ico { 46 | access_log off; 47 | log_not_found off; 48 | } 49 | location = /robots.txt { 50 | access_log off; 51 | log_not_found off; 52 | } 53 | 54 | 55 | error_log /var/log/nginx/laravel_error.log; 56 | access_log /var/log/nginx/laravel_access.log; 57 | } 58 | -------------------------------------------------------------------------------- /docker/nginx/ssl/generate-keys.sh: -------------------------------------------------------------------------------- 1 | openssl genrsa -out "./default.key" 2048 2 | chmod 644 ./default.key 3 | openssl req -new -key "./default.key" -out "./default.csr" -subj "/CN=default/O=default/C=UK" 4 | openssl x509 -req -days 365 -in "./default.csr" -signkey "./default.key" -out "./default.crt" 5 | -------------------------------------------------------------------------------- /docker/nginx/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ ! -f /etc/nginx/ssl/default.crt ]; then 4 | openssl genrsa -out "/etc/nginx/ssl/default.key" 2048 5 | openssl req -new -key "/etc/nginx/ssl/default.key" -out "/etc/nginx/ssl/default.csr" -subj "/CN=default/O=default/C=UK" 6 | openssl x509 -req -days 365 -in "/etc/nginx/ssl/default.csr" -signkey "/etc/nginx/ssl/default.key" -out "/etc/nginx/ssl/default.crt" 7 | chmod 644 /etc/nginx/ssl/default.key 8 | fi 9 | 10 | 11 | # cron job to restart nginx every 6 hour 12 | (crontab -l ; echo "0 0 */4 * * nginx -s reload") | crontab - 13 | 14 | # Start crond in background 15 | crond -l 2 -b 16 | 17 | 18 | #* * * * * root nginx -s reload >> /var/log/cron.log 19 | 20 | # Start nginx in foreground 21 | echo "NGINX started, daemon will restart every 6 hours now."; 22 | nginx 23 | 24 | -------------------------------------------------------------------------------- /docker/php-fpm/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copied from cyberduck/php-fpm-laravel 2 | #https://github.com/Cyber-Duck/php-fpm-laravel/blob/8.1/Dockerfile 3 | FROM php:8.1-fpm 4 | 5 | MAINTAINER support@cyber-duck.co.uk 6 | 7 | ENV COMPOSER_MEMORY_LIMIT='-1' 8 | 9 | RUN apt-get update && \ 10 | apt-get install -y --force-yes --no-install-recommends \ 11 | libmemcached-dev \ 12 | libzip-dev \ 13 | libz-dev \ 14 | libzip-dev \ 15 | libpq-dev \ 16 | libjpeg-dev \ 17 | libpng-dev \ 18 | libfreetype6-dev \ 19 | libssl-dev \ 20 | openssh-server \ 21 | libmagickwand-dev \ 22 | git \ 23 | cron \ 24 | nano \ 25 | libxml2-dev \ 26 | libreadline-dev \ 27 | libgmp-dev \ 28 | mariadb-client \ 29 | unzip 30 | 31 | # Install soap extention 32 | RUN docker-php-ext-install soap 33 | 34 | # Install for image manipulation 35 | RUN docker-php-ext-install exif 36 | 37 | # Install the PHP pcntl extention 38 | RUN docker-php-ext-install pcntl 39 | 40 | # Install the PHP zip extention 41 | RUN docker-php-ext-install zip 42 | 43 | # Install the PHP pdo_mysql extention 44 | RUN docker-php-ext-install pdo_mysql 45 | 46 | # Install the PHP pdo_pgsql extention 47 | RUN docker-php-ext-install pdo_pgsql 48 | 49 | # Install the PHP bcmath extension 50 | RUN docker-php-ext-install bcmath 51 | 52 | # Install the PHP intl extention 53 | RUN docker-php-ext-install intl 54 | 55 | # Install the PHP gmp extention 56 | RUN docker-php-ext-install gmp 57 | 58 | ##################################### 59 | # PHPRedis: 60 | ##################################### 61 | RUN pecl install redis && docker-php-ext-enable redis 62 | 63 | ##################################### 64 | # Imagick: 65 | ##################################### 66 | 67 | RUN pecl install imagick && \ 68 | docker-php-ext-enable imagick 69 | 70 | ##################################### 71 | # GD: 72 | ##################################### 73 | 74 | # Install the PHP gd library 75 | RUN docker-php-ext-install gd && \ 76 | docker-php-ext-configure gd --with-freetype --with-jpeg && \ 77 | docker-php-ext-install gd 78 | 79 | ##################################### 80 | # xDebug: 81 | ##################################### 82 | 83 | # Install the xdebug extension 84 | RUN pecl install xdebug 85 | 86 | ##################################### 87 | # PHP Memcached: 88 | ##################################### 89 | 90 | # Install the php memcached extension 91 | RUN pecl install memcached && docker-php-ext-enable memcached 92 | 93 | ##################################### 94 | # Composer: 95 | ##################################### 96 | 97 | # Install composer and add its bin to the PATH. 98 | RUN curl -s http://getcomposer.org/installer | php && \ 99 | echo "export PATH=${PATH}:/var/www/vendor/bin" >> ~/.bashrc && \ 100 | mv composer.phar /usr/local/bin/composer 101 | # Source the bash 102 | RUN . ~/.bashrc 103 | 104 | ##################################### 105 | # Laravel Schedule Cron Job: 106 | ##################################### 107 | 108 | RUN echo "* * * * * www-data /usr/local/bin/php /var/www/artisan schedule:run >> /dev/null 2>&1" >> /etc/cron.d/laravel-scheduler 109 | RUN chmod 0644 /etc/cron.d/laravel-scheduler 110 | 111 | # 112 | #-------------------------------------------------------------------------- 113 | # Final Touch 114 | #-------------------------------------------------------------------------- 115 | # 116 | 117 | ADD ./laravel.ini /usr/local/etc/php/conf.d 118 | 119 | ##################################### 120 | # Aliases: 121 | ##################################### 122 | # docker-compose exec php-fpm dep --> locally installed Deployer binaries 123 | RUN echo '#!/bin/bash\n/usr/local/bin/php /var/www/vendor/bin/dep "$@"' > /usr/bin/dep 124 | RUN chmod +x /usr/bin/dep 125 | # docker-compose exec php-fpm art --> php artisan 126 | RUN echo '#!/bin/bash\n/usr/local/bin/php /var/www/artisan "$@"' > /usr/bin/art 127 | RUN chmod +x /usr/bin/art 128 | # docker-compose exec php-fpm migrate --> php artisan migrate 129 | RUN echo '#!/bin/bash\n/usr/local/bin/php /var/www/artisan migrate "$@"' > /usr/bin/migrate 130 | RUN chmod +x /usr/bin/migrate 131 | # docker-compose exec php-fpm fresh --> php artisan migrate:fresh --seed 132 | RUN echo '#!/bin/bash\n/usr/local/bin/php /var/www/artisan migrate:fresh --seed' > /usr/bin/fresh 133 | RUN chmod +x /usr/bin/fresh 134 | # docker-compose exec php-fpm t --> run the tests for the project and generate testdox 135 | RUN echo '#!/bin/bash\n/usr/local/bin/php /var/www/artisan config:clear\n/var/www/vendor/bin/phpunit -d memory_limit=2G --stop-on-error --stop-on-failure --testdox-text=tests/report.txt "$@"' > /usr/bin/t 136 | RUN chmod +x /usr/bin/t 137 | # docker-compose exec php-fpm d --> run the Laravel Dusk browser tests for the project 138 | RUN echo '#!/bin/bash\n/usr/local/bin/php /var/www/artisan config:clear\n/bin/bash\n/usr/local/bin/php /var/www/artisan dusk -d memory_limit=2G --stop-on-error --stop-on-failure --testdox-text=tests/report-dusk.txt "$@"' > /usr/bin/d 139 | RUN chmod +x /usr/bin/d 140 | 141 | RUN rm -r /var/lib/apt/lists/* 142 | 143 | RUN usermod -u 1000 www-data 144 | 145 | WORKDIR /var/www 146 | 147 | COPY ./docker-entrypoint.sh /usr/local/bin/ 148 | RUN chmod +x /usr/local/bin/docker-entrypoint.sh 149 | RUN ln -s /usr/local/bin/docker-entrypoint.sh / 150 | ENTRYPOINT ["docker-entrypoint.sh"] 151 | 152 | EXPOSE 9000 153 | CMD ["php-fpm"] -------------------------------------------------------------------------------- /docker/php-fpm/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Destination of env file inside container 4 | ENV_FILE="/var/www/.env" 5 | 6 | # Loop through XDEBUG, PHP_IDE_CONFIG and REMOTE_HOST variables and check if they are set. 7 | # If they are not set then check if we have values for them in the env file, if the env file exists. If we have values 8 | # in the env file then add exports for these in in the ~./bashrc file. 9 | for VAR in XDEBUG PHP_IDE_CONFIG REMOTE_HOST 10 | do 11 | if [ -z "${!VAR}" ] && [ -f "${ENV_FILE}" ]; then 12 | VALUE=$(grep $VAR $ENV_FILE | cut -d '=' -f 2-) 13 | if [ ! -z "${VALUE}" ]; then 14 | # Before adding the export we clear the value, if set, to prevent duplication. 15 | sed -i "/$VAR/d" ~/.bashrc 16 | echo "export $VAR=$VALUE" >> ~/.bashrc; 17 | fi 18 | fi 19 | done 20 | 21 | # If there is still no value for the REMOTE_HOST variable then we set it to the default of host.docker.internal. This 22 | # value will be sufficient for windows and mac environments. 23 | if [ -z "${REMOTE_HOST}" ]; then 24 | REMOTE_HOST="host.docker.internal" 25 | sed -i "/REMOTE_HOST/d" ~/.bashrc 26 | echo "export REMOTE_HOST=\"$REMOTE_HOST\"" >> ~/.bashrc; 27 | fi 28 | 29 | # Source the .bashrc file so that the exported variables are available. 30 | . ~/.bashrc 31 | 32 | # Start the cron service. 33 | service cron start 34 | 35 | # Toggle xdebug 36 | if [ "true" == "$XDEBUG" ] && [ ! -f /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ]; then 37 | # Remove PHP_IDE_CONFIG from cron file so we do not duplicate it when adding below 38 | sed -i '/PHP_IDE_CONFIG/d' /etc/cron.d/laravel-scheduler 39 | if [ ! -z "${PHP_IDE_CONFIG}" ]; then 40 | # Add PHP_IDE_CONFIG to cron file. Cron by default does not load enviromental variables. The server name, set here, is 41 | # used by PHPSTORM for path mappings 42 | echo -e "PHP_IDE_CONFIG=\"$PHP_IDE_CONFIG\"\n$(cat /etc/cron.d/laravel-scheduler)" > /etc/cron.d/laravel-scheduler 43 | fi 44 | # Enable xdebug estension and set up the docker-php-ext-xdebug.ini file with the required xdebug settings 45 | docker-php-ext-enable xdebug && \ 46 | echo "xdebug.remote_enable=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; \ 47 | echo "xdebug.remote_autostart=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; \ 48 | echo "xdebug.remote_connect_back=0" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; \ 49 | echo "xdebug.remote_host=$REMOTE_HOST" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; 50 | 51 | elif [ -f /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ]; then 52 | # Remove PHP_IDE_CONFIG from cron file if already added 53 | sed -i '/PHP_IDE_CONFIG/d' /etc/cron.d/laravel-scheduler 54 | # Remove Xdebug config file disabling xdebug 55 | rm -rf /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini 56 | fi 57 | 58 | exec "$@" -------------------------------------------------------------------------------- /docker/php-fpm/laravel.ini: -------------------------------------------------------------------------------- 1 | date.timezone=UTC 2 | display_errors=Off 3 | log_errors=On 4 | 5 | ; Maximum amount of memory a script may consume (128MB) 6 | ; http://php.net/memory-limit 7 | memory_limit = 128M 8 | ; Maximum allowed size for uploaded files. 9 | ; http://php.net/upload-max-filesize 10 | upload_max_filesize = 20M 11 | ; Sets max size of post data allowed. 12 | ; http://php.net/post-max-size 13 | post_max_size = 20M 14 | --------------------------------------------------------------------------------