I received a Raspberry Pi 3 Model B last Christmas, but I did not know what to do with. Or at least not yet. The problem has little to do with the Pi and more of the fact that most of the projects that I do can easily be solved with an Arduino.
When I stumbled upon these series of posts by the Docker Captain Alex Ellis, I figured out that this is a perfect opportunity to learn a tool I have always wanted to use. I know virtual machines well, but I had a hard time understanding how to make Docker fit into my workflow. The idea of containers that I cannot simply SSH into (I now know that you can exec bash to peek inside them, but that's not the point), just seemed absurd when I was first trying to use it. To be honest it felt too complex and cumbersome that I just dismissed it as something that was not worth it. Well, it turned out that I did not understand the philosophy behind it. I would like to talk about it and discuss images and containers in depth, but I decided that it will be better to have a dedicated post for that. After getting my hands dirty with Docker last weekend, I can say that I have attained a working proficiency with it and I can comfortably use it for my projects from here on.
After three days, I finally got it to work. The blog that you are reading right now is hosted on a Raspberry Pi with Docker Engine installed. I have two Docker containers running: the Ghost blog and the NGINX server that handles the caching. It took me a lot of trial and errors before I finally got it to work; I do not have any prior knowledge of NGINX when I embarked on this weekend project. The Pi's limited hardware made building images painstakingly slow. Building SQLite3 from source for the ARM architecture was excruciating.
I will be sharing my Dockerfiles and some configuration below. I won't go into more detail right now, but I am hoping that I will have the time to do so in my next post. Some of these are directly forked/copied from [Alex]((http://blog.alexellis.io)'s GitHub repositories; I could have pulled the images from Docker Hub or cloned the Dockerfiles but I decided to train my muscle memory by typing the Dockerfiles manually. I still have a lot to learn about NGINX and Docker in particular, but I consider this blog as a milestone.
Ghost Dockerfile
FROM alexellis2/node4.x-arm:latestUSER rootWORKDIR /var/www/RUN mkdir -p ghostRUN apt-get update && \apt-get -qy install wget unzip && \wget https://github.com/TryGhost/Ghost/releases/download/0.11.4/Ghost-0.11.4.zip && \unzip Ghost-*.zip -d ghost && \apt-get -y remove wget unzip && \rm -rf /var/lib/apt/lists/*RUN useradd ghost -m -G www-data -s /bin/bashRUN chown ghost:www-data .RUN chown ghost:www-data ghostRUN chown ghost:www-data -R ghost/*RUN npm install -g pm2USER ghostWORKDIR /var/www/ghostRUN /bin/bash -c "time (npm install sqlite3)"RUN npm installEXPOSE 2368EXPOSE 2369RUN ls && pwdENV NODE_ENV productionRUN sed -e s/127.0.0.1/0.0.0.0/g ./config.example.js > ./config.jsCMD ["pm2", "start", "index.js", "--name", "blog", "--no-daemon"]
Blog Dockerfile
FROM johncrisostomo/ghost-on-docker-arm:0.11.4ADD Vapor /var/www/ghost/content/themes/VaporRUN sed -i s/my-ghost-blog.com/blog.johncrisostomo.com/g config.js
NGINX Dockerfile
FROM resin/rpi-raspbian:latestRUN apt-get update && apt-get install -qy nginxWORKDIR /etc/nginx/RUN rm /var/www/html/index.nginx-debian.html && \rm sites-available/default && \rm sites-enabled/default && \rm nginx.confCOPY nginx.conf /etc/nginx/COPY johncrisostomo.com.conf conf.d/EXPOSE 80CMD ["nginx", "-g", "daemon off;"]
JOHNCRISOSTOMO.COM.CONF
server {listen 80;server_name blog.johncrisostomo.com;access_log /var/log/nginx/blog.access.log;error_log /var/log/nginx/blog.error.log;location / {proxy_cache blog_cache;add_header X-Proxy-Cache $upstream_cache_status;proxy_ignore_headers Cache-Control;proxy_cache_valid any 10m;proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;proxy_set_header X-Real-IP $remote_addr;proxy_set_header Host $http_host;proxy_pass http://blog:2368;}}
docker-compose.yml
version: "2.0"services:nginx:ports:- "80:80"build: "./nginx/"restart: alwaysblog:ports:- "2368:2368"build: "./blog.johncrisostomo.com/"volumes:- ghost_apps:/var/www/ghost/content/apps- ghost_data:/var/www/ghost/content/data- ghost_images:/var/www/ghost/content/images- ghost_themes:/var/www/ghost/content/themesrestart: alwaysvolumes:ghost_apps:driver: localghost_data:driver: localghost_images:driver: localghost_themes:driver: local
I have written several follow up posts about this project. Feel free to check them out as most of them are troubleshooting issues and optimizations that are built on top of this project.