Moving Jekyll to Docker

a.k.a. Docker Jekyl and Mr. Hyde. (Sorry, I couldn’t resist.)

At this point, the only Ruby thing I’m using on my Macbook is Jekyll. Instead of installing an up-to-date ruby, chruby, bundler, and ruby-build (which was how I’d previously run Jekyll). This is the story of how I migrated my Jekyll sites (kleinfelter.com and k4kpk.com) into Docker containers.

 

Notes:

  • My local copy of my primary web site lives in the directory ‘kleinfelter.github.io’.
  • I launch my Jekyll via a Launch Agent, which runs the shell script runme-local.sh in the site directory.
  • I have a newer, canonical form for using Docker.

Steps:

  • Install Docker for Mac.
  • Since I’m auto-starting Jekyll via a Launch Agent, I need to stop the existing one:
    • launchctl unload /Users/kevin/Library/LaunchAgents/com.kleinfelter.jekyll.kleinfelter.plist
  • Since I’m going to use the jekyll/jekyll image, I can stop using bundler. I’m not going to uninstall bundler, since that’s part of my Macbook’s ruby installs, but since I’m going to be using the gems provided in the image, I don’t need to be coordinating my own gems.
    • cd kleinfelter.github.io
    • git rm Gemfile
    • git rm Gemfile.lock
    • git rm -r vendor
    • rm -r vendor
  • Create a docker-compose.yml in kleinfelter.github.io containing:
jekyll-kleinfelter:
    build: .
    command: jekyll serve --watch --incremental
    ports:
        - 4000:4000
    volumes:
        - /Users/kevin/Sync/Sites/kleinfelter.github.io:/srv/jekyll
  • Strictly speaking, docker-compose is about running multiple containers. However, you can use it to run a single container, and it makes the command line for that container simpler, by allowing you to put some of your options in the docker-compose file. This config says:
    • Service is named ‘jekyll-kleinfelter’
    • Build per the ‘Dockerfile’ in the current directory.
    • Launch the process to run in the container with: the given ‘command’ line.
    • Connect host port 4000 to container port 4000.
    • Mount the given host volume onto /srv/jekyll
  • I’m using the jekyll-admin plugin. I was using the gem for it, with bundle. Now that jekyll runs in a container, I can install the gem into the container’s site-ruby. Create the file ‘Dockerfile’ in kleinfelter.github.io:
FROM jekyll/jekyll:pages
RUN gem install jekyll-admin
  • That says:
    • Base your image on the official jekyll plugin, the version designed to work with github-pages.
    • When building your image, run the given ‘gem’ command to add the gem.
  • Test it with:
docker-compose build --no-cache
docker-compose up --force-recreate
  • Edit runme-local.sh to contain:
#!/bin/bash
cd /Users/kevin/Sync/Sites/kleinfelter.github.io
/usr/local/bin/docker-compose up
  • Once you’re done testing: launchctl load /Users/kevin/Library/LaunchAgents/com.kleinfelter.jekyll.kleinfelter.plist
  • Occasionally, when Jekyll is running, I need to force a site rebuild.
    • Discover the proper container via: docker ps --format 'table {{.Names}}'
    • Connect to the existing container: docker exec -it CONTAINER_NAME_HERE /bin/bash
    • Run: jekyll build

Jekyll Not Updating Front Page With Incremental

When I used ‘–incremental –watch’, it looked like Jekyll was not updating. It turns out that it was rebuilding the page itself, but not the content which was loaded to the landing page (a.k.a. the front page). The solution is to add this to index.html in the main site directory:

regenerate: true

Works much better now.

Jekyll Daemon on Mac OS X

eee I wanted to have jekyll always running on my Macbook, so that I could preview my posts before pushing them to my Github Pages site. Here’s how I set it up with a Launch Agent. (The challenging parts were learning how to use Launch Agents to run shell scripts and learning how to run Jekyll from a non-login shell.)

I’m using chruby to manage multiple versions of Ruby, and bundle to manage multiple gem levels, and I use Homebrew as a package manager. YMMV if you use other tools. I’ve previously confirmed that I can manually launch Jekyll for both of my sites.

 

I have two sites: k4kpk.com and kleinfelter.com, at k4kpk.github.io and kleinfelter.github.io respectively.

 

