├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── base-php-nginx.Dockerfile ├── composer.json ├── docker-compose.yml ├── docker-php-entrypoint ├── docker-php-entrypoint-dev ├── install-composer.sh ├── nginx-site.conf ├── nginx.conf ├── package.json └── supervisord.conf /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | node_modules/ 3 | npm-debug.log 4 | 5 | # Laravel 4 specific 6 | bootstrap/compiled.php 7 | app/storage/ 8 | 9 | # Laravel 5 & Lumen specific 10 | public/storage 11 | public/hot 12 | storage/*.key 13 | .env.*.php 14 | .env.php 15 | .env 16 | Homestead.yaml 17 | Homestead.json 18 | 19 | # Rocketeer PHP task runner and deployment package. https://github.com/rocketeers/rocketeer 20 | .rocketeer/ 21 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM yourdockername/base-php-nginx:latest 2 | 3 | # add bitbucket and github to known hosts for ssh needs 4 | WORKDIR /root/.ssh 5 | RUN chmod 0600 /root/.ssh \ 6 | && ssh-keyscan -t rsa bitbucket.org >> known_hosts \ 7 | && ssh-keyscan -t rsa github.com >> known_hosts 8 | 9 | ## 10 | ## Compose Package Manager 11 | ## 12 | 13 | # install composer dependencies 14 | WORKDIR /var/www/app 15 | COPY ./composer.json ./composer.lock* ./ 16 | ENV COMPOSER_VENDOR_DIR=/var/www/vendor 17 | # RUN composer config github-oauth.github.com YOUROAUTHKEYHERE 18 | RUN composer install --no-scripts --no-autoloader --ansi --no-interaction 19 | 20 | ## 21 | ## Node Build Tools 22 | ## 23 | 24 | # we hardcode to develop so all tools are there for npm build 25 | ENV NODE_ENV=develop 26 | # install dependencies first, in a different location for easier app bind mounting for local development 27 | WORKDIR /var/www 28 | COPY ./package.json . 29 | RUN npm install 30 | # no need to cache clean in non-final build steps 31 | ENV PATH /var/www/node_modules/.bin:$PATH 32 | ENV NODE_PATH=/var/www/node_modules 33 | WORKDIR /var/www/app 34 | 35 | ## 36 | ## We Are Go for Bower 37 | ## 38 | 39 | # If you were to use Bower, this might be how to do it 40 | # COPY ./bower.json . 41 | # RUN bower install --allow-root 42 | 43 | # add custom php-fpm pool settings, these get written at entrypoint startup 44 | ENV FPM_PM_MAX_CHILDREN=20 \ 45 | FPM_PM_START_SERVERS=2 \ 46 | FPM_PM_MIN_SPARE_SERVERS=1 \ 47 | FPM_PM_MAX_SPARE_SERVERS=3 48 | 49 | # Laravel App Config 50 | # setup app config environment at runtime 51 | # gets put into ./.env at startup 52 | ENV APP_NAME=Laravel \ 53 | APP_ENV=local \ 54 | APP_DEBUG=true \ 55 | APP_KEY=KEYGOESHERE \ 56 | APP_LOG=errorlog \ 57 | APP_URL=http://localhost \ 58 | DB_CONNECTION=mysql \ 59 | DB_HOST=mysql \ 60 | DB_PORT=3306 \ 61 | DB_DATABASE=homestead \ 62 | DB_USERNAME=homestead \ 63 | DB_PASSWORD=secret 64 | # Many more ENV may be needed here, and updated in docker-php-entrypoint file 65 | 66 | 67 | # update the entrypoint to write config files and do last minute builds on startup 68 | # notice we have a -dev version, which does different things on local docker-compose 69 | # but we'll default to entrypoint of running the non -dev one 70 | COPY docker-php-* /usr/local/bin/ 71 | RUN dos2unix /usr/local/bin/docker-php-entrypoint 72 | RUN dos2unix /usr/local/bin/docker-php-entrypoint-dev 73 | 74 | 75 | # copy in nginx config 76 | COPY ./nginx.conf /etc/nginx/nginx.conf 77 | COPY ./nginx-site.conf /etc/nginx/conf.d/default.conf 78 | 79 | 80 | # copy in app code as late as possible, as it changes the most 81 | WORKDIR /var/www/app 82 | COPY --chown=www-data:www-data . . 83 | RUN composer dump-autoload -o 84 | 85 | # be sure nginx is properly passing to php-fpm and fpm is responding 86 | HEALTHCHECK --interval=5s --timeout=3s \ 87 | CMD curl -f http://localhost/ping || exit 1 88 | 89 | WORKDIR /var/www/app/public 90 | EXPOSE 80 443 9000 9001 91 | 92 | CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/conf.d/supervisord.conf"] 93 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Bret Fisher 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 | ## PHP (Laravel) + Docker Hello World, for Showing Good Defaults for Using A PHP Stack in Docker 2 | 3 | > This tries to be a "good defaults" example of using PHP, Nginx, PHP-FPM, Laravel, and Composer in Docker for local development and shipping to production with all the bells, whistles, and best practices. Issues/PR welcome. 4 | 5 | **NOTE:** This is not a full PHP sample project. It's a collection of the Docker and Nginx related things you'll need to have this sort of setup fully in Docker. I'm not a PHP/Laravel developer, but rather an ops guy working with many smart PHP dev's. I continue to refine this repo as I work with teams to dev with, test on, and deploy production containers on PHP. 6 | 7 | Also Note [I have courses on Docker, Swarm, and upcoming Docker for Node.js here](https://www.bretfisher.com/docker). 8 | 9 | ### Official Laravel Docker Environment 10 | 11 | As of version 8 of Laravel there is an offically supported Docker development environment called 'Sail'. If you are specifically doing Laravel development you may want to check it out at [the Laravel website](https://laravel.com/docs/sail). 12 | 13 | ### Contribuitions 14 | 15 | This project was made possible in part with support and development from [PrinterLogic](https://www.printerlogic.com/). 16 | 17 | ### Local Development Features 18 | 19 | - **Dev as close to prod as you can**. docker-compose builds a local development image that is just like production image except for the below dev-only features needed in image. Goal is to have dev env be as close to test and prod as possible while still giving all the nice tools to make you a happy dev. 20 | - **Prevent needing node/npm on host**. Installs `node_modules` outside app root in container so local development won't run into a problem of bind-mounting over it with local source code. This means it will run `npm install` once on container build and you don't need to run npm on host or on each docker run. It will re-run on build if you change `package.json`. 21 | - **One line startup**. Uses `docker-compose up` for single-line build and run of local development server. 22 | - **Edit locally while code runs in container**. docker-compose uses proper bind-mounts of host source code into container so you can edit locally while running code in Linux container. 23 | - **Enable debug from host to container**. opens the legacy debug port 5858 and new inspect port 9229 for using host-based debugging like chrome tools or VS Code. Nodemon enables `--inspect` by default in docker-compose, but you can change to `--debug` for < 6.3 debugging. 24 | - **Quick re-builds**. `COPY` in `package.json` and run `npm install && npm cache clean` **before** `COPY` in your source code. This saves big on build time and keep container lean. Same for Composer and Bower. 25 | 26 | 27 | ### Production-minded Features 28 | 29 | - **Use Docker build-in healthchecks**. uses Dockerfile `HEALTHCHECK` with php-fpm `/ping` route to help Docker know if your container is running properly. 30 | - **Nginx + PHP-FPM in one container**. Supervisor is used to combine the two services, Nginx and PHP-FPM in a single container. Those two services have to work together to give you a webserver and PHP processor. Unlike Apache + mod\_php, which runs under the Apache process and only needs to start one process on container startup, the combo of Nginx + PHP-FPM have to be started separately. Docker is designed to run a single process with CMD in the Dockerfile, so the simple Supervisor program is used to manage them with a simple config file. Having them both in one container makes the app easier to manage in my real-world experience. [Docker has a Docs page on various ways to start multi-service containers](https://docs.docker.com/engine/admin/multi-service_container/), showing a Supervisor example. So far, the Nginx + PHP-FPM combo is the *only* scenario that I recommend using multi-service containers for. It's a rather unique problem that doesn't always fit well in the model of "one container, one service". You *could* use two separate containers, one with `nginx` and one with `php:fpm` but I've tried that in production, and there are lots of downsides. A copy of the PHP code has to be in each container, they have to communicate over TCP which is much slower than Linux sockets used in a single container, and since you usually have a 1-to-1 relationship between them, the argument of individual service control is rather moot. 31 | 32 | 33 | ### Assumptions 34 | 35 | - You have Docker and Docker-Compose installed (Docker for Mac, Docker for Windows, get.docker.com and manual Compose installed for Linux). 36 | - You want to use Docker for local development (i.e. never need to install php or npm on host) and have dev and prod Docker images be as close as possible. 37 | - You don't want to lose fidelity in your dev workflow. You want a easy environment setup, using local editors, debug/inspect, local code repo, while web server runs in a container. 38 | - You use `docker-compose` for local development only (docker-compose was never intended to be a production deployment tool anyway). 39 | - The `docker-compose.yml` is not meant for `docker stack deploy` in Docker Swarm, it's meant for happy local development. 40 | 41 | 42 | ### Getting Started 43 | 44 | If this was your app, to start local development you would: 45 | 46 | - Running `docker-compose up` is all you need. It will: 47 | - Build custom local image enabled for development. 48 | - Start container from that image with ports 80, 443, 9000, and 9001 open (on localhost or docker-machine). 49 | - Mount the pwd to the app dir in container. 50 | - If you need other services like databases, just add to compose file and they'll be added to the custom Docker network for this app on `up`. 51 | - If you need to add packages to Composer, npm, bower, etc. then stop docker-compose and run `docker-compose up --build` to ensure image is updated. 52 | - Be sure to use `docker-compose down` to cleanup after your done dev'ing. 53 | 54 | 55 | 56 | MIT License, 57 | 58 | Copyright (c) Bret Fisher 59 | 60 | Permission is hereby granted, free of charge, to any person obtaining a copy 61 | of this software and associated documentation files (the "Software"), to deal 62 | in the Software without restriction, including without limitation the rights 63 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 64 | copies of the Software, and to permit persons to whom the Software is 65 | furnished to do so, subject to the following conditions: 66 | 67 | The above copyright notice and this permission notice shall be included in all 68 | copies or substantial portions of the Software. 69 | 70 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 71 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 72 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 73 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 74 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 75 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 76 | SOFTWARE. 77 | -------------------------------------------------------------------------------- /base-php-nginx.Dockerfile: -------------------------------------------------------------------------------- 1 | # php:7.4.23-fpm-buster breaks readline which is one of the extensions 2 | # installed in this image. Keep an eye on issue number 1197 on github 3 | # https://github.com/docker-library/php/issues/1197 4 | FROM php:7.4.22-fpm-buster 5 | 6 | ENV NGINX_VERSION=1.20.1 \ 7 | PKG_RELEASE=1~buster \ 8 | NJS_VERSION=0.5.3 \ 9 | NODE_VERSION=14.17.6 10 | 11 | # this is a sample BASE image, that php_fpm projects can start FROM 12 | # it's got a lot in it, but it's designed to meet dev and prod needs in single image 13 | # I've tried other things like splitting out php_fpm and nginx containers 14 | # or multi-stage builds to keep it lean, but this is my current design for 15 | ## single image that does nginx and php_fpm 16 | ## usable with bind-mount and unique dev-only entrypoint file that builds 17 | ## some things on startup when developing locally 18 | ## stores all code in image with proper default builds for production 19 | 20 | # install apt dependencies 21 | # some of these are not needed in all php projects 22 | # NOTE: you should prob use specific versions of some of these so you don't break your app 23 | RUN apt-get update && apt-get install --no-install-recommends --no-install-suggests -y \ 24 | apt-transport-https \ 25 | ca-certificates \ 26 | openssh-client \ 27 | curl \ 28 | dos2unix \ 29 | git \ 30 | gnupg2 \ 31 | dirmngr \ 32 | g++ \ 33 | jq \ 34 | libedit-dev \ 35 | libfcgi0ldbl \ 36 | libfreetype6-dev \ 37 | libicu-dev \ 38 | libjpeg62-turbo-dev \ 39 | libmcrypt-dev \ 40 | libpq-dev \ 41 | # libssl-dev \ 42 | # openssh-client \ 43 | supervisor \ 44 | unzip \ 45 | zip \ 46 | && rm -r /var/lib/apt/lists/* 47 | 48 | 49 | # Install extensions using the helper script provided by the base image 50 | RUN docker-php-ext-install \ 51 | pdo_mysql \ 52 | mysqli \ 53 | json \ 54 | readline \ 55 | gd \ 56 | intl 57 | 58 | # configure gd 59 | RUN docker-php-ext-configure gd \ 60 | --with-freetype=/usr/include/freetype2 \ 61 | --with-jpeg=/usr/include/ 62 | 63 | # configure intl 64 | RUN docker-php-ext-configure intl 65 | 66 | 67 | # install nginx (copied from official nginx Dockerfile) 68 | RUN NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62; \ 69 | found=''; \ 70 | for server in \ 71 | ha.pool.sks-keyservers.net \ 72 | hkp://keyserver.ubuntu.com:80 \ 73 | hkp://p80.pool.sks-keyservers.net:80 \ 74 | pgp.mit.edu \ 75 | ; do \ 76 | echo "Fetching GPG key $NGINX_GPGKEY from $server"; \ 77 | apt-key adv --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" && found=yes && break; \ 78 | done; \ 79 | test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" && exit 1; \ 80 | echo "deb http://nginx.org/packages/debian/ buster nginx" >> /etc/apt/sources.list.d/nginx.list \ 81 | && apt-get update \ 82 | && apt-get install --no-install-recommends --no-install-suggests -y \ 83 | nginx=${NGINX_VERSION}-${PKG_RELEASE} \ 84 | nginx-module-xslt=${NGINX_VERSION}-${PKG_RELEASE} \ 85 | nginx-module-geoip=${NGINX_VERSION}-${PKG_RELEASE} \ 86 | nginx-module-image-filter=${NGINX_VERSION}-${PKG_RELEASE} \ 87 | nginx-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${PKG_RELEASE} \ 88 | gettext-base \ 89 | && rm -rf /var/lib/apt/lists/* 90 | 91 | # forward nginx request and error logs to docker log collector 92 | RUN ln -sf /dev/stdout /var/log/nginx/access.log \ 93 | && ln -sf /dev/stderr /var/log/nginx/error.log 94 | 95 | # install composer so we can run dump-autoload at entrypoint startup in dev 96 | # copied from official composer Dockerfile 97 | ENV PATH="/composer/vendor/bin:$PATH" \ 98 | COMPOSER_ALLOW_SUPERUSER=1 \ 99 | COMPOSER_VENDOR_DIR=/var/www/vendor \ 100 | COMPOSER_HOME=/composer 101 | 102 | COPY ./install-composer.sh /tmp//install-composer.sh 103 | 104 | RUN /tmp/install-composer.sh && rm -f /tmp//install-composer.sh \ 105 | && composer --ansi --version --no-interaction 106 | 107 | # install node for running gulp at container entrypoint startup in dev 108 | # copied from official node Dockerfile 109 | # gpg keys listed at https://github.com/nodejs/node#release-team 110 | RUN set -ex \ 111 | && for key in \ 112 | 4ED778F539E3634C779C87C6D7062848A1AB005C \ 113 | 94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \ 114 | 74F12602B6F1C4E913FAA37AD3A89613643B6201 \ 115 | 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \ 116 | 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 117 | C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \ 118 | C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 119 | DD8F2338BAE7501E3DD5AC78C273792F7D83545D \ 120 | A48C2BEE680E841632CD4E44F07496B3EB3C1762 \ 121 | 108F52B48DB57BB0CC439B2997B01419BD92F80A \ 122 | B9E2F5981AA6E0CD28160D9FF13993A75599653C \ 123 | ; do \ 124 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" || \ 125 | gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ; \ 126 | done 127 | 128 | ENV NPM_CONFIG_LOGLEVEL info 129 | 130 | RUN curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \ 131 | && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ 132 | && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ 133 | && grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ 134 | && tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ 135 | && rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ 136 | && ln -s /usr/local/bin/node /usr/local/bin/nodejs 137 | 138 | ENV PATH /var/www/node_modules/.bin:$PATH 139 | 140 | COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf 141 | 142 | CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/conf.d/supervisord.conf"] 143 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bretfisher/php-docker-good-defaults", 3 | "description": "Sample composer config", 4 | "require": { 5 | "monolog/monolog": "1.0.*" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | 3 | services: 4 | php: 5 | # note you need to manually build this image from base dockerfile above FIRST! 6 | image: yourdockername/base-php-nginx 7 | build: . 8 | volumes: 9 | # used delegated mode here on docker for mac for faster disk I/O 10 | - .:/var/www/app:delegated 11 | - ./supervisord.conf:/etc/supervisor/conf.d/supervisord.conf 12 | - ./nginx/nginx.conf:/etc/nginx/nginx.conf 13 | - ./nginx/nginx-site.conf:/etc/nginx/conf.d/default.conf 14 | # mount in dev certs if you want to dev over ssl 15 | #- ./dev-cert.crt:/etc/nginx/ssl/cert.crt 16 | #- ./dev-key.pem:/etc/nginx/ssl/key.pem 17 | entrypoint: /usr/local/bin/docker-php-entrypoint-dev 18 | command: ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/conf.d/supervisord.conf"] 19 | ports: 20 | - "8080:80" 21 | - "8443:443" 22 | - "9001:9001" 23 | depends_on: 24 | - mysql 25 | environment: 26 | APP_NAME: Laravel 27 | APP_ENV: local 28 | APP_DEBUG: "true" 29 | APP_KEY: KEYGOESHERE 30 | APP_LOG: errorlog 31 | APP_URL: "http://localhost" 32 | DB_CONNECTION: mysql 33 | DB_HOST: mysql 34 | DB_PORT: 3306 35 | DB_DATABASE: homestead 36 | DB_USERNAME: homestead 37 | DB_PASSWORD: secret 38 | 39 | mysql: 40 | image: mysql:5.7 41 | volumes: 42 | - mysql:/var/lib/mysql 43 | ports: 44 | # we only expose this port in local dev for using mysql tools/guis on your host 45 | - "3306:3306" 46 | environment: 47 | MYSQL_DATABASE: ${DB_DATABASE:-homestead} 48 | MYSQL_USER: ${DB_USERNAME:-homestead} 49 | MYSQL_PASSWORD: ${DB_PASSWORD:-secret} 50 | MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-secret} 51 | 52 | # using this named volume ensures db's hang around between "up's" 53 | volumes: 54 | mysql: 55 | 56 | -------------------------------------------------------------------------------- /docker-php-entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | # write the php-fpm config 5 | { \ 6 | echo listen = /var/run/php-fpm.sock; \ 7 | echo listen.owner = www-data; \ 8 | echo listen.group = www-data; \ 9 | echo ping.path = /ping; \ 10 | echo pm.status_path = /status; \ 11 | echo pm.max_children = "$FPM_PM_MAX_CHILDREN"; \ 12 | echo pm.start_servers = "$FPM_PM_START_SERVERS"; \ 13 | echo pm.min_spare_servers = "$FPM_PM_MIN_SPARE_SERVERS"; \ 14 | echo pm.max_spare_servers = "$FPM_PM_MAX_SPARE_SERVERS"; \ 15 | } > /usr/local/etc/php-fpm.d/zzz-app.conf 16 | 17 | exec "$@" 18 | -------------------------------------------------------------------------------- /docker-php-entrypoint-dev: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | # run last minute build tools just for local dev 5 | # this file should just be used to override on local dev in a compose file 6 | 7 | # run default entrypoint first 8 | /usr/local/bin/docker-php-entrypoint 9 | 10 | # ensure bind mount permissions are what we need 11 | chown -R :www-data /var/www/app/cache/ \ 12 | /var/www/app/bootstrap/cache/ \ 13 | /var/www/app/public/ \ 14 | /var/www/app/build/ 15 | 16 | chmod -R g+w /var/www/app/cache/ \ 17 | /var/www/app/bootstrap/cache/ \ 18 | /var/www/app/public/ \ 19 | /var/www/app/build/ 20 | 21 | # run last minute build tools just for local dev 22 | cd /var/www/app 23 | composer dump-autoload 24 | cd /var/www/app/public 25 | 26 | 27 | exec "$@" 28 | -------------------------------------------------------------------------------- /install-composer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | EXPECTED_SIGNATURE="$(curl https://composer.github.io/installer.sig)" 4 | php -r "copy('https://getcomposer.org/installer', '/tmp/composer-setup.php');" 5 | ACTUAL_SIGNATURE="$(php -r "echo hash_file('SHA384', '/tmp/composer-setup.php');")" 6 | 7 | if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ] 8 | then 9 | >&2 echo 'ERROR: Invalid installer signature' 10 | rm /tmp/composer-setup.php 11 | exit 1 12 | fi 13 | 14 | php /tmp/composer-setup.php --no-ansi --install-dir=/usr/bin --filename=composer \ 15 | && rm /tmp/composer-setup.php \ 16 | && composer --ansi --version --no-interaction -------------------------------------------------------------------------------- /nginx-site.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | #listen 443 ssl; 4 | 5 | # make sure use Swarm secrets or something to get cert and key into container 6 | #ssl_certificate /etc/nginx/ssl/cert.crt; 7 | #ssl_certificate_key /etc/nginx/ssl/key.pem; 8 | 9 | # Laravel default root I think 10 | root /var/www/app/public; 11 | index index.php index.html index.htm; 12 | 13 | server_name nginx; 14 | 15 | #App paths 16 | location / { 17 | try_files $uri $uri/ /index.php$is_args$args; 18 | } 19 | 20 | location ~ \.php$ { 21 | try_files $uri /index.php =404; 22 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 23 | fastcgi_pass unix:/var/run/php-fpm.sock; 24 | fastcgi_index index.php; 25 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 26 | fastcgi_param PATH_INFO $fastcgi_path_info; 27 | include fastcgi_params; 28 | 29 | # Mitigate https://httpoxy.org/ vulnerabilities 30 | fastcgi_param HTTP_PROXY ""; 31 | } 32 | 33 | # nginx status page, you can make location whatever you want 34 | location /status-nginx { 35 | stub_status on; 36 | access_log off; 37 | } 38 | 39 | # fpm status page and ping page 40 | location ~ ^/(status|ping)$ { 41 | access_log off; 42 | include fastcgi_params; 43 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 44 | fastcgi_pass unix:/var/run/php-fpm.sock; 45 | } 46 | 47 | location ~ /\.ht { 48 | deny all; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | user www-data; 2 | worker_processes auto; 3 | worker_rlimit_nofile 8192; 4 | 5 | error_log /var/log/nginx/error.log warn; 6 | pid /var/run/nginx.pid; 7 | 8 | events { 9 | worker_connections 4096; 10 | multi_accept on; 11 | } 12 | 13 | http { 14 | include /etc/nginx/mime.types; 15 | default_type application/octet-stream; 16 | 17 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 18 | '$status $body_bytes_sent "$http_referer" ' 19 | '"$http_user_agent" "$http_x_forwarded_for"'; 20 | 21 | access_log /var/log/nginx/access.log main; 22 | 23 | sendfile on; 24 | tcp_nopush on; 25 | tcp_nodelay on; 26 | types_hash_max_size 2048; 27 | 28 | keepalive_timeout 65; 29 | 30 | gzip on; 31 | 32 | include /etc/nginx/conf.d/*.conf; 33 | } 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "php-docker-good-defaults", 3 | "version": "1.0.0", 4 | "description": "sample npm config", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/BretFisher/php-docker-good-defaults.git" 12 | }, 13 | "author": "Bret Fisher", 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/BretFisher/php-docker-good-defaults/issues" 17 | }, 18 | "homepage": "https://github.com/BretFisher/php-docker-good-defaults#readme" 19 | } 20 | -------------------------------------------------------------------------------- /supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | user=root 3 | nodaemon=true 4 | logfile=/dev/stdout 5 | logfile_maxbytes=0 6 | pidfile=/var/run/supervisord.pid 7 | loglevel = INFO 8 | 9 | [unix_http_server] 10 | file=/var/run/supervisor.sock 11 | chmod=0700 12 | username=docker 13 | password=docker 14 | 15 | [supervisorctl] 16 | serverurl=unix:///var/run/supervisord.sock 17 | username=docker 18 | password=docker 19 | 20 | [rpcinterface:supervisor] 21 | supervisor.rpcinterface_factory=supervisor.rpcinterface:make_main_rpcinterface 22 | 23 | [program:php-fpm] 24 | command = /usr/local/sbin/php-fpm 25 | autostart=true 26 | autorestart=true 27 | priority=5 28 | stdout_logfile=/dev/stdout 29 | stdout_logfile_maxbytes=0 30 | stderr_logfile=/dev/stderr 31 | stderr_logfile_maxbytes=0 32 | 33 | [program:nginx] 34 | command=/usr/sbin/nginx -g "daemon off;" 35 | autostart=true 36 | autorestart=true 37 | priority=10 38 | stdout_events_enabled=true 39 | stderr_events_enabled=true 40 | stdout_logfile=/dev/stdout 41 | stdout_logfile_maxbytes=0 42 | stderr_logfile=/dev/stderr 43 | stderr_logfile_maxbytes=0 44 | --------------------------------------------------------------------------------