Skip to content

Commit

Permalink
change lic date
Browse files Browse the repository at this point in the history
  • Loading branch information
BretFisher committed Dec 26, 2017
1 parent dd3015e commit 610f33e
Show file tree
Hide file tree
Showing 10 changed files with 520 additions and 1 deletion.
96 changes: 96 additions & 0 deletions Dockerfile
@@ -0,0 +1,96 @@
FROM yourdockername/base-php-nginx:latest

# add bitbucket and github to known hosts for ssh needs
RUN ssh-keyscan -t rsa bitbucket.org >> /root/.ssh/known_hosts \
&& ssh-keyscan -t rsa github.com >> /root/.ssh/known_hosts

##
## Compose Package Manager
##

# install composer dependencies
WORKDIR /var/www/app
COPY ./composer.json ./composer.lock ./
ENV COMPOSER_VENDOR_DIR=/var/www/vendor
# RUN composer config github-oauth.github.com YOUROAUTHKEYHERE
RUN composer install --no-scripts --no-autoloader --ansi --no-interaction

##
## Node Build Tools
##

# we hardcode to develop so all tools are there for npm build
ENV NODE_ENV=develop
# install dependencies first, in a different location for easier app bind mounting for local development
WORKDIR /var/www
COPY ./package.json .
RUN npm install
# no need to cache clean in non-final build steps
ENV PATH /var/www/node_modules/.bin:$PATH
ENV NODE_PATH=/var/www/node_modules
WORKDIR /var/www/app

##
## We Are Go for Bower
##

COPY ./bower.json .
RUN bower install --allow-root

# ensure node can reach our modules
ENV PATH /var/www/node_modules/.bin:$PATH
ENV NODE_PATH=/var/www/node_modules

# ensure compose can fine its vendor
ENV COMPOSER_VENDOR_DIR=/var/www/vendor

# add custom php-fpm pool settings, these get written at entrypoint startup
ENV FPM_PM_MAX_CHILDREN=20 \
FPM_PM_START_SERVERS=2 \
FPM_PM_MIN_SPARE_SERVERS=1 \
FPM_PM_MAX_SPARE_SERVERS=3

# Laravel App Config
# setup app config environment at runtime
# gets put into ./.env at startup
ENV APP_NAME=Laravel \
APP_ENV=local \
APP_DEBUG=true \
APP_KEY=KEYGOESHERE \
APP_LOG=errorlog \
APP_URL=http://localhost \
DB_CONNECTION=mysql \
DB_HOST=mysql \
DB_PORT=3306 \
DB_DATABASE=homestead \
DB_USERNAME=homestead \
DB_PASSWORD=secret
# Many more ENV may be needed here, and updated in docker-php-entrypoint file


# update the entrypoint to write config files and do last minute builds on startup
# notice we have a -dev version, which does different things on local docker-compose
# but we'll default to entrypoint of running the non -dev one
COPY docker-php-* /usr/local/bin/
RUN dos2unix /usr/local/bin/docker-php-entrypoint
RUN dos2unix /usr/local/bin/docker-php-entrypoint-dev


# copy in nginx config
COPY ./nginx.conf /etc/nginx/nginx.conf
COPY ./nginx-site.conf /etc/nginx/conf.d/default.conf


# copy in app code as late as possible, as it changes the most
WORKDIR /var/www/app
COPY --chown=www-data:www-data . .
RUN composer dump-autoload -o

# be sure nginx is properly passing to php-fpm and fpm is responding
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -f http://localhost/ping || exit 1

WORKDIR /var/www/app/public
EXPOSE 80 443 9000 9001

CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
2 changes: 1 addition & 1 deletion LICENSE
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2017 Bret Fisher
Copyright (c) Bret Fisher

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
65 changes: 65 additions & 0 deletions README.md
@@ -0,0 +1,65 @@
## PHP (Laravel) + Docker Hello World, for Showing Good Defaults for Using A PHP Stack in Docker

> 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.
**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.

### Local Development Features

