August 21, 2020#technical

Dockerizing My Website

I tend to revamp my website in part or whole every six months or so. This time, I didn't exactly switch it up entirely, but I did switch from static hosting to hosting on a server. Mostly for fun, but also because I wanted to move away from the restrictions of static hosting.

If you've kept up with my website, you may know that I use Netlify to host it. Netlify is a neat and free service that picks up changes to Git repos via webhooks and runs a script or two to generate static files to serve as your website. As part of the Github Education Pack, though, I realized I had access to $50 worth of DigitalOcean credits. This happens to be enough for 10 months of hosting on their smallest machine, which is plenty for my needs.

Now, I didn't need to switch. I did so simply because I felt like it, and because I wanted to learn how Docker worked. I had previously blindly set up a local webserver using Dokku, which hosted my startpage and my custom-made calendar. The downside was that Dokku was incredibly slow and resource-heavy when I was deploying things, so I neglected both of my local apps and they never got updated to have what I needed them to. I wasn't particularly thrilled about Docker because of this experience, but I figured I'd give it a shot because it sounded fun.

A couple of days worth of fooling around later, I had a clear idea of what I wanted to do, and my DigitalOcean droplet serves as a Git remote now. Instead of just pushing to Gitlab and being done, I set up a series of post-receive scripts on my droplet remote that read from a stack file. This stack file tells the remote what kind of website I had just pushed, and it deploys accordingly. For example, if stack contains the word next, then the website is a next.js website. There's a relevant Dockerfile stored that it copies and uses, and that's how my website is deployed. It's exposed to a port that nginx knows to proxy the relevant domain to, so that part only had to be taken care of once per website.

The Dockerfile for my next.js websites, by the way, looks like this:

# set up the node modules
FROM node:14-alpine AS dep

WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install

# set up the website itself
FROM node:14-alpine AS release

COPY --from=dep /usr/src/app/node_modules ./node_modules
COPY . .
RUN npm run build

CMD npm start

I almost always use Alpine-based images, which are remarkably small. The only thing that doesn't use an Alpine-based image is my resume host, which renders all of the LaTeX resumes at buildtime and therefore cannot work off of Alpine Linux (since pdflatex setup is far more complicated, if not possible, on Alpine).

The server is overkill, no doubt about it. My purpose was being fully served with Netlify hosting, and there's nothing really new that I'm doing here that I couldn't have accomplished there. However, it was an excellent learning experience and it serves as a nice gateway to potential dynamic apps in the future. Not only did I learn how to use Docker, I also learned how to set up an nginx webserver proxy as well as how to deal with certbot to acquire SSL certificates for my websites.

I learn by doing, which is precisely why I redo my website so often. It's not just because I get bored of the design, it's in fact mostly because I've heard of a different web development stack that I've never used before that I want to learn. It just so happens that I end up redesigning my website while I'm at it (though I think the current design is here to stay for a while, as it seems like I'm not the only one who really likes it). Learning by doing is highly effective for me, so if anyone wants to try a new way of expanding knowledge, I'd doubtlessly suggest experimenting with something new. You never know when it'll click!