create ~/Library/LaunchAgents/com.kleinfelter.jekyll.k4kpk.plist:

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.kleinfelter.jekyll.k4kpk</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>/Users/kevin/Sync/Sites/k4kpk.github.io/runme-local.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/tmp/k4kpk.jekyll.log</string>
    <key>StandardErrorPath</key>
    <string>/tmp/k4kpk.jekyll.err</string>
</dict>
</plist>

 

Similarly, create ~/Library/LaunchAgents/com.kleinfelter.jekyll.kleinfelter.plist, with ‘kleinfelter’ substituted for ‘k4kpk’.

 

/Users/kevin/Sync/Sites/k4kpk.github.io/runme-local.sh should contain:

#!/bin/bash
source /Users/kevin/.bash_profile
cd /Users/kevin/Sync/Sites/k4kpk.github.io
chruby 2.4.2
bundle exec jekyll serve --incremental

 

  • Test it with: launchctl start com.kleinfelter.jekyll.k4kpk.plist

  • Check output in /tmp/k4kpk.jekyll.err and /tmp/kleinfelter.jekyll.err

 

I had to add this to my Gemfile to prevent an “invalid byte sequence in US-ASCII” error:

Encoding.default_external = Encoding::UTF_8

 

I also added this to my _config.yml

encoding: utf-8

Plotting Two Kinds of Points on Google Maps

(This story is an enhanced edition of this story from my ham radio site.)

Suppose you have a set of names and addresses, and you’d like to display them on a Google Map. Further suppose that you have two kinds of items to display – perhaps you’re displaying members of your family and you’d like red markers for the girls and blue markers for the boys. (It is a contrived example – what can I say?)

The first thing you need is to create a text file with names and addresses.

  • Column 1 should be Name.
  • Column 2 should be Address. Enter street address, a comma, city name, a comma, state name.
  • Column 3 should be Marker_Type. Girls get “large_red”. Boys get “large_blue”.

Separate your columns with TAB character. I’ll refer to this as a CSV file, but tab works better as a delimiter because you’ll have commas in your data. You really want the Address column to contain street address, city, and state, separated by commas.

Here’s an example:

NAME    Address Marker_Type
Fred Smith      123 Maple St,Anytown,OH large_blue
Mary Smith      246 Oak St,Anytown,OH   large_red
Jane Smith      100 Park Place,New York,NY   large_red

Save the file on your computer. (You could also store it on the web, but my example assumes it is stored locally.)

To load this data into Google Maps, we’re going to use something Google calls Fusion Tables. Navigate to drive.google.com. (You’ll have to sign up for a Google account, if you don’t have one.)

  • Choose New, then More, then Google Fusion Tables.
  • Tell it you want to load a file ‘From this computer’.
  • Select the data file you created (per above instructions).
  • Import the data. Importing goes pretty fast.
  • Select ‘Map of Address’. The first time you do this, Google must geocode your addresses. This is slow - about 1 second per address.
    • As this progresses, keep an eye on “Quality: 0% ambiguous”. If that 0 changes, it means Google had to guess where an address was. For me, it guessed that Rome, GA was really Rome, Italy. Bad guess. I fixed that by putting street, city, and state into a SINGLE field, as mentioned above. Google looks at only a SINGLE field for address.
  • On the left side of the page, you’ll see a “Configure map” panel. Press the “Change feature styles” button.
  • In the “Map marker icons” area, select the Column tab, to tell Google which column contains red/blue information.
  • Select “Use icon specified in a column”, select your Marker_Type column, and Save your update.
  • When you’re done, press the Done button.
  • In the upper-right corner is a Share button. I like to set my sharing option to “On - anyone with the link”, but your needs may differ.
  • Copy the URL from the “Link to share” field, press Done and save your changes.

Distribute the copied URL to people who you’d like to share with.

OS X Sidebar Missing Favorites

The sidebar in my OS X el Capitan is missing my Faviorites, but just in file Open/Save dialogs, not in Finder.

There are published work-arounds. Some of them result in having to recreate one’s Favorites. I don’t like that.

What worked for me on September 27, 2017:

  • Make a change to my Favorites on my Finder sidebar. (Add/delete/move an item.)
  • Reboot

I think you have to do both. It might be enough to change Favorites and then restart Finder.

Tiddlywiki or zim

I’ve been using TiddlyWiki Classic (TWC) as a personal knowledgebase (PKB). At first, it was real handy in that I just had a single file with the code and data and it ran in any browser.

Then that devolved to “runs in Firefox with the Tiddlyfox extension” due to browsers ‘improving’ their security. (Yeah, I’m aware of the stand-alone TiddlyWiki browser.) Soon, it will stop running in Firefox, when Firefox drops support for the old extension architecture.