- **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.
- **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`.
- **One line startup**. Uses `docker-compose up` for single-line build and run of local development server.
- **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.
- **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.
- **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.


### Production-minded Features

- **Use Docker build-in healthchecks**. uses Dockerfile `HEALTHCHECK` with php-fpm `/ping` route to help Docker know if your container is running properly.


### Assumptions

- You have Docker and Docker-Compose installed (Docker for Mac, Docker for Windows, get.docker.com and manual Compose installed for Linux).
- 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.
- You don't want to loose 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.
- You use `docker-compose` for local development only (docker-compose was never intended to be a production deployment tool anyway).
- The `docker-compose.yml` is not meant for `docker stack deploy` in Docker Swarm, it's meant for happy local development.


### Getting Started

If this was your app, to start local development you would:

- Running `docker-compose up` is all you need. It will:
- Build custom local image enabled for development.
- Start container from that image with ports 80, 443, 9000, and 9001 open (on localhost or docker-machine).
- Mounts the pwd to the app dir in container.
- 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`.
- 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.
- Be sure to use `docker-compose down` to cleanup after your done dev'ing.



MIT License,

Copyright (c) Bret Fisher

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
144 changes: 144 additions & 0 deletions base-php-nginx.Dockerfile
@@ -0,0 +1,144 @@
FROM php:7.2-fpm


ENV COMPOSER_VERSION=1.5.5 \
NGINX_VERSION=1.12.2-1~jessie \
NJS_VERSION=1.12.2.0.1.14-1~jessie \
NODE_VERSION=6.12.1

# this is a sample BASE image, that php_fpm projects can start FROM
# it's got a lot in it, but it's designed to meet dev and prod needs in single image
# I've tried other things like splitting out php_fpm and nginx containers
# or multi-stage builds to keep it lean, but this is my current design for
## single image that does nginx and php_fpm
## usable with bind-mount and unique dev-only entrypoint file that builds
## some things on startup when developing locally
## stores all code in image with proper default builds for production

# install apt dependencies
# some of these are not needed in all php projects
# NOTE: you should prob use specific versions of some of these so you don't break your app
RUN apt-get update && apt-get install --no-install-recommends --no-install-suggests -y \
ca-certificates \
curl \
dos2unix \
git \
gnupg2 \
g++ \
jq \
libedit-dev \
libfcgi0ldbl \
libfreetype6-dev \
libicu-dev \
libjpeg62-turbo-dev \
libmcrypt-dev \
libpq-dev \
libssl-dev \
openssh-client \
supervisor \
unzip \
zip \
&& rm -r /var/lib/apt/lists/*


# Install extensions using the helper script provided by the base image
RUN docker-php-ext-install \
pdo_mysql \
mysqli \
json \
readline \
gd \
intl

# configure gd
RUN docker-php-ext-configure gd \
--enable-gd-native-ttf \
--with-freetype-dir=/usr/include/freetype2 \
--with-jpeg-dir=/usr/include/

# configure intl
RUN docker-php-ext-configure intl


# install nginx (copied from official nginx Dockerfile)
RUN NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62; \
found=''; \
for server in \
ha.pool.sks-keyservers.net \
hkp://keyserver.ubuntu.com:80 \
hkp://p80.pool.sks-keyservers.net:80 \
pgp.mit.edu \
; do \
echo "Fetching GPG key $NGINX_GPGKEY from $server"; \
apt-key adv --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" && found=yes && break; \
done; \
test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" && exit 1; \
echo "deb http://nginx.org/packages/debian/ jessie nginx" >> /etc/apt/sources.list \
&& apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y \
nginx=${NGINX_VERSION} \
nginx-module-xslt=${NGINX_VERSION} \
nginx-module-geoip=${NGINX_VERSION} \
nginx-module-image-filter=${NGINX_VERSION} \
nginx-module-njs=${NJS_VERSION} \
gettext-base \
&& rm -rf /var/lib/apt/lists/*

# forward nginx request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log

# install composer so we can run dump-autoload at entrypoint startup in dev
# copied from official composer Dockerfile
ENV PATH="/composer/vendor/bin:$PATH" \
COMPOSER_ALLOW_SUPERUSER=1 \
COMPOSER_VENDOR_DIR=/var/www/vendor \
COMPOSER_HOME=/composer
RUN curl -s -f -L -o /tmp/installer.php https://raw.githubusercontent.com/composer/getcomposer.org/da290238de6d63faace0343efbdd5aa9354332c5/web/installer \
&& php -r " \
\$signature = '669656bab3166a7aff8a7506b8cb2d1c292f042046c5a994c43155c0be6190fa0355160742ab2e1c88d40d5be660b410'; \
\$hash = hash('SHA384', file_get_contents('/tmp/installer.php')); \
if (!hash_equals(\$signature, \$hash)) { \
unlink('/tmp/installer.php'); \
echo 'Integrity check failed, installer is either corrupt or worse.' . PHP_EOL; \
exit(1); \
}" \
&& php /tmp/installer.php --no-ansi --install-dir=/usr/bin --filename=composer --version=${COMPOSER_VERSION} \
&& rm /tmp/installer.php \
&& composer --ansi --version --no-interaction


# install node for running gulp at container entrypoint startup in dev
# copied from official node Dockerfile
# gpg keys listed at https://github.com/nodejs/node#release-team
RUN set -ex \
&& for key in \
9554F04D7259F04124DE6B476D5A82AC7E37093B \
94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
FD3A5288F042B6850C66B31F09FE44734EB7990E \
71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
B9AE9905FFD7803F25714661B63B535A4C206CA9 \
C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
56730D5401028683275BD23C23EFEFE93C4CFFFE \
; do \
gpg --keyserver pgp.mit.edu --recv-keys "$key" || \
gpg --keyserver keyserver.pgp.com --recv-keys "$key" || \
gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key" ; \
done

ENV NPM_CONFIG_LOGLEVEL info

RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
&& grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
&& tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 \
&& rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs

ENV PATH /var/www/node_modules/.bin:$PATH

COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
55 changes: 55 additions & 0 deletions docker-compose.yml
@@ -0,0 +1,55 @@
version: '3.3'

services:
php:
# note you need to manually build this image from base dockerfile above FIRST!
image: yourdockername/base-php-nginx
build: .
volumes:
# used delegated mode here on docker for mac for faster disk I/O
- .:/var/www/app:delegated
- ./supervisord.conf:/etc/supervisor/conf.d/supervisord.conf
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/nginx-site.conf:/etc/nginx/conf.d/default.conf
# mount in dev certs if you want to dev over ssl
#- ./dev-cert.crt:/etc/nginx/ssl/cert.crt
#- ./dev-key.pem:/etc/nginx/ssl/key.pem
entrypoint: /usr/local/bin/docker-php-entrypoint-dev
command: ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
ports:
- "8080:80"
- "8443:443"
- "9001:9001"
depends_on:
- mysql
environment:
APP_NAME: Laravel
APP_ENV: local
APP_DEBUG: true
APP_KEY: KEYGOESHERE
APP_LOG: errorlog
APP_URL: "http://localhost"
DB_CONNECTION: mysql
DB_HOST: mysql
DB_PORT: 3306
DB_DATABASE: homestead
DB_USERNAME: homestead
DB_PASSWORD: secret

mysql:
image: mysql:5.7
volumes:
- mysql:/var/lib/mysql
ports:
# we only expose this port in local dev for using mysql tools/guis on your host
- "3306:3306"
environment:
MYSQL_DATABASE: ${DB_DATABASE:-homestead}
MYSQL_USER: ${DB_USERNAME:-homestead}
MYSQL_PASSWORD: ${DB_PASSWORD:-secret}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-secret}

# using this named volume ensures db's hang around between "up's"
volumes:
mysql:

17 changes: 17 additions & 0 deletions docker-php-entrypoint
@@ -0,0 +1,17 @@
#!/bin/sh
set -e

# write the php-fpm config
{ \
echo listen = /var/run/php-fpm.sock; \
echo listen.owner = www-data; \
echo listen.group = www-data; \
echo ping.path = /ping; \
echo pm.status_path = /status; \
echo pm.max_children = "$FPM_PM_MAX_CHILDREN"; \
echo pm.start_servers = "$FPM_PM_START_SERVERS"; \
echo pm.min_spare_servers = "$FPM_PM_MIN_SPARE_SERVERS"; \
echo pm.max_spare_servers = "$FPM_PM_MAX_SPARE_SERVERS"; \
} > /usr/local/etc/php-fpm.d/zzz-app.conf

exec "$@"

0 comments on commit 610f33e

Please sign in to comment.