From 97d537d35d0b13b70e2931308cb2ce69d69a2db7 Mon Sep 17 00:00:00 2001 From: Donovan Muller Date: Sun, 4 Sep 2016 21:43:26 +0200 Subject: [PATCH] Updated to Ghost 0.9. Added Docker Cloud support and updated README. Added styling for blockquotes. Updated Sass and Bourbon Neat and included source maps. Other dependency updates. --- .gitignore | 3 +- README.md | 129 +++++++++++++++++++------- app/assets/scss/base/_typography.scss | 7 ++ app/assets/scss/screen.scss | 1 - app/package.json | 6 +- docker/cloud/docker-cloud.yml | 15 +++ docker/content/Dockerfile | 2 +- docker/docker-compose.https.yml | 72 ++++++++++++++ docker/docker-compose.yml | 8 +- docker/ghost/Dockerfile | 10 +- docker/ghost/brage-entrypoint.sh | 11 --- docker/ghost/config-prod.js | 2 +- docker/nginx/Dockerfile | 2 +- docker/nginx/brage-blog | 10 +- docker/nginx/nginx.conf | 5 +- gulp/config.js | 4 +- gulp/tasks/development/sass.js | 20 ++-- gulp/tasks/development/watch.js | 2 +- gulp/tasks/ghost-reset.js | 6 +- package.json | 22 +++-- 20 files changed, 238 insertions(+), 99 deletions(-) create mode 100644 docker/cloud/docker-cloud.yml create mode 100644 docker/docker-compose.https.yml delete mode 100755 docker/ghost/brage-entrypoint.sh diff --git a/.gitignore b/.gitignore index 5b8bf9f..5c5b748 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,11 @@ node_modules app/bower_components -dist* +/dist* .tmp .sass-cache .idea *.iml +*.map # Ghost *.db diff --git a/README.md b/README.md index 782de3e..84c0289 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Brage Theme Screenshot](http://i.imgur.com/0ydeDsH.png) -**Live demo at [brage.switchbit.io](http://brage.switchbit.io/)** +**Live demo at [brage.switchbit.io](https://brage.switchbit.io/)** # Brage Ghost Theme @@ -8,7 +8,7 @@ A [Ghost](https://ghost.org/) theme built using Gulp. This theme can be used as is or as a seed project for developing your own Ghost theme using Gulp to simplify and speed up development. -Please read the following post for a more detailed description of the various Gulp tasks: **[blog.switchbit.io/developing-a-ghost-theme-with-gulp](http://blog.switchbit.io/developing-a-ghost-theme-with-gulp)** +Please read the following blog series for a more detailed description: **[blog.switchbit.io/tag/ghost-tag](https://blog.switchbit.io/tag/ghost-tag/)** To make developing a custom Ghost theme as seamless as possible, you would expect the following: @@ -26,6 +26,8 @@ As well as the usual suspects for optimising our assets. The layout of the Gulp tasks as well as some of the configurations are inspired by Stefan Imhoff's ["Introduction to Gulp.js 15: Performance Improvements with WebP and Gzip"](http://stefanimhoff.de/2014/gulp-tutorial-15-performance-improvements-webp-gzip/) ## Using the Brage theme as is + +### By building a release If you simply want to use the Brage theme for your own Ghost blog then you can [download](https://github.com/switchbitio/brage-ghost-theme/releases) the latest release or if you prefer building it yourself, clone this repository and run: @@ -38,6 +40,95 @@ $ gulp dist && gulp zip Then upload the `brage-ghost-theme.zip` to your Ghost Pro instance or [install](https://www.digitalocean.com/community/questions/installing-themes-in-ghost) on your own hosted Ghost instance. +### By running it with Docker Compose + +> #### Blog URL +> +> You must specify the blog URL by setting the `BLOG_URL` environment variable. +> For example, if you would like a blog URL of `http://my-blog.com`, then `BLOG_URL` must be +> set to `http://my-blog.com`. + +If you choose to run your Ghost blog as Docker containers, you can stand up a complete production instance of Ghost, +with the Brage theme installed, by running the following: + +``` +# You MUST have docker-compose > 1.4.0 installed +$ gulp ghost:docker +``` + +This will use `docker-compose` to build the images and stand up the following containers: + +* `brage_content` - A volume container that will contain your Ghost content, theme files etc. +* `brage_ghost` - Container that will contain your Ghost instance. This is separated from your blog content so that you can upgrade Ghost versions or configurations without losing your content. +* `brage_nginx` - An nginx container pre-configured and optimised to serve your Ghost blog + +You can navigate to [http://localhost](http://localhost) +or the blog URL referenced by `BLOG_URL` to view your Ghost instance. + +**NOTE:** You must first setup your blog by going to [http://localhost/ghost](http://localhost/ghost) and following the instructions. +Once you're done setting up your blog. + +### By running in Docker Cloud + +You can run your Brage themed Ghost instance in [Docker Cloud](https://cloud.docker.com/_/dashboard/onboarding) by using the +Ghost Nginx Stack and the [Brage Docker image](https://hub.docker.com/r/donovanmuller/ghost-with-brage-theme/). + +> Make sure you have a Docker Cloud account that has a valid Cloud Provider connected. +> If you don't have an existing cloud provider, I recommend using [Digital Ocean](https://m.do.co/c/9063364d02d8) (note: this is a referral link). + +#### Nginx Ghost Stack + +The [Nginx Ghost Stack](https://github.com/donovanmuller/nginx-ghost-stack) provides the necessary +platform to proxy a Ghost instance with the following features: + +* Optimised asset caching strategies +* SLL/TLS encryption using [Let's Encrypt](https://letsencrypt.org/) +* All content is served using HTTP/2 when possible + +Click the button below to create and deploy a Nginx Ghost Stack. + +[![Deploy to Docker Cloud](https://files.cloud.docker.com/images/deploy-to-dockercloud.svg)](https://cloud.docker.com/stack/deploy/?repo=https://github.com/donovanmuller/nginx-ghost-stack) + +#### Brage Ghost Stack + +Once you have the Nginx Ghost Stack successfully running in Docker Cloud, click the button below +to create the Brage Ghost Stack, which will be proxied by the Nginx Ghost Stack. + +[![Deploy to Docker Cloud](https://files.cloud.docker.com/images/deploy-to-dockercloud.svg)](https://cloud.docker.com/stack/deploy/?repo=https://github.com/switchbitio/brage-ghost-theme/docker/cloud) + +**Before deploying the Stack** make sure to provide the necessary details matching your blog for the following +environment variables in the Stack file: + +```yaml +... + +ghost: + image: donovanmuller/ghost-with-brage-theme:0.9 + volumes_from: + - ghost-content + environment: + - VIRTUAL_HOST=? + - LETSENCRYPT_HOST=? + - LETSENCRYPT_EMAIL=? + - BLOG_URL=? + restart: always +``` + +Once you've added your specific values you can click the "Create & Deploy" button. +The Nginx Ghost Stack should take care of requesting and installing your certificate and configuring +the Nginx proxy. After a few seconds your blog should be available at `BLOG_URL`. + +*Please see [Part 5](https://blog.switchbit.io/developing-a-ghost-theme-with-gulp-part-5) of the Developing a Ghost theme with Gulp for a more detailed guide.* + +### Mail configuration + +By default [Mailgun](http://www.mailgun.com/) is used as the mail provider. +Set the following environment variables (`MAILGUN_USER` and `MAILGUN_PASSWORD`) for the `brage_ghost` container to the correct values for your Mailgun account. +You can also add these to `docker/ghost/Dockerfile`. + +Alternatively, configure Ghost mail in `docker/ghost/config-prod.js` according to these instructions: [http://support.ghost.org/mail](http://support.ghost.org/mail). +Don't forget to rebuild (this is done for you with `gulp ghost:docker`) your images after making any changes. + ## Developing your own theme If you want to use Brage Ghost theme as a seed project to develop your own theme and assuming you have Gulp installed, install all dependencies: @@ -92,40 +183,6 @@ $ gulp dist && gulp zip The theme `.zip` will be located in the `dist` directory. You can now upload your theme to your Ghost Pro instance or install on your self hosted Ghost instance. -## Run as Docker containers - -If you choose to run your Ghost blog as Docker containers, you can stand up a complete production instance of Ghost, with the Brage theme installed, by running the following: - -``` -# You MUST have docker-compose > 1.4.0 installed -$ gulp ghost:docker -``` - -This will use `docker-compose` to build the images and stand up the following containers: - -* `brage_content` - A volume container that will contain your Ghost content, theme files etc. -* `brage_ghost` - Container that will contain your Ghost instance. This is separated from your blog content so that you can upgrade Ghost versions or configurations without losing your content. -* `brage_nginx` - An nginx container pre-configured and optimised to serve your Ghost blog - -You can navigate to [http://localhost:2368](http://localhost:2368) or the blog URL configured in `docker/ghost/config-prod.js` to view your Ghost instance. - -**NOTE:** You must first setup your blog by going to [http://localhost:2368/ghost](http://localhost:2368/ghost) and following the instructions. -Once you're done setting up your blog, don't forget to select the Brage theme under `Settings > General > Theme`. - -### Mail configuration - -By default [Mailgun](http://www.mailgun.com/) is used as the mail provider. -Set the following environment variables (`MAILGUN_USER` and `MAILGUN_PASSWORD`) for the `brage_ghost` container to the correct values for your Mailgun account. -You can also add these to `docker/ghost/Dockerfile`. - -Alternatively, configure Ghost mail in `docker/ghost/config-prod.js` according to these instructions: [http://support.ghost.org/mail](http://support.ghost.org/mail). -Don't forget to rebuild (this is done for you with `gulp ghost:docker`) your images after making any changes. - -### Blog URL - -The default blog URL is brage.switchbit.io. -Change the URL to that of your blog in `docker/ghost/config-prod.js` and don't forget to rebuild your Ghost image. - ## License See the LICENSE file for license rights and limitations (MIT). diff --git a/app/assets/scss/base/_typography.scss b/app/assets/scss/base/_typography.scss index ce9d700..50805ac 100644 --- a/app/assets/scss/base/_typography.scss +++ b/app/assets/scss/base/_typography.scss @@ -40,3 +40,10 @@ p, li { font-size: 1.2rem; color: $black; } + +blockquote { + padding: 20px 40px; + background-color: lighten($code-grey, 2%); + margin: 0; + border-bottom: $secondary-colour 1px solid; +} diff --git a/app/assets/scss/screen.scss b/app/assets/scss/screen.scss index ea88ae0..9d4d5a3 100644 --- a/app/assets/scss/screen.scss +++ b/app/assets/scss/screen.scss @@ -3,7 +3,6 @@ // endbower // Bourbon Neat - http://neat.bourbon.io/ - //$visual-grid: true; @import "grid-settings.scss"; diff --git a/app/package.json b/app/package.json index 8c4faf9..330fa21 100644 --- a/app/package.json +++ b/app/package.json @@ -1,5 +1,7 @@ { "name": "Brage", - "version": "1.2.0", - "description": "Brage Ghost theme" + "version": "1.3.0", + "description": "Brage Ghost theme", + "repository": "switchbitio/brage-ghost-theme", + "license" : "MIT" } diff --git a/docker/cloud/docker-cloud.yml b/docker/cloud/docker-cloud.yml new file mode 100644 index 0000000..ffcae5e --- /dev/null +++ b/docker/cloud/docker-cloud.yml @@ -0,0 +1,15 @@ +ghost-content: + image: donovanmuller/ghost-content:0.9 + command: echo "Ghost content volume" + autoredeploy: false + +ghost: + image: donovanmuller/ghost-with-brage-theme:0.9 + volumes_from: + - ghost-content + environment: + - VIRTUAL_HOST=? + - LETSENCRYPT_HOST=? + - LETSENCRYPT_EMAIL=? + - BLOG_URL=? + restart: always diff --git a/docker/content/Dockerfile b/docker/content/Dockerfile index 536c1ce..55724a3 100644 --- a/docker/content/Dockerfile +++ b/docker/content/Dockerfile @@ -1,3 +1,3 @@ -FROM ghost:0.8 +FROM ghost:0.9 VOLUME $GHOST_CONTENT diff --git a/docker/docker-compose.https.yml b/docker/docker-compose.https.yml new file mode 100644 index 0000000..c3d69b8 --- /dev/null +++ b/docker/docker-compose.https.yml @@ -0,0 +1,72 @@ +version: "2" + +services: + + nginx-ghost-proxy-template: + image: donovanmuller/nginx-ghost-proxy-template:1 + container_name: nginx-ghost-proxy-template + command: echo "Ghost Nginx proxy configuration volume" + + letsencrypt-certs: + image: busybox + container_name: letsencrypt-certs + volumes: + - "/etc/nginx/certs" + command: echo "Letsencrypt certificate volume" + + nginx-proxy: + image: nginx:1 + container_name: nginx-proxy + ports: + - "80:80" + - "443:443" + volumes_from: + - letsencrypt-certs + - nginx-ghost-proxy-template + networks: + - proxy-tier + + nginx-gen: + image: jwilder/docker-gen:0.7.3 + container_name: nginx-gen + volumes: + - "/var/run/docker.sock:/tmp/docker.sock:ro" + volumes_from: + - nginx-proxy + - nginx-ghost-proxy-template + entrypoint: /usr/local/bin/docker-gen -notify-sighup nginx-proxy -watch -only-exposed -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf + + letsencrypt-nginx-proxy-companion: + image: jrcs/letsencrypt-nginx-proxy-companion:latest + container_name: letsencrypt-nginx-proxy-companion + volumes_from: + - nginx-proxy + volumes: + - "/var/run/docker.sock:/var/run/docker.sock:ro" + environment: + - NGINX_DOCKER_GEN_CONTAINER=nginx-gen + + content: + build: content + container_name: ghost-content + command: echo "Ghost content volume" + + ghost: + build: ghost + container_name: ghost + volumes_from: + - content + environment: + - VIRTUAL_HOST=? + - VIRTUAL_NETWORK=nginx-proxy + - VIRTUAL_PORT=2368 + - LETSENCRYPT_HOST=? + - LETSENCRYPT_EMAIL=? + - BLOG_URL=http://brage.switchbit.local.io + networks: + - proxy-tier + +networks: + proxy-tier: + external: + name: nginx-proxy diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index c3bb0fc..a1ad336 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -3,15 +3,17 @@ nginx: ports: - "80:80" links: - - brage-ghost + - ghost -brage-ghost: +ghost: build: ghost ports: - "2368:2368" volumes_from: - content + environment: + - BLOG_URL=http://brage.switchbit.local.io content: build: content - command: echo "Brage ghost blog content volume" + command: echo "Ghost content volume" diff --git a/docker/ghost/Dockerfile b/docker/ghost/Dockerfile index 4c35837..5f49d10 100644 --- a/docker/ghost/Dockerfile +++ b/docker/ghost/Dockerfile @@ -1,14 +1,14 @@ -FROM ghost:0.8 +FROM ghost:0.9 WORKDIR $GHOST_SOURCE ADD dist/ content/themes/brage +RUN sed -i.bak s/casper/brage/g "/usr/src/ghost/core/server/data/schema/default-settings.json" + ADD config-prod.js config.example.js ENV NODE_ENV production +ENV BLOG_URL ? ENV MAILGUN_USER ? ENV MAILGUN_PASSWORD ? -COPY brage-entrypoint.sh /brage-entrypoint.sh -RUN ["chmod", "+x", "/brage-entrypoint.sh"] -ENTRYPOINT ["/brage-entrypoint.sh"] -CMD ["npm", "start"] +EXPOSE 2368 diff --git a/docker/ghost/brage-entrypoint.sh b/docker/ghost/brage-entrypoint.sh deleted file mode 100755 index 65c968f..0000000 --- a/docker/ghost/brage-entrypoint.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -set -e - -# Force copies of config.js and content/themes -rm -rf $GHOST_CONTENT/themes -rm -f $GHOST_CONTENT/config.js - -chown -R user:user "$GHOST_CONTENT" -chown -R user:user "$GHOST_SOURCE" - -exec /entrypoint.sh $@ diff --git a/docker/ghost/config-prod.js b/docker/ghost/config-prod.js index 0d668fc..d95bc98 100644 --- a/docker/ghost/config-prod.js +++ b/docker/ghost/config-prod.js @@ -5,7 +5,7 @@ var path = require('path'), config = { production: { - url: 'http://brage.switchbit.io', + url: process.env.BLOG_URL, database: { client: 'sqlite3', diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile index 3561117..036d5fc 100644 --- a/docker/nginx/Dockerfile +++ b/docker/nginx/Dockerfile @@ -1,4 +1,4 @@ -FROM nginx:1-alpine +FROM nginx:1 COPY nginx.conf /etc/nginx/nginx.conf COPY brage-blog /etc/nginx/sites-enabled/brage-blog diff --git a/docker/nginx/brage-blog b/docker/nginx/brage-blog index 8e4c72a..6aab001 100644 --- a/docker/nginx/brage-blog +++ b/docker/nginx/brage-blog @@ -1,6 +1,6 @@ server { listen 80; - server_name localhost brage.switchbit.io; + server_name localhost brage.switchbit.local.io; location / { proxy_set_header Host $host; @@ -22,7 +22,7 @@ server { proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; - proxy_pass http://brage-ghost:2368; + proxy_pass http://ghost:2368; } # tokenized images can be cached forever @@ -31,7 +31,7 @@ server { add_header Cache-Control public; add_header Vary Accept; - proxy_pass http://brage-ghost:2368/$uri$webp_suffix; + proxy_pass http://ghost:2368/$uri$webp_suffix; access_log off; } @@ -41,7 +41,7 @@ server { expires 1w; add_header Cache-Control public; - proxy_pass http://brage-ghost:2368/$uri; + proxy_pass http://ghost:2368/$uri; access_log off; } @@ -51,7 +51,7 @@ server { expires max; add_header Cache-Control public; - proxy_pass http://brage-ghost:2368/$uri; + proxy_pass http://ghost:2368/$uri; access_log off; } diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf index 4f6099a..b0a90c4 100644 --- a/docker/nginx/nginx.conf +++ b/docker/nginx/nginx.conf @@ -1,6 +1,6 @@ user nginx; worker_processes 1; -error_log /var/log/nginx/error.log warn; +error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { @@ -15,12 +15,11 @@ http { '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; - access_log /var/log/nginx/access.log main; + access_log /var/log/nginx/access.log main; error_log /var/log/nginx/error.log; sendfile on; keepalive_timeout 90; - gzip_static on; gzip_proxied expired no-cache no-store private auth; gzip on; gzip_types text/plain text/css application/json application/javascript text/xml application/xml diff --git a/gulp/config.js b/gulp/config.js index 758c5cc..cdace8e 100644 --- a/gulp/config.js +++ b/gulp/config.js @@ -163,7 +163,7 @@ module.exports = { dist: { docker: { src: 'docker', - command: 'docker-compose -p brage build' + command: 'docker-compose -f docker-compose.http.yml -p brage build' } }, ghost: { @@ -173,7 +173,7 @@ module.exports = { prod: { env: 'gulp/prod.env.json', config: '../../ghost-prod-config.js', - docker: 'docker-compose -p brage build && docker-compose -p brage up' + docker: 'docker-compose -f docker-compose.http.yml -p brage build && docker-compose -f docker-compose.http.yml -p brage up' } } }; diff --git a/gulp/tasks/development/sass.js b/gulp/tasks/development/sass.js index d4de5fd..b6b06d6 100644 --- a/gulp/tasks/development/sass.js +++ b/gulp/tasks/development/sass.js @@ -1,25 +1,19 @@ var gulp = require('gulp'); -var plumber = require('gulp-plumber'); var sass = require('gulp-sass'); -var browserSync = require('browser-sync'); +var sourcemaps = require('gulp-sourcemaps'); var autoprefixer = require('gulp-autoprefixer'); -var neat = require('node-neat').includePaths; +var neat = require("bourbon-neat").includePaths; +var bourbon = require("bourbon").includePaths; var config = require('../../config').sass; gulp.task('sass', function () { - browserSync.notify('Compiling Sass...'); - return gulp .src(config.src) - .pipe(plumber({ - errorHandler: function (err) { - console.log(err); - this.emit('end'); - } - })) + .pipe(sourcemaps.init()) .pipe(sass({ - includePaths: ['sass'].concat(neat) - })) + includePaths: ['sass'].concat(neat).concat(bourbon) + }).on('error', sass.logError)) .pipe(autoprefixer()) + .pipe(sourcemaps.write('./maps')) .pipe(gulp.dest(config.dest)); }); diff --git a/gulp/tasks/development/watch.js b/gulp/tasks/development/watch.js index 47fb8c8..b8e8111 100644 --- a/gulp/tasks/development/watch.js +++ b/gulp/tasks/development/watch.js @@ -7,7 +7,7 @@ gulp.task('ghost', function (callback) { 'symlink', 'ghost:start', // sass (dependency of ghost:start) does not like it when symlink is run async function () { - gulp.watch(config.templates, ['ghost:restart', 'browser-sync:reload']); + gulp.watch(config.templates, ['browser-sync:reload']); gulp.watch(config.scss, ['sass']); gulp.watch(config.js, ['jshint']); diff --git a/gulp/tasks/ghost-reset.js b/gulp/tasks/ghost-reset.js index 9aeb577..2d7c5d2 100644 --- a/gulp/tasks/ghost-reset.js +++ b/gulp/tasks/ghost-reset.js @@ -10,11 +10,11 @@ gulp.task('ghost:reset', function (callback) { 'ghost:install', 'init', callback - ) + ); }); -gulp.task('ghost:delete', function (callback) { - del(config.src, callback); +gulp.task('ghost:delete', function () { + del.sync(config.src); }); gulp.task('ghost:install', function () { diff --git a/package.json b/package.json index a4e5690..ce2ea2f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "brage-ghost-theme", - "version": "1.2.0", + "version": "1.3.0", "description": "Brage Ghost theme", "license": "MIT", "repository": "switchbitio/brage-ghost-theme", @@ -11,37 +11,39 @@ "bower": "~1.7.9", "browser-sync": "~2.12.10", "del": "~2.2.0", - "ghost": "~0.8.0", + "ghost": "~0.9.0", "gulp": "~3.9.1", "gulp-autoprefixer": "^3.1.0", - "gulp-cdnizer": "~1.1.6", + "gulp-cdnizer": "~1.1.7", "gulp-cssnano": "~2.1.2", "gulp-env": "~0.4.0", "gulp-google-webfonts": "~0.0.12", "gulp-gzip": "~1.3.0", "gulp-htmlmin": "~2.0.0", - "gulp-imagemin": "~3.0.1", + "gulp-imagemin": "~3.0.3", "gulp-install": "~0.6.0", "gulp-jshint": "~2.0.1", - "gulp-msg": "~0.0.1", - "gulp-plumber": "~1.1.0", "gulp-rename": "~1.2.2", "gulp-replace": "~0.5.4", - "gulp-rev": "~7.0.0", - "gulp-rev-collector": "~1.0.3", + "gulp-rev": "~7.1.2", + "gulp-rev-collector": "~1.0.5", "gulp-sass": "~2.3.1", + "gulp-sourcemaps": "~1.6.0", "gulp-shell": "~0.5.2", "gulp-size": "~2.1.0", "gulp-sym": "~0.0.14", - "gulp-uglify": "~1.5.3", + "gulp-uglify": "~2.0.0", "gulp-useref": "~3.1.0", "gulp-webp": "~2.3.0", "gulp-zip": "^3.2.0", "jshint": "~2.9.2", "jshint-stylish": "~2.2.0", - "node-neat": "~1.7.2", "require-dir": "~0.3.0", "run-sequence": "~1.2.1", "wiredep": "~4.0.0" + }, + "dependencies": { + "bourbon": "^4.2.7", + "bourbon-neat": "^1.8.0" } }