I could keep an old copy of Firefox around, just to run the old extension. Under Windows, I’d use an old Firefox Portable. Under Mac, I’d go through a song-and-dance to use two Firefox.app. And I’d also have to ensure that the different editions of Firefox never stepped on each other’s profile. No thanks.

Why not use Evernote? It’s real handy, but I’m not willing to bet they will never be compromised. I store seriously confidential data like account numbers.

Why not use OneNote? I use Mac and Windows, and the Mac edition does not support local notebooks. It’s real handy, but I’m not willing to bet they will nev er be compromised. I store seriously confidential data like account numbers.

OK. So I’m going to run a local app (or at least an on-MY-server app). What else do I want?

  • Store each note in a separate file, searchable by my OS’s search routine, with content recovery via plain-text editor.

    • I’ve decided on the single-file-local-search paradigm in the past. It has many advantages (documented elsewhere).
  • Need to access content from my employer-provided (and controlled) notebook, and on my Macbook.
  • Need real wiki-style hyperlinking.
  • Some ability to include images. It is OK if the images must be stored separately, although integrated image management is better. Plain copy/paste is best, with zim’s “attachments” being a compromise.
  • I need some way to import 700+ tiddlers from my TWC.

Windows Portability:

  • I’m not supposed to install un-approved software on my employer’s notebook. Right now, node.js is on the approved list, but it could vanish or they could decide that “approved” means “on a server”. There are reports of how to run node.js without install, which could become my work-around, or I could move my work notebook to a personal (or Amazon AWS) web server. Or there’s zim portable. Advantage: tie

OS Portability:

  • node.js TW and zim both can be made to work on Windows, Mac, Linux. Advantage: tie

Moving the Wiki Portability:

  • With the Windows portable-zim, you can just copy the directory tree to a new Windows PC. You can’t move it to OS X that way.
  • Whether zim or TW5 on node.js, it isn’t just copy-the-wiki-file like it was with TWC.

Learning:

  • I’d like to better learn Python; I’d like to better learn JavaScript. Advantage: tie
  • It might be interesting to run node.js TW via Docker.

File format:

  • Both the node.js TW and zim store documents as separate files. Advantage: tie

Import:

  • node.js TW is going to import my TWC tiddlers. zim isn’t. I could import TWC into TW5, then write code to move the TW5 files to zim, along with re-formatting. Lots of work. Advantage: TW

Markdown:

  • Markdown is a non-standard. Every implementation is different. But it is at least a pseudo-standard. TW5 and zim both use unique ‘blended’ markup. But TW5 can be told to use Markdown. Advantage: TW

Putzing:

  • TW has a high risk of wasting time tinkering with it. zim less so. Advantage: zim

Export:

  • zim has more options to export to something else. TW exports to TW. That’s automated export. With either one, they store data as files, so I could write my own. Advantage: zim.
  • Both can export the whole wiki as a single HTML file for viewing elsewhere.

Math:

  • I dabble in statistics. I need to be able to enter mathematical formulae. There’s a MathJax plugin for TW. zim has Equation Editor. Advantage: tie

Table:

  • I insist on being able to create tables. Both offer some form of tables. Neither does them as slick as Word. Advantage: tie

Transclusion:

  • TW does; zim doesn’t. Advantage: tie

WYSIWYG:

  • zim has it built-in; TW has a plugin at http://bjtools.tiddlyspot.com. Advantage: zim

Recent Changes:

  • TW lists recently updated pages; zim doesn’t. Advantage: TW

Attachments:

  • zim has built-in attachments; TW5 yes, with some limits. Advantage: not sure.

As I was creating this document, I had a thought: “What about just using Jekyll?” I’m already using Jekyll (via GitHub Pages) for my blogs. I could focus my learning on a sigle platform if I kept a private Jekyll notebook.

  • Advantage: Learn one platform; learn it well.
  • Disadvantage: Higher friction to get content into it. You can certainly create pages, and you can search pages, but you can’t just add a wiki word to a page and then follow it to a new page.
  • Disadvantage: Have to get Ruby onto my employer’s laptop, where it is classed as “emerging” (meaning “not forbidden but you must justify its use.”)

Someone really could build a hybrid of jekyll and jekyll-admin and add wiki-like features to it, but right now, friction is the killer for using jekyll as a PKB.


Conclusion: zim and TW5 are roughly on par with each other. If I were starting a new PKB, I might choose otherwise, but TW5’s ability to import TWC makes moving to TW5 much easier than any other choice. I’m moving my PKB to TW5 on node.js.

Side note: I’m going to start using jekyll-admin for my blogs. It is simple, but handier than using vi.

Chrome, Firefox, or Safari

August 2017, with minor edits May 2018:

Issues with IE:

  • I don’t use Internet Explorer because I run on Mac and Windows, and there is no IE for Mac.

Issues with Safari:

  • Safari isn’t available on Windows. (Not a current version.)
  • I used to avoid Safari because it didn’t pin tabs. Safari now pins tabs. It sometimes does not load favicons on these tabs which Chrome does.
  • When you open more tabs than fits well on your screen, Safari handles it poorly.
  • Safari Problem: LastPass export doesn’t work in Safari (Sept 1, 2017). It silently fails after re-entering my password to enale export. No prompt for export filename or download-starting message. It doesn’t work in Firefox either. Right now, the only way I can export LastPass is via Chrome. I’ve quit using LastPass, so this is no longer an issue.
  • Fluid.app is a clever idea, but Wunderground behaves poorly (intermittently), Nirvana suddenly closes item-edits while I’m entering valid data. I don’t need another source of weirdness to debug.

Safari Advantages:

Issues with Firefox:

  • I used to use Chrome instead of Firefox because the Chrome edition of AdBlock was better, but that’s no longer the case.

Firefox Advantages:

  • TiddlyFox. (Although this extension will die when Firefox upates to its new extension model.)

Issues with Chrome:

  • May 2018: I picked up some kind of Chrome malware. Whenever I went to msn.com, I got redirected to a cheesy site. This persisted when I launched Chrome with extensions disabled. It persisted through a Chrome remove+reinstall. To cure it, I had to remove Chrome, and search my home folder for everything with “Chrome” in the name, and remove all files truly related to Chrome.
  • Chrome’s extension ecosystem is a break-in waiting to happen. There have been cases where a Chrome extension developer lost control of his account and a bad guy pushed an unauthorized update to an extension. Every extension in Chrome means I have to trust its developer’s staff not to be tricked by phishing. Every extension on any browser weakens the browser’s security by adding any of the extension’s vulnerabilities to the browser footprint. Malware authors are now targeting extension vulnerabilities.
  • Important: Firefox and Safari let you disable extension auto-update. Chrome does not.
  • Chrome consumes way too much Mac battery.
  • Consumes excess battery on my Macbook

Chrome Advantages:

  • Chrome now prevents blocking of HTML5 video auto-play. There is an extension called Disable HTML5 Autoplay, but it doesn’t block sites such as https://www.usatoday.com/story/news/politics/onpolitics/2017/07/11/majority-republicans-say-colleges-have-negative-impact-country-poll-says/468869001/.
  • LastPass export doesn’t work in Safari or Firefox. Right now, Chrome is the only way I can export/back-up my critical Lastpass data.
  • Right now Chrome is the dominant browser. This means most sites will test with Chrome.

Extension List:

  • Adblock: I used to really value AdBlock (the getadblock.com one). I now get so much “we won’t show you content because you are blocking ads” that it is almost worthless.
  • Lastpass: I really need a password manager. I need to be able to share passwords with my wife and I need to share between PC, Mac, and Android. Do I need it to be integrated into my browser?
  • Authy: I need Authy. Do I need it integrated into my browser?
  • Session Buddy: I need bullet-proof session restore.
  • Stop Video/Animation: I don’t want movies to auto-play. I need them to be quiet if I can’t block them.
  • Amazon Wish List: Handy to be able to add non-Amazon stuff to my wishlist, but hardly indispensable.
  • Copy All URLS: Handy. It is really slow if I have to copy 99 URLs, one at a time.
  • Pushbullet. Handy. I can live without it, if doing so increases my security.
  • Stylish. Ow. I really like to restyle some sites, but Stylish has had some significant vulnerabilities.

Do Not Use the Default ruby and Do Not sudo gem install

Don’t use the default ruby on Mac OS X.

Don’t run “sudo gem install gemname_here”.

Sooner or later, you will need multiple versions of ruby.

Sooner or later, you will need multiple versions of a gem.

Use chruby and ruby-install to manage different versions of ruby. Create a ~/.ruby-version to specify your default ruby version.

Use bundler to put your gems into your project folder instead of the global OS X folder.