From 5e5541386d548d4cddde9a11f8aec8658535429c Mon Sep 17 00:00:00 2001 From: Nick Jones Date: Fri, 12 Feb 2016 10:33:57 +0000 Subject: [PATCH] Add Magento 2 services --- .gitignore | 2 + 7.0-cli/Dockerfile | 55 ++++++++++++ 7.0-cli/bin/docker-environment | 29 +++++++ 7.0-cli/bin/magento-command | 8 ++ 7.0-cli/bin/magento-installer | 47 ++++++++++ 7.0-cli/etc/php.ini | 3 + 7.0-fpm/Dockerfile | 50 +++++++++++ 7.0-fpm/bin/docker-environment | 20 +++++ 7.0-fpm/etc/php-fpm.conf | 29 +++++++ 7.0-fpm/etc/php.ini | 3 + Readme.md | 50 +++++++++++ composer.env.sample | 3 + docker-compose.yml | 79 +++++++++++++++++ global.env | 4 + nginx/Dockerfile | 16 ++++ nginx/bin/docker-environment | 16 ++++ nginx/etc/vhost.conf | 153 +++++++++++++++++++++++++++++++++ 17 files changed, 567 insertions(+) create mode 100644 .gitignore create mode 100644 7.0-cli/Dockerfile create mode 100755 7.0-cli/bin/docker-environment create mode 100755 7.0-cli/bin/magento-command create mode 100755 7.0-cli/bin/magento-installer create mode 100644 7.0-cli/etc/php.ini create mode 100644 7.0-fpm/Dockerfile create mode 100755 7.0-fpm/bin/docker-environment create mode 100644 7.0-fpm/etc/php-fpm.conf create mode 100644 7.0-fpm/etc/php.ini create mode 100644 Readme.md create mode 100644 composer.env.sample create mode 100644 docker-compose.yml create mode 100644 global.env create mode 100644 nginx/Dockerfile create mode 100755 nginx/bin/docker-environment create mode 100644 nginx/etc/vhost.conf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9cebb7b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/composer.env +/magento diff --git a/7.0-cli/Dockerfile b/7.0-cli/Dockerfile new file mode 100644 index 0000000..1fc6634 --- /dev/null +++ b/7.0-cli/Dockerfile @@ -0,0 +1,55 @@ +# +# Command line, PHP 7.0, Magento 2 compatible container. +# +# Credit to Mark Shust for the basis of this +# Dockerfile in the https://github.com/mageinferno/docker-magento2-php project. +# + +FROM php:7.0-cli + +MAINTAINER Nick Jones + +# Install dependencies +RUN apt-get update \ + && apt-get install -y \ + cron \ + libfreetype6-dev \ + libicu-dev \ + libjpeg62-turbo-dev \ + libmcrypt-dev \ + libpng12-dev \ + libxslt1-dev + +# Configure the gd library +RUN docker-php-ext-configure \ + gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ + +# Install required PHP extensions +RUN docker-php-ext-install \ + gd \ + intl \ + mbstring \ + mcrypt \ + pdo_mysql \ + xsl \ + zip + +# Get composer installed to /usr/local/bin/composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +VOLUME /root/.composer/cache + +ADD bin/* /usr/local/bin/ +ADD etc/php.ini /usr/local/etc/php/conf.d/zz-magento.ini + +ENV PHP_MEMORY_LIMIT 2G +ENV MAGENTO_ROOT /magento +ENV COMPOSER_GITHUB_TOKEN "" +ENV COMPOSER_MAGENTO_USERNAME "" +ENV COMPOSER_MAGENTO_PASSWORD "" +ENV DEBUG false +ENV IS_OSX false + +ENTRYPOINT ["/usr/local/bin/docker-environment"] + +CMD ["bash"] diff --git a/7.0-cli/bin/docker-environment b/7.0-cli/bin/docker-environment new file mode 100755 index 0000000..dec6931 --- /dev/null +++ b/7.0-cli/bin/docker-environment @@ -0,0 +1,29 @@ +#!/bin/bash + +[ "$DEBUG" = "true" ] && set -x + +# If we're using OSX then we need to mess with the permissions +if [[ "$IS_OSX" = "true" ]]; then + echo "OSX flag is set, changing www-data uid/gid" + + usermod -u 501 www-data + groupmod -g 9920 dialout # Move dialout from 20 to make room for www-data + groupmod -g 20 www-data +fi + +# Ensure our Magento directory exists +mkdir -p $MAGENTO_ROOT +chown www-data:www-data $MAGENTO_ROOT + +# Configure PHP +[ ! -z "${PHP_MEMORY_LIMIT}" ] && sed -i "s/!PHP_MEMORY_LIMIT!/${PHP_MEMORY_LIMIT}/" /usr/local/etc/php/conf.d/zz-magento.ini + +# Configure composer +[ ! -z "${COMPOSER_GITHUB_TOKEN}" ] && \ + composer config --global github-oauth.github.com $COMPOSER_GITHUB_TOKEN + +[ ! -z "${COMPOSER_MAGENTO_USERNAME}" ] && \ + composer config --global http-basic.repo.magento.com \ + $COMPOSER_MAGENTO_USERNAME $COMPOSER_MAGENTO_PASSWORD + +exec "$@" diff --git a/7.0-cli/bin/magento-command b/7.0-cli/bin/magento-command new file mode 100755 index 0000000..b90fc58 --- /dev/null +++ b/7.0-cli/bin/magento-command @@ -0,0 +1,8 @@ +#!/bin/bash + +[ "$DEBUG" = "true" ] && set -x + +MAGENTO_COMMAND="$MAGENTO_ROOT/bin/magento" + +chmod +x $MAGENTO_COMMAND +su -c "$MAGENTO_COMMAND $*" -s /bin/bash www-data diff --git a/7.0-cli/bin/magento-installer b/7.0-cli/bin/magento-installer new file mode 100755 index 0000000..5a7472c --- /dev/null +++ b/7.0-cli/bin/magento-installer @@ -0,0 +1,47 @@ +#!/bin/bash + +[ "$DEBUG" = "true" ] && set -x + +# Get composer auth information into an environment variable to avoid "you need +# to be using an interactive terminal to authenticate". +COMPOSER_AUTH=`cat /root/.composer/auth.json` + +composer --version + +echo "Creating Magento ($M2SETUP_VERSION) project from composer" + +composer create-project \ + --repository-url=https://repo.magento.com/ \ + magento/project-community-edition=$M2SETUP_VERSION \ + --no-interaction \ + $MAGENTO_ROOT + +echo "Install Magento" + +php /magento/bin/magento setup:install \ + --db-host=$M2SETUP_DB_HOST \ + --db-name=$M2SETUP_DB_NAME \ + --db-user=$M2SETUP_DB_USER \ + --db-password=$M2SETUP_DB_PASSWORD \ + --base-url=$M2SETUP_BASE_URL \ + --admin-firstname=$M2SETUP_ADMIN_FIRSTNAME \ + --admin-lastname=$M2SETUP_ADMIN_LASTNAME \ + --admin-email=$M2SETUP_ADMIN_EMAIL \ + --admin-user=$M2SETUP_ADMIN_USER \ + --admin-password=$M2SETUP_ADMIN_PASSWORD + +php /magento/bin/magento index:reindex +php /magento/bin/magento setup:static-content:deploy + +echo "Fixing file permissions.." + +sed -i 's/0770/0775/g' $MAGENTO_ROOT/vendor/magento/framework/Filesystem/DriverInterface.php +sed -i 's/0660/0664/g' $MAGENTO_ROOT/vendor/magento/framework/Filesystem/DriverInterface.php + +find $MAGENTO_ROOT/pub -type f -exec chmod 664 {} \; +find $MAGENTO_ROOT/pub -type d -exec chmod 775 {} \; +find $MAGENTO_ROOT/var/generation -type d -exec chmod g+s {} \; + +chown -R www-data:www-data $MAGENTO_ROOT + +echo "Installation complete" diff --git a/7.0-cli/etc/php.ini b/7.0-cli/etc/php.ini new file mode 100644 index 0000000..0a1cf51 --- /dev/null +++ b/7.0-cli/etc/php.ini @@ -0,0 +1,3 @@ +; This file is created automatically by the docker build + +memory_limit = !PHP_MEMORY_LIMIT! ; Variable: PHP_MEMORY_LIMIT diff --git a/7.0-fpm/Dockerfile b/7.0-fpm/Dockerfile new file mode 100644 index 0000000..9831437 --- /dev/null +++ b/7.0-fpm/Dockerfile @@ -0,0 +1,50 @@ +# +# FPM, PHP 7.0, Magento 2 compatible container. +# +# Credit to Mark Shust for the basis of this +# Dockerfile in the https://github.com/mageinferno/docker-magento2-php project. +# + +FROM php:7.0-fpm + +MAINTAINER Nick Jones + +# Install dependencies +RUN apt-get update \ + && apt-get install -y \ + cron \ + libfreetype6-dev \ + libicu-dev \ + libjpeg62-turbo-dev \ + libmcrypt-dev \ + libpng12-dev \ + libxslt1-dev + +# Configure the gd library +RUN docker-php-ext-configure \ + gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ + +# Install required PHP extensions +RUN docker-php-ext-install \ + gd \ + intl \ + mbstring \ + mcrypt \ + pdo_mysql \ + xsl \ + zip + +VOLUME /root/.composer/cache + +ADD bin/docker-environment /usr/local/bin/ +ADD etc/php.ini /usr/local/etc/php/conf.d/zz-magento.ini +ADD etc/php-fpm.conf /usr/local/etc/ + +ENV PHP_MEMORY_LIMIT 2G +ENV MAGENTO_ROOT /magento +ENV MAGENTO_RUN_MODE developer +ENV DEBUG false +ENV IS_OSX false + +ENTRYPOINT ["/usr/local/bin/docker-environment"] +CMD ["php-fpm", "-F"] diff --git a/7.0-fpm/bin/docker-environment b/7.0-fpm/bin/docker-environment new file mode 100755 index 0000000..b4a39b4 --- /dev/null +++ b/7.0-fpm/bin/docker-environment @@ -0,0 +1,20 @@ +#!/bin/bash + +[ "$DEBUG" = "true" ] && set -x + +# If we're using OSX then we need to mess with the permissions +if [[ "$IS_OSX" = "true" ]]; then + echo "OSX flag is set, changing www-data uid/gid" + + usermod -u 501 www-data + groupmod -g 9920 dialout # Move dialout from 20 to make room for www-data + groupmod -g 20 www-data +fi + +# Configure PHP +[ ! -z "${PHP_MEMORY_LIMIT}" ] && sed -i "s/!PHP_MEMORY_LIMIT!/${PHP_MEMORY_LIMIT}/" /usr/local/etc/php/conf.d/zz-magento.ini + +# Configure PHP-FPM +[ ! -z "${MAGENTO_RUN_MODE}" ] && sed -i "s/!MAGENTO_RUN_MODE!/${MAGENTO_RUN_MODE}/" /usr/local/etc/php-fpm.conf + +exec "$@" diff --git a/7.0-fpm/etc/php-fpm.conf b/7.0-fpm/etc/php-fpm.conf new file mode 100644 index 0000000..ee89ce8 --- /dev/null +++ b/7.0-fpm/etc/php-fpm.conf @@ -0,0 +1,29 @@ +; This file is created automatically by the docker build + +[global] + +error_log = /proc/self/fd/2 +daemonize = no + +[www] + +; if we send this to /proc/self/fd/1, it never appears +access.log = /proc/self/fd/2 + +user = www-data +group = www-data + +listen = [::]:9000 + +pm = dynamic +pm.max_children = 10 +pm.start_servers = 4 +pm.min_spare_servers = 2 +pm.max_spare_servers = 6 + +env[MAGE_MODE] = !MAGENTO_RUN_MODE!; # Variable: MAGENTO_RUN_MODE + +clear_env = no + +; Ensure worker stdout and stderr are sent to the main error log. +catch_workers_output = yes diff --git a/7.0-fpm/etc/php.ini b/7.0-fpm/etc/php.ini new file mode 100644 index 0000000..0a1cf51 --- /dev/null +++ b/7.0-fpm/etc/php.ini @@ -0,0 +1,3 @@ +; This file is created automatically by the docker build + +memory_limit = !PHP_MEMORY_LIMIT! ; Variable: PHP_MEMORY_LIMIT diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..ab717c8 --- /dev/null +++ b/Readme.md @@ -0,0 +1,50 @@ +#Magento 2 Docker + +## Quick Start + + cp composer.env.sample composer.env + # ..put the correct tokens into composer.env + + docker-compose run cli magento-installer + docker-compose up -d + docker-compose restart + +## Configuration + +Configuration is driven through environment variables. A comprehensive list of the environment variables used can be found in each `Dockerfile` and the commands in each `bin/` directory. + +* `PHP_MEMORY_LIMIT` - The memory limit to be set in the `php.ini` +* `MAGENTO_ROOT` - The directory to which Magento should be installed +* `MAGENTO_RUN_MODE` - Valid values, as defined in `Magento\Framework\App\State`: `developer`, `production`, `default`. +* `COMPOSER_GITHUB_TOKEN` - Your [GitHub OAuth token](https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens), should it be needed +* `COMPOSER_MAGENTO_USERNAME` - Your Magento Connect public authentication key ([how to get](http://devdocs.magento.com/guides/v2.0/install-gde/prereq/connect-auth.html)) +* `COMPOSER_MAGENTO_PASSWORD` - Your Magento Connect private authentication key +* `DEBUG` - Toggles tracing in the bash commands when exectued; nothing to do with Magento` +* `IS_OSX` - If this is set to "true" then the uid and gid of `www-data` will be modified in the container + +A sample `docker-compose.yml` is provided in this repository. + +## CLI Usage + +A number of commands are baked into the image and are available on the `$PATH`. These are: + +* `magento-command` - Provides a user-safe wrapper around the `bin/magento` command. +* `magento-installer` - Installs and configures Magento into the directory defined in the `$MAGENTO_ROOT` environment variable. + +It's recommended that you mount an external folder to `/root/.composer/cache`, otherwise you'll be waiting all day for Magento to download every time the container is booted. + +CLI commands can be triggered by running: + + docker-compose run cli magento-installer + +Shell access to a CLI container can be triggered by running: + + docker-compose run cli bash + +## Implementation Notes + +* In order to achieve a sane environment for executing commands in, a `docker-environment` script is included as the `ENTRYPOINT` in the container. + +## Credits + +Thanks to [Mark Shust](https://twitter.com/markshust) for his work on [docker-magento2-php](https://github.com/mageinferno/docker-magento2-php) that was used as a basis for this implementation. You solved a lot of the problems so I didn't need to! diff --git a/composer.env.sample b/composer.env.sample new file mode 100644 index 0000000..aaecf28 --- /dev/null +++ b/composer.env.sample @@ -0,0 +1,3 @@ +COMPOSER_GITHUB_TOKEN=0000000000000000000000000000000000000000 +COMPOSER_MAGENTO_USERNAME=00000000000000000000000000000000 +COMPOSER_MAGENTO_PASSWORD=00000000000000000000000000000000 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..5be1e5a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,79 @@ +version: "2" +services: + web: + # image: meanbee/magento2-nginx + build: + context: ./nginx + ports: + - "80:80" + links: + - fpm + - db + volumes_from: + - appdata + env_file: + - ./global.env + environment: + - VIRTUAL_HOST=magento2.docker + + fpm: + # image: meanbee/magento2-php-fpm:7.0 + build: + context: ./7.0-fpm + ports: + - 9000 + links: + - db + volumes_from: + - appdata + env_file: + - ./global.env + + db: + image: mariadb:10 + ports: + - 3306 + volumes_from: + - dbdata + environment: + - MYSQL_ROOT_PASSWORD=magento2 + - MYSQL_DATABASE=magento2 + - MYSQL_USER=magento2 + - MYSQL_PASSWORD=magento2 + + cli: +# image: meanbee/magento2-php-fpm:7.0 + build: + context: ./7.0-cli + links: + - db + volumes: + - ~/.composer/cache:/root/.composer/cache + volumes_from: + - appdata + env_file: + - ./global.env + - ./composer.env + environment: + - M2SETUP_DB_HOST=db + - M2SETUP_DB_NAME=magento2 + - M2SETUP_DB_USER=magento2 + - M2SETUP_DB_PASSWORD=magento2 + - M2SETUP_BASE_URL=http://magento2.docker/ + - M2SETUP_ADMIN_FIRSTNAME=Admin + - M2SETUP_ADMIN_LASTNAME=User + - M2SETUP_ADMIN_EMAIL=dummy@gmail.com + - M2SETUP_ADMIN_USER=admin + - M2SETUP_ADMIN_PASSWORD=password1 + - M2SETUP_VERSION=2.0.2 + # - M2SETUP_USE_SAMPLE_DATA=true + + appdata: + image: tianon/true + volumes: + - ./magento:/magento + + dbdata: + image: tianon/true + volumes: + - /var/lib/mysql diff --git a/global.env b/global.env new file mode 100644 index 0000000..8389c5d --- /dev/null +++ b/global.env @@ -0,0 +1,4 @@ +MAGENTO_RUN_MODE=developer +PHP_MEMORY_LIMIT=2048M +IS_OSX=true +DEBUG=false diff --git a/nginx/Dockerfile b/nginx/Dockerfile new file mode 100644 index 0000000..39a9917 --- /dev/null +++ b/nginx/Dockerfile @@ -0,0 +1,16 @@ +FROM nginx:1.9 + +MAINTAINER Nick Jones + +ADD etc/vhost.conf /etc/nginx/conf.d/default.conf +ADD bin/* /usr/local/bin/ + +ENV FPM_HOST fpm +ENV FPM_PORT 9000 +ENV VIRTUAL_HOST magento.docker +ENV MAGENTO_ROOT /magento +ENV MAGENTO_RUN_MODE developer +ENV DEBUG false + +ENTRYPOINT ["/usr/local/bin/docker-environment"] +CMD ["nginx", "-g", "daemon off;"] diff --git a/nginx/bin/docker-environment b/nginx/bin/docker-environment new file mode 100755 index 0000000..b28d1be --- /dev/null +++ b/nginx/bin/docker-environment @@ -0,0 +1,16 @@ +#!/bin/bash + +[ "$DEBUG" = "true" ] && set -x + +VHOST_FILE="/etc/nginx/conf.d/default.conf" + +[ ! -z "${FPM_HOST}" ] && sed -i "s/!FPM_HOST!/${FPM_HOST}/" $VHOST_FILE +[ ! -z "${FPM_PORT}" ] && sed -i "s/!FPM_PORT!/${FPM_PORT}/" $VHOST_FILE +[ ! -z "${VIRTUAL_HOST}" ] && sed -i "s/!VIRTUAL_HOST!/${VIRTUAL_HOST}/" $VHOST_FILE +[ ! -z "${MAGENTO_ROOT}" ] && sed -i "s#!MAGENTO_ROOT!#${MAGENTO_ROOT}#" $VHOST_FILE +[ ! -z "${MAGENTO_RUN_MODE}" ] && sed -i "s/!MAGENTO_RUN_MODE!/${MAGENTO_RUN_MODE}/" $VHOST_FILE + +# Check if the nginx syntax is fine, then launch. +nginx -t + +exec "$@" diff --git a/nginx/etc/vhost.conf b/nginx/etc/vhost.conf new file mode 100644 index 0000000..dddb78c --- /dev/null +++ b/nginx/etc/vhost.conf @@ -0,0 +1,153 @@ +# This file is created automatically by the docker build + +upstream fastcgi_backend { + server !FPM_HOST!:!FPM_PORT!; # Variables: FPM_HOST and FPM_PORT +} + +server { + listen 80; + + server_name !VIRTUAL_HOST!; # Variable: VIRTUAL_HOST + + set $MAGE_ROOT !MAGENTO_ROOT!; # Variable: MAGENTO_ROOT + set $MAGE_MODE !MAGENTO_RUN_MODE!; # Variable: MAGENTO_RUN_MODE + + root $MAGE_ROOT/pub; + + index index.php; + autoindex off; + charset off; + + location /setup { + root $MAGE_ROOT; + location ~ ^/setup/index.php { + fastcgi_pass fastcgi_backend; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } + + location ~ ^/setup/(?!pub/). { + deny all; + } + + location ~ ^/setup/pub/ { + add_header X-Frame-Options "SAMEORIGIN"; + } + } + + location /update { + root $MAGE_ROOT; + + location ~ ^/update/index.php { + fastcgi_split_path_info ^(/update/index.php)(/.+)$; + fastcgi_pass fastcgi_backend; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + include fastcgi_params; + } + + # deny everything but index.php + location ~ ^/update/(?!pub/). { + deny all; + } + + location ~ ^/update/pub/ { + add_header X-Frame-Options "SAMEORIGIN"; + } + } + + location / { + try_files $uri $uri/ /index.php?$args; + } + + location /pub { + location ~ ^/pub/media/(downloadable|customer|import|theme_customization/.*\.xml) { + deny all; + } + alias $MAGE_ROOT/pub; + add_header X-Frame-Options "SAMEORIGIN"; + } + + location /static/ { + if ($MAGE_MODE = "production") { + expires max; + } + location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ { + add_header Cache-Control "public"; + add_header X-Frame-Options "SAMEORIGIN"; + expires +1y; + + if (!-f $request_filename) { + rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last; + } + } + location ~* \.(zip|gz|gzip|bz2|csv|xml)$ { + add_header Cache-Control "no-store"; + add_header X-Frame-Options "SAMEORIGIN"; + expires off; + + if (!-f $request_filename) { + rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last; + } + } + if (!-f $request_filename) { + rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last; + } + add_header X-Frame-Options "SAMEORIGIN"; + } + + location /media/ { + try_files $uri $uri/ /get.php?$args; + + location ~ ^/media/theme_customization/.*\.xml { + deny all; + } + + location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ { + add_header Cache-Control "public"; + add_header X-Frame-Options "SAMEORIGIN"; + expires +1y; + try_files $uri $uri/ /get.php?$args; + } + location ~* \.(zip|gz|gzip|bz2|csv|xml)$ { + add_header Cache-Control "no-store"; + add_header X-Frame-Options "SAMEORIGIN"; + expires off; + try_files $uri $uri/ /get.php?$args; + } + add_header X-Frame-Options "SAMEORIGIN"; + } + + location /media/customer/ { + deny all; + } + + location /media/downloadable/ { + deny all; + } + + location /media/import/ { + deny all; + } + + location ~ cron\.php { + deny all; + } + + location ~ (index|get|static|report|404|503)\.php$ { + try_files $uri =404; + fastcgi_pass fastcgi_backend; + + fastcgi_param PHP_FLAG "session.auto_start=off \n suhosin.session.cryptua=off"; + fastcgi_param PHP_VALUE "memory_limit=256M \n max_execution_time=600"; + fastcgi_read_timeout 600s; + fastcgi_connect_timeout 600s; + fastcgi_param MAGE_MODE $MAGE_MODE; + + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } +}