Sculpin and Docker
I've been running this blog on Sculpin for quite a while now, and I'm quite happy with how that works. We've been in a process of migrating some of our websites off a standard VPS towards a setup with Docker, Gitlab CI and Rancher. I've now migrated some websites, which is relatively easy, but most of those sites were dynamic PHP websites. Migrating a site that generates static HTML and running that is a slightly different thing. Here's how I ended up doing it.
The old setup
First, let me quickly describe my old setup. I had set up Sculpin on my webserver and put only the blogposts into a Git repository that was hosted on Github. After committing and pushing a new blogpost, I'd manually run a shell command that would generate the new static version:
ssh -t user@domain 'cd /var/www/vhosts/leftontheweb.com/site/source/_posts;git pull origin master;cd /var/www/vhosts/leftontheweb.com/site;php /var/www/vhosts/leftontheweb.com/site/bin/sculpin.phar generate --env=prod --url=http://leftontheweb.com'
This worked, but would be a bit harder with a new setup. Besides, why would I want to do it manually when I could have it all be done automatically after pushing a new blogpost?
The new setup
First, let's have a look at the global setup that we have:
- Gitlab for Git repository hosting, we're using Gitlab pipelines to build and push changes
- We've got droplets on Digital Ocean which contains our Docker/Rancher setup
- Our production setup is managed by Rancher
So once we push some changes to master (I mean: merge a merge request) a Gitlab pipeline is triggered that builds the Docker container, and pushes the new container to Rancher. All of a sudden, the website is updated.
Now that we've got that basic setup described, let's have a look at how I've set this up with Sculpin.
My initial attempt
In my initial attempt I started with the base Nginx container and started working from there.
I started running into some issues with installing PHP, so I decided to approach it from the opposite side.
My second attempt
I started over by using the base PHP7 container
So, first things first: I'll need to install Nginx, because eventually I need to serve my static website to anyone wanting to visit my site.
RUN apt-get update RUN apt-get install -y nginx
For installing Sculpin I'll need Git and the Zlib library, so I'll also install that.
RUN apt-get install -y git RUN apt-get install -y zlib1g-dev && docker-php-ext-install zip
Now, let's install Composer so I can use that for installing Sculpin.
ADD https://getcomposer.org/installer /tmp/composer-installer.php RUN php /tmp/composer-installer.php --install-dir=/usr/local/bin --filename=composer && \ rm /tmp/composer-installer.php
OK, all prerequisites are installed, let's install Sculpin.
RUN git clone https://github.com/sculpin/sculpin.git /usr/lib/sculpin && \ cd /usr/lib/sculpin && \ composer install && \ ln -s /usr/lib/sculpin/bin/sculpin /usr/local/bin/sculpin
Now I have a basic Sculpin install in /usr/lib/sculpin. I now want to customize that installation with my own custom information. I've structured my Git repository in such a way that I can easily copy my custom configuration into this base installation. My repository layout is:
/app /posts /source
app/ contains a
config/ directory that contains the Sculpin configuration files (
sculpin_kernel.yml which contains the URL structure and
sculpin_site.yml which contains some basic site information, my Google Analytics ID and the Disqus configuration).
posts/ contains all my blogposts. This is basically what I imported from my old Git repository. All the blogposts are in here with any images that may be needed for the blogposts.
source/ is my own source directory for Sculpin. It contains my theme and custom pages. As we'll see later, this is also where the contents of
posts/ will end up being placed, but I wanted the blogposts to be more easily accessible, so I've seperated the
So, given that structure, I can now copy the contents of those directories to my container.
COPY app /usr/lib/sculpin/app COPY source /usr/lib/sculpin/source COPY posts /usr/lib/sculpin/source/_posts
I copy the
app/ directory to the Sculpin installation, I copy
source/ to the Sculpin directory, and now I copy the posts to the
_posts/ to the
source/ directory. Now I've got everything I need to generate the static website using Sculpin.
RUN cd /usr/lib/sculpin && bin/sculpin generate --env=prod --url=https://leftontheweb.com
This will call Sculpin to generate the new static version of my blog. The new version is generated in the
output_prod/ directory in my Sculpin installation. Of course, this is not the Nginx document root, so I need to make sure I can expose the static site using Nginx.
RUN rm -rf /var/www/html RUN ln -s /usr/lib/sculpin/output_prod /var/www/html
Firstly, I remove the default Nginx document root. After that, I create a symlink to the
output_prod/ directory. Now I can serve my static site. The only thing that is left is to ensure Nginx gets started.
CMD ["nginx", "-g", "daemon off;"]
This starts Nginx and makes sure the site is now being served. Everything is up and running!
I need to give some credits of course, because I have used some sources for inspiration. First of all, I used the gitlab runner sculpin to check some of steps in the Dockerfile in my second attempt. Also, my standard "HELP! IT NO WORK!" person Mike gave me some insights in to how to solve some of the problems I encountered along the